/** * Publishes new items to a parent entity and node. The item elements to publish MUST have at * least a 'jid' attribute specifying the Entity ID of the item, and an action attribute which * specifies the action being taken for that item. Possible action values are: "update" and * "remove". * * @param entityID the address of the XMPP entity. * @param node the attribute that supplements the 'jid' attribute. * @param discoverItems the DiscoveryItems to publish. * @throws XMPPErrorException if the operation failed for some reason. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException */ public void publishItems(String entityID, String node, DiscoverItems discoverItems) throws NoResponseException, XMPPErrorException, NotConnectedException { discoverItems.setType(IQ.Type.set); discoverItems.setTo(entityID); discoverItems.setNode(node); connection().createPacketCollectorAndSend(discoverItems).nextResultOrThrow(); }
/** * Publishes new items to a parent entity and node. The item elements to publish MUST have at * least a 'jid' attribute specifying the Entity ID of the item, and an action attribute which * specifies the action being taken for that item. Possible action values are: "update" and * "remove". * * @param entityID the address of the XMPP entity. * @param node the attribute that supplements the 'jid' attribute. * @param discoverItems the DiscoveryItems to publish. * @throws XMPPException if the operation failed for some reason. */ public void publishItems(String entityID, String node, DiscoverItems discoverItems) throws XMPPException { Connection connection = ServiceDiscoveryManager.this.connection.get(); if (connection == null) throw new XMPPException("Connection instance already gc'ed"); discoverItems.setType(IQ.Type.SET); discoverItems.setTo(entityID); discoverItems.setNode(node); connection.createPacketCollectorAndSend(discoverItems).nextResultOrThrow(); }
/** * Returns the discovered items of a given XMPP entity addressed by its JID and note attribute. * Use this message only when trying to query information which is not directly addressable. * * @param entityID the address of the XMPP entity. * @param node the optional attribute that supplements the 'jid' attribute. * @return the discovered items. * @throws XMPPErrorException if the operation failed for some reason. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException */ public DiscoverItems discoverItems(String entityID, String node) throws NoResponseException, XMPPErrorException, NotConnectedException { // Discover the entity's items DiscoverItems disco = new DiscoverItems(); disco.setType(IQ.Type.get); disco.setTo(entityID); disco.setNode(node); Packet result = connection().createPacketCollectorAndSend(disco).nextResultOrThrow(); return (DiscoverItems) result; }
/** * Returns the discovered items of a given XMPP entity addressed by its JID and note attribute. * Use this message only when trying to query information which is not directly addressable. * * @param entityID the address of the XMPP entity. * @param node the optional attribute that supplements the 'jid' attribute. * @return the discovered items. * @throws XMPPException if the operation failed for some reason. */ public DiscoverItems discoverItems(String entityID, String node) throws XMPPException { Connection connection = ServiceDiscoveryManager.this.connection.get(); if (connection == null) throw new XMPPException("Connection instance already gc'ed"); // Discover the entity's items DiscoverItems disco = new DiscoverItems(); disco.setType(IQ.Type.GET); disco.setTo(entityID); disco.setNode(node); Packet result = connection.createPacketCollectorAndSend(disco).nextResultOrThrow(); return (DiscoverItems) result; }
/** * Returns the address of the multiple recipients service. To obtain such address service * discovery is going to be used on the connected server and if none was found then another * attempt will be tried on the server items. The discovered information is going to be cached for * 24 hours. * * @param connection the connection to use for disco. The connected server is going to be queried. * @return the address of the multiple recipients service or <tt>null</tt> if none was found. */ private static String getMultipleRecipienServiceAddress(Connection connection) { String serviceName = connection.getServiceName(); String serviceAddress = (String) services.get(serviceName); if (serviceAddress == null) { synchronized (services) { serviceAddress = (String) services.get(serviceName); if (serviceAddress == null) { // Send the disco packet to the server itself try { DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(serviceName); // Check if the server supports JEP-33 if (info.containsFeature("http://jabber.org/protocol/address")) { serviceAddress = serviceName; } else { // Get the disco items and send the disco packet to each server item DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(serviceName); for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext(); ) { DiscoverItems.Item item = it.next(); info = ServiceDiscoveryManager.getInstanceFor(connection) .discoverInfo(item.getEntityID(), item.getNode()); if (info.containsFeature("http://jabber.org/protocol/address")) { serviceAddress = serviceName; break; } } } // Cache the discovered information services.put(serviceName, serviceAddress == null ? "" : serviceAddress); } catch (XMPPException e) { LOGGER.log(Level.SEVERE, "Error occurred retrieving multiple recipients service", e); } } } } return "".equals(serviceAddress) ? null : serviceAddress; }
/** * Find all services under the users service that provide a given feature. * * @param feature the feature to search for * @param stopOnFirst if true, stop searching after the first service was found * @param useCache if true, query a cache first to avoid network I/O * @return a possible empty list of services providing the given feature * @throws NoResponseException * @throws XMPPErrorException * @throws NotConnectedException */ public List<String> findServices(String feature, boolean stopOnFirst, boolean useCache) throws NoResponseException, XMPPErrorException, NotConnectedException { List<String> serviceAddresses = null; String serviceName = connection().getServiceName(); if (useCache) { serviceAddresses = (List<String>) services.get(feature); if (serviceAddresses != null) { return serviceAddresses; } } serviceAddresses = new LinkedList<String>(); // Send the disco packet to the server itself DiscoverInfo info; try { info = discoverInfo(serviceName); } catch (XMPPErrorException e) { // Be extra robust here: Return the empty linked list and log this situation LOGGER.log(Level.WARNING, "Could not discover information about service", e); return serviceAddresses; } // Check if the server supports XEP-33 if (info.containsFeature(feature)) { serviceAddresses.add(serviceName); if (stopOnFirst) { if (useCache) { // Cache the discovered information services.put(feature, serviceAddresses); } return serviceAddresses; } } DiscoverItems items; try { // Get the disco items and send the disco packet to each server item items = discoverItems(serviceName); } catch (XMPPErrorException e) { LOGGER.log(Level.WARNING, "Could not discover items about service", e); return serviceAddresses; } for (DiscoverItems.Item item : items.getItems()) { try { // TODO is it OK here in all cases to query without the node attribute? // MultipleRecipientManager queried initially also with the node attribute, but this // could be simply a fault instead of intentional. info = discoverInfo(item.getEntityID()); } catch (XMPPErrorException | NoResponseException e) { // Don't throw this exceptions if one of the server's items fail LOGGER.log( Level.WARNING, "Exception while discovering info for feature " + feature + " of " + item.getEntityID() + " node: " + item.getNode(), e); continue; } if (info.containsFeature(feature)) { serviceAddresses.add(item.getEntityID()); if (stopOnFirst) { break; } } } if (useCache) { // Cache the discovered information services.put(feature, serviceAddresses); } return serviceAddresses; }