All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.everrest.websockets.WSConnectionContext Maven / Gradle / Ivy

There is a newer version: 1.15.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2012-2016 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.everrest.websockets;

import org.everrest.websockets.message.ChannelBroadcastMessage;
import org.everrest.websockets.message.Pair;
import org.everrest.websockets.message.RestOutputMessage;
import org.slf4j.LoggerFactory;

import javax.websocket.EncodeException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author andrew00x
 */
public class WSConnectionContext {

    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(WSConnectionContext.class);

    static final List  connectionListeners = new CopyOnWriteArrayList<>();
    static final Map connections         = new ConcurrentHashMap<>();

    public static boolean registerConnectionListener(WSConnectionListener listener) {
        return connectionListeners.add(listener);
    }

    public static boolean removeConnectionListener(WSConnectionListener listener) {
        return connectionListeners.remove(listener);
    }

    /**
     * Send message to all connections subscribed to the channel. Method tries to send message to as many connections as
     * possible. Even if method fails to send message to the first connection it will try to send message to other
     * connections, if any. After that a first occurred error is rethrown.
     *
     * @param message
     *         message
     * @throws EncodeException
     *         if message cannot be serialized
     * @throws IOException
     *         if any i/o error occurs when try to send message to client
     * @see org.everrest.websockets.message.ChannelBroadcastMessage#getChannel()
     */
    public static void sendMessage(ChannelBroadcastMessage message) throws EncodeException, IOException {
        final String channel = message.getChannel();
        final RestOutputMessage transport = newRestOutputMessage(message);
        Exception error = null;
        for (WSConnectionImpl connection : connections.values()) {
            if (connection.getChannels().contains(channel)) {
                try {
                    connection.sendMessage(transport);
                } catch (EncodeException | IOException e) {
                    if (error == null) {
                        error = e;
                    }
                }
            }
        }
        if (error instanceof EncodeException) {
            throw (EncodeException)error;
        } else if (error != null) {
            // If error is not null then may be IOException only.
            throw (IOException)error;
        }
    }

    private static RestOutputMessage newRestOutputMessage(ChannelBroadcastMessage message) {
        final RestOutputMessage transport = new RestOutputMessage();
        transport.setUuid(message.getUuid());
        transport.setHeaders(new Pair[]{Pair.of("x-everrest-websocket-channel", message.getChannel()),
                                        Pair.of("x-everrest-websocket-message-type", message.getType().toString())});
        transport.setBody(message.getBody());
        return transport;
    }

    static {
        registerConnectionListener(new WSConnectionListener() {
            @Override
            public void onOpen(WSConnection connection) {
                LOG.debug("Open connection {} ", connection);
            }

            @Override
            public void onClose(WSConnection connection) {
                LOG.debug("Close connection {} with status {} ", connection, connection.getCloseStatus());
                connections.remove(connection.getId());
            }
        });
    }

    private WSConnectionContext() {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy