public synchronized void process() {
    WoTIdentityManager identityManager = (WoTIdentityManager) mFreetalk.getIdentityManager();

    long now = CurrentTimeUTC.getInMillis();

    try {
      MessageManager messageManager = mFreetalk.getMessageManager();

      // We must tell the user to solve puzzles if he as written a message ...
      if (messageManager.getOwnMessagesBy(mOwner).size() > 0
          || messageManager.getMessagesBy(mOwner).size()
              > 0) { // Also check for messages which are not stored as own messages anymore.

        int minimumTrusterCount = mFreetalk.getConfig().getInt(Config.MINIMUM_TRUSTER_COUNT);

        // ... and if he has not received enough trust values.
        if (identityManager.getReceivedTrustsCount(mOwner) < minimumTrusterCount) {
          mPuzzlesToSolve = minimumTrusterCount * 2;
          mNextDisplayTime = now;
          mNextProcessingTime =
              Long.MAX_VALUE; // Task is in display mode now, no need to proccess it anymore
          storeAndCommit();
          return;
        }
      }

      mNextProcessingTime = now + PROCESSING_INTERVAL;
      storeAndCommit();
      return;

    } catch (Exception e) {
      mNextProcessingTime = now + PROCESSING_INTERVAL_SHORT;
      Logger.error(this, "Error while processing an IntroduceIdentityTask", e);
    }
  }
  @Override
  public void terminate() {
    if (logDEBUG) Logger.debug(this, "Terminating Freetalk ...");

    /* We use single try/catch blocks so that failure of termination of one service does not prevent termination of the others */
    try {
      mWebInterface.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    if (mNNTPServer != null) {
      try {
        mNNTPServer.terminate();
      } catch (Exception e) {
        Logger.error(this, "Error during termination.", e);
      }
    }

    try {
      mFCPInterface.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    /* WebInterface is stateless and does not need to be terminated */

    try {
      mTaskManager.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mMessageListInserter.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mOldMessageListFetcher.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mNewMessageListFetcher.stop();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mMessageInserter.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mMessageFetcher.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mMessageManager.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      mIdentityManager.terminate();
    } catch (Exception e) {
      Logger.error(this, "Error during termination.", e);
    }

    try {
      closeDatabase();
    } catch (Exception e) {
      Logger.error(this, "Error while closing database.", e);
    }

    if (logDEBUG) Logger.debug(this, "Freetalk plugin terminated.");
  }
  @Override
  public void runPlugin(PluginRespirator myPR) {
    try {
      Logger.normal(this, "Plugin starting up...");

      mPluginRespirator = myPR;

      if (logDEBUG) Logger.debug(this, "Opening database...");
      db = openDatabase(new File(getUserDataDirectory(), DATABASE_FILENAME));
      if (logDEBUG) Logger.debug(this, "Database opened.");

      mConfig = Configuration.loadOrCreate(this, db);
      if (mConfig.getDatabaseFormatVersion() > Freetalk.DATABASE_FORMAT_VERSION)
        throw new RuntimeException(
            "The Freetalk plugin's database format is newer than the Freetalk plugin which is being used.");

      // Create & start the core classes

      if (logDEBUG) Logger.debug(this, "Creating identity manager...");
      mIdentityManager = new WoTIdentityManager(this, mPluginRespirator.getNode().executor);

      if (logDEBUG) Logger.debug(this, "Creating message manager...");
      mMessageManager = new WoTMessageManager(db, mIdentityManager, this, mPluginRespirator);

      if (logDEBUG) Logger.debug(this, "Creating task manager...");
      mTaskManager = new PersistentTaskManager(this, db);

      upgradeDatabase();

      // We only do this if debug logging is enabled since the integrity verification cannot repair
      // anything anyway,
      // if the user does not read his logs there is no need to check the integrity.
      // TODO: Do this once every few startups and notify the user in the web ui if errors are
      // found.
      if (logDEBUG)
        databaseIntegrityTest(); // Some tests need the Identity-/Message-/TaskManager so we call
      // this after creating them.

      if (logDEBUG) Logger.debug(this, "Creating message XML...");
      mMessageXML = new WoTMessageXML();

      if (logDEBUG) Logger.debug(this, "Creating message list XML...");
      mMessageListXML = new WoTMessageListXML();

      if (logDEBUG) Logger.debug(this, "Creating old-messagelist fetcher...");
      mOldMessageListFetcher =
          new WoTOldMessageListFetcher(this, "Freetalk WoTOldMessageListFetcher", mMessageListXML);

      if (logDEBUG) Logger.debug(this, "Creating new-messagelist fetcher...");
      mNewMessageListFetcher =
          new WoTNewMessageListFetcher(
              this, "Freetalk WoTNewMessageListFetcher", mMessageListXML, db);
      mNewMessageListFetcher.start();

      if (logDEBUG) Logger.debug(this, "Creating message fetcher...");
      mMessageFetcher =
          new WoTMessageFetcher(
              mPluginRespirator.getNode(),
              mPluginRespirator.getHLSimpleClient(),
              "Freetalk WoTMessageFetcher",
              this,
              mIdentityManager,
              mMessageManager,
              mMessageXML);
      mMessageFetcher.start();

      if (logDEBUG) Logger.debug(this, "Creating message inserter...");
      mMessageInserter =
          new WoTMessageInserter(
              mPluginRespirator.getNode(),
              mPluginRespirator.getHLSimpleClient(),
              "Freetalk WoTMessageInserter",
              mIdentityManager,
              mMessageManager,
              mMessageXML);
      mMessageInserter.start();

      if (logDEBUG) Logger.debug(this, "Creating message list inserter...");
      mMessageListInserter =
          new WoTMessageListInserter(
              mPluginRespirator.getNode(),
              mPluginRespirator.getHLSimpleClient(),
              "Freetalk WoTMessageListInserter",
              mIdentityManager,
              mMessageManager,
              mMessageListXML);
      mMessageListInserter.start();

      // They need each users so they must be started after they exist all three.
      // Further, we must start them after starting the message list fetches: Otherwise the message
      // manager etc. might take locks for ages, effectively
      // preventing this startup function from finishing. So we just start them after all core
      // classes are running and before starting the UI.
      mIdentityManager.start();
      mMessageManager.start();
      mTaskManager.start();

      // This must be started after the identity manager because it will need the identity manager
      // to be connected to WoT.
      mOldMessageListFetcher.start();

      // Create & start the UI

      if (logDEBUG) Logger.debug(this, "Creating Web interface...");
      mWebInterface = new WebInterface(this);

      if (logDEBUG) Logger.debug(this, "Creating FCP interface...");
      mFCPInterface = new FCPInterface(this);

      if (mConfig.getBoolean(Configuration.NNTP_SERVER_ENABLED)) {
        if (logDEBUG) Logger.debug(this, "Creating NNTP server...");
        String bindTo = mConfig.getString(Configuration.NNTP_SERVER_BINDTO);
        if (bindTo == null) {
          bindTo = "127.0.0.1";
        }
        String allowedHosts = mConfig.getString(Configuration.NNTP_SERVER_ALLOWED_HOSTS);
        if (allowedHosts == null) {
          allowedHosts = "127.0.0.1";
        }
        mNNTPServer = new FreetalkNNTPServer(this, 1199, bindTo, allowedHosts);
        mNNTPServer.start();
      } else {
        if (logDEBUG) Logger.debug(this, "NNTP server disabled by user...");
        mNNTPServer = null;
      }

      Logger.normal(this, "Freetalk starting up completed.");
    } catch (RuntimeException e) {
      Logger.error(this, "Startup failed!", e);
      terminate();
      throw e;
    }
  }