test_class.declarator: mobileV3
test_class.modifier: private
test_class.original_string: private MobileV3 mobileV3;
test_class.type: MobileV3
test_class.var_name: mobileV3
test_class.declarator: loginHandler
test_class.modifier: private
test_class.original_string: private SessionManagerHandler loginHandler;
test_class.type: SessionManagerHandler
test_class.var_name: loginHandler
test_class.file: tigase-server 7.1.0/src/test/java/tigase/xmpp/impl/MobileV3Test.java
test_class.identifier: MobileV3Test
test_class.superclass: extends ProcessorTestCase
test_case.body: @Test
  	public void testRecipientEnabledFor2ResourcesMixed() throws TigaseStringprepException, NotAuthorizedException {
  		String recipient = "recipient-1@localhost";
  		JID recp1 = JID.jidInstanceNS(recipient + "/res1");
  		JID recp2 = JID.jidInstanceNS(recipient + "/res2");
  		JID connId1 = JID.jidInstanceNS("c2s@localhost/recipient1-res1");
  		JID connId2 = JID.jidInstanceNS("c2s@localhost/recipient1-res2");
  		XMPPResourceConnection session1 = getSession(connId1, recp1);
  		getSession(connId2, recp2);
  		
  		enableMobileV3(session1, recp1);
  		
  		Packet presence = Packet.packetInstance("presence", "sender-1@localhost/res1", recp1.toString(), StanzaType.available);
  		presence.setPacketTo(connId1);
  		ArrayDeque<Packet> results = new ArrayDeque<Packet>();
  		results.offer(presence);
  		Packet[] expected = new Packet[0];// results.toArray(new Packet[0]);
  		mobileV3.filter(presence, session1, null, results);
  		Packet[] processed = results.toArray(new Packet[0]);
  		Assert.assertArrayEquals(expected, processed);
  
  		results.clear();
  		Packet m1 = Packet.packetInstance("message", recp2.toString(), recp1.toString(), StanzaType.chat);
  		Element receivedEl = new Element("received", new String[] { "xmlns" }, new String[] { "urn:xmpp:carbons:2" });
  		Element forwardedEl = new Element("forwarded", new String[] {"xmlns" }, new String[] { "urn:xmpp:forward:0" });
  		forwardedEl.addChild(new Element("message", new String[] { "from", "to" }, new String[] { recp2.toString(), "sender-1@localhost/res1" }));
  		receivedEl.addChild(forwardedEl);
  		m1.getElement().addChild(receivedEl);
  		m1.setPacketTo(connId1);
  		results.offer(m1);
  		expected = new Packet[0];
  		mobileV3.filter(m1, session1, null, results);
  		processed = results.toArray(new Packet[0]);
  		Assert.assertArrayEquals(expected, processed);			
  		
  		results.clear();
  		presence = Packet.packetInstance("presence", "sender-1@localhost/res1", recp1.toString(), StanzaType.available);
  		presence.setPacketTo(connId1);
  		results.offer(presence);
  		expected = new Packet[0];// results.toArray(new Packet[0]);
  		mobileV3.filter(presence, session1, null, results);
  		processed = results.toArray(new Packet[0]);
  		Assert.assertArrayEquals(expected, processed);
  	
  		results.clear();
  		Packet p = Packet.packetInstance("message", "sender-1@localhost/res1", recp1.toString(), StanzaType.chat);
  		p.setPacketTo(connId1);
  		results.offer(p);
  		Packet p1 = Packet.packetInstance("presence", "sender-1@localhost/res1", recp1.toString(), StanzaType.error);
  		p1.setPacketTo(connId1);		
  		results.offer(p1);
  		expected = new Packet[] { presence, m1, p, p1 };
  		mobileV3.filter(p, session1, null, results);
  		processed = results.toArray(new Packet[0]);
  		Assert.assertArrayEquals(expected, processed);		
  	}
test_case.class_method_signature: MobileV3Test.testRecipientEnabledFor2ResourcesMixed()
test_case.full_signature: @Test public void testRecipientEnabledFor2ResourcesMixed()
test_case.identifier: testRecipientEnabledFor2ResourcesMixed
test_case.invocations: jidInstanceNS jidInstanceNS jidInstanceNS jidInstanceNS getSession getSession enableMobileV3 packetInstance toString setPacketTo offer filter toArray assertArrayEquals clear packetInstance toString toString addChild toString addChild addChild getElement setPacketTo offer filter toArray assertArrayEquals clear packetInstance toString setPacketTo offer filter toArray assertArrayEquals clear packetInstance toString setPacketTo offer packetInstance toString setPacketTo offer filter toArray assertArrayEquals
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void testRecipientEnabledFor2ResourcesMixed()
focal_class.declarator: DEF_MAX_QUEUE_SIZE_VAL = 50
focal_class.modifier: private static final
focal_class.original_string: private static final int    DEF_MAX_QUEUE_SIZE_VAL = 50;
focal_class.type: int
focal_class.var_name: DEF_MAX_QUEUE_SIZE_VAL
focal_class.declarator: ID                     = "mobile_v3"
focal_class.modifier: protected static final
focal_class.original_string: protected static final String ID                     = "mobile_v3";
focal_class.type: String
focal_class.var_name: ID
focal_class.declarator: log = Logger.getLogger(MobileV3.class.getCanonicalName())
focal_class.modifier: private static final
focal_class.original_string: private static final Logger log = Logger.getLogger(MobileV3.class.getCanonicalName());
focal_class.type: Logger
focal_class.var_name: log
focal_class.declarator: MAX_QUEUE_SIZE_KEY = "max-queue-size"
focal_class.modifier: private static final
focal_class.original_string: private static final String     MAX_QUEUE_SIZE_KEY = "max-queue-size";
focal_class.type: String
focal_class.var_name: MAX_QUEUE_SIZE_KEY
focal_class.declarator: MOBILE_EL_NAME     = "mobile"
focal_class.modifier: protected static final
focal_class.original_string: protected static final String     MOBILE_EL_NAME     = "mobile";
focal_class.type: String
focal_class.var_name: MOBILE_EL_NAME
focal_class.declarator: XMLNS = "http://tigase.org/protocol/mobile#v3"
focal_class.modifier: protected static final
focal_class.original_string: protected static final String     XMLNS = "http://tigase.org/protocol/mobile#v3";
focal_class.type: String
focal_class.var_name: XMLNS
focal_class.declarator: PRESENCE_QUEUE_KEY = ID + "-presence-queue"
focal_class.modifier: private static final
focal_class.original_string: private static final String PRESENCE_QUEUE_KEY = ID + "-presence-queue";
focal_class.type: String
focal_class.var_name: PRESENCE_QUEUE_KEY
focal_class.declarator: PACKET_QUEUE_KEY = ID + "-packet-queue"
focal_class.modifier: private static final
focal_class.original_string: private static final String PACKET_QUEUE_KEY = ID + "-packet-queue";
focal_class.type: String
focal_class.var_name: PACKET_QUEUE_KEY
focal_class.declarator: DELAY_ELEM_NAME = "delay"
focal_class.modifier: private static final
focal_class.original_string: private static final String DELAY_ELEM_NAME = "delay";
focal_class.type: String
focal_class.var_name: DELAY_ELEM_NAME
focal_class.declarator: DELAY_XMLNS = "urn:xmpp:delay"
focal_class.modifier: private static final
focal_class.original_string: private static final String DELAY_XMLNS = "urn:xmpp:delay";
focal_class.type: String
focal_class.var_name: DELAY_XMLNS
focal_class.declarator: MESSAGE_ELEM_NAME = "message"
focal_class.modifier: private static final
focal_class.original_string: private static final String MESSAGE_ELEM_NAME = "message";
focal_class.type: String
focal_class.var_name: MESSAGE_ELEM_NAME
focal_class.declarator: threadState = new ThreadLocal<StateHolder>()
focal_class.modifier: private static final
focal_class.original_string: private static final ThreadLocal<StateHolder> threadState = new ThreadLocal<StateHolder>();
focal_class.type: ThreadLocal<StateHolder>
focal_class.var_name: threadState
focal_class.declarator: maxQueueSize = DEF_MAX_QUEUE_SIZE_VAL
focal_class.modifier: private
focal_class.original_string: private int maxQueueSize = DEF_MAX_QUEUE_SIZE_VAL;
focal_class.type: int
focal_class.var_name: maxQueueSize
focal_class.declarator: formatter
focal_class.modifier: private
focal_class.original_string: private SimpleDateFormat formatter;
focal_class.type: SimpleDateFormat
focal_class.var_name: formatter
focal_class.file: tigase-server 7.1.0/src/main/java/tigase/xmpp/impl/MobileV3.java
focal_class.identifier: MobileV3
focal_class.interfaces: implements XMPPProcessorIfc, XMPPPacketFilterIfc
focal_class.class_method_signature: MobileV3.init(Map<String, Object> settings)
focal_class.full_signature: @Override public void init(Map<String, Object> settings)
focal_class.identifier: init
focal_class.modifiers: @Override public
focal_class.parameters: (Map<String, Object> settings)
focal_class.return: void
focal_class.signature: void init(Map<String, Object> settings)
focal_class.class_method_signature: MobileV3.process(final Packet packet, final XMPPResourceConnection session,
  			final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,
  			Object> settings)
focal_class.full_signature: @Override public void process(final Packet packet, final XMPPResourceConnection session,
  			final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,
  			Object> settings)
focal_class.identifier: process
focal_class.modifiers: @Override public
focal_class.parameters: (final Packet packet, final XMPPResourceConnection session,
  			final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,
  			Object> settings)
focal_class.return: void
focal_class.signature: void process(final Packet packet, final XMPPResourceConnection session,
  			final NonAuthUserRepository repo, final Queue<Packet> results, final Map<String,
  			Object> settings)
focal_class.class_method_signature: MobileV3.supStreamFeatures(XMPPResourceConnection session)
focal_class.full_signature: @Override public Element[] supStreamFeatures(XMPPResourceConnection session)
focal_class.identifier: supStreamFeatures
focal_class.modifiers: @Override public
focal_class.parameters: (XMPPResourceConnection session)
focal_class.return: Element[]
focal_class.signature: Element[] supStreamFeatures(XMPPResourceConnection session)
focal_class.class_method_signature: MobileV3.filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_class.full_signature: @Override @SuppressWarnings("unchecked") public void filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_class.identifier: filter
focal_class.modifiers: @Override @SuppressWarnings("unchecked") public
focal_class.parameters: (Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_class.return: void
focal_class.signature: void filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_class.class_method_signature: MobileV3.filter(XMPPResourceConnection session, Packet res, QueueState state,
  			Map<JID,Packet> presenceQueue, Queue<Packet> packetQueue)
focal_class.full_signature: private QueueState filter(XMPPResourceConnection session, Packet res, QueueState state,
  			Map<JID,Packet> presenceQueue, Queue<Packet> packetQueue)
focal_class.identifier: filter
focal_class.modifiers: private
focal_class.parameters: (XMPPResourceConnection session, Packet res, QueueState state,
  			Map<JID,Packet> presenceQueue, Queue<Packet> packetQueue)
focal_class.return: QueueState
focal_class.signature: QueueState filter(XMPPResourceConnection session, Packet res, QueueState state,
  			Map<JID,Packet> presenceQueue, Queue<Packet> packetQueue)
focal_class.class_method_signature: MobileV3.createDelayElem(XMPPResourceConnection session)
focal_class.full_signature: private Element createDelayElem(XMPPResourceConnection session)
focal_class.identifier: createDelayElem
focal_class.modifiers: private
focal_class.parameters: (XMPPResourceConnection session)
focal_class.return: Element
focal_class.signature: Element createDelayElem(XMPPResourceConnection session)
focal_class.class_method_signature: MobileV3.isQueueEnabled(XMPPResourceConnection session)
focal_class.full_signature: protected static boolean isQueueEnabled(XMPPResourceConnection session)
focal_class.identifier: isQueueEnabled
focal_class.modifiers: protected static
focal_class.parameters: (XMPPResourceConnection session)
focal_class.return: boolean
focal_class.signature: boolean isQueueEnabled(XMPPResourceConnection session)
focal_class.superclass: extends AnnotatedXMPPProcessor
focal_method.body: @Override
  	@SuppressWarnings("unchecked")
  	public void filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results) {
  		if ((sessionFromSM == null) ||!sessionFromSM.isAuthorized() || (results == null) ||
  				(results.size() == 0)) {
  			return;
  		}
  		
  		StateHolder holder = threadState.get();
  		if (holder == null) {
  			holder = new StateHolder();
  			threadState.set(holder);
  		}
  		
  		for (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {
  			Packet res = it.next();
  
  			// check if packet contains destination
  			if ((res == null) || (res.getPacketTo() == null)) {
  				if (log.isLoggable(Level.FINEST)) {
  					log.finest("packet without destination");
  				}
  
  				continue;
  			}
  
  			// get resource connection for destination
  			XMPPResourceConnection session = sessionFromSM.getParentSession()
  					.getResourceForConnectionId(res.getPacketTo());
  
  			if (session == null) {
  				if (log.isLoggable(Level.FINEST)) {
  					log.log(Level.FINEST, "no session for destination {0} for packet {1}",
  							new Object[] { res.getPacketTo().toString(),
  							res.toString() });
  				}
  
  				// if there is no session we should not queue
  				continue;
  			}
  
  			Map<JID, Packet> presenceQueue = (Map<JID, Packet>) session.getSessionData(PRESENCE_QUEUE_KEY);
  			Queue<Packet> packetQueue = (Queue<Packet>) session.getSessionData(PACKET_QUEUE_KEY);
  			
  			//QueueState state = QueueState.need_flush;
  			if (!isQueueEnabled(session)) {
  				if ((presenceQueue == null && packetQueue == null)
  						|| (presenceQueue.isEmpty() && packetQueue.isEmpty())) {
  					continue;
  				}
  				if (log.isLoggable(Level.FINEST)) {
  					log.log(Level.FINEST, "mobile queues needs flushing - presences: {0}, packets: {1}", 
  							new Object[] {presenceQueue.size(), packetQueue.size() });
  				}
  				holder.setState(res.getPacketTo(), QueueState.need_flush);
  			} else {
  				QueueState state = filter(session, res, holder.getState(res.getPacketTo()), presenceQueue, packetQueue);
  				if (state == QueueState.queued) {
  					it.remove();
  					if (log.isLoggable(Level.FINEST))
  						log.log(Level.FINEST, "queue packet = {0}", res.toString());
  					if (presenceQueue.size() > maxQueueSize) {
  						state = QueueState.need_flush;
  					}
  					else if (packetQueue.size() > maxQueueSize)
  						state = QueueState.need_packet_flush;
  				}
  				state = holder.setState(res.getPacketTo(), state);
  			}
  			
  //			switch (state) {
  //				case need_flush:
  //					prependResults = prependResultsThreadQueue.get();
  //					if (prependResults == null) {
  //						prependResults = new ArrayDeque<Packet>();
  //						prependResultsThreadQueue.set(prependResults);
  //					}
  //					
  //					try {
  //						synchronized (presenceQueue) {
  //							JID connId = session.getConnectionId();
  //							for (Packet p : presenceQueue.values()) {
  //								// we need to set packet to again in case Stream
  //								// Management resumption happend in meanwhile
  //								p.setPacketTo(connId);
  //								prependResults.offer(p);
  //							}
  //							presenceQueue.clear();
  //						}
  //					}
  //					catch (NoConnectionIdException ex) {
  //						log.log(Level.SEVERE, "this should not happen", ex);
  //					}
  //					
  //				case need_packet_flush:
  //					if (prependResults == null) {
  //						prependResults = prependResultsThreadQueue.get();
  //						if (prependResults == null) {
  //							prependResults = new ArrayDeque<Packet>();
  //							prependResultsThreadQueue.set(prependResults);
  //						}
  //					}
  //					try {
  //						synchronized (packetQueue) {
  //							JID connId = session.getConnectionId();
  //							Packet p = null;
  //							while ((p = packetQueue.poll()) != null) {
  //								// we need to set packet to again in case Stream
  //								// Management resumption happend in meanwhile
  //								p.setPacketTo(connId);
  //								prependResults.offer(p);
  //							}
  //							packetQueue.clear();
  //						}
  //					}
  //					catch (NoConnectionIdException ex) {
  //						log.log(Level.SEVERE, "this should not happen", ex);
  //					}				
  //				case queued:					
  //					break;
  //					
  //				default:
  //					break;
  //			}
  		}
  
  		for (Map.Entry<JID,QueueState> e : holder.states.entrySet()) {
  			XMPPResourceConnection session = null;
  			switch (e.getValue()) {
  				case need_flush:
  					try {
  						session = sessionFromSM.getParentSession().getResourceForConnectionId(e.getKey());
  						if (session != null) {
  							Map<JID, Packet> presenceQueue = (Map<JID, Packet>) session.getSessionData(PRESENCE_QUEUE_KEY);
  							synchronized (presenceQueue) {
  								JID connId = session.getConnectionId();
  								for (Packet p : presenceQueue.values()) {
  								// we need to set packet to again in case Stream
  									// Management resumption happend in meanwhile
  									p.setPacketTo(connId);
  									holder.queue.offer(p);
  								}
  								presenceQueue.clear();
  							}
  						}
  					}
  					catch (NoConnectionIdException ex) {
  						log.log(Level.SEVERE, "this should not happen", ex);
  					}
  				case need_packet_flush:
  					try {
  						if (session == null)
  							session = sessionFromSM.getParentSession().getResourceForConnectionId(e.getKey());
  						if (session != null) {
  							Queue<Packet> packetQueue = (Queue<Packet>) session.getSessionData(PACKET_QUEUE_KEY);
  							synchronized (packetQueue) {
  								JID connId = session.getConnectionId();
  								Packet p = null;
  								while ((p = packetQueue.poll()) != null) {
  								// we need to set packet to again in case Stream
  									// Management resumption happend in meanwhile
  									p.setPacketTo(connId);
  									holder.queue.offer(p);
  								}
  								packetQueue.clear();
  							}
  						}
  					}
  					catch (NoConnectionIdException ex) {
  						log.log(Level.SEVERE, "this should not happen", ex);
  					}				
  					break;
  				case queued:
  					break;
  				default:
  					break;
  			}
  		}
  		if (!holder.queue.isEmpty()) {
  			if (log.isLoggable(Level.FINEST)) 
  				log.log(Level.FINEST, "sending queued packets = {0}", holder.queue.size());
  			holder.queue.addAll(results);
  			results.clear();
  			results.addAll(holder.queue);
  			//holder.queue.clear();
  		}
  		holder.reset();
  	}
focal_method.class_method_signature: MobileV3.filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_method.full_signature: @Override @SuppressWarnings("unchecked") public void filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_method.identifier: filter
focal_method.invocations: isAuthorized size get set iterator hasNext next getPacketTo isLoggable finest getResourceForConnectionId getParentSession getPacketTo isLoggable log toString getPacketTo toString getSessionData getSessionData isQueueEnabled isEmpty isEmpty isLoggable log size size setState getPacketTo filter getState getPacketTo remove isLoggable log toString size size setState getPacketTo entrySet getValue getResourceForConnectionId getParentSession getKey getSessionData getConnectionId values setPacketTo offer clear log getResourceForConnectionId getParentSession getKey getSessionData getConnectionId poll setPacketTo offer clear log isEmpty isLoggable log size addAll clear addAll reset
focal_method.modifiers: @Override @SuppressWarnings("unchecked") public
focal_method.parameters: (Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)
focal_method.return: void
focal_method.signature: void filter(Packet _packet, XMPPResourceConnection sessionFromSM,
  			NonAuthUserRepository repo, Queue<Packet> results)