/** * Test if entity caps actually prevent a disco info request and reply * * @throws XMPPException */ public void testPreventDiscoInfo() throws XMPPException { con0.addPacketSendingListener( new PacketListener() { @Override public void processPacket(Packet packet) { discoInfoSend = true; } }, new AndFilter(new PacketTypeFilter(DiscoverInfo.class), new IQTypeFilter(IQ.Type.get))); // add a bogus feature so that con1 ver won't match con0's sdm1.addFeature(DISCOVER_TEST_FEATURE); dropCapsCache(); // discover that DiscoverInfo info = sdm0.discoverInfo(con1.getUser()); // that discovery should cause a disco#info assertTrue(discoInfoSend); assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE)); discoInfoSend = false; // discover that info = sdm0.discoverInfo(con1.getUser()); // that discovery shouldn't cause a disco#info assertFalse(discoInfoSend); assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE)); }
public void testLocalEntityCaps() throws InterruptedException { DiscoverInfo info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecm1.getLocalNodeVer()); assertFalse(info.containsFeature(DISCOVER_TEST_FEATURE)); dropWholeEntityCapsCache(); // This should cause a new presence stanza from con1 with and updated // 'ver' String sdm1.addFeature(DISCOVER_TEST_FEATURE); // Give the server some time to handle the stanza and send it to con0 Thread.sleep(2000); // The presence stanza should get received by con0 and the data should // be recorded in the map // Note that while both connections use the same static Entity Caps // cache, // it's assured that *not* con1 added the data to the Entity Caps cache. // Every time the entities features // and identities change only a new caps 'ver' is calculated and send // with the presence stanza // The other connection has to receive this stanza and record the // information in order for this test to succeed. info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecm1.getLocalNodeVer()); assertNotNull(info); assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE)); }
/** * Perform a service discovery and check if the given feature is among the features supported by * the given recipient. All registered listeners will be notified about the result. * * @param jid A RQ-JID (user@host/resource) of the user to query support for or a non RQ-JID to * query all presences for this JID. * @blocking This method blocks until the ServiceDiscovery returns. * @reentrant This method can be called concurrently. * @caching If results are available in the cache, they are used instead of querying the server. */ private Boolean queryFeatureSupport(JID jid, String namespace) { Boolean supported = null; checkJID(jid); DiscoverInfoWrapper wrapper; final List<JID> jidsToQuery = new ArrayList<JID>(); if (jid.isBareJID()) jidsToQuery.addAll(rosterTracker.getAvailablePresences(jid)); else jidsToQuery.add(jid); for (JID rqJID : jidsToQuery) { // add dummy synchronized (cache) { wrapper = cache.get(rqJID.toString()); if (wrapper == null) { wrapper = new DiscoverInfoWrapper(); cache.put(rqJID.toString(), wrapper); } } DiscoverInfo disco = null; // wait if there is already a discovery for the JID in progress synchronized (wrapper) { if (wrapper.isAvailable()) disco = wrapper.item; else { disco = wrapper.item = performServiceDiscovery(rqJID); if (disco != null) LOG.debug("Inserted DiscoveryInfo into Cache for: " + rqJID); } } // Null means that the discovery failed if (disco == null) { // and so we do not know if the feature is supported // notifyFeatureSupportUpdated(jid, namespace, false); continue; } notifyFeatureSupportUpdated(rqJID, namespace, disco.containsFeature(namespace)); /* * loop through all presence regardless if we already know that the * feature is supported to notify the listener for every current * presence */ if (supported != null) supported |= disco.containsFeature(namespace); else supported = disco.containsFeature(namespace); } return supported; }
/** * Checks if the given {@linkplain JID} supports the requested feature. The JID may be non * resource qualified in which case all presences belonging to that JID are checked. * * <p>This method does <b>not</b> perform any I/O operation and will return immediately. * * <p><b>Please note the return value: <code>if(isFeatureSupported(foo, bar)) ... </code> is * likely to produce a {@link NullPointerException NPE}.</b> * * @param jid {@link JID} to query support for * @param namespace the namespace of the feature * @return <code>true</code> if the given feature is supported, <code>false</code> if it is not * supported or <b><code>null</code> </b> if no information is available * @see #queryFeatureSupport(JID, String, boolean) */ public Boolean isFeatureSupported(final JID jid, final String namespace) { checkJID(jid); Boolean supported = null; final List<JID> jidsToQuery = new ArrayList<JID>(); if (jid.isBareJID()) jidsToQuery.addAll(rosterTracker.getAvailablePresences(jid)); else jidsToQuery.add(jid); for (JID rqJID : jidsToQuery) { DiscoverInfoWrapper info = cache.get(rqJID.toString()); if (info == null) continue; DiscoverInfo disco = info.item; if (disco == null) continue; supported = disco.containsFeature(namespace); if (supported) break; } return supported; }
/** * Returns true if the specified user handles XHTML messages. * * @param connection the connection to use to perform the service discovery * @param userID the user to check. A fully qualified xmpp ID, e.g. [email protected] * @return a boolean indicating whether the specified user handles XHTML messages */ public static boolean isServiceEnabled(Connection connection, String userID) { try { DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(userID); return result.containsFeature(namespace); } catch (XMPPException e) { e.printStackTrace(); return false; } }
RoomInfo(DiscoverInfo info) { super(); this.room = info.getFrom(); // Get the information based on the discovered features this.membersOnly = info.containsFeature("muc_membersonly"); this.moderated = info.containsFeature("muc_moderated"); this.nonanonymous = info.containsFeature("muc_nonanonymous"); this.passwordProtected = info.containsFeature("muc_passwordprotected"); this.persistent = info.containsFeature("muc_persistent"); // Get the information based on the discovered extended information Form form = Form.getFormFrom(info); if (form != null) { this.description = form.getField("muc#roominfo_description").getValues().next(); Iterator<String> values = form.getField("muc#roominfo_subject").getValues(); if (values.hasNext()) { this.subject = values.next(); } else { this.subject = ""; } this.occupantsCount = Integer.parseInt(form.getField("muc#roominfo_occupants").getValues().next()); } }
public void testEntityCaps() throws XMPPException, InterruptedException { dropWholeEntityCapsCache(); sdm1.addFeature(DISCOVER_TEST_FEATURE); Thread.sleep(3000); DiscoverInfo info = sdm0.discoverInfo(con1.getUser()); assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE)); String u1ver = EntityCapsManager.getNodeVersionByJid(con1.getUser()); assertNotNull(u1ver); DiscoverInfo entityInfo = EntityCapsManager.caps.get(u1ver); assertNotNull(entityInfo); assertEquals(info.toXML(), entityInfo.toXML()); }
/** * Returns true if the server supports Flexible Offline Message Retrieval. When the server * supports Flexible Offline Message Retrieval it is possible to get the header of the offline * messages, get specific messages, delete specific messages, etc. * * @return a boolean indicating if the server supports Flexible Offline Message Retrieval. * @throws XMPPException If the user is not allowed to make this request. */ public boolean supportsFlexibleRetrieval() throws XMPPException { DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null); return info.containsFeature(namespace); }
/** * Returns true if the server supports publishing of items. A client may wish to publish items to * the server so that the server can provide items associated to the client. These items will be * returned by the server whenever the server receives a disco request targeted to the bare * address of the client (i.e. [email protected]). * * @param DiscoverInfo the discover info packet to check. * @return true if the server supports publishing of items. */ public static boolean canPublishItems(DiscoverInfo info) { return info.containsFeature("http://jabber.org/protocol/disco#publish"); }
public static boolean containsFeature(String feature) { if (featureInfo == null) return true; return featureInfo.containsFeature(feature); }
/** * Returns true if the server supports publishing of items. A client may wish to publish items to * the server so that the server can provide items associated to the client. These items will be * returned by the server whenever the server receives a disco request targeted to the bare * address of the client (i.e. [email protected]). * * @param entityID the address of the XMPP entity. * @return true if the server supports publishing of items. * @throws XMPPException if the operation failed for some reason. */ public boolean canPublishItems(String entityID) throws XMPPException { DiscoverInfo info = discoverInfo(entityID); return info.containsFeature("http://jabber.org/protocol/disco#publish"); }