private void configureConnection(final Connection connection) { connection.addConnectionListener( new ConnectionListener() { @Override public void connectionClosed() { cleanup(connection); } @Override public void connectionClosedOnError(Exception e) { cleanup(connection); } @Override public void reconnectingIn(int seconds) { // ignore } @Override public void reconnectionFailed(Exception e) { // ignore } @Override public void reconnectionSuccessful() { // ignore } }); }
/** * Initializes the packet listeners of the connection that will answer to any service discovery * request. */ private void init() { // Register the new instance and associate it with the connection instances.put(connection, this); // Add a listener to the connection that removes the registered instance when // the connection is closed connection.addConnectionListener( new ConnectionListener() { public void connectionClosed() { // Unregister this instance since the connection has been closed instances.remove(connection); } public void connectionClosedOnError(Exception e) { // ignore } public void reconnectionFailed(Exception e) { // ignore } public void reconnectingIn(int seconds) { // ignore } public void reconnectionSuccessful() { // ignore } }); // Intercept presence packages and add caps data when inteded. // XEP-0115 specifies that a client SHOULD include entity capabilities // with every presence notification it sends. PacketFilter capsPacketFilter = new PacketTypeFilter(Presence.class); PacketInterceptor packetInterceptor = new PacketInterceptor() { public void interceptPacket(Packet packet) { if (capsManager != null) { String ver = getEntityCapsVersion(); CapsExtension caps = new CapsExtension(capsManager.getNode(), ver, "sha-1"); packet.addExtension(caps); } } }; connection.addPacketInterceptor(packetInterceptor, capsPacketFilter); // Listen for disco#items requests and answer with an empty result PacketFilter packetFilter = new PacketTypeFilter(DiscoverItems.class); PacketListener packetListener = new PacketListener() { public void processPacket(Packet packet) { DiscoverItems discoverItems = (DiscoverItems) packet; // Send back the items defined in the client if the request is of type GET if (discoverItems != null && discoverItems.getType() == IQ.Type.GET) { DiscoverItems response = new DiscoverItems(); response.setType(IQ.Type.RESULT); response.setTo(discoverItems.getFrom()); response.setPacketID(discoverItems.getPacketID()); response.setNode(discoverItems.getNode()); // Add the defined items related to the requested node. Look for // the NodeInformationProvider associated with the requested node. NodeInformationProvider nodeInformationProvider = getNodeInformationProvider(discoverItems.getNode()); if (nodeInformationProvider != null) { // Specified node was found List<DiscoverItems.Item> items = nodeInformationProvider.getNodeItems(); if (items != null) { for (DiscoverItems.Item item : items) { response.addItem(item); } } } else if (discoverItems.getNode() != null) { // Return <item-not-found/> error since client doesn't contain // the specified node response.setType(IQ.Type.ERROR); response.setError(new XMPPError(XMPPError.Condition.item_not_found)); } connection.sendPacket(response); } } }; connection.addPacketListener(packetListener, packetFilter); // Listen for disco#info requests and answer the client's supported features // To add a new feature as supported use the #addFeature message packetFilter = new PacketTypeFilter(DiscoverInfo.class); packetListener = new PacketListener() { public void processPacket(Packet packet) { DiscoverInfo discoverInfo = (DiscoverInfo) packet; // Answer the client's supported features if the request is of the GET type if (discoverInfo != null && discoverInfo.getType() == IQ.Type.GET) { DiscoverInfo response = new DiscoverInfo(); response.setType(IQ.Type.RESULT); response.setTo(discoverInfo.getFrom()); response.setPacketID(discoverInfo.getPacketID()); response.setNode(discoverInfo.getNode()); // Add the client's identity and features if "node" is // null or our entity caps version. if (discoverInfo.getNode() == null || (capsManager == null ? true : (capsManager.getNode() + "#" + getEntityCapsVersion()) .equals(discoverInfo.getNode()))) { addDiscoverInfoTo(response); } else { // Disco#info was sent to a node. Check if we have information of the // specified node NodeInformationProvider nodeInformationProvider = getNodeInformationProvider(discoverInfo.getNode()); if (nodeInformationProvider != null) { // Node was found. Add node features List<String> features = nodeInformationProvider.getNodeFeatures(); if (features != null) { for (String feature : features) { response.addFeature(feature); } } // Add node identities List<DiscoverInfo.Identity> identities = nodeInformationProvider.getNodeIdentities(); if (identities != null) { for (DiscoverInfo.Identity identity : identities) { response.addIdentity(identity); } } } else { // Return <item-not-found/> error since specified node was not found response.setType(IQ.Type.ERROR); response.setError(new XMPPError(XMPPError.Condition.item_not_found)); } } connection.sendPacket(response); } } }; connection.addPacketListener(packetListener, packetFilter); }
/** * * * <ul> * <li>Adds listeners to the connection * <li>Registers the ad-hoc command feature to the ServiceDiscoveryManager * <li>Registers the items of the feature * <li>Adds packet listeners to handle execution requests * <li>Creates and start the session sweeper * </ul> */ private void init() { // Register the new instance and associate it with the connection synchronized (instances) { instances.put(connection, this); } // Add a listener to the connection that removes the registered instance // when the connection is closed connection.addConnectionListener( new ConnectionListener() { public void connectionClosed() { synchronized (instances) { instances.remove(connection); } } public void connectionClosedOnError(Exception e) { synchronized (instances) { instances.remove(connection); } } public void reconnectionSuccessful() { synchronized (instances) { instances.put(connection, AdHocCommandManager.this); } } public void reconnectingIn(int seconds) {} public void reconnectionFailed(Exception e) {} }); // Add the feature to the service discovery manage to show that this // connection supports the AdHoc-Commands protocol. // This information will be used when another client tries to // discover whether this client supports AdHoc-Commands or not. ServiceDiscoveryManager.getInstanceFor(connection).addFeature(DISCO_NAMESPACE); // Set the NodeInformationProvider that will provide information about // which AdHoc-Commands are registered, whenever a disco request is // received ServiceDiscoveryManager.getInstanceFor(connection) .setNodeInformationProvider( discoNode, new NodeInformationProvider() { public List<DiscoverItems.Item> getNodeItems() { List<DiscoverItems.Item> answer = new ArrayList<DiscoverItems.Item>(); Collection<AdHocCommandInfo> commandsList = getRegisteredCommands(); for (AdHocCommandInfo info : commandsList) { DiscoverItems.Item item = new DiscoverItems.Item(info.getOwnerJID()); item.setName(info.getName()); item.setNode(info.getNode()); answer.add(item); } return answer; } public List<String> getNodeFeatures() { return null; } public List<Identity> getNodeIdentities() { return null; } }); // The packet listener and the filter for processing some AdHoc Commands // Packets PacketListener listener = new PacketListener() { public void processPacket(Packet packet) { AdHocCommandData requestData = (AdHocCommandData) packet; processAdHocCommand(requestData); } }; PacketFilter filter = new PacketTypeFilter(AdHocCommandData.class); connection.addPacketListener(listener, filter); // Create a thread to reap sessions. But, we'll only start it later when commands are // actually registered. sessionsSweeper = new Thread( new Runnable() { public void run() { while (true) { for (String sessionId : executingCommands.keySet()) { LocalCommand command = executingCommands.get(sessionId); // Since the command could be removed in the meanwhile // of getting the key and getting the value - by a // processed packet. We must check if it still in the // map. if (command != null) { long creationStamp = command.getCreationDate(); // Check if the Session data has expired (default is // 10 minutes) // To remove it from the session list it waits for // the double of the of time out time. This is to // let // the requester know why his execution request is // not accepted. If the session is removed just // after the time out, then whe the user request to // continue the execution he will recieved an // invalid session error and not a time out error. if (System.currentTimeMillis() - creationStamp > SESSION_TIMEOUT * 1000 * 2) { // Remove the expired session executingCommands.remove(sessionId); } } } try { Thread.sleep(1000); } catch (InterruptedException ie) { // Ignore. } } } }); sessionsSweeper.setDaemon(true); }