/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.jack.server;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.cache.Weigher;

import com.android.jack.api.JackProvider;
import com.android.jack.api.ResourceController;
import com.android.jack.api.ResourceController.Category;
import com.android.jack.api.ResourceController.Impact;
import com.android.jack.server.ServerLogConfiguration.ServerLogConfigurationException;
import com.android.jack.server.api.v01.LauncherHandle;
import com.android.jack.server.api.v01.ServerException;
import com.android.jack.server.router.AcceptContentTypeParameterRouter;
import com.android.jack.server.router.AcceptContentTypeRouter;
import com.android.jack.server.router.BooleanCodec;
import com.android.jack.server.router.ContentTypeParameterRouter;
import com.android.jack.server.router.ContentTypeRouter;
import com.android.jack.server.router.ErrorContainer;
import com.android.jack.server.router.MethodRouter;
import com.android.jack.server.router.PartContentTypeParameterRouter;
import com.android.jack.server.router.PartContentTypeRouter;
import com.android.jack.server.router.PartParserRouter;
import com.android.jack.server.router.PathRouter;
import com.android.jack.server.router.RootContainer;
import com.android.jack.server.router.TextPlainPartParser;
import com.android.jack.server.tasks.GC;
import com.android.jack.server.tasks.GetJackVersions;
import com.android.jack.server.tasks.GetLauncherHome;
import com.android.jack.server.tasks.GetLauncherLog;
import com.android.jack.server.tasks.GetLauncherVersion;
import com.android.jack.server.tasks.GetServerVersion;
import com.android.jack.server.tasks.InstallJack;
import com.android.jack.server.tasks.InstallServer;
import com.android.jack.server.tasks.JackTaskBase64Out;
import com.android.jack.server.tasks.JackTaskRawOut;
import com.android.jack.server.tasks.JillTask;
import com.android.jack.server.tasks.QueryJackVersion;
import com.android.jack.server.tasks.QueryServerVersion;
import com.android.jack.server.tasks.ReloadConfig;
import com.android.jack.server.tasks.ResetStats;
import com.android.jack.server.tasks.SetLoggerParameters;
import com.android.jack.server.tasks.Stat;
import com.android.jack.server.tasks.Stop;
import com.android.jack.server.type.CommandOutBase64;
import com.android.jack.server.type.CommandOutRaw;
import com.android.jack.server.type.ExactCodeVersionFinder;
import com.android.jack.server.type.TextPlain;
import com.android.sched.util.FinalizerRunner;
import com.android.sched.util.Version;
import com.android.sched.util.codec.IntCodec;
import com.android.sched.util.codec.PairCodec.Pair;
import com.android.sched.util.codec.ParsingException;
import com.android.sched.util.file.CannotChangePermissionException;
import com.android.sched.util.file.CannotCreateFileException;
import com.android.sched.util.file.Directory;
import com.android.sched.util.file.FileAlreadyExistsException;
import com.android.sched.util.file.FileOrDirectory.ChangePermission;
import com.android.sched.util.file.FileOrDirectory.Existence;
import com.android.sched.util.file.FileOrDirectory.Permission;
import com.android.sched.util.file.NoSuchFileException;
import com.android.sched.util.file.NotDirectoryException;
import com.android.sched.util.file.NotFileException;
import com.android.sched.util.file.WrongPermissionException;
import com.android.sched.util.findbugs.SuppressFBWarnings;

import org.simpleframework.http.ContentType;
import org.simpleframework.http.Method;
import org.simpleframework.http.Status;
import org.simpleframework.http.core.Container;
import org.simpleframework.http.core.ContainerSocketProcessor;
import org.simpleframework.transport.Socket;
import org.simpleframework.transport.connect.Connection;
import org.simpleframework.transport.connect.SocketConnection;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.channels.ServerSocketChannel;
import java.nio.file.Files;
import java.nio.file.attribute.FileOwnerAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;

/**
 * Server controlling the number of Jack compilations that are executed simultaneously.
 */
public class JackHttpServer implements HasVersion {

  @Nonnull
  public static final String VERSION_CODE = "jack-server";

  /**
   * Define an assertion status.
   */
  public static enum Assertion {
    ENABLED {
      @Override
      public boolean isEnabled() {
        return true;
      }
    },
    DISABLED {
      @Override
      public boolean isEnabled() {
        return false;
      }
    };

    public abstract boolean isEnabled();
  }

  /**
   * A program that can be run by this server as a service.
   */
  public static class Program<T> implements HasVersion {

    private abstract static class ProgramReference<U, T extends Reference<U>> {
      @Nonnull
      private T program = newReference(null);
      @Nonnull
      private T assertingProgram = newReference(null);

      @Nonnull
      protected abstract T newReference(@CheckForNull U program);

      @CheckForNull
      public U get(@Nonnull Assertion assertion) {
        switch (assertion) {
          case ENABLED:
            return assertingProgram.get();
          case DISABLED:
            return program.get();
          default:
            throw new AssertionError();
        }
      }

      public void set(@Nonnull Assertion status, @CheckForNull U program) {
        switch (status) {
          case ENABLED:
            assertingProgram = newReference(program);
            break;
          case DISABLED:
            this.program = newReference(program);
            break;
          default:
            throw new AssertionError();
        }
      }
    }

    private static class ProgramSoftReference<U> extends ProgramReference<U, SoftReference<U>> {
      @Override
      @Nonnull
      protected SoftReference<U> newReference(@CheckForNull U referent) {
        return new SoftReference<U>(referent);
      }
    }

    @Nonnull
    private final Version version;

    @Nonnull
    private final File jar;

    @Nonnull
    private final ProgramSoftReference<T> loadedProgram;

    /**
     * This is used to track garbage collection of classloaders on this program. It shared between
     * classloaders which are preventing its collection as long as the classloaders are not
     * collected.
     */
    @Nonnull
    private WeakReference<URL[]> urlPath;

    public Program(@Nonnull Version version, @Nonnull File jar, @CheckForNull URL[] path) {
      this.version = version;
      this.jar = jar;
      loadedProgram = new ProgramSoftReference<T>();
      urlPath = new WeakReference<URL[]>(path);
    }

    @Override
    @Nonnull
    public Version getVersion() {
      return version;
    }

    @Nonnull
    private File getJar() {
      return jar;
    }

    @Nonnull
    private URL[] getUrlPath() {
      URL[] path = urlPath.get();
      if (path == null) {
        try {
          path = new URL[] {jar.toURI().toURL()};
        } catch (MalformedURLException e) {
          logger.log(Level.SEVERE, e.getMessage(), e);
          throw new AssertionError();
        }
        urlPath = new WeakReference<URL[]>(path);
      }
      return path;
    }

    @CheckForNull
    private Object getGCProbe() {
      return urlPath.get();
    }

    @CheckForNull
    private T getLoadedProgram(@Nonnull Assertion status) {
      return loadedProgram.get(status);
    }

    /**
     * Should be called only by code synchronized on {@link #installedJack}, or at creation.
     */
    private void setLoadedProgram(@Nonnull Assertion status, @CheckForNull T program) {
      if (program == null) {
        loadedProgram.set(status, null);
      } else {
        assert loadedProgram.get(status) == null;
        this.loadedProgram.set(status, program);
      }
    }
  }

  /**
   * Thrown when attempting to start new task while server is closed or shutdown is in progress.
   */
  public static class ServerClosedException extends Exception {
    private static final long serialVersionUID = 1L;
  }

  private static class URLClassLoaderWithProbe extends URLClassLoader {

    // The purpose of this subclass of URLClassLoader is to ensure urls won't be garbaged
    // collected before this classloader.
    @SuppressWarnings("unused")
    private final URL[] urls;

    public URLClassLoaderWithProbe(@Nonnull URL[] urls, @CheckForNull ClassLoader parent) {
      super(urls, parent);
      this.urls = urls;
    }
  }

  private static class VersionKey implements HasVersion {

    @Nonnull
    private final Version version;

    public VersionKey(@Nonnull Version version) {
      this.version = version;
    }

    @Override
    public final boolean equals(Object obj) {
      if (obj == this) {
        return true;
      }
      if (obj instanceof VersionKey) {
        VersionKey other = (VersionKey) obj;
        return version.getReleaseCode() == other.version.getReleaseCode()
            && version.getSubReleaseCode() == other.version.getSubReleaseCode();
      }
      return false;
    }

    @Override
    public final int hashCode() {
      return (version.getReleaseCode() * 7) ^ (version.getSubReleaseCode() * 17);
    }

    @Override
    @Nonnull
    public Version getVersion() {
      return version;
    }

    @Nonnull
    @Override
    public String toString() {
      return version.toString();
    }
  }

  private static class Deleter implements Runnable {
    @Nonnull
    private final File[] toDelete;

    private Deleter(@Nonnull File[] toDelete) {
      this.toDelete = toDelete;
    }

    @Override
    public void run() {
      for (File file : toDelete) {
        if (!file.delete()) {
          logger.log(Level.WARNING, "Failed to delete file '" + file.getPath() + "'");
        } else {
          logger.log(Level.FINE, "Deleted file '" + file.getPath() + "'");
        }
      }
    }
  }

  private class TimedServerMode {
    @Nonnegative
    private final long delay;

    private final ServerMode newMode;

    public TimedServerMode(@Nonnegative long delay, @Nonnull ServerMode serverMode) {
      this.delay = delay;
      this.newMode = serverMode;
    }

    public void registerTo(@Nonnull Timer timer) {
      timer.schedule(new TimerTask() {
        @Override
        public void run() {
          setServerMode(newMode);
        }
      }, delay);
    }
  }

  private static interface ServerModeWatcher {
    void changedMode(@Nonnull ServerMode oldMode, @Nonnull ServerMode newMode);
  }

  @Nonnull
  private static final String JAR_SUFFIX = ".jar";

  @Nonnull
  private static final String DELETED_SUFFIX = ".deleted";

  @Nonnull
  private static final String DELETED_JAR_SUFFIX = JAR_SUFFIX + DELETED_SUFFIX;

  @Nonnull
  private static final String LOG_FILE_PATTERN = "logs/jack-server-%u-%g.log";

  @Nonnull
  private static final String KEYSTORE_SERVER = "server.jks";

  @Nonnull
  private static final String KEYSTORE_CLIENT = "client.jks";

  @Nonnull
  private static final String SERVER_KEY_ALIAS = "server";

  @Nonnull
  private static final String CLIENT_KEY_ALIAS = "client";

  @Nonnull
  private static final char[] KEYSTORE_PASSWORD = "Jack-Server".toCharArray();

  @Nonnull
  private static final String PEM_CLIENT = "client.pem";

  @Nonnull
  private static final String PEM_SERVER = "server.pem";

  private static final FileFilter JAR_FILTER = new FileFilter() {
    @Override
    public boolean accept(File pathname) {
      return pathname.isFile() && pathname.getName().endsWith(JAR_SUFFIX)
          && !new File(pathname.getPath() + DELETED_SUFFIX).exists();
    }
  };

  @Nonnull
  private static Logger logger = Logger.getLogger(JackHttpServer.class.getName());

  private int portService;

  private int portAdmin;

  private long maxJarSize;

  @Nonnull
  private final LauncherHandle launcherHandle;
  @Nonnull
  private final File serverDir;

  @CheckForNull
  private Connection serviceConnection;
  @CheckForNull
  private Connection adminConnection;
  @CheckForNull
  private ServerParameters serverParameters;

  @CheckForNull
  private Timer timer;
  @Nonnull
  private final Object lock = new Object();

  private int maxServices;

  @Nonnull
  private final ServerInfo serviceInfo = new ServerInfo();

  @Nonnull
  private final ServerInfo adminInfo = new ServerInfo();

  private boolean shuttingDown;

  private Cache<VersionKey, Program<JackProvider>> installedJack = null;

  @CheckForNull
  private ServerSocketChannel adminChannel;

  @CheckForNull
  private ServerSocketChannel serviceChannel;

  @Nonnull
  private ServerLogConfiguration logConfiguration;

  @Nonnull
  private final String currentUser;

  @CheckForNull
  private String[] filteredCiphersArray = null;

  @Nonnull
  private final FinalizerRunner finalizer = new FinalizerRunner("Server finalizer");

  private ServerMode serverMode = ServerMode.WAIT;

  @Nonnull
  private final List<TimedServerMode> delayedModes =
    new ArrayList<JackHttpServer.TimedServerMode>();

  @Nonnull
  private final Map<ServerMode, ServerModeWatcher> modeWatchers = new HashMap<>();

  @Nonnull
  public static Version getServerVersion() {
    try {
      return new Version(VERSION_CODE, JackHttpServer.class.getClassLoader());
    } catch (IOException e) {
      logger.log(Level.SEVERE, "Failed to read Jack-server version properties", e);
      throw new AssertionError();
    }
  }

  JackHttpServer(@Nonnull LauncherHandle launcherHandle)
      throws IOException, ServerLogConfigurationException, NotFileException,
      WrongPermissionException, CannotCreateFileException {
    this.launcherHandle = launcherHandle;
    serverDir = launcherHandle.getServerDir();

    logConfiguration = ServerLogConfiguration.setupLog(
        serverDir.getPath().replace(File.separatorChar, '/') + '/' + LOG_FILE_PATTERN);

    currentUser = getCurrentUser(serverDir);

    addServerModeWatcher(ServerMode.WORK, new ServerModeWatcher() {
      @Override
      public void changedMode(@Nonnull ServerMode oldMode, @Nonnull ServerMode newMode) {
        cancelTimer();
      }
    });
    addServerModeWatcher(ServerMode.WAIT, new ServerModeWatcher() {
      @Override
      public void changedMode(@Nonnull ServerMode oldMode, @Nonnull ServerMode newMode) {
        startTimer();
        cleanJacks(EnumSet.of(Category.CODE, Category.MEMORY), Collections.<Impact>emptySet());
      }
    });
    addServerModeWatcher(ServerMode.IDLE, new ServerModeWatcher() {
      @Override
      public void changedMode(@Nonnull ServerMode oldMode, @Nonnull ServerMode newMode) {

        cleanJacks(EnumSet.of(Category.CODE, Category.MEMORY), EnumSet.of(Impact.LATENCY));

        assert timer != null;
        timer.schedule(new TimerTask() {
          // Even if its just a hint, a gc would be nice.
          @SuppressFBWarnings("DM_GC")
          @Override
          public void run() {
            System.gc();
          }
        }, 0L, 60 * 60 * 1000);
      }

    });
    addServerModeWatcher(ServerMode.DEEP_IDLE, new ServerModeWatcher() {
      @Override
      public void changedMode(@Nonnull ServerMode oldMode, @Nonnull ServerMode newMode) {
        cleanJacks(EnumSet.of(Category.CODE, Category.MEMORY),
            EnumSet.of(Impact.LATENCY, Impact.PERFORMANCE));
      }

    });
    addServerModeWatcher(ServerMode.SLEEP, new ServerModeWatcher() {
      @Override
      public void changedMode(@Nonnull ServerMode oldMode, @Nonnull ServerMode newMode) {
        freeLoadedPrograms();
      }
    });

    loadConfig();
  }

  @Nonnull
  public ServerLogConfiguration getLogConfiguration() {
    return logConfiguration.clone();
  }

  public void setLogConfiguration(ServerLogConfiguration logConfiguration)
      throws IOException {
    logConfiguration.apply();
    this.logConfiguration = logConfiguration;
  }

  @Nonnull
  public String getLogPattern() {
    return ServerLogConfiguration.getLogFilePattern(
        serverDir.getAbsolutePath().replace(File.separatorChar, '/') + '/' + LOG_FILE_PATTERN);
  }

  private void buildInstalledJackCache() throws IOException, NotDirectoryException,
      WrongPermissionException, CannotChangePermissionException, NoSuchFileException,
      FileAlreadyExistsException, CannotCreateFileException {
    Cache<VersionKey, Program<JackProvider>> previousInstalledJack = installedJack;
    installedJack = CacheBuilder.newBuilder()
        .weigher(new Weigher<VersionKey, Program<JackProvider>>() {
          @Override
          public int weigh(VersionKey version, Program<JackProvider> program) {
            long length = program.getJar().length();
            return (int) Math.min(Integer.MAX_VALUE, length);
          }
        })
        .maximumWeight(maxJarSize == -1 ? Long.MAX_VALUE : maxJarSize)
        .removalListener(new RemovalListener<VersionKey, Program<JackProvider>>() {

          @Override
          public void onRemoval(
              @Nonnull RemovalNotification<VersionKey, Program<JackProvider>> notification) {
            Program<JackProvider> program = notification.getValue();
            final File jar = program.getJar();
            Object gcProbe = program.getGCProbe();
            if (gcProbe != null) {
              logger.info("Queuing " + jar.getPath() + " for deletion");
              final File deleteMarker = new File(jar.getPath() + DELETED_SUFFIX);
              try {
                if (!deleteMarker.createNewFile()) {
                  throw new IOException("File already exists");
                }
              } catch (IOException e) {
                logger.log(Level.SEVERE, "Failed to create delete file marker '" + deleteMarker
                    + "' aborting deletion by finalizer", e);
                return;
              }
              finalizer.registerFinalizer(new Deleter(new File[]{deleteMarker, jar}), gcProbe);
              deleteMarker.deleteOnExit();
              jar.deleteOnExit();
            } else {
              logger.info("Deleting " + jar.getPath() + " immediatly");
              if (!jar.delete()) {
                logger.log(Level.SEVERE, "Failed to delete file '" + jar + "'");
              }
            }
          }
        })
        .concurrencyLevel(1)
        .build();
    if (previousInstalledJack != null) {
      installedJack.putAll(previousInstalledJack.asMap());
    } else {
      loadInstalledJacks();
    }
  }

  @Nonnull
  public ServerParameters getServerParameters() {
    assert serverParameters != null;
    return serverParameters;
  }

  public void addInstalledJack(@Nonnull Program<JackProvider> jack) {
    synchronized (installedJack) {
      installedJack.put(new VersionKey(jack.getVersion()), jack);
    }
    logger.log(Level.INFO, "New installed Jack " + jack.getVersion().getVerboseVersion() + " in "
        + jack.getJar().getPath());
  }

  private void loadInstalledJacks() throws IOException, NotDirectoryException,
      WrongPermissionException, CannotChangePermissionException, NoSuchFileException,
      FileAlreadyExistsException, CannotCreateFileException {
    File jackDir = new File(serverDir, "jack");
    new Directory(jackDir.getPath(), null, Existence.MAY_EXIST,
        Permission.READ | Permission.WRITE | Permission.EXECUTE, ChangePermission.NOCHANGE);
    File[] jars = jackDir.listFiles(JAR_FILTER);
    if (jars == null) {
      throw new IOException("Failed to list Jack installation directory '"
          + jackDir + "'");
    }
    for (File jackJar : jars) {
      try {
        URL[] path = new URL[]{jackJar.toURI().toURL()};
        JackProvider jackProvider = loadJack(path, Assertion.DISABLED);
        Version version = new Version("jack", jackProvider.getClass().getClassLoader());
        Program<JackProvider> jackProgram = new Program<JackProvider>(version, jackJar, path);
        jackProgram.setLoadedProgram(Assertion.DISABLED, jackProvider);
        installedJack.put(new VersionKey(version), jackProgram);
        logger.log(Level.INFO, "Jack " + version.getVerboseVersion()
            + " available in " + jackJar.getPath());
      } catch (UnsupportedProgramException | IOException e) {
        logger.log(Level.SEVERE, "Invalid installed jack file '" + jackJar
            + "'. Deleting.");
        if (!jackJar.delete()) {
          logger.log(Level.WARNING,
              "Failed to delete invalid installed jack file '" + jackJar + "'");
        }
      }
    }
  }

  public void reloadConfig() throws IOException, WrongPermissionException, NotFileException,
      ServerException, CannotCreateFileException {
    shutdownConnections();
    try {
      checkAccess(serverDir, EnumSet.of(PosixFilePermission.OWNER_READ,
          PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE));

      loadConfig();
    } catch (CannotCreateFileException | IOException | NotFileException
        | WrongPermissionException e) {
      shutdown();
      throw e;
    }
    start(new HashMap<String, Object>());
  }

  private void loadConfig() throws IOException, WrongPermissionException, NotFileException,
      CannotCreateFileException {

    logger.log(Level.INFO, "Loading config of jack server version: "
        + getVersion().getVerboseVersion());

    ConfigFile config = new ConfigFile(serverDir);
    checkAccess(config.getStorageFile(), EnumSet.of(PosixFilePermission.OWNER_READ,
        PosixFilePermission.OWNER_WRITE));

    portService = config.getServicePort();
    portAdmin = config.getAdminPort();
    maxJarSize = config.getMaxJarSize();

    delayedModes.clear();
    addServerMode(config.getIdleDelay(), ServerMode.IDLE);
    addServerMode(config.getDeepIdleDelay(), ServerMode.DEEP_IDLE);
    addServerMode(config.getTimeout(), ServerMode.SLEEP);

    maxServices = config.getMaxServices();
    List<Pair<Integer, Long>> maxServicesByMem = config.getMaxServiceByMem();
    if (!maxServicesByMem.isEmpty()) {
      long maxMemory = Runtime.getRuntime().maxMemory();
      for (Pair<Integer, Long> pair : maxServicesByMem) {
        if (maxMemory < pair.getSecond().longValue()) {
          maxServices = Math.min(pair.getFirst().intValue(), maxServices);
        }
      }
    }

    if (config.isModified() && config.getConfigVersion() < ConfigFile.CURRENT_CONFIG_VERSION) {
      config.store();
    }
  }

  @Override
  @Nonnull
  public Version getVersion() {
    return getServerVersion();
  }

  void start(@Nonnull Map<String, Object> parameters) throws ServerException {

    try {
      buildInstalledJackCache();
    } catch (IOException | NotDirectoryException | WrongPermissionException
        | CannotChangePermissionException | NoSuchFileException | FileAlreadyExistsException
        | CannotCreateFileException e) {
      throw new ServerException("Problem while loading installed Jack", e);
    }

    InetSocketAddress serviceAddress = new InetSocketAddress("127.0.0.1", portService);
    InetSocketAddress adminAddress   = new InetSocketAddress("127.0.0.1", portAdmin);

    serverParameters = new ServerParameters(parameters);

    ContainerSocketProcessor adminProcessor =  null;
    ContainerSocketProcessor serviceProcessor =  null;
    try {
      synchronized (lock) {
        shuttingDown = false;
      }

      logger.log(Level.INFO, "Starting service connection server on " + serviceAddress);
      try {
        assert serverParameters != null;
        serviceChannel = serverParameters.getServiceSocket(serviceAddress);
      } catch (IOException e) {
        if (e.getCause() instanceof BindException) {
          throw new ServerException("Problem while opening service port: "
              + e.getCause().getMessage());
        } else {
          throw new ServerException("Problem while opening service port", e);
        }
      }
      logger.log(Level.INFO, "Starting admin connection on " + adminAddress);
      try {
        assert serverParameters != null;
        adminChannel = serverParameters.getAdminSocket(adminAddress);
      } catch (IOException e) {
        if (e.getCause() instanceof BindException) {
          throw new ServerException("Problem while opening admin port: "
              + e.getCause().getMessage());
        } else {
          throw new ServerException("Problem while opening admin port", e);
        }
      }

      SSLContext sslContext = setupSsl();

      try {
        Container router = createServiceRouter();

        serviceProcessor = new ContainerSocketProcessor(new RootContainer(router), maxServices) {
          @Override
          public void process(Socket socket) throws IOException {
            configureSocket(socket);
            super.process(socket);
          }
        };
        SocketConnection connection = new SocketConnection(serviceProcessor);
        serviceConnection = connection;
        connection.connect(serviceChannel, sslContext);
      } catch (IOException e) {
        throw new ServerException("Problem during service connection ", e);
      }

      try {
        Container router = createAdminRouter();

        adminProcessor = new ContainerSocketProcessor(new RootContainer(router), 1) {
          @Override
          public void process(Socket socket) throws IOException {
            configureSocket(socket);
            super.process(socket);
          }
        };
        SocketConnection connection = new SocketConnection(adminProcessor);
        adminConnection = connection;
        connection.connect(adminChannel, sslContext);
      } catch (IOException e) {
        throw new ServerException("Problem during admin connection ", e);
      }

      startTimer();
    } catch (ServerException e) {
      if (serviceProcessor != null) {
        try {
          serviceProcessor.stop();
        } catch (IOException stopException) {
          logger.log(Level.SEVERE, "Cannot close the service processor: ", stopException);
        }
      }

      if (adminProcessor != null) {
        try {
          adminProcessor.stop();
        } catch (IOException stopException) {
          logger.log(Level.SEVERE, "Cannot close the admin processor: ", stopException);
        }
      }

      shutdown();
      throw e;
    }
  }

  private void checkAccess(@Nonnull File file, @Nonnull Set<PosixFilePermission> check)
      throws IOException {
    FileOwnerAttributeView ownerAttribute =
        Files.getFileAttributeView(file.toPath(), FileOwnerAttributeView.class);
    if (!currentUser.equals(ownerAttribute.getOwner().getName())) {
      throw new IOException("'" + file.getPath() + "' is not owned by '" + currentUser
          + "' but by '" + ownerAttribute.getOwner().getName() + "'");
    }
    Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file.toPath());
    if (!check.equals(permissions)) {
      throw new IOException("'" + file.getPath() + "' must have permission "
          + PosixFilePermissions.toString(check) + " but have "
          + PosixFilePermissions.toString(permissions));
    }
  }

  private void refreshPEMFiles(@Nonnull KeyStore keystoreServer, @Nonnull KeyStore keystoreClient)
      throws IOException, UnrecoverableKeyException, KeyStoreException,
      NoSuchAlgorithmException {
    {
      File clientPEM = new File(getServerDir(), PEM_CLIENT);

      PEMWriter pem = new PEMWriter(clientPEM);
      try {
        pem.writeKey(keystoreClient.getKey(CLIENT_KEY_ALIAS, KEYSTORE_PASSWORD));
        pem.writeCertificate(keystoreClient.getCertificate(CLIENT_KEY_ALIAS));
      } finally {
        pem.close();
      }
    }
    {
      File serverPEM = new File(getServerDir(), PEM_SERVER);
      PEMWriter pem = new PEMWriter(serverPEM);
      try {
        pem.writeCertificate(keystoreServer.getCertificate(SERVER_KEY_ALIAS));
      } finally {
        pem.close();
      }
    }
  }

  @Nonnull
  private ServerSocketChannel openSocket(@Nonnull InetSocketAddress serviceAddress,
      @CheckForNull Object existingChannel) throws IOException,
      SocketException {
    if (existingChannel instanceof ServerSocketChannel) {
      return (ServerSocketChannel) existingChannel;
    } else {
      ServerSocketChannel channel = ServerSocketChannel.open();
      channel.configureBlocking(false);
      ServerSocket socket = channel.socket();
      socket.setReuseAddress(true);
      socket.bind(serviceAddress, 100);
      return channel;
    }
  }

  public void waitServerShutdown() throws InterruptedException {
    synchronized (lock) {
      while ((!shuttingDown) || serviceInfo.currentLocal > 0 || adminInfo.currentLocal > 0) {
        lock.wait();
      }
    }
  }

  @Nonnull
  public Program<JackProvider> selectJack(@Nonnull VersionFinder finder)
      throws NoSuchVersionException {
    synchronized (installedJack) {
      VersionKey selected = finder.select(installedJack.asMap().keySet());
      if (selected == null) {
        throw new NoSuchVersionException();
      }
      Program<JackProvider> program = installedJack.getIfPresent(selected);
      assert program != null;
      return program;
    }
  }

  @Nonnull
  public Collection<Program<JackProvider>> getInstalledJacks() {
    synchronized (installedJack) {
      return new ArrayList<>(installedJack.asMap().values());
    }
  }

  @Nonnull
  public JackProvider getProvider(@Nonnull Program<JackProvider> program, @Nonnull Assertion status)
      throws UnsupportedProgramException {
    synchronized (program) {
      JackProvider jackProvider = program.getLoadedProgram(status);
      if (jackProvider == null) {
        jackProvider = loadJack(program.getUrlPath(), status);
        program.setLoadedProgram(status, jackProvider);
      }
      return jackProvider;
    }
  }

  @Nonnull
  public VersionFinder parseVersionFinder(@Nonnull ContentType versionType,
      @Nonnull String versionString) throws TypeNotSupportedException, ParsingException {
    if (versionType.getType().equals(ExactCodeVersionFinder.SELECT_EXACT_VERSION_CONTENT_TYPE)
        && "1".equals(versionType.getParameter("version"))) {
      return ExactCodeVersionFinder.parse(versionString);
    } else {
      throw new TypeNotSupportedException(versionString);
    }
  }

  // We have no privilege restriction for now and there is no call back here from a Jack thread so
  // we should be fine keeping the code simple
  @SuppressFBWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
  public JackProvider loadJack(@Nonnull URL[] path, @Nonnull Assertion status)
      throws UnsupportedProgramException {
    URLClassLoader jackLoader;
    jackLoader = new URLClassLoaderWithProbe(path, this.getClass().getClassLoader());
    jackLoader.setDefaultAssertionStatus(status.isEnabled());
    ServiceLoader<JackProvider> serviceLoader = ServiceLoader.load(JackProvider.class, jackLoader);
    JackProvider provider;
    try {
      provider = serviceLoader.iterator().next();
    } catch (NoSuchElementException | ServiceConfigurationError e) {
      logger.log(Level.SEVERE, "Failed to load jack from " + Arrays.toString(path), e);
      throw new UnsupportedProgramException("Jack");
    }
    return provider;
  }

  private void startTimer() {
    synchronized (lock) {
      if (timer != null) {
        cancelTimer();
      }

      if (delayedModes.isEmpty()) {
        return;
      }

      logger.log(Level.INFO, "Start timer");

      timer = new Timer("jack-server-timeout");
      assert timer != null;
      for (TimedServerMode mode : delayedModes) {
        mode.registerTo(timer);
      }
    }
  }

  public void shutdown() {
    synchronized (lock) {
      if (!shuttingDown) {
        shutdownConnections();

        shuttingDown = true;
        lock.notifyAll();
      }
    }
  }

  public void shutdownServerOnly() {

    synchronized (lock) {
      if (!shuttingDown) {
        shutdownSimpleServer();

        shuttingDown = true;
        lock.notifyAll();
      }
    }
  }

  private void cleanJacks(@Nonnull Set<Category> categories, @Nonnull Set<Impact> impacts) {
    for (Program<JackProvider> program : getInstalledJacks()) {
      JackProvider provider = program.getLoadedProgram(Assertion.DISABLED);
      if (provider instanceof ResourceController) {
        ((ResourceController) provider).clean(categories, impacts);
      }
      provider = program.getLoadedProgram(Assertion.ENABLED);
      if (provider instanceof ResourceController) {
        ((ResourceController) provider).clean(categories, impacts);
      }
    }
  }

  // Even if its just a hint, this is a nice time for a gc.
  @SuppressFBWarnings("DM_GC")
  private void freeLoadedPrograms() {
    Collection<Program<JackProvider>> programs = getInstalledJacks();
    for (Program<JackProvider> program : programs) {
      synchronized (program) {
        program.setLoadedProgram(Assertion.ENABLED, null);
      }
    }
    System.gc();
  }

  private void shutdownConnections() {
    shutdownSimpleServer();

    try {
      if (serviceChannel != null) {
        logger.log(Level.FINE, "Closing service server socket");
        serviceChannel.close();
      }
    } catch (IOException e) {
      logger.log(Level.SEVERE, "Cannot close the service server socket: ", e);
    }
    serviceChannel = null;

    try {
      if (adminChannel != null) {
        logger.log(Level.FINE, "Closing admin server socket");
        adminChannel.close();
      }
    } catch (IOException e) {
      logger.log(Level.SEVERE, "Cannot close the admin server socket: ", e);
    }
    adminChannel = null;
  }

  private void shutdownSimpleServer() {
    synchronized (lock) {
      delayedModes.clear();
      cancelTimer();
    }

    Connection conn = serviceConnection;
    if (conn != null) {
      logger.log(Level.INFO, "Shutdowning service connection");
      logger.log(Level.INFO, "# max of concurrent compilations: " + serviceInfo.maxLocal);
      logger.log(Level.INFO, "# total of compilations: " + serviceInfo.totalLocal);
      logger.log(Level.INFO, "# max of concurrent forward compilations: " + serviceInfo.maxForward);
      logger.log(Level.INFO, "# total of forward compilations: " + serviceInfo.totalForward);
      try {
        conn.close();
        logger.log(Level.INFO, "Done");
      } catch (IOException e) {
        logger.log(Level.SEVERE, "Cannot shutdown the service connection: ", e);
      }
    }

    conn = adminConnection;
    if (conn != null) {
      logger.log(Level.INFO, "Shutdowning admin connection");
      try {
        conn.close();
        logger.log(Level.INFO, "Done");
      } catch (IOException e) {
        logger.log(Level.SEVERE, "Cannot shutdown the admin connection: ", e);
      }
    }
  }

  private void cancelTimer() {
    synchronized (lock) {
      if (timer != null) {
        logger.log(Level.INFO, "Cancel timer");

        timer.cancel();
        timer.purge();
        timer = null;
      }
    }
  }

  public long startingServiceTask() {
    return startingTask(serviceInfo);
  }

  public void endingServiceTask() {
    endingTask(serviceInfo);
  }

  public long startingAdministrativeTask() throws ServerClosedException {
    synchronized (lock) {
      if (shuttingDown) {
        throw new ServerClosedException();
      }

      return startingTask(adminInfo);
    }
  }

  public void endingAdministrativeTask() {
    endingTask(adminInfo);
  }

  private long startingTask(@Nonnull ServerInfo info) {
    long id;

    synchronized (lock) {
      id = info.totalLocal;
      info.totalLocal++;
      setServerMode(ServerMode.WORK);

      info.currentLocal++;
      if (info.currentLocal > info.maxLocal) {
        info.maxLocal = info.currentLocal;
      }

    }
    return id;
  }

  private void endingTask(@Nonnull ServerInfo info) {
    synchronized (lock) {
      info.currentLocal--;
      if (adminInfo.currentLocal == 0
          && serviceInfo.currentLocal == 0) {
        setServerMode(ServerMode.WAIT);
      }
      lock.notifyAll();
    }
  }

  @Nonnull
  public File getServerDir() {
    return serverDir;
  }

  @Nonnull
  public LauncherHandle getLauncherHandle() {
    return launcherHandle;
  }

  @Nonnull
  public ServerInfo getServiceStat() {
    synchronized (lock) {
      return serviceInfo.clone();
    }
  }

  public void resetMaxServiceStat() {
    synchronized (lock) {
      serviceInfo.maxForward = serviceInfo.currentForward;
      serviceInfo.maxLocal = serviceInfo.currentLocal;
    }
  }

  public void uninstallJack(@Nonnull Program<JackProvider> existingJack) {
    installedJack.invalidate(existingJack.getVersion());
  }

  @Nonnull
  private static String getCurrentUser(@Nonnull File serverDir) throws IOException {
    Set<PosixFilePermission> check = EnumSet.of(PosixFilePermission.OWNER_READ,
        PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE);
    Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(serverDir.toPath());
    if (!check.equals(permissions)) {
      throw new IOException("'" + serverDir.getPath() + "' must have permission "
          + PosixFilePermissions.toString(check) + " but have "
          + PosixFilePermissions.toString(permissions));
    }

    File tmp = File.createTempFile("jackserver-", ".tmp", serverDir);
    try {
      String tmpUser = Files.getFileAttributeView(tmp.toPath(),
          FileOwnerAttributeView.class).getOwner().getName();

      FileOwnerAttributeView ownerAttribute =
          Files.getFileAttributeView(serverDir.toPath(), FileOwnerAttributeView.class);
      if (!tmpUser.equals(ownerAttribute.getOwner().getName())) {
        throw new IOException("'" + serverDir.getPath() + "' is not owned by '" + tmpUser
            + "' but by '" + ownerAttribute.getOwner().getName() + "'");
      }

      return tmpUser;
    } finally {
      if (!tmp.delete()) {
        logger.log(Level.WARNING, "Failed to delete temp file '" + tmp.getPath() + "'");
      }
    }

  }

  @Nonnull
  private PathRouter createAdminRouter() {
    return new PathRouter()

      .add("/gc",
        new MethodRouter()
          .add(Method.POST, new GC(this)))

      .add("/stat",
        new MethodRouter()
          .add(Method.GET,
            new AcceptContentTypeRouter()
              .add(TextPlain.CONTENT_TYPE_NAME, new Stat(this)))
          .add(Method.DELETE, new ResetStats(this)))

      .add("/server/stop",
          new MethodRouter()
            .add(Method.POST, new Stop(this)))

      .add("/server/reload",
        new MethodRouter()
          .add(Method.POST, new ReloadConfig(this)))

      .add("/jack",
        new MethodRouter()
          .add(Method.PUT,
            new ContentTypeRouter()
              .add("multipart/form-data",
                new PartParserRouter<>("force", new TextPlainPartParser<>(new BooleanCodec()),
                  new PartContentTypeRouter("jar")
                    .add("application/octet-stream", new InstallJack(this)))))
          .add(Method.HEAD,
            new ContentTypeRouter()
              .add(ExactCodeVersionFinder.SELECT_EXACT_VERSION_CONTENT_TYPE,
                new ContentTypeParameterRouter("version")
                  .add("1", new QueryJackVersion(this))))
          .add(Method.GET,
            new AcceptContentTypeRouter()
              .add(TextPlain.CONTENT_TYPE_NAME, new GetJackVersions(this))))

      .add("/server",
        new MethodRouter()
          .add(Method.PUT,
            new ContentTypeRouter()
              .add("multipart/form-data",
                  new PartParserRouter<>("force", new TextPlainPartParser<>(new BooleanCodec()),
                    new PartContentTypeRouter("jar")
                      .add("application/octet-stream", new InstallServer(this)))))
          .add(Method.HEAD,
            new ContentTypeRouter()
              .add(ExactCodeVersionFinder.SELECT_EXACT_VERSION_CONTENT_TYPE,
                new ContentTypeParameterRouter("version")
                 .add("1", new QueryServerVersion(this))))
          .add(Method.GET,
            new AcceptContentTypeRouter()
              .add(TextPlain.CONTENT_TYPE_NAME, new GetServerVersion(this))))

      .add("/launcher",
        new MethodRouter()
          .add(Method.PUT,
            new ErrorContainer(Status.BAD_REQUEST))
          .add(Method.GET,
            new AcceptContentTypeRouter()
              .add(TextPlain.CONTENT_TYPE_NAME, new GetLauncherVersion(this))))

      .add("/launcher/home",
        new MethodRouter()
          .add(Method.GET,
             new AcceptContentTypeRouter()
               .add(TextPlain.CONTENT_TYPE_NAME, new GetLauncherHome(this))))

      .add("/launcher/log",
          new MethodRouter()
            .add(Method.GET,
                new AcceptContentTypeRouter()
                  .add(TextPlain.CONTENT_TYPE_NAME, new GetLauncherLog(this))))

      .add("/launcher/log/level",
        new MethodRouter()
          .add(Method.PUT,
            new ContentTypeRouter()
              .add("multipart/form-data",
                 new PartContentTypeRouter("level")
                   .add(TextPlain.CONTENT_TYPE_NAME,
                     new PartParserRouter<>("limit",
                           new TextPlainPartParser<>(new IntCodec(0, Integer.MAX_VALUE)),
                       new PartParserRouter<>("count",
                             new TextPlainPartParser<>(new IntCodec(1, Integer.MAX_VALUE)),
                         new SetLoggerParameters(this)))))));
  }

  @Nonnull
  private Container createServiceRouter() {
    return new MethodRouter()
      .add(Method.POST,
        new ContentTypeRouter()
          .add("multipart/form-data",
            new AcceptContentTypeParameterRouter("version")
              .add("1",
                new PartContentTypeRouter("cli")
                  .add(TextPlain.CONTENT_TYPE_NAME,
                    new PartContentTypeRouter("pwd")
                      .add(TextPlain.CONTENT_TYPE_NAME,
                        new PartContentTypeRouter("version")
                          .add(ExactCodeVersionFinder.SELECT_EXACT_VERSION_CONTENT_TYPE,
                            new PartContentTypeParameterRouter("version", "version")
                              .add("1",
                                 new PathRouter()
                                  .add("/jack",
                                    new PartParserRouter<>("assert",
                                      new TextPlainPartParser<>(new BooleanCodec(), Boolean.FALSE),
                                        new AcceptContentTypeRouter()
                                          .add(CommandOutRaw.JACK_COMMAND_OUT_CONTENT_TYPE,
                                              new JackTaskRawOut(this))
                                          .add(CommandOutBase64.JACK_COMMAND_OUT_CONTENT_TYPE,
                                              new JackTaskBase64Out(this))

                                  .add("/jill", new JillTask(this)))))))))));
  }

  @Nonnull
  private SSLContext setupSsl() throws ServerException {
    FileInputStream keystoreServerIn = null;
    FileInputStream keystoreClientIn = null;
    SSLContext sslContext = null;

    try {
      File keystoreServerFile = new File(serverDir, KEYSTORE_SERVER);
      File keystoreClientFile = new File(serverDir, KEYSTORE_CLIENT);
      checkAccess(keystoreServerFile, EnumSet.of(PosixFilePermission.OWNER_READ,
          PosixFilePermission.OWNER_WRITE));
      checkAccess(keystoreClientFile, EnumSet.of(PosixFilePermission.OWNER_READ,
          PosixFilePermission.OWNER_WRITE));

      keystoreServerIn = new FileInputStream(keystoreServerFile);
      KeyStore keystoreServer = KeyStore.getInstance("jks");
      keystoreServer.load(keystoreServerIn, KEYSTORE_PASSWORD);

      keystoreClientIn = new FileInputStream(keystoreClientFile);
      KeyStore keystoreClient = KeyStore.getInstance("jks");
      keystoreClient.load(keystoreClientIn, KEYSTORE_PASSWORD);

      refreshPEMFiles(keystoreServer, keystoreClient);

      KeyManagerFactory keyManagerFactory =
          KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
      keyManagerFactory.init(keystoreServer, KEYSTORE_PASSWORD);

      TrustManagerFactory tm =
          TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
      tm.init(keystoreClient);

      sslContext = SSLContext.getInstance("SSLv3");
      sslContext.init(keyManagerFactory.getKeyManagers(), tm.getTrustManagers(), null);
    } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException
        | UnrecoverableKeyException | KeyManagementException e) {
      throw new ServerException("Failed to setup ssl context", e);
    } finally {
      if (keystoreClientIn != null) {
        try {
          keystoreClientIn.close();
        } catch (IOException e) {
          // ignore
        }
      }
      if (keystoreServerIn != null) {
        try {
          keystoreServerIn.close();
        } catch (IOException e) {
          // ignore
        }
      }
    }
    return sslContext;
  }

  private void configureSocket(@Nonnull Socket socket) {
    SSLEngine engine = socket.getEngine();

    if (filteredCiphersArray == null) {
      // Synchronization not necessary since there's no going back to null and duplicate
      // computations would produce the same result.
      String[] enabledCyphers = engine.getEnabledCipherSuites();
      ArrayList<String> filteredCiphers = new ArrayList<>(enabledCyphers.length);
      // Filter out TLS_DHE and TLS_EDH because they are weak when running on a jre 7
      // and may cause connection issues depending on curl and libraries version.
      Pattern excludePattern = Pattern.compile("TLS_(DHE)|(EDH).*");
      for (String string : enabledCyphers) {
        if (!excludePattern.matcher(string).matches()) {
          filteredCiphers.add(string);
        }
      }

      filteredCiphersArray = filteredCiphers.toArray(
          new String[filteredCiphers.size()]);
    }

    engine.setEnabledCipherSuites(filteredCiphersArray);
    engine.setNeedClientAuth(true);
  }

  private void addServerMode(@Nonnegative int delay, @Nonnull ServerMode newMode) {
    delayedModes.add(new TimedServerMode(delay * 1000L, newMode));
  }

  private void setServerMode(@Nonnull ServerMode newMode) {
    synchronized (lock) {
      if (this.serverMode.equals(newMode)) {
        return;
      }
      ServerMode oldMode = this.serverMode;
      this.serverMode = newMode;
      logger.log(Level.INFO, "Server mode changing from " + oldMode + " to " + newMode);
      ServerModeWatcher watcher = modeWatchers.get(newMode);
      if (watcher != null) {
        watcher.changedMode(oldMode, newMode);
      }
    }
  }

  private void addServerModeWatcher(@Nonnull ServerMode newMode,
      @Nonnull ServerModeWatcher watcher) {
    assert modeWatchers.get(newMode) == null;
    modeWatchers.put(newMode, watcher);
  }
}
