private synchronized void doConfigClearspace() throws UnauthorizedException {

    Log.debug("Starting Clearspace configuration.");

    List<String> bindInterfaces = getServerInterfaces();
    if (bindInterfaces.size() == 0) {
      // We aren't up and running enough to tell Clearspace what interfaces to bind to.
      Log.debug("No bind interfaces found to config Clearspace");
      throw new IllegalStateException("There are no binding interfaces.");
    }

    try {

      XMPPServerInfo serverInfo = XMPPServer.getInstance().getServerInfo();

      String path = IM_URL_PREFIX + "configureComponent/";

      // Creates the XML with the data
      Document groupDoc = DocumentHelper.createDocument();
      Element rootE = groupDoc.addElement("configureComponent");
      Element domainE = rootE.addElement("domain");
      domainE.setText(serverInfo.getXMPPDomain());
      for (String bindInterface : bindInterfaces) {
        Element hostsE = rootE.addElement("hosts");
        hostsE.setText(bindInterface);
      }
      Element portE = rootE.addElement("port");
      portE.setText(String.valueOf(ExternalComponentManager.getServicePort()));

      Log.debug(
          "Trying to configure Clearspace with: Domain: "
              + serverInfo.getXMPPDomain()
              + ", hosts: "
              + bindInterfaces.toString()
              + ", port: "
              + port);

      executeRequest(POST, path, rootE.asXML());

      // Done, Clearspace was configured correctly, clear the task
      Log.debug("Clearspace was configured, stopping the task.");
      TaskEngine.getInstance().cancelScheduledTask(configClearspaceTask);
      configClearspaceTask = null;

    } catch (UnauthorizedException ue) {
      throw ue;
    } catch (Exception e) {
      // It is not supported exception, wrap it into an UnsupportedOperationException
      throw new UnsupportedOperationException("Unexpected error", e);
    }
  }
  private List<String> getServerInterfaces() {

    List<String> bindInterfaces = new ArrayList<String>();

    String interfaceName = JiveGlobals.getXMLProperty("network.interface");
    String bindInterface = null;
    if (interfaceName != null) {
      if (interfaceName.trim().length() > 0) {
        bindInterface = interfaceName;
      }
    }

    int adminPort = JiveGlobals.getXMLProperty("adminConsole.port", 9090);
    int adminSecurePort = JiveGlobals.getXMLProperty("adminConsole.securePort", 9091);

    if (bindInterface == null) {
      try {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netInterface : Collections.list(nets)) {
          Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
          for (InetAddress address : Collections.list(addresses)) {
            if ("127.0.0.1".equals(address.getHostAddress())) {
              continue;
            }
            if (address.getHostAddress().startsWith("0.")) {
              continue;
            }
            Socket socket = new Socket();
            InetSocketAddress remoteAddress =
                new InetSocketAddress(address, adminPort > 0 ? adminPort : adminSecurePort);
            try {
              socket.connect(remoteAddress);
              bindInterfaces.add(address.getHostAddress());
              break;
            } catch (IOException e) {
              // Ignore this address. Let's hope there is more addresses to validate
            }
          }
        }
      } catch (SocketException e) {
        // We failed to discover a valid IP address where the admin console is running
        return null;
      }
    } else {
      bindInterfaces.add(bindInterface);
    }

    return bindInterfaces;
  }
  /**
   * Sends an IQ packet to the Clearspace external component and returns the IQ packet returned by
   * CS or <tt>null</tt> if no answer was received before the specified timeout.
   *
   * @param packet IQ packet to send.
   * @param timeout milliseconds to wait before timing out.
   * @return IQ packet returned by Clearspace responsing the packet we sent.
   */
  public IQ query(final IQ packet, int timeout) {
    // Complain if FROM is empty
    if (packet.getFrom() == null) {
      throw new IllegalStateException("IQ packets with no FROM cannot be sent to Clearspace");
    }
    // If CS is not connected then return null
    if (clearspaces.isEmpty()) {
      return null;
    }
    // Set the target address to the IQ packet. Roate list so we distribute load
    String component;
    synchronized (clearspaces) {
      component = clearspaces.get(0);
      Collections.rotate(clearspaces, 1);
    }
    packet.setTo(component);
    final LinkedBlockingQueue<IQ> answer = new LinkedBlockingQueue<IQ>(8);
    final IQRouter router = XMPPServer.getInstance().getIQRouter();
    router.addIQResultListener(
        packet.getID(),
        new IQResultListener() {
          public void receivedAnswer(IQ packet) {
            answer.offer(packet);
          }

          public void answerTimeout(String packetId) {
            Log.warn("No answer from Clearspace was received for IQ stanza: " + packet);
          }
        });
    XMPPServer.getInstance().getIQRouter().route(packet);
    IQ reply = null;
    try {
      reply = answer.poll(timeout, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
      // Ignore
    }
    return reply;
  }
 public void componentInfoReceived(IQ iq) {
   // Check if it's a Clearspace component
   boolean isClearspace = false;
   Element childElement = iq.getChildElement();
   for (Iterator it = childElement.elementIterator("identity"); it.hasNext(); ) {
     Element identity = (Element) it.next();
     if ("component".equals(identity.attributeValue("category"))
         && "clearspace".equals(identity.attributeValue("type"))) {
       isClearspace = true;
     }
   }
   // If component is Clearspace then keep track of the component
   if (isClearspace) {
     clearspaces.add(iq.getFrom().getDomain());
   }
 }
 public void componentUnregistered(JID componentJID) {
   // Remove stored information about this component
   clearspaces.remove(componentJID.getDomain());
 }
 /**
  * Returns true if a given JID belongs to a known Clearspace component domain.
  *
  * @param address Address to check.
  * @return True if the specified address is a Clearspace component.
  */
 public boolean isFromClearspace(JID address) {
   return clearspaces.contains(address.getDomain());
 }