public void removeThread(WorkerThread thread) {
   threads.remove(thread);
   Logger.log(Level.DEBUG, Messages.getString("connection_closed", Settings.getLocale()));
   if (FancyFileServer.getGUI() != null) {
     FancyFileServer.getGUI().updateConnectionsCounter();
   }
 }
  public void deinit(Appendable out, boolean force) throws Exception {
    Settings settings = new Settings(platform.getConfigFile());

    if (!force) {
      Justif justify = new Justif(80, 40);
      StringBuilder sb = new StringBuilder();
      Formatter f = new Formatter(sb);

      try {
        String list = listFiles(platform.getGlobal());
        if (list != null) {
          f.format("In global default environment:%n");
          f.format(list);
        }

        list = listFiles(platform.getLocal());
        if (list != null) {
          f.format("In local default environment:%n");
          f.format(list);
        }

        if (settings.containsKey(JPM_CACHE_GLOBAL)) {
          list = listFiles(IO.getFile(settings.get(JPM_CACHE_GLOBAL)));
          if (list != null) {
            f.format("In global configured environment:%n");
            f.format(list);
          }
        }

        if (settings.containsKey(JPM_CACHE_LOCAL)) {
          list = listFiles(IO.getFile(settings.get(JPM_CACHE_LOCAL)));
          if (list != null) {
            f.format("In local configured environment:%n");
            f.format(list);
          }
        }

        list = listSupportFiles();
        if (list != null) {
          f.format("jpm support files:%n");
          f.format(list);
        }

        f.format("%n%n");

        f.format(
            "All files listed above will be deleted if deinit is run with the force flag set"
                + " (\"jpm deinit -f\" or \"jpm deinit --force\"%n%n");
        f.flush();

        justify.wrap(sb);
        out.append(sb.toString());
      } finally {
        f.close();
      }
    } else { // i.e. if(force)
      int count = 0;
      File[] caches = {platform.getGlobal(), platform.getLocal(), null, null};
      if (settings.containsKey(JPM_CACHE_LOCAL)) {
        caches[2] = IO.getFile(settings.get(JPM_CACHE_LOCAL));
      }
      if (settings.containsKey(JPM_CACHE_GLOBAL)) {
        caches[3] = IO.getFile(settings.get(JPM_CACHE_GLOBAL));
      }
      ArrayList<File> toDelete = new ArrayList<File>();

      for (File cache : caches) {
        if (cache == null || !cache.exists()) {
          continue;
        }
        listFiles(cache, toDelete);
        if (toDelete.size() > count) {
          count = toDelete.size();
          if (!cache.canWrite()) {
            reporter.error(PERMISSION_ERROR + " (" + cache + ")");
            return;
          }
          toDelete.add(cache);
        }
      }
      listSupportFiles(toDelete);

      for (File f : toDelete) {
        if (f.exists() && !f.canWrite()) {
          reporter.error(PERMISSION_ERROR + " (" + f + ")");
        }
      }
      if (reporter.getErrors().size() > 0) {
        return;
      }

      for (File f : toDelete) {
        if (f.exists()) {
          IO.deleteWithException(f);
        }
      }
    }
  }
  public void run() {
    try {
      this.serverSocket = new ServerSocket(Settings.getPropertyInteger("server_port"));
    } catch (Exception e) {
      Logger.log(
          Level.WARNING,
          Messages.getString("can_not_open_port_", Settings.getLocale())
              + Settings.getPropertyInteger("server_port"));
      if (FancyFileServer.getGUI() != null) {
        FancyFileServer.getGUI().updateServerStatus();
      }
      return;
    }

    running = true;

    this.parameters = new BasicHttpParams();
    this.parameters.setIntParameter(HttpConnectionParams.SO_TIMEOUT, 5000);
    this.parameters.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8 * 1024);
    this.parameters.setBooleanParameter(HttpConnectionParams.STALE_CONNECTION_CHECK, false);
    this.parameters.setBooleanParameter(HttpConnectionParams.TCP_NODELAY, true);
    this.parameters.setParameter(
        HttpProtocolParams.ORIGIN_SERVER,
        FancyFileServer.NAME.replaceAll("\\s", "-") + "/" + FancyFileServer.VERSION);

    Logger.log(Level.INFO, Messages.getString("server_started", Settings.getLocale()));

    try {
      Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
      while (interfaces.hasMoreElements()) {
        NetworkInterface i = (NetworkInterface) interfaces.nextElement();
        if (i.isLoopback() || i.isVirtual()) {
          continue;
        }
        Enumeration<InetAddress> addresses = i.getInetAddresses();
        while (addresses.hasMoreElements()) {
          InetAddress a = (InetAddress) addresses.nextElement();
          if (a instanceof Inet4Address) {
            Logger.log(
                Level.INFO,
                Messages.getString("server_address_", Settings.getLocale())
                    + "http://"
                    + a.getHostAddress()
                    + ":"
                    + serverSocket.getLocalPort()
                    + "/");
          }
        }
      }
    } catch (Exception e) {
      Logger.log(
          Level.WARNING,
          Messages.getString("can_not_get_server_address_", Settings.getLocale()) + e.getMessage());
    }

    if (FancyFileServer.getGUI() != null) {
      FancyFileServer.getGUI().updateServerStatus();
    }

    while (running) {
      try {
        /** Set up HTTP connection */
        Socket socket = this.serverSocket.accept();
        DefaultHttpServerConnection connection = new DefaultHttpServerConnection();
        Logger.log(
            Level.DEBUG,
            Messages.getString("incoming_connection_from_", Settings.getLocale())
                + socket.getInetAddress().getHostAddress());
        connection.bind(socket, this.parameters);

        /** Set up HTTP protocol processor */
        BasicHttpProcessor processor = new BasicHttpProcessor();
        processor.addInterceptor(new ResponseDate());
        processor.addInterceptor(new ResponseServer());
        processor.addInterceptor(new ResponseContent());
        processor.addInterceptor(new ResponseConnControl());

        /** Set up HTTP request handlers */
        HttpRequestHandlerRegistry registry = new HttpRequestHandlerRegistry();
        registry.register("*", new FileHandler());

        /** Set up HTTP service */
        HttpService service =
            new HttpService(
                processor,
                new DefaultConnectionReuseStrategy(),
                new DefaultHttpResponseFactory(),
                registry,
                this.parameters);

        /** Start worker thread */
        WorkerThread t = new WorkerThread(this, service, connection);
        t.setDaemon(true);
        t.start();
      } catch (IOException e) {
        if (running) {
          running = false;
          Logger.log(
              Level.SEVERE,
              Messages.getString("i_o_error_", Settings.getLocale()) + e.getMessage());
          break;
        }
      }
    }

    if (FancyFileServer.getGUI() != null) {
      FancyFileServer.getGUI().updateServerStatus();
    }
    Logger.log(Level.INFO, Messages.getString("server_stopped", Settings.getLocale()));
  }