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

com.dataheaps.beanszoo.web.WebSocketNotifier Maven / Gradle / Ivy

package com.dataheaps.beanszoo.web;

import com.dataheaps.aspectrest.serializers.Serializer;
import com.dataheaps.beanszoo.utils.Multimap;
import lombok.Data;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.servlet.*;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by matteo on 10/2/16.
 */

public class WebSocketNotifier extends WebSocketServlet {

    enum Command {
        sub, unsub
    }

    @Data
    static class ControlMessage {
        Command command;
        String[] ids;
    }


    Serializer serializer;
    WebsocketHandler handler;

    public WebSocketNotifier(Serializer serializer) {
        this.serializer = serializer;
    }

    @Override
    public void configure(WebSocketServletFactory f) {

        ExtensionFactory extFact = f.getExtensionFactory();
        extFact.unregister("deflate-frame");
        extFact.unregister("permessage-deflate");
        extFact.unregister("x-webkit-deflate-frame");

        handler = new WebsocketHandler(serializer);
        f.setCreator((req, resp) -> handler);
    }

    public void sendMessage(String subid, Object message) {
        handler.sendMessage(subid, message);
    }

    @WebSocket
    public static class WebsocketHandler {

        ExecutorService sender = Executors.newSingleThreadExecutor();
        Multimap subs = new Multimap<>();
        Multimap subsReverse = new Multimap<>();
        ReadWriteLock lock = new ReentrantReadWriteLock();

        Serializer serializer;

        public WebsocketHandler(Serializer serializer) {
            this.serializer = serializer;
        }

        public void sendMessage(String id, Object o) {
            sender.submit(() -> {
                lock.readLock().lock();
                byte[] data = serializer.serialize(o);
                try {
                    if (id != null) {
                       Set sessions = subs.get(id);
                       for (Session s : sessions)
                           s.getRemote().sendString(new String(data));
                    }
                }
                catch (Exception e) {

                }
                finally {
                    lock.readLock().unlock();
                }
            });
        }

        @OnWebSocketMessage
        public void messageReceived(Session session, Reader reader) throws Exception {
            lock.writeLock().lock();
            try {
                byte[] data = IOUtils.toByteArray(reader);
                ControlMessage message = (ControlMessage)
                        serializer.deserialize(new ByteArrayInputStream(data), ControlMessage.class);
                for (String id: message.getIds()) {
                    if (message.getCommand().equals(Command.sub)) {
                        subs.put(id, session);
                        subsReverse.put(session, id);
                    }
                    else if (message.getCommand().equals(Command.unsub)) {
                        subs.remove(id, session);
                        subsReverse.remove(session, id);
                    }
                }
            }
            catch (Exception e) {

            }
            finally {
                lock.writeLock().unlock();
            }
        }

        @OnWebSocketConnect
        public void connected(Session s) throws IOException {
            System.out.println("connected");
        }

        @OnWebSocketClose
        public void close(Session s, int closeCode, String closeReason) {
            lock.writeLock().lock();
            try {
                Set ids = subsReverse.get(s);
                for (String id: ids)
                    subs.remove(id, s);
                subsReverse.removeAll(s);
            }
            catch (Exception e) {

            }
            finally {
                lock.writeLock().unlock();
            }
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy