/*
 * Copyright 2008 Google Inc.
 *
 * 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.google.gwt.dev.shell.jetty;

import com.google.gwt.core.ext.ServletContainer;
import com.google.gwt.core.ext.ServletContainerLauncher;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.util.InstalledHelpInfo;
import com.google.gwt.dev.util.Util;
import com.google.gwt.thirdparty.guava.common.collect.Iterators;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.ClasspathPattern;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * A {@link ServletContainerLauncher} for an embedded Jetty server.
 */
public class JettyLauncher extends ServletContainerLauncher {

  /**
   * Log jetty requests/responses to TreeLogger.
   */
  public static class JettyRequestLogger extends AbstractLifeCycle implements
      RequestLog {

    private final TreeLogger logger;
    private final TreeLogger.Type normalLogLevel;

    public JettyRequestLogger(TreeLogger logger, TreeLogger.Type normalLogLevel) {
      this.logger = logger;
      assert (normalLogLevel != null);
      this.normalLogLevel = normalLogLevel;
    }

    /**
     * Log an HTTP request/response to TreeLogger.
     */
    public void log(Request request, Response response) {
      int status = response.getStatus();
      if (status < 0) {
        // Copied from NCSARequestLog
        status = 404;
      }
      TreeLogger.Type logStatus, logHeaders;
      if (status >= 500) {
        logStatus = TreeLogger.ERROR;
        logHeaders = TreeLogger.INFO;
      } else if (status == 404) {
        if ("/favicon.ico".equals(request.getRequestURI())
            && request.getQueryString() == null) {
          /*
           * We do not want to call the developer's attention to a 404 when
           * requesting favicon.ico. This is a very common 404.
           */
          logStatus = TreeLogger.TRACE;
          logHeaders = TreeLogger.DEBUG;
        } else {
          logStatus = TreeLogger.WARN;
          logHeaders = TreeLogger.INFO;
        }
      } else if (status >= 400) {
        logStatus = TreeLogger.WARN;
        logHeaders = TreeLogger.INFO;
      } else {
        logStatus = normalLogLevel;
        logHeaders = TreeLogger.DEBUG;
      }

      String userString = request.getRemoteUser();
      if (userString == null) {
        userString = "";
      } else {
        userString += "@";
      }
      String bytesString = "";
      if (response.getContentCount() > 0) {
        bytesString = " " + response.getContentCount() + " bytes";
      }
      if (logger.isLoggable(logStatus)) {
        TreeLogger branch = logger.branch(logStatus, String.valueOf(status)
            + " - " + request.getMethod() + ' ' + request.getRequestURI() + " ("
            + userString + request.getRemoteHost() + ')' + bytesString);
        if (branch.isLoggable(logHeaders)) {
          logHeaders(branch.branch(logHeaders, "Request headers"), logHeaders,
              request.getHttpFields());
          logHeaders(branch.branch(logHeaders, "Response headers"), logHeaders,
              response.getHttpFields());
        }
      }
    }

    private void logHeaders(TreeLogger logger, TreeLogger.Type logLevel, HttpFields fields) {
      for (int i = 0; i < fields.size(); ++i) {
        HttpField field = fields.getField(i);
        logger.log(logLevel, field.getName() + ": " + field.getValue());
      }
    }
  }

  /**
   * An adapter for the Jetty logging system to GWT's TreeLogger. This
   * implementation class is only public to allow {@link Log} to instantiate it.
   *
   * The weird static data / default construction setup is a game we play with
   * {@link Log}'s static initializer to prevent the initial log message from
   * going to stderr.
   */
  public static class JettyTreeLogger implements Logger {
    private final TreeLogger logger;

    public JettyTreeLogger(TreeLogger logger) {
      if (logger == null) {
        throw new NullPointerException();
      }
      this.logger = logger;
    }

    public void debug(String msg, long arg) {
      logger.log(TreeLogger.SPAM, format(msg, arg));
    }

    public void debug(String msg, Object... args) {
      if (logger.isLoggable(TreeLogger.SPAM)) {
        logger.log(TreeLogger.SPAM, format(msg, args));
      }
    }

    public void debug(String msg, Throwable th) {
      logger.log(TreeLogger.SPAM, msg, th);
    }

    public void debug(Throwable th) {
      logger.log(TreeLogger.SPAM, "", th);
    }

    public Logger getLogger(String name) {
      return this;
    }

    public String getName() {
      return "";
    }

    public void info(String msg, Object... args) {
      if (logger.isLoggable(TreeLogger.TRACE)) {
        logger.log(TreeLogger.TRACE, format(msg, args));
      }
    }

    public void info(String msg, Throwable th) {
      logger.log(TreeLogger.TRACE, msg, th);
    }

    public void info(Throwable th) {
      logger.log(TreeLogger.TRACE, "", th);
    }

    public boolean isDebugEnabled() {
      return logger.isLoggable(TreeLogger.SPAM);
    }

    public void setDebugEnabled(boolean enabled) {
      // ignored
    }

    public void warn(String msg, Object... args) {
      if (logger.isLoggable(TreeLogger.WARN)) {
        logger.log(TreeLogger.WARN, format(msg, args));
      }
    }

    public void warn(String msg, Throwable th) {
      logger.log(TreeLogger.WARN, msg, th);
    }

    public void warn(Throwable th) {
      logger.log(TreeLogger.WARN, "", th);
    }

    public void ignore(Throwable th) {
      logger.log(TreeLogger.SPAM, "IGNORE", th);
    }

    /**
     * Copied from org.eclipse.log.StdErrLog.
     */
    private String format(String msg, Object... args) {
      if (msg == null) {
        msg = "";
        for (int i = 0; i < args.length; i++) {
          msg += "{} ";
        }
      }
      String braces = "{}";
      int start = 0;
      StringBuilder builder = new StringBuilder();
      for (Object arg : args) {
        int bracesIndex = msg.indexOf(braces, start);
        if (bracesIndex < 0) {
          builder.append(msg.substring(start));
          builder.append(" ");
          builder.append(arg);
          start = msg.length();
        } else {
          builder.append(msg.substring(start, bracesIndex));
          builder.append(String.valueOf(arg));
          start = bracesIndex + braces.length();
        }
      }
      builder.append(msg.substring(start));
      return builder.toString();
    }
  }

  /**
   * The resulting {@link ServletContainer} this is launched.
   */
  protected static class JettyServletContainer extends ServletContainer {
    private final int actualPort;
    private final File appRootDir;
    private final TreeLogger logger;
    private final Server server;
    private final WebAppContext wac;

    public JettyServletContainer(TreeLogger logger, Server server,
        WebAppContext wac, int actualPort, File appRootDir) {
      this.logger = logger;
      this.server = server;
      this.wac = wac;
      this.actualPort = actualPort;
      this.appRootDir = appRootDir;
    }

    @Override
    public int getPort() {
      return actualPort;
    }

    @Override
    public void refresh() throws UnableToCompleteException {
      String msg = "Reloading web app to reflect changes in "
          + appRootDir.getAbsolutePath();
      TreeLogger branch = logger.branch(TreeLogger.INFO, msg);
      // Temporarily log Jetty on the branch.
      Log.setLog(new JettyTreeLogger(branch));
      try {
        server.stop();
        server.start();
        branch.log(TreeLogger.INFO, "Reload completed successfully");
      } catch (Exception e) {
        branch.log(TreeLogger.ERROR, "Unable to restart embedded Jetty server",
            e);
        throw new UnableToCompleteException();
      } finally {
        // Reset the top-level logger.
        Log.setLog(new JettyTreeLogger(logger));
      }
    }

    @Override
    public void stop() throws UnableToCompleteException {
      TreeLogger branch = logger.branch(TreeLogger.INFO,
          "Stopping Jetty server");
      // Temporarily log Jetty on the branch.
      Log.setLog(new JettyTreeLogger(branch));
      try {
        server.stop();
        server.setStopAtShutdown(false);
        branch.log(TreeLogger.TRACE, "Stopped successfully");
      } catch (Exception e) {
        branch.log(TreeLogger.ERROR, "Unable to stop embedded Jetty server", e);
        throw new UnableToCompleteException();
      } finally {
        // Reset the top-level logger.
        Log.setLog(new JettyTreeLogger(logger));
      }
    }
  }

  /**
   * A {@link WebAppContext} tailored to GWT hosted mode. Features hot-reload
   * with a new {@link WebAppClassLoader} to pick up disk changes. The default
   * Jetty {@code WebAppContext} will create new instances of servlets, but it
   * will not create a brand new {@link ClassLoader}. By creating a new {@code
   * ClassLoader} each time, we re-read updated classes from disk.
   *
   * Also provides special class filtering to isolate the web app from the GWT
   * hosting environment.
   */
  protected static final class WebAppContextWithReload extends WebAppContext {

    /**
     * Specialized {@link WebAppClassLoader} that allows outside resources to be
     * brought in dynamically from the system path. A warning is issued when
     * this occurs.
     */
    private class WebAppClassLoaderExtension extends WebAppClassLoader {

      private static final String META_INF_SERVICES = "META-INF/services/";

      private final ClasspathPattern systemClassesFromWebappFirst = new ClasspathPattern(new String[] {
          "-javax.servlet.",
          "-javax.el.",
          "-javax.websocket.",
          "javax.",
      });
      private final ClasspathPattern allowedFromSystemClassLoader = new ClasspathPattern(new String[] {
          "org.eclipse.jetty.",
          "javax.websocket.",
          // Jasper
          "org.apache.jasper.",
          "org.apache.juli.logging.",
          "org.apache.tomcat.",
          "org.apache.el.",
          // Xerces
          "org.apache.xerces.",
          "javax.xml.", // Used by Jetty for jetty-web.xml parsing
      });

      public WebAppClassLoaderExtension() throws IOException {
        super(bootStrapOnlyClassLoader, WebAppContextWithReload.this);
      }

      @Override
      public Enumeration<URL> getResources(String name) throws IOException {
        // Logic copied from Jetty's WebAppClassLoader, modified to use the system classloader
        // instead of the parent classloader for server classes
        List<URL> fromParent = WebAppContextWithReload.this.isServerClass(name)
            ? Collections.<URL>emptyList()
            : Lists.newArrayList(Iterators.forEnumeration(systemClassLoader.getResources(name)));
        Iterator<URL> fromWebapp = WebAppContextWithReload.this.isSystemClass(name)
                && !fromParent.isEmpty()
            ? Collections.<URL>emptyIterator()
            : Iterators.forEnumeration(findResources(name));
        return Iterators.asEnumeration(Iterators.concat(fromWebapp, fromParent.iterator()));
      }

      @Override
      public URL findResource(String name) {
        // Specifically for META-INF/services/javax.xml.parsers.SAXParserFactory
        String checkName = name;
        if (checkName.startsWith(META_INF_SERVICES)) {
          checkName = checkName.substring(META_INF_SERVICES.length());
        }
        checkName = checkName.replace('/', '.');

        // For a system path, load from the outside world.
        // Note: bootstrap has already been searched, so javax. classes should be
        // tried from the webapp first (except for javax.servlet and javax.el).
        URL found;
        if (WebAppContextWithReload.this.isSystemClass(checkName)
                && !systemClassesFromWebappFirst.match(checkName)) {
          found = systemClassLoader.getResource(name);
          if (found != null) {
            return found;
          }
        }

        // Always check this ClassLoader first.
        found = super.findResource(name);
        if (found != null) {
          return found;
        }

        // See if the outside world has it.
        found = systemClassLoader.getResource(name);
        if (found == null || WebAppContextWithReload.this.isServerClass(checkName)) {
          return null;
        }

        // Special-case Jetty/Jasper/etc. resources
        if (allowedFromSystemClassLoader.match(checkName) ||
            // Jetty-plus reads jndi.properties
            "jndi.properties".equals(name)) {
          return found;
        }

        // Warn, add containing URL to our own ClassLoader, and retry the call.
        String warnMessage = "Server resource '"
            + name
            + "' could not be found in the web app, but was found on the system classpath";
        if (!addContainingClassPathEntry(warnMessage, found, name)) {
          return null;
        }
        return super.findResource(name);
      }

      @Override
      protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // For system path, always prefer the outside world.
        // Note: bootstrap has already been searched, so javax. classes should be
        // tried from the webapp first (except for javax.servlet).
        if (WebAppContextWithReload.this.isSystemClass(name)
                && !systemClassesFromWebappFirst.match(name)) {
          try {
            Class<?> loaded = systemClassLoader.loadClass(name);
            if (resolve) {
              resolveClass(loaded);
            }
            return loaded;
          } catch (ClassNotFoundException e) {
          }
        }

        try {
          return super.loadClass(name, resolve);
        } catch (ClassNotFoundException e) {
          // Don't allow server classes to be loaded from the outside.
          if (WebAppContextWithReload.this.isServerClass(name)) {
            throw e;
          }
        }

        // See if the outside world has a URL for it.
        String resourceName = name.replace('.', '/') + ".class";
        URL found = systemClassLoader.getResource(resourceName);
        if (found == null) {
          throw new ClassNotFoundException(name);
        }

        // Special-case JDBCUnloader; it should always be loaded in the webapp classloader
        if (JDBCUnloader.class.getName().equals(name)) {
          byte[] jdbcUnloader = Util.readURLAsBytes(found);
          return defineClass(name, jdbcUnloader, 0, jdbcUnloader.length);
        }

        // Those classes are allowed to be loaded right from the systemClassLoader
        // Note: Jetty classes here are not "server classes", handled above.
        if (allowedFromSystemClassLoader.match(name)) {
          Class<?> loaded = systemClassLoader.loadClass(name);
          if (resolve) {
            resolveClass(loaded);
          }
          return loaded;
        }

        // Warn, add containing URL to our own ClassLoader, and retry the call.
        String warnMessage = "Server class '"
                + name
                + "' could not be found in the web app, but was found on the system classpath";
        if (!addContainingClassPathEntry(warnMessage, found, resourceName)) {
          throw new ClassNotFoundException(name);
        }
        return super.loadClass(name, resolve);
      }

      private boolean addContainingClassPathEntry(String warnMessage,
          URL resource, String resourceName) {
        TreeLogger.Type logLevel = (System.getProperty(PROPERTY_NOWARN_WEBAPP_CLASSPATH) == null)
            ? TreeLogger.WARN : TreeLogger.DEBUG;
        TreeLogger branch = logger.branch(logLevel, warnMessage);
        String classPathURL;
        String foundStr = resource.toExternalForm();
        if (resource.getProtocol().equals("file")) {
          assert foundStr.endsWith(resourceName);
          classPathURL = foundStr.substring(0, foundStr.length()
              - resourceName.length());
        } else if (resource.getProtocol().equals("jar")) {
          assert foundStr.startsWith("jar:");
          assert foundStr.endsWith("!/" + resourceName);
          classPathURL = foundStr.substring(4, foundStr.length()
              - (2 + resourceName.length()));
        } else {
          branch.log(TreeLogger.ERROR,
              "Found resouce but unrecognized URL format: '" + foundStr + '\'');
          return false;
        }
        branch = branch.branch(logLevel, "Adding classpath entry '"
            + classPathURL + "' to the web app classpath for this session",
            null, new InstalledHelpInfo("webAppClassPath.html"));
        try {
          addClassPath(classPathURL);
          return true;
        } catch (IOException e) {
          branch.log(TreeLogger.ERROR, "Failed add container URL: '"
              + classPathURL + '\'', e);
          return false;
        }
      }
    }

    /**
     * Parent ClassLoader for the Jetty web app, which can only load JVM
     * classes. We would just use <code>null</code> for the parent ClassLoader
     * except this makes Jetty unhappy.
     */
    private final ClassLoader bootStrapOnlyClassLoader = new ClassLoader(null) {
    };

    private final TreeLogger logger;

    /**
     * In the usual case of launching {@link com.google.gwt.dev.DevMode}, this
     * will always by the system app ClassLoader.
     */
    private final ClassLoader systemClassLoader = Thread.currentThread().getContextClassLoader();

    private WebAppContextWithReload(TreeLogger logger, String webApp,
        String contextPath) {
      super(null, contextPath, null, null, null, new ErrorPageErrorHandler(),
              ServletContextHandler.SESSIONS);
      this.setWar(webApp);
      this.logger = logger;

      // Prevent file locking on Windows; pick up file changes.
      getInitParams().put(
          "org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");

      // Since the parent class loader is bootstrap-only, prefer it first.
      setParentLoaderPriority(true);
    }

    @Override
    protected void doStart() throws Exception {
      setClassLoader(new WebAppClassLoaderExtension());
      super.doStart();
    }

    @Override
    protected void doStop() throws Exception {
      super.doStop();

      Class<?> jdbcUnloader =
          getClassLoader().loadClass("com.google.gwt.dev.shell.jetty.JDBCUnloader");
      java.lang.reflect.Method unload = jdbcUnloader.getMethod("unload");
      unload.invoke(null);

      setClassLoader(null);
    }
  }

  /**
   * Represents the type of SSL client certificate authentication desired.
   */
  private enum ClientAuth {
    NONE,
    WANT,
    REQUIRE,
  }

  /**
   * System property to suppress warnings about loading web app classes from the
   * system classpath.
   */
  private static final String PROPERTY_NOWARN_WEBAPP_CLASSPATH = "gwt.nowarn.webapp.classpath";

  /**
   * Setup a connector for the bind address/port.
   *
   * @param connector
   * @param bindAddress
   * @param port
   */
  private static void setupConnector(ServerConnector connector,
      String bindAddress, int port) {
    if (bindAddress != null) {
      connector.setHost(bindAddress.toString());
    }
    connector.setPort(port);

    // Allow binding to a port even if it's still in state TIME_WAIT.
    connector.setReuseAddress(true);
  }

  // default value used if setBaseLogLevel isn't called
  private TreeLogger.Type baseLogLevel = TreeLogger.INFO;

  private String bindAddress = null;

  private ClientAuth clientAuth;

  private String keyStore;

  private String keyStorePassword;

  private final Object privateInstanceLock = new Object();

  private boolean useSsl;

  @Override
  public String getName() {
    return "Jetty";
  }

  @Override
  public boolean isSecure() {
    return useSsl;
  }

  @Override
  public boolean processArguments(TreeLogger logger, String arguments) {
    if (arguments != null && arguments.length() > 0) {
      // TODO(jat): better parsing of the args
      for (String arg : arguments.split(",")) {
        int equals = arg.indexOf('=');
        String tag;
        String value = null;
        if (equals < 0) {
          tag = arg;
        } else {
          tag = arg.substring(0, equals);
          value = arg.substring(equals + 1);
        }
        if ("ssl".equals(tag)) {
          useSsl = true;
          URL keyStoreUrl = getClass().getResource("localhost.keystore");
          if (keyStoreUrl == null) {
            logger.log(TreeLogger.ERROR, "Default GWT keystore not found");
            return false;
          }
          keyStore = keyStoreUrl.toExternalForm();
          keyStorePassword = "localhost";
        } else if ("keystore".equals(tag)) {
          useSsl = true;
          keyStore = value;
        } else if ("password".equals(tag)) {
          useSsl = true;
          keyStorePassword = value;
        } else if ("pwfile".equals(tag)) {
          useSsl = true;
          keyStorePassword = Util.readFileAsString(new File(value));
          if (keyStorePassword == null) {
            logger.log(TreeLogger.ERROR,
                "Unable to read keystore password from '" + value + "'");
            return false;
          }
          keyStorePassword = keyStorePassword.trim();
        } else if ("clientAuth".equals(tag)) {
          useSsl = true;
          try {
            clientAuth = ClientAuth.valueOf(value);
          } catch (IllegalArgumentException e) {
            logger.log(TreeLogger.WARN, "Ignoring invalid clientAuth of '"
                + value + "'");
          }
        } else {
          logger.log(TreeLogger.ERROR, "Unexpected argument to "
              + JettyLauncher.class.getSimpleName() + ": " + arg);
          return false;
        }
      }
      if (useSsl) {
        if (keyStore == null) {
          logger.log(TreeLogger.ERROR, "A keystore is required to use SSL");
          return false;
        }
        if (keyStorePassword == null) {
          logger.log(TreeLogger.ERROR,
              "A keystore password is required to use SSL");
          return false;
        }
      }
    }
    return true;
  }

  /*
   * TODO: This is a hack to pass the base log level to the SCL. We'll have to
   * figure out a better way to do this for SCLs in general. Please do not
   * depend on this method, as it is subject to change.
   */
  public void setBaseRequestLogLevel(TreeLogger.Type baseLogLevel) {
    synchronized (privateInstanceLock) {
      this.baseLogLevel = baseLogLevel;
    }
  }

  @Override
  public void setBindAddress(String bindAddress) {
    this.bindAddress = bindAddress;
  }

  @Override
  public ServletContainer start(TreeLogger logger, int port, File appRootDir)
      throws Exception {
    TreeLogger branch = logger.branch(TreeLogger.TRACE,
        "Starting Jetty on port " + port, null);

    checkStartParams(branch, port, appRootDir);

    // Setup our branch logger during startup.
    Log.setLog(new JettyTreeLogger(branch));

    // Force load some JRE singletons that can pin the classloader.
    jreLeakPrevention(logger);

    // Turn off XML validation.
    System.setProperty("org.eclipse.jetty.xml.XmlParser.Validating", "false");

    Server server = new Server();

    ServerConnector connector = getConnector(server, logger);
    setupConnector(connector, bindAddress, port);
    server.addConnector(connector);

    Configuration.ClassList cl = Configuration.ClassList.setServerDefault(server);
    try {
      // from jetty-plus.xml
      Thread.currentThread().getContextClassLoader().loadClass("org.eclipse.jetty.plus.webapp.PlusConfiguration");
      cl.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
          "org.eclipse.jetty.plus.webapp.EnvConfiguration",
          "org.eclipse.jetty.plus.webapp.PlusConfiguration");
    } catch (ClassNotFoundException cnfe) {
      logger.log(TreeLogger.Type.DEBUG, "jetty-plus isn't on the classpath, JNDI won't work. This might also affect annotations scanning and JSP.");
    }
    try {
      // from jetty-annotations.xml
      Thread.currentThread().getContextClassLoader()
          .loadClass("org.eclipse.jetty.annotations.AnnotationConfiguration");
      cl.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
          "org.eclipse.jetty.annotations.AnnotationConfiguration");
    } catch (ClassNotFoundException cnfe) {
      logger.log(TreeLogger.Type.DEBUG, "jetty-annotations isn't on the classpath, annotation scanning won't work. This might also affect annotations scanning.");
    }

    // Create a new web app in the war directory.
    WebAppContext wac = createWebAppContext(logger, appRootDir);
    wac.setSecurityHandler(new ConstraintSecurityHandler());

    RequestLogHandler logHandler = new RequestLogHandler();
    logHandler.setRequestLog(new JettyRequestLogger(logger, getBaseLogLevel()));
    logHandler.setHandler(wac);
    server.setHandler(logHandler);
    server.start();
    server.setStopAtShutdown(true);

    // Now that we're started, log to the top level logger.
    Log.setLog(new JettyTreeLogger(logger));

    // DevMode#doStartUpServer() fails from time to time (rarely) due
    // to an unknown error. Adding some logging to pinpoint the problem.
    int connectorPort = connector.getLocalPort();
    if (connector.getLocalPort() < 0) {
      branch.log(TreeLogger.ERROR, String.format(
          "Failed to connect to open channel with port %d (return value %d)",
          port, connectorPort));
    }
    return createServletContainer(logger, appRootDir, server, wac,
        connectorPort);
  }

  protected JettyServletContainer createServletContainer(TreeLogger logger,
      File appRootDir, Server server, WebAppContext wac, int localPort) {
    return new JettyServletContainer(logger, server, wac, localPort, appRootDir);
  }

  protected WebAppContext createWebAppContext(TreeLogger logger, File appRootDir) {
    WebAppContext context = new WebAppContextWithReload(logger, appRootDir.getAbsolutePath(), "/");
    context.setConfigurationClasses(new String[] {
        "org.eclipse.jetty.webapp.WebInfConfiguration",
        "org.eclipse.jetty.webapp.WebXmlConfiguration",
        "org.eclipse.jetty.webapp.MetaInfConfiguration",
        "org.eclipse.jetty.webapp.FragmentConfiguration",
        "org.eclipse.jetty.plus.webapp.EnvConfiguration",
        "org.eclipse.jetty.plus.webapp.PlusConfiguration",
        "org.eclipse.jetty.annotations.AnnotationConfiguration",
        "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
    });
    return context;
  }

  protected ServerConnector getConnector(Server server, TreeLogger logger) {
    HttpConfiguration config = defaultConfig();
    if (useSsl) {
      TreeLogger sslLogger = logger.branch(TreeLogger.INFO,
          "Listening for SSL connections");
      if (sslLogger.isLoggable(TreeLogger.TRACE)) {
        sslLogger.log(TreeLogger.TRACE, "Using keystore " + keyStore);
      }
      SslContextFactory ssl = new SslContextFactory();
      if (clientAuth != null) {
        switch (clientAuth) {
          case NONE:
            ssl.setWantClientAuth(false);
            ssl.setNeedClientAuth(false);
            break;
          case WANT:
            sslLogger.log(TreeLogger.TRACE, "Requesting client certificates");
            ssl.setWantClientAuth(true);
            ssl.setNeedClientAuth(false);
            break;
          case REQUIRE:
            sslLogger.log(TreeLogger.TRACE, "Requiring client certificates");
            ssl.setWantClientAuth(true);
            ssl.setNeedClientAuth(true);
            break;
        }
      }
      ssl.setKeyStorePath(keyStore);
      ssl.setTrustStorePath(keyStore);
      ssl.setKeyStorePassword(keyStorePassword);
      ssl.setTrustStorePassword(keyStorePassword);
      config.addCustomizer(new SecureRequestCustomizer());
      return new ServerConnector(server,
          null, null, null, 0, 2,
          new SslConnectionFactory(ssl, "http/1.1"),
          new HttpConnectionFactory(config));
    }
    return new ServerConnector(server, new HttpConnectionFactory(config));
  }

  protected HttpConfiguration defaultConfig() {
     HttpConfiguration config = new HttpConfiguration();
     config.setRequestHeaderSize(16386);
     config.setSendServerVersion(false);
     config.setSendDateHeader(true);
     return config;
  }

  private void checkStartParams(TreeLogger logger, int port, File appRootDir) {
    if (logger == null) {
      throw new NullPointerException("logger cannot be null");
    }

    if (port < 0 || port > 65535) {
      throw new IllegalArgumentException(
          "port must be either 0 (for auto) or less than 65536");
    }

    if (appRootDir == null) {
      throw new NullPointerException("app root direcotry cannot be null");
    }
  }

  /*
   * TODO: This is a hack to pass the base log level to the SCL. We'll have to
   * figure out a better way to do this for SCLs in general.
   */
  private TreeLogger.Type getBaseLogLevel() {
    synchronized (privateInstanceLock) {
      return this.baseLogLevel;
    }
  }

  /**
   * This is a modified version of JreMemoryLeakPreventionListener.java found
   * in the Apache Tomcat project at
   *
   * http://svn.apache.org/repos/asf/tomcat/trunk/java/org/apache/catalina/core/
   * JreMemoryLeakPreventionListener.java
   *
   * Relevant part of the Tomcat NOTICE, retrieved from
   * http://svn.apache.org/repos/asf/tomcat/trunk/NOTICE Apache Tomcat Copyright
   * 1999-2010 The Apache Software Foundation
   *
   * This product includes software developed by The Apache Software Foundation
   * (http://www.apache.org/).
   */
  private void jreLeakPrevention(TreeLogger logger) {
    // Trigger a call to sun.awt.AppContext.getAppContext(). This will
    // pin the common class loader in memory but that shouldn't be an
    // issue.
    ImageIO.getCacheDirectory();

    /*
     * Several components end up calling: sun.misc.GC.requestLatency(long)
     *
     * Those libraries / components known to trigger memory leaks due to
     * eventual calls to requestLatency(long) are: -
     * javax.management.remote.rmi.RMIConnectorServer.start()
     */
    try {
      Class<?> clazz = Class.forName("sun.misc.GC");
      Method method = clazz.getDeclaredMethod("requestLatency",
          new Class[]{long.class});
      method.invoke(null, Long.valueOf(3600000));
    } catch (ClassNotFoundException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.gcDaemonFail", e);
    } catch (SecurityException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.gcDaemonFail", e);
    } catch (NoSuchMethodException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.gcDaemonFail", e);
    } catch (IllegalArgumentException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.gcDaemonFail", e);
    } catch (IllegalAccessException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.gcDaemonFail", e);
    } catch (InvocationTargetException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.gcDaemonFail", e);
    }

    /*
     * Calling getPolicy retains a static reference to the context class loader.
     */
    try {
      // Policy.getPolicy();
      Class<?> policyClass = Class.forName("javax.security.auth.Policy");
      Method method = policyClass.getMethod("getPolicy");
      method.invoke(null);
    } catch (ClassNotFoundException e) {
      // Ignore. The class is deprecated.
    } catch (SecurityException e) {
      // Ignore. Don't need call to getPolicy() to be successful,
      // just need to trigger static initializer.
    } catch (NoSuchMethodException e) {
      logger.log(TreeLogger.WARN, "jreLeakPrevention.authPolicyFail", e);
    } catch (IllegalArgumentException e) {
      logger.log(TreeLogger.WARN, "jreLeakPrevention.authPolicyFail", e);
    } catch (IllegalAccessException e) {
      logger.log(TreeLogger.WARN, "jreLeakPrevention.authPolicyFail", e);
    } catch (InvocationTargetException e) {
      logger.log(TreeLogger.WARN, "jreLeakPrevention.authPolicyFail", e);
    }

    /*
     * Creating a MessageDigest during web application startup initializes the
     * Java Cryptography Architecture. Under certain conditions this starts a
     * Token poller thread with TCCL equal to the web application class loader.
     *
     * Instead we initialize JCA right now.
     */
    java.security.Security.getProviders();

    /*
     * Several components end up opening JarURLConnections without first
     * disabling caching. This effectively locks the file. Whilst more
     * noticeable and harder to ignore on Windows, it affects all operating
     * systems.
     *
     * Those libraries/components known to trigger this issue include: - log4j
     * versions 1.2.15 and earlier - javax.xml.bind.JAXBContext.newInstance()
     */

    // Set the default URL caching policy to not to cache
    try {
      // Doesn't matter that this JAR doesn't exist - just as long as
      // the URL is well-formed
      URL url = new URL("jar:file://dummy.jar!/");
      URLConnection uConn = url.openConnection();
      uConn.setDefaultUseCaches(false);
    } catch (MalformedURLException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.jarUrlConnCacheFail", e);
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.jarUrlConnCacheFail", e);
    }

    /*
     * Haven't got to the root of what is going on with this leak but if a web
     * app is the first to make the calls below the web application class loader
     * will be pinned in memory.
     */
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    try {
      factory.newDocumentBuilder();
    } catch (ParserConfigurationException e) {
      logger.log(TreeLogger.ERROR, "jreLeakPrevention.xmlParseFail", e);
    }
  }
}
