/**
   * Returns all properties necessary for the intialization of the account with
   * <tt>accountPrefix</tt>.
   *
   * @param accountPrefix the prefix contained by all property names for the the account we'd like
   *     to initialized
   * @return a Hashtable that can be used when creating the account in a protocol provider factory.
   */
  private Hashtable<String, String> getAccountProperties(String accountPrefix) {
    Hashtable<String, String> table = new Hashtable<String, String>();

    String userID = System.getProperty(accountPrefix + ProtocolProviderFactory.USER_ID, null);

    assertNotNull(
        "The system property named "
            + accountPrefix
            + ProtocolProviderFactory.USER_ID
            + " has to tontain a valid Jabber address that could be used during "
            + "SIP Communicator's tests.",
        userID);

    table.put(ProtocolProviderFactory.USER_ID, userID);

    String passwd = System.getProperty(accountPrefix + ProtocolProviderFactory.PASSWORD, null);

    assertNotNull(
        "The system property named "
            + accountPrefix
            + ProtocolProviderFactory.PASSWORD
            + " has to contain the password corresponding to the account "
            + "specified in "
            + accountPrefix
            + ProtocolProviderFactory.USER_ID,
        passwd);

    table.put(ProtocolProviderFactory.PASSWORD, passwd);

    String serverAddress =
        System.getProperty(accountPrefix + ProtocolProviderFactory.SERVER_ADDRESS, null);

    // optional
    if (serverAddress != null) table.put(ProtocolProviderFactory.SERVER_ADDRESS, serverAddress);

    String serverPort =
        System.getProperty(accountPrefix + ProtocolProviderFactory.SERVER_PORT, null);

    // optional
    if (serverPort != null) table.put(ProtocolProviderFactory.SERVER_PORT, serverPort);

    return table;
  }
  /**
   * The dependent service is available and the bundle will start.
   *
   * @param dependentService the UIService this activator is waiting.
   */
  @Override
  public void start(Object dependentService) {
    if (logger.isDebugEnabled()) logger.debug("Update checker [STARTED]");

    ConfigurationService cfg = getConfiguration();

    if (OSUtils.IS_WINDOWS) {
      updateService = new Update();

      bundleContext.registerService(UpdateService.class.getName(), updateService, null);

      // Register the "Check for Updates" menu item if
      // the "Check for Updates" property isn't disabled.
      if (!cfg.getBoolean(CHECK_FOR_UPDATES_MENU_DISABLED_PROP, false)) {
        // Register the "Check for Updates" menu item.
        CheckForUpdatesMenuItemComponent checkForUpdatesMenuItemComponent =
            new CheckForUpdatesMenuItemComponent(Container.CONTAINER_HELP_MENU);

        Hashtable<String, String> toolsMenuFilter = new Hashtable<String, String>();
        toolsMenuFilter.put(Container.CONTAINER_ID, Container.CONTAINER_HELP_MENU.getID());

        bundleContext.registerService(
            PluginComponent.class.getName(), checkForUpdatesMenuItemComponent, toolsMenuFilter);
      }

      // Check for software update upon startup if enabled.
      if (cfg.getBoolean(UPDATE_ENABLED, true)) updateService.checkForUpdates(false);
    }

    if (cfg.getBoolean(CHECK_FOR_UPDATES_DAILY_ENABLED_PROP, false)) {
      logger.info("Scheduled update checking enabled");

      // Schedule a "check for updates" task that will run once a day
      int hoursToWait = calcHoursToWait();
      Runnable updateRunnable =
          new Runnable() {
            public void run() {
              logger.debug("Performing scheduled update check");
              getUpdateService().checkForUpdates(false);
            }
          };

      mUpdateExecutor = Executors.newSingleThreadScheduledExecutor();
      mUpdateExecutor.scheduleAtFixedRate(
          updateRunnable, hoursToWait, 24 * 60 * 60, TimeUnit.SECONDS);
    }

    if (logger.isDebugEnabled()) logger.debug("Update checker [REGISTERED]");
  }
  /**
   * Creates a protocol provider for the given <tt>accountID</tt> and registers it in the bundle
   * context. This method has a persistent effect. Once created the resulting account will remain
   * installed until removed through the uninstallAccount method.
   *
   * @param accountID the account identifier
   * @return <tt>true</tt> if the account with the given <tt>accountID</tt> is successfully loaded,
   *     otherwise returns <tt>false</tt>
   */
  public boolean loadAccount(AccountID accountID) {
    // Need to obtain the original user id property, instead of calling
    // accountID.getUserID(), because this method could return a modified
    // version of the user id property.
    String userID = accountID.getAccountPropertyString(ProtocolProviderFactory.USER_ID);

    ProtocolProviderService service = createService(userID, accountID);

    Dictionary<String, String> properties = new Hashtable<String, String>();
    properties.put(PROTOCOL, protocolName);
    properties.put(USER_ID, userID);

    ServiceRegistration serviceRegistration =
        bundleContext.registerService(ProtocolProviderService.class.getName(), service, properties);

    if (serviceRegistration == null) return false;
    else {
      synchronized (registeredAccounts) {
        registeredAccounts.put(accountID, serviceRegistration);
      }
      return true;
    }
  }