@Override
    public void run() {
      try {
        Thread.sleep(myReconnectTimeout);

        if (myFacade.connect() != null && myFacade.getMyAccount().isLoginAllowed()) {
          myReconnectProcess = myIdeFacade.runOnPooledThread(this);
        }
      } catch (InterruptedException ignored) {
        // return
      }
    }
  protected void setUp() throws Exception {
    super.setUp();
    try {
      getConnection(0)
          .getRoster()
          .createEntry(getBareJID(2), "gato5", new String[] {"Friends, Coworker"});
      getConnection(0).getRoster().createEntry(getBareJID(3), "gato6", null);
      Thread.sleep(100);

    } catch (Exception e) {
      fail(e.getMessage());
    }
  }
  /**
   * High level API test. 1. User_1 will send his/her roster to user_2 2. User_2 will automatically
   * add the entries that receives to his/her roster in the corresponding group 3. User_1 will wait
   * several seconds for an ACK from user_2, if none is received then something is wrong
   */
  public void testSendAndAcceptRoster() {
    RosterExchangeManager rosterExchangeManager1 = new RosterExchangeManager(getConnection(0));
    RosterExchangeManager rosterExchangeManager2 = new RosterExchangeManager(getConnection(1));

    // Create a RosterExchangeListener that will accept all the received roster entries
    RosterExchangeListener rosterExchangeListener =
        new RosterExchangeListener() {
          public void entriesReceived(String from, Iterator remoteRosterEntries) {
            int received = 0;
            assertNotNull("From is null", from);
            assertNotNull("remoteRosterEntries is null", remoteRosterEntries);
            assertTrue("Roster without entries", remoteRosterEntries.hasNext());
            while (remoteRosterEntries.hasNext()) {
              received++;
              try {
                RemoteRosterEntry remoteRosterEntry =
                    (RemoteRosterEntry) remoteRosterEntries.next();
                getConnection(1)
                    .getRoster()
                    .createEntry(
                        remoteRosterEntry.getUser(),
                        remoteRosterEntry.getName(),
                        remoteRosterEntry.getGroupArrayNames());
              } catch (Exception e) {
                fail(e.toString());
              }
            }
            entriesReceived = received;
          }
        };
    rosterExchangeManager2.addRosterListener(rosterExchangeListener);

    // Send user1's roster to user2
    try {
      entriesSent = getConnection(0).getRoster().getEntryCount();
      entriesReceived = 0;
      rosterExchangeManager1.send(getConnection(0).getRoster(), getBareJID(1));
      // Wait up to 2 seconds
      long initial = System.currentTimeMillis();
      while (System.currentTimeMillis() - initial < 2000 && (entriesSent != entriesReceived)) {
        Thread.sleep(100);
      }
    } catch (Exception e) {
      fail("An error occured sending the message with the roster");
    }
    assertEquals(
        "Number of sent and received entries does not match", entriesSent, entriesReceived);
    assertTrue("Roster2 has no entries", getConnection(1).getRoster().getEntryCount() > 0);
  }
  /**
   * Implements {@link PacketListener}. Notifies this instance that a specific {@link Packet} (which
   * this instance has already expressed interest into by returning <tt>true</tt> from {@link
   * #accept(Packet)}) has been received.
   *
   * @param packet the <tt>Packet</tt> which has been received and which this instance is given a
   *     chance to process
   */
  public void processPacket(Packet packet) {
    /*
     * As we do elsewhere, acknowledge the receipt of the Packet first and
     * then go about our business with it.
     */
    IQ iq = (IQ) packet;

    if (iq.getType() == IQ.Type.SET)
      protocolProvider.getConnection().sendPacket(IQ.createResultIQ(iq));

    /*
     * Now that the acknowledging is out of the way, do go about our
     * business with the Packet.
     */
    ColibriConferenceIQ conferenceIQ = (ColibriConferenceIQ) iq;
    boolean interrupted = false;

    try {
      processColibriConferenceIQ(conferenceIQ);
    } catch (Throwable t) {
      logger.error(
          "An error occurred during the processing of a " + packet.getClass().getName() + " packet",
          t);

      if (t instanceof InterruptedException) {
        /*
         * We cleared the interrupted state of the current Thread by
         * catching the InterruptedException. However, we do not really
         * care whether the current Thread has been interrupted - we
         * caught the InterruptedException because we want to swallow
         * any Throwable. Consequently, we should better restore the
         * interrupted state.
         */
        interrupted = true;
      } else if (t instanceof ThreadDeath) throw (ThreadDeath) t;
    }
    if (interrupted) Thread.currentThread().interrupt();
  }
예제 #5
0
  public void run() throws XMPPException, IOException, InterruptedException {
    logger.debug("Trying to connect to " + host + ":" + port);
    ConnectionConfiguration configuration = new ConnectionConfiguration(host, port, "gmail.com");
    final XMPPConnection connection = new XMPPConnection(configuration);
    connection.connect();
    logger.debug("...connected");
    SASLAuthentication.supportSASLMechanism("PLAIN", 0);
    logger.debug("Trying to log in with credentials " + login + ":" + password);
    connection.login(login, password, "MyXmppBot");
    logger.debug("...logged in");

    final Process process = Runtime.getRuntime().exec("/bin/bash");
    final InputStream inputStream = process.getInputStream();
    final OutputStream outputStream = process.getOutputStream();

    Thread inputThread =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                try {
                  while (true) {
                    String line = bufferedReader.readLine();
                    Message message = new Message(to);
                    message.setBody(line);
                    connection.sendPacket(message);
                  }
                } catch (IOException e) {
                  e.printStackTrace();
                }
              }
            });
    inputThread.start();

    final PrintWriter commandWriter = new PrintWriter(outputStream, true);
    PacketListener listener =
        new PacketListener() {
          @Override
          public void processPacket(Packet packet) {
            if (packet instanceof Message) {
              Message message = (Message) packet;
              to = message.getFrom();
              String command = message.getBody();
              if (command != null) {
                logger.debug("Command received:" + command);
                if (command.equalsIgnoreCase("exit")) {
                  process.destroy();
                  System.exit(0);
                } else {
                  commandWriter.println(command);
                }
              }
            }
          }
        };

    PacketFilter filter = new FromContainsFilter("carlos.prados");
    Thread.sleep(1000);
    connection.addPacketListener(listener, null);
  }
    /** Thread entry point. */
    @Override
    public void run() {
      int status;
      long progress;
      String statusReason = "";

      while (true) {
        try {
          Thread.sleep(10);

          status = parseJabberStatus(jabberTransfer.getStatus());
          progress = fileTransfer.getTransferedBytes();

          if (status == FileTransferStatusChangeEvent.FAILED
              || status == FileTransferStatusChangeEvent.COMPLETED
              || status == FileTransferStatusChangeEvent.CANCELED
              || status == FileTransferStatusChangeEvent.REFUSED) {
            if (fileTransfer instanceof OutgoingFileTransferJabberImpl) {
              ((OutgoingFileTransferJabberImpl) fileTransfer).removeThumbnailRequestListener();
            }

            // sometimes a filetransfer can be preparing
            // and than completed :
            // transfered in one iteration of current thread
            // so it won't go through intermediate state - inProgress
            // make sure this won't happen
            if (status == FileTransferStatusChangeEvent.COMPLETED
                && fileTransfer.getStatus() == FileTransferStatusChangeEvent.PREPARING) {
              fileTransfer.fireStatusChangeEvent(
                  FileTransferStatusChangeEvent.IN_PROGRESS, "Status changed");
              fileTransfer.fireProgressChangeEvent(System.currentTimeMillis(), progress);
            }

            break;
          }

          fileTransfer.fireStatusChangeEvent(status, "Status changed");
          fileTransfer.fireProgressChangeEvent(System.currentTimeMillis(), progress);
        } catch (InterruptedException e) {
          if (logger.isDebugEnabled()) logger.debug("Unable to sleep thread.", e);
        }
      }

      if (jabberTransfer.getError() != null) {
        logger.error(
            "An error occured while transfering file: " + jabberTransfer.getError().getMessage());
      }

      if (jabberTransfer.getException() != null) {
        logger.error(
            "An exception occured while transfering file: ", jabberTransfer.getException());

        if (jabberTransfer.getException() instanceof XMPPException) {
          XMPPError error = ((XMPPException) jabberTransfer.getException()).getXMPPError();
          if (error != null)
            if (error.getCode() == 406 || error.getCode() == 403)
              status = FileTransferStatusChangeEvent.REFUSED;
        }

        statusReason = jabberTransfer.getException().getMessage();
      }

      if (initialFileSize > 0
          && status == FileTransferStatusChangeEvent.COMPLETED
          && fileTransfer.getTransferedBytes() < initialFileSize) {
        status = FileTransferStatusChangeEvent.CANCELED;
      }

      fileTransfer.fireStatusChangeEvent(status, statusReason);
      fileTransfer.fireProgressChangeEvent(System.currentTimeMillis(), progress);
    }
예제 #7
0
  /** @see net.sf.kraken.session.TransportSession#cleanUp() */
  @Override
  public void cleanUp() {
    if (timer != null) {
      try {
        timer.cancel();
      } catch (Exception e) {
        // Ignore
      }
      timer = null;
    }
    if (mailCheck != null) {
      try {
        mailCheck.cancel();
      } catch (Exception e) {
        // Ignore
      }
      mailCheck = null;
    }
    if (conn != null) {
      try {
        conn.removeConnectionListener(listener);
      } catch (Exception e) {
        // Ignore
      }

      try {
        conn.removePacketListener(listener);
      } catch (Exception e) {
        // Ignore
      }
      try {
        conn.removePacketListener(presenceHandler);
      } catch (Exception e) {
        // Ignore
      }
      try {
        conn.getChatManager().removeChatListener(listener);
      } catch (Exception e) {
        // Ignore
      }
      try {
        conn.getRoster().removeRosterListener(listener);
      } catch (Exception e) {
        // Ignore
      }
      try {
        conn.disconnect();
      } catch (Exception e) {
        // Ignore
      }
    }
    conn = null;
    listener = null;
    presenceHandler = null;
    if (runThread != null) {
      try {
        runThread.interrupt();
      } catch (Exception e) {
        // Ignore
      }
      runThread = null;
    }
  }
예제 #8
0
  /** @see net.sf.kraken.session.TransportSession#logIn(net.sf.kraken.type.PresenceType, String) */
  @Override
  public void logIn(PresenceType presenceType, String verboseStatus) {
    final org.jivesoftware.smack.packet.Presence presence =
        new org.jivesoftware.smack.packet.Presence(
            org.jivesoftware.smack.packet.Presence.Type.available);
    if (JiveGlobals.getBooleanProperty(
            "plugin.gateway." + getTransport().getType() + ".avatars", true)
        && getAvatar() != null) {
      Avatar avatar = getAvatar();
      // Same thing in this case, so lets go ahead and set them.
      avatar.setLegacyIdentifier(avatar.getXmppHash());
      VCardUpdateExtension ext = new VCardUpdateExtension();
      ext.setPhotoHash(avatar.getLegacyIdentifier());
      presence.addExtension(ext);
    }
    final Presence.Mode pMode =
        ((XMPPTransport) getTransport()).convertGatewayStatusToXMPP(presenceType);
    if (pMode != null) {
      presence.setMode(pMode);
    }
    if (verboseStatus != null && verboseStatus.trim().length() > 0) {
      presence.setStatus(verboseStatus);
    }
    setPendingPresenceAndStatus(presenceType, verboseStatus);

    if (!this.isLoggedIn()) {
      listener = new XMPPListener(this);
      presenceHandler = new XMPPPresenceHandler(this);
      runThread =
          new Thread() {
            @Override
            public void run() {
              String userName = generateUsername(registration.getUsername());
              conn = new XMPPConnection(config);
              try {
                conn.getSASLAuthentication()
                    .registerSASLMechanism("DIGEST-MD5", MySASLDigestMD5Mechanism.class);
                if (getTransport().getType().equals(TransportType.facebook)
                    && registration.getUsername().equals("{PLATFORM}")) {
                  conn.getSASLAuthentication()
                      .registerSASLMechanism(
                          "X-FACEBOOK-PLATFORM", FacebookConnectSASLMechanism.class);
                  conn.getSASLAuthentication().supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
                }

                Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
                conn.connect();
                conn.addConnectionListener(listener);
                try {
                  conn.addPacketListener(
                      presenceHandler,
                      new PacketTypeFilter(org.jivesoftware.smack.packet.Presence.class));
                  // Use this to filter out anything we don't care about
                  conn.addPacketListener(
                      listener,
                      new OrFilter(
                          new PacketTypeFilter(GoogleMailBoxPacket.class),
                          new PacketExtensionFilter(
                              GoogleNewMailExtension.ELEMENT_NAME,
                              GoogleNewMailExtension.NAMESPACE)));
                  conn.login(userName, registration.getPassword(), xmppResource);
                  conn.sendPacket(presence); // send initial presence.
                  conn.getChatManager().addChatListener(listener);
                  conn.getRoster().addRosterListener(listener);

                  if (JiveGlobals.getBooleanProperty(
                          "plugin.gateway." + getTransport().getType() + ".avatars",
                          !TransportType.facebook.equals(getTransport().getType()))
                      && getAvatar() != null) {
                    new Thread() {
                      @Override
                      public void run() {
                        Avatar avatar = getAvatar();

                        VCard vCard = new VCard();
                        try {
                          vCard.load(conn);
                          vCard.setAvatar(
                              Base64.decode(avatar.getImageData()), avatar.getMimeType());
                          vCard.save(conn);
                        } catch (XMPPException e) {
                          Log.debug("XMPP: Error while updating vcard for avatar change.", e);
                        } catch (NotFoundException e) {
                          Log.debug("XMPP: Unable to find avatar while setting initial.", e);
                        }
                      }
                    }.start();
                  }

                  setLoginStatus(TransportLoginStatus.LOGGED_IN);
                  syncUsers();

                  if (getTransport().getType().equals(TransportType.gtalk)
                      && JiveGlobals.getBooleanProperty(
                          "plugin.gateway.gtalk.mailnotifications", true)) {
                    conn.sendPacket(
                        new IQWithPacketExtension(
                            generateFullJID(getRegistration().getUsername()),
                            new GoogleUserSettingExtension(null, true, null),
                            IQ.Type.SET));
                    conn.sendPacket(
                        new IQWithPacketExtension(
                            generateFullJID(getRegistration().getUsername()),
                            new GoogleMailNotifyExtension()));
                    mailCheck = new MailCheck();
                    timer.schedule(mailCheck, timerInterval, timerInterval);
                  }
                } catch (XMPPException e) {
                  Log.debug(
                      getTransport().getType()
                          + " user's login/password does not appear to be correct: "
                          + getRegistration().getUsername(),
                      e);
                  setFailureStatus(ConnectionFailureReason.USERNAME_OR_PASSWORD_INCORRECT);
                  sessionDisconnectedNoReconnect(
                      LocaleUtils.getLocalizedString("gateway.xmpp.passwordincorrect", "kraken"));
                }
              } catch (XMPPException e) {
                Log.debug(
                    getTransport().getType()
                        + " user is not able to connect: "
                        + getRegistration().getUsername(),
                    e);
                setFailureStatus(ConnectionFailureReason.CAN_NOT_CONNECT);
                sessionDisconnected(
                    LocaleUtils.getLocalizedString("gateway.xmpp.connectionfailed", "kraken"));
              }
            }
          };
      runThread.start();
    }
  }
예제 #9
0
  /**
   * Process the AdHoc-Command packet that request the execution of some action of a command. If
   * this is the first request, this method checks, before executing the command, if:
   *
   * <ul>
   *   <li>The requested command exists
   *   <li>The requester has permissions to execute it
   *   <li>The command has more than one stage, if so, it saves the command and session ID for
   *       further use
   * </ul>
   *
   * <br>
   * <br>
   * If this is not the first request, this method checks, before executing the command, if:
   *
   * <ul>
   *   <li>The session ID of the request was stored
   *   <li>The session life do not exceed the time out
   *   <li>The action to execute is one of the available actions
   * </ul>
   *
   * @param requestData the packet to process.
   */
  private void processAdHocCommand(AdHocCommandData requestData) {
    // Only process requests of type SET
    if (requestData.getType() != IQ.Type.SET) {
      return;
    }

    // Creates the response with the corresponding data
    AdHocCommandData response = new AdHocCommandData();
    response.setTo(requestData.getFrom());
    response.setPacketID(requestData.getPacketID());
    response.setNode(requestData.getNode());
    response.setId(requestData.getTo());

    String sessionId = requestData.getSessionID();
    String commandNode = requestData.getNode();

    if (sessionId == null) {
      // A new execution request has been received. Check that the
      // command exists
      if (!commands.containsKey(commandNode)) {
        // Requested command does not exist so return
        // item_not_found error.
        respondError(response, XMPPError.Condition.item_not_found);
        return;
      }

      // Create new session ID
      sessionId = StringUtils.randomString(15);

      try {
        // Create a new instance of the command with the
        // corresponding sessioid
        LocalCommand command = newInstanceOfCmd(commandNode, sessionId);

        response.setType(IQ.Type.RESULT);
        command.setData(response);

        // Check that the requester has enough permission.
        // Answer forbidden error if requester permissions are not
        // enough to execute the requested command
        if (!command.hasPermission(requestData.getFrom())) {
          respondError(response, XMPPError.Condition.forbidden);
          return;
        }

        Action action = requestData.getAction();

        // If the action is unknown then respond an error.
        if (action != null && action.equals(Action.unknown)) {
          respondError(
              response,
              XMPPError.Condition.bad_request,
              AdHocCommand.SpecificErrorCondition.malformedAction);
          return;
        }

        // If the action is not execute, then it is an invalid action.
        if (action != null && !action.equals(Action.execute)) {
          respondError(
              response,
              XMPPError.Condition.bad_request,
              AdHocCommand.SpecificErrorCondition.badAction);
          return;
        }

        // Increase the state number, so the command knows in witch
        // stage it is
        command.incrementStage();
        // Executes the command
        command.execute();

        if (command.isLastStage()) {
          // If there is only one stage then the command is completed
          response.setStatus(Status.completed);
        } else {
          // Else it is still executing, and is registered to be
          // available for the next call
          response.setStatus(Status.executing);
          executingCommands.put(sessionId, command);
          // See if the session reaping thread is started. If not, start it.
          if (!sessionsSweeper.isAlive()) {
            sessionsSweeper.start();
          }
        }

        // Sends the response packet
        connection.sendPacket(response);

      } catch (XMPPException e) {
        // If there is an exception caused by the next, complete,
        // prev or cancel method, then that error is returned to the
        // requester.
        XMPPError error = e.getXMPPError();

        // If the error type is cancel, then the execution is
        // canceled therefore the status must show that, and the
        // command be removed from the executing list.
        if (XMPPError.Type.CANCEL.equals(error.getType())) {
          response.setStatus(Status.canceled);
          executingCommands.remove(sessionId);
        }
        respondError(response, error);
        e.printStackTrace();
      }
    } else {
      LocalCommand command = executingCommands.get(sessionId);

      // Check that a command exists for the specified sessionID
      // This also handles if the command was removed in the meanwhile
      // of getting the key and the value of the map.
      if (command == null) {
        respondError(
            response,
            XMPPError.Condition.bad_request,
            AdHocCommand.SpecificErrorCondition.badSessionid);
        return;
      }

      // Check if the Session data has expired (default is 10 minutes)
      long creationStamp = command.getCreationDate();
      if (System.currentTimeMillis() - creationStamp > SESSION_TIMEOUT * 1000) {
        // Remove the expired session
        executingCommands.remove(sessionId);

        // Answer a not_allowed error (session-expired)
        respondError(
            response,
            XMPPError.Condition.not_allowed,
            AdHocCommand.SpecificErrorCondition.sessionExpired);
        return;
      }

      /*
       * Since the requester could send two requests for the same
       * executing command i.e. the same session id, all the execution of
       * the action must be synchronized to avoid inconsistencies.
       */
      synchronized (command) {
        Action action = requestData.getAction();

        // If the action is unknown the respond an error
        if (action != null && action.equals(Action.unknown)) {
          respondError(
              response,
              XMPPError.Condition.bad_request,
              AdHocCommand.SpecificErrorCondition.malformedAction);
          return;
        }

        // If the user didn't specify an action or specify the execute
        // action then follow the actual default execute action
        if (action == null || Action.execute.equals(action)) {
          action = command.getExecuteAction();
        }

        // Check that the specified action was previously
        // offered
        if (!command.isValidAction(action)) {
          respondError(
              response,
              XMPPError.Condition.bad_request,
              AdHocCommand.SpecificErrorCondition.badAction);
          return;
        }

        try {
          // TODO: Check that all the requierd fields of the form are
          // TODO: filled, if not throw an exception. This will simplify the
          // TODO: construction of new commands

          // Since all errors were passed, the response is now a
          // result
          response.setType(IQ.Type.RESULT);

          // Set the new data to the command.
          command.setData(response);

          if (Action.next.equals(action)) {
            command.incrementStage();
            command.next(new Form(requestData.getForm()));
            if (command.isLastStage()) {
              // If it is the last stage then the command is
              // completed
              response.setStatus(Status.completed);
            } else {
              // Otherwise it is still executing
              response.setStatus(Status.executing);
            }
          } else if (Action.complete.equals(action)) {
            command.incrementStage();
            command.complete(new Form(requestData.getForm()));
            response.setStatus(Status.completed);
            // Remove the completed session
            executingCommands.remove(sessionId);
          } else if (Action.prev.equals(action)) {
            command.decrementStage();
            command.prev();
          } else if (Action.cancel.equals(action)) {
            command.cancel();
            response.setStatus(Status.canceled);
            // Remove the canceled session
            executingCommands.remove(sessionId);
          }

          connection.sendPacket(response);
        } catch (XMPPException e) {
          // If there is an exception caused by the next, complete,
          // prev or cancel method, then that error is returned to the
          // requester.
          XMPPError error = e.getXMPPError();

          // If the error type is cancel, then the execution is
          // canceled therefore the status must show that, and the
          // command be removed from the executing list.
          if (XMPPError.Type.CANCEL.equals(error.getType())) {
            response.setStatus(Status.canceled);
            executingCommands.remove(sessionId);
          }
          respondError(response, error);

          e.printStackTrace();
        }
      }
    }
  }
예제 #10
0
  /**
   *
   *
   * <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);
  }