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

jlibs.wamp4j.router.Topics Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2015 Santhosh Kumar Tekuri
 *
 * The JLibs authors license this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package jlibs.wamp4j.router;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jlibs.wamp4j.Debugger;
import jlibs.wamp4j.Util;
import jlibs.wamp4j.WAMPSerialization;
import jlibs.wamp4j.msg.EventMessage;
import jlibs.wamp4j.spi.WAMPOutputStream;
import jlibs.wamp4j.spi.WAMPServerEndPoint;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static jlibs.wamp4j.Debugger.ROUTER;

/**
 * @author Santhosh Kumar Tekuri
 */
public class Topics{
    private final WAMPServerEndPoint server;
    private final Map uris = new HashMap();
    private final Map ids = new HashMap();
    private Long lastID = -1L;

    public Topics(WAMPServerEndPoint server){
        this.server = server;
    }

    public long subscribe(Session session, String uri){
        Topic topic = uris.get(uri);
        if(topic==null){
            lastID = Util.generateID(ids, lastID);
            topic = new Topic(uri, lastID);
            uris.put(uri, topic);
            ids.put(lastID, topic);
            topic.sessions[session.serialization.ordinal()].add(session);
            session.subscriptions.put(lastID, topic);
        }
        return topic.subscriptionID;
    }

    public boolean unsubscribe(Session session, long subscriptionID){
        Topic topic = ids.get(subscriptionID);
        if(topic==null)
            return false;
        if(!topic.sessions[session.serialization.ordinal()].remove(session))
            return false;
        if(topic.sessions[0].isEmpty() && topic.sessions[1].isEmpty()){
            uris.remove(topic.uri);
            ids.remove(topic.subscriptionID);
        }
        session.subscriptions.remove(subscriptionID);
        return true;
    }

    public void publish(Session publisher, ObjectNode options, JsonParser publish) throws Throwable{
        String uri = publish.nextTextValue();
        Topic topic = uris.get(uri);
        if(topic==null)
            return;

        int jsonSubscribers = topic.sessions[0].size();
        int messagePackSubscribers = topic.sessions[1].size();
        if(publisher.subscriptions.get(topic.subscriptionID)!=null){
            if(publisher.serialization.ordinal()==0)
                --jsonSubscribers;
            else
                --messagePackSubscribers;
        }
        if(jsonSubscribers==0 && messagePackSubscribers==0)
            return;

        if(ROUTER)
            Debugger.temp("<- EventMessage: [%d, %d, %d, %s, ...]", EventMessage.ID, topic.subscriptionID, 0, options);
        if(jsonSubscribers>0 && messagePackSubscribers>0){
            WAMPOutputStream jsonOut = server.createOutputStream();
            WAMPOutputStream messagePackOut = server.createOutputStream();
            try{
                JsonGenerator json = WAMPSerialization.json.mapper().getFactory().createGenerator(jsonOut);
                JsonGenerator messagePack = WAMPSerialization.messagePack.mapper().getFactory().createGenerator(messagePackOut);
                json.writeStartArray();
                messagePack.writeStartArray();
                json.writeNumber(EventMessage.ID);
                messagePack.writeNumber(EventMessage.ID);
                json.writeNumber(topic.subscriptionID);
                messagePack.writeNumber(topic.subscriptionID);
                json.writeNumber(0); // publicationID
                messagePack.writeNumber(0); // publicationID
                if(options==null){
                    json.writeStartObject();
                    messagePack.writeStartObject();
                    json.writeEndObject();
                    messagePack.writeEndObject();
                }else{
                    json.writeTree(options);
                    messagePack.writeTree(options);
                }
                while(publish.nextToken()!=null){
                    json.copyCurrentEvent(publish);
                    messagePack.copyCurrentEvent(publish);
                }
                json.close();
                messagePack.close();
            }catch(Throwable thr){
                jsonOut.release();
                messagePackOut.release();
                throw thr;
            }
            publish(publisher, topic.sessions[0], jsonOut);
            publish(publisher, topic.sessions[1], messagePackOut);
        }else{
            WAMPOutputStream out = server.createOutputStream();
            WAMPSerialization serialization = jsonSubscribers>0 ? WAMPSerialization.json : WAMPSerialization.messagePack;
            try{
                JsonGenerator json = serialization.mapper().getFactory().createGenerator(out);
                json.writeStartArray();
                json.writeNumber(EventMessage.ID);
                json.writeNumber(topic.subscriptionID);
                json.writeNumber(0); // publicationID
                if(options==null){
                    json.writeStartObject();
                    json.writeEndObject();
                }else
                    json.writeTree(options);
                while(publish.nextToken()!=null)
                    json.copyCurrentEvent(publish);
                json.close();
            }catch(Throwable thr){
                out.release();
                throw thr;
            }
            publish(publisher, topic.sessions[serialization.ordinal()], out);
        }
    }

    private void publish(Session publisher, List sessions, WAMPOutputStream out){
        Session prev = null;
        for(Session session : sessions){
            if(session!=publisher){
                if(prev!=null)
                    prev.send(out.duplicate());
                prev = session;
            }
        }
        assert prev!=null;
        prev.send(out);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy