/** * 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<String, Topic> uris = new HashMap<String, Topic>(); private final Map<Long, Topic> ids = new HashMap<Long, Topic>(); 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<Session> 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); } }