/** Prepares the factory for bundle shutdown. */
  public void stop() {
    if (logger.isTraceEnabled()) logger.trace("Preparing to stop all protocol providers of" + this);

    synchronized (registeredAccounts) {
      for (Enumeration<ServiceRegistration> registrations = registeredAccounts.elements();
          registrations.hasMoreElements(); ) {
        ServiceRegistration reg = registrations.nextElement();

        stop(reg);

        reg.unregister();
      }

      registeredAccounts.clear();
    }
  }
  /** Prepares the factory for bundle shutdown. */
  public void stop() {
    logger.trace("Preparing to stop all SIP protocol providers.");
    Enumeration registrations = this.registeredAccounts.elements();

    while (registrations.hasMoreElements()) {
      ServiceRegistration reg = ((ServiceRegistration) registrations.nextElement());

      ProtocolProviderServiceSipImpl provider =
          (ProtocolProviderServiceSipImpl)
              SipActivator.getBundleContext().getService(reg.getReference());

      // do an attempt to kill the provider
      provider.shutdown();

      reg.unregister();
    }

    registeredAccounts.clear();
  }
  /**
   * Returns an InetAddress instance that represents the localhost, and that a socket can bind upon
   * or distribute to peers as a contact address.
   *
   * @param intendedDestination the destination that we'd like to use the localhost address with.
   * @return an InetAddress instance representing the local host, and that a socket can bind upon or
   *     distribute to peers as a contact address.
   */
  public synchronized InetAddress getLocalHost(InetAddress intendedDestination) {
    // no point in making sure that the localHostFinderSocket is initialized.
    // better let it through a NullPointerException.
    InetAddress localHost = null;
    localHostFinderSocket.connect(intendedDestination, this.RANDOM_ADDR_DISC_PORT);
    localHost = localHostFinderSocket.getLocalAddress();
    localHostFinderSocket.disconnect();
    // windows socket implementations return the any address so we need to
    // find something else here ... InetAddress.getLocalHost seems to work
    // better on windows so lets hope it'll do the trick.
    if (localHost.isAnyLocalAddress()) {
      try {
        // all that's inside the if is an ugly IPv6 hack
        // (good ol' IPv6 - always causing more problems than it solves.)
        if (intendedDestination instanceof Inet6Address) {
          // return the first globally routable ipv6 address we find
          // on the machine (and hope it's a good one)
          Enumeration interfaces = NetworkInterface.getNetworkInterfaces();

          while (interfaces.hasMoreElements()) {
            NetworkInterface iface = (NetworkInterface) interfaces.nextElement();
            Enumeration addresses = iface.getInetAddresses();
            while (addresses.hasMoreElements()) {
              InetAddress address = (InetAddress) addresses.nextElement();
              if (address instanceof Inet6Address) {
                if (!address.isAnyLocalAddress()
                    && !address.isLinkLocalAddress()
                    && !address.isSiteLocalAddress()
                    && !address.isLoopbackAddress()) {
                  return address;
                }
              }
            }
          }
        } else localHost = InetAddress.getLocalHost();
        /** @todo test on windows for ipv6 cases */
      } catch (Exception ex) {
        // sigh ... ok return 0.0.0.0
        logger.warn("Failed to get localhost ", ex);
      }
    }

    return localHost;
  }
  /**
   * Create the contact list. Later will be test to be sure that creating is ok
   *
   * @throws Exception
   */
  public void prepareContactList() throws Exception {
    fixture.clearProvidersLists();

    Object o = new Object();
    synchronized (o) {
      o.wait(3000);
    }

    String contactList =
        System.getProperty(GibberishProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME, null);

    logger.debug(
        "The "
            + GibberishProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME
            + " property is set to="
            + contactList);

    if (contactList == null || contactList.trim().length() < 6) // at least 4 for a UIN, 1 for the
      // dot and 1 for the grp name
      throw new IllegalArgumentException(
          "The "
              + GibberishProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME
              + " property did not contain a contact list.");
    StringTokenizer tokenizer = new StringTokenizer(contactList, " \n\t");

    logger.debug("tokens contained by the CL tokenized=" + tokenizer.countTokens());

    Hashtable<String, List<String>> contactListToCreate = new Hashtable<String, List<String>>();

    // go over all group.uin tokens
    while (tokenizer.hasMoreTokens()) {
      String groupUinToken = tokenizer.nextToken();
      int dotIndex = groupUinToken.indexOf(".");

      if (dotIndex == -1) {
        throw new IllegalArgumentException(groupUinToken + " is not a valid Group.UIN token");
      }

      String groupName = groupUinToken.substring(0, dotIndex);
      String uin = groupUinToken.substring(dotIndex + 1);

      if (groupName.trim().length() < 1 || uin.trim().length() < 4) {
        throw new IllegalArgumentException(
            groupName + " or " + uin + " are not a valid group name or Gibberish user id.");
      }

      // check if we've already seen this group and if not - add it
      List<String> uinInThisGroup = contactListToCreate.get(groupName);
      if (uinInThisGroup == null) {
        uinInThisGroup = new ArrayList<String>();
        contactListToCreate.put(groupName, uinInThisGroup);
      }

      uinInThisGroup.add(uin);
    }

    // now init the list
    Enumeration<String> newGroupsEnum = contactListToCreate.keys();

    // go over all groups in the contactsToAdd table
    while (newGroupsEnum.hasMoreElements()) {
      String groupName = newGroupsEnum.nextElement();
      logger.debug("Will add group " + groupName);

      opSetPersPresence1.createServerStoredContactGroup(
          opSetPersPresence1.getServerStoredContactListRoot(), groupName);

      ContactGroup newlyCreatedGroup =
          opSetPersPresence1.getServerStoredContactListRoot().getGroup(groupName);

      Iterator<String> contactsToAddToThisGroup = contactListToCreate.get(groupName).iterator();
      while (contactsToAddToThisGroup.hasNext()) {
        String id = contactsToAddToThisGroup.next();

        logger.debug("Will add buddy " + id);
        opSetPersPresence1.subscribe(newlyCreatedGroup, id);
      }
    }

    // store the created contact list for later reference
    GibberishSlickFixture.preInstalledBuddyList = contactListToCreate;
  }