public void process(Packet packet) throws ComponentException {

    logger.debug("Packet payload " + packet.toXML() + " going to federation.");

    String to = packet.getTo().toString();

    String uniqueId = generateUniqueId(packet);
    idMap.put(uniqueId, packet.getID());
    packet.setID(uniqueId);

    sentRemotePackets.put(uniqueId, packet.getFrom());
    try {
      extractNodeDetails(packet);
      // Do we have a map already?
      if (discoveredServers.containsKey(to)) {
        packet.setTo(new JID(discoveredServers.get(to)));
        sendPacket(packet.createCopy());
        return;
      }
      // Are we already discovering a remote server?
      if (!remoteChannelDiscoveryStatus.containsKey(to)) {
        discoverRemoteChannelServer(to, packet.getID());
      } else if (remoteChannelDiscoveryStatus.get(to).equals(NO_CHANNEL_SERVER)) {
        logger.error("No remote channel server for " + to);
        IQ reply = IQ.createResultIQ((IQ) packet);
        reply.setError(
            new PacketError(
                PacketError.Condition.remote_server_not_found, PacketError.Type.cancel));
        component.sendPacket(reply);
        return;
      }
      // Add packet to list
      if (!waitingStanzas.containsKey(to)) {
        waitingStanzas.put(to, new ArrayList<Packet>());
      }
      waitingStanzas.get(to).add(packet);
      logger.debug(
          "Adding packet to waiting stanza list for "
              + to
              + " (size "
              + waitingStanzas.get(to).size()
              + ")");
    } catch (Exception e) {
      logger.error(e);
    }
  }
  protected IQ error(Packet packet, PacketError.Condition condition) {
    IQ reply;

    reply = new IQ(IQ.Type.error, packet.getID());
    reply.setFrom(packet.getTo());
    reply.setTo(packet.getFrom());
    reply.setError(condition);
    return reply;
  }
 private void extractNodeDetails(Packet packet) {
   try {
     String packetXml = packet.toXML();
     if (!packetXml.contains("node=")) {
       return;
     }
     nodeMap.put(packet.getID(), packetXml.split("node=\"")[1].split("\"")[0]);
   } catch (NullPointerException e) {
     logger.info("No node details found in federated packet");
     logger.error(e);
   } catch (ArrayIndexOutOfBoundsException e) {
     logger.info("Error extracting node information from federated packet");
     logger.error(e);
   }
 }
 /**
  * Generate a unique ID for a packet
  *
  * <p>Supplied packet IDs might not be unique so we use the ID and the FROM values to create a
  * hash which we map back to the original packet ID.
  *
  * @param packet
  * @return unique ID for the packet
  */
 private String generateUniqueId(Packet packet) {
   return generateMd5(packet.getID() + packet.getFrom());
 }