/*
 * Copyright 2006 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.tomcat;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.impl.ClassPathEntry;
import com.google.gwt.dev.resource.impl.PathPrefix;
import com.google.gwt.dev.resource.impl.PathPrefixSet;
import com.google.gwt.dev.resource.impl.ResourceOracleImpl;
import com.google.gwt.dev.shell.WorkDirs;
import com.google.gwt.dev.util.Util;

import org.apache.catalina.Connector;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Engine;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Logger;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Embedded;
import org.apache.catalina.startup.HostConfig;
import org.apache.coyote.tomcat5.CoyoteConnector;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Wraps an instance of the Tomcat web server used in hosted mode.
 */
public class EmbeddedTomcatServer {

  static EmbeddedTomcatServer sTomcat;

  public static int getPort() {
    return sTomcat.port;
  }

  public static String start(TreeLogger topLogger, int port, WorkDirs workDirs) {
    return start(topLogger, port, workDirs, true);
  }

  public static synchronized String start(TreeLogger topLogger, int port,
      WorkDirs workDirs, boolean shouldAutoGenerateResources) {
    if (sTomcat != null) {
      throw new IllegalStateException("Embedded Tomcat is already running");
    }

    try {
      new EmbeddedTomcatServer(topLogger, port, workDirs,
          shouldAutoGenerateResources);
      return null;
    } catch (LifecycleException e) {
      String msg = e.getMessage();
      if (msg != null && msg.indexOf("already in use") != -1) {
        msg = "Port "
            + port
            + " is already is use; you probably still have another session active";
      } else {
        msg = "Unable to start the embedded Tomcat server; double-check that your configuration is valid";
      }
      return msg;
    }
  }

  // Stop the embedded Tomcat server.
  //
  public static synchronized void stop() {
    if (sTomcat != null) {
      try {
        sTomcat.catEmbedded.stop();
      } catch (LifecycleException e) {
        // There's nothing we can really do about this and the logger is
        // gone in many scenarios, so we just ignore it.
        //
      } finally {
        sTomcat = null;
      }
    }
  }

  /**
   * Returns what local port the Tomcat connector is running on.
   * 
   * When starting Tomcat with port 0 (i.e. choose an open port), there is just
   * no way to figure out what port it actually chose. So we're using pure
   * hackery to steal the port via reflection. The only works because we bundle
   * Tomcat with GWT and know exactly what version it is.
   */
  private static int computeLocalPort(Connector connector) {
    Throwable caught = null;
    try {
      Field phField = CoyoteConnector.class.getDeclaredField("protocolHandler");
      phField.setAccessible(true);
      Object protocolHandler = phField.get(connector);

      Field epField = protocolHandler.getClass().getDeclaredField("ep");
      epField.setAccessible(true);
      Object endPoint = epField.get(protocolHandler);

      Field ssField = endPoint.getClass().getDeclaredField("serverSocket");
      ssField.setAccessible(true);
      ServerSocket serverSocket = (ServerSocket) ssField.get(endPoint);

      return serverSocket.getLocalPort();
    } catch (SecurityException e) {
      caught = e;
    } catch (NoSuchFieldException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    }
    throw new RuntimeException(
        "Failed to retrieve the startup port from Embedded Tomcat", caught);
  }

  private Embedded catEmbedded;

  private Engine catEngine;

  private StandardHost catHost = null;

  private int port;

  private final TreeLogger startupBranchLogger;

  private EmbeddedTomcatServer(final TreeLogger topLogger, int listeningPort,
      final WorkDirs workDirs, final boolean shouldAutoGenerateResources)
      throws LifecycleException {
    if (topLogger == null) {
      throw new NullPointerException("No logger specified");
    }

    final TreeLogger logger = topLogger.branch(TreeLogger.INFO,
        "Starting HTTP on port " + listeningPort, null);

    startupBranchLogger = logger;

    // Make myself the one static instance.
    // NOTE: there is only one small implementation reason that this has
    // to be a singleton, which is that the commons logger LogFactory insists
    // on creating your logger class which must have a constructor with
    // exactly one String argument, and since we want LoggerAdapter to delegate
    // to the logger instance available through instance host, there is no
    // way I can think of to delegate without accessing a static field.
    // An inner class is almost right, except there's no outer instance.
    //
    sTomcat = this;

    // Assume the working directory is simply the user's current directory.
    //
    File topWorkDir = new File(System.getProperty("user.dir"));

    // Tell Tomcat its base directory so that it won't complain.
    //
    String catBase = System.getProperty("catalina.base");
    if (catBase == null) {
      // we (briefly) supported catalina.base.create, so let's not cut support
      // until the deprecated sunset
      catBase = System.getProperty("catalina.base.create");
      if (catBase != null) {
        logger.log(TreeLogger.WARN, "catalina.base.create is deprecated.  " +
            "Use catalina.base, and it will be created if necessary.");
        topWorkDir = new File(catBase);
      }
      catBase = generateDefaultCatalinaBase(logger, topWorkDir);
      System.setProperty("catalina.base", catBase);
    }

    // Some debug messages for ourselves.
    //
    logger.log(TreeLogger.DEBUG, "catalina.base = " + catBase, null);

    // Set up the logger that will be returned by the Commons logging factory.
    //
    String adapterClassName = CommonsLoggerAdapter.class.getName();
    System.setProperty("org.apache.commons.logging.Log", adapterClassName);

    // And set up an adapter that will work with the Catalina logger family.
    //
    Logger catalinaLogger = new CatalinaLoggerAdapter(topLogger);

    // Create an embedded server.
    //
    catEmbedded = new Embedded();
    catEmbedded.setDebug(0);
    catEmbedded.setLogger(catalinaLogger);

    // The embedded engine is called "gwt".
    //
    catEngine = catEmbedded.createEngine();
    catEngine.setName("gwt");
    catEngine.setDefaultHost("localhost");
    catEngine.setParentClassLoader(this.getClass().getClassLoader());

    // It answers localhost requests.
    //
    // String appBase = fCatalinaBaseDir.getAbsolutePath();
    String appBase = catBase + "/webapps";
    catHost = (StandardHost) catEmbedded.createHost("localhost", appBase);

    // Hook up a host config to search for and pull in webapps.
    //
    HostConfig hostConfig = new HostConfig();
    catHost.addLifecycleListener(hostConfig);

    // Hook pre-install events so that we can add attributes to allow loaded
    // instances to find their development instance host.
    //
    catHost.addContainerListener(new ContainerListener() {
      public void containerEvent(ContainerEvent event) {
        if (StandardHost.PRE_INSTALL_EVENT.equals(event.getType())) {
          StandardContext webapp = (StandardContext) event.getData();
          publishShellLoggerAttribute(logger, topLogger, webapp);
          publishShellWorkDirsAttribute(logger, workDirs, webapp);
          publishShouldAutoGenerateResourcesAttribute(logger,
              shouldAutoGenerateResources, webapp);
        }
      }
    });

    // Tell the engine about the host.
    //
    catEngine.addChild(catHost);
    catEngine.setDefaultHost(catHost.getName());

    // Tell the embedded manager about the engine.
    //
    catEmbedded.addEngine(catEngine);
    InetAddress nullAddr = null;
    Connector connector = catEmbedded.createConnector(nullAddr, listeningPort,
        false);
    catEmbedded.addConnector(connector);

    // start up!
    catEmbedded.start();
    port = computeLocalPort(connector);

    if (port != listeningPort) {
      logger.log(TreeLogger.INFO, "HTTP listening on port " + port, null);
    }
  }

  public TreeLogger getLogger() {
    return startupBranchLogger;
  }

  /*
   * Assumes that the leaf is a file (not a directory).
   */
  private void copyFileNoOverwrite(TreeLogger logger, String srcResName,
      Resource srcRes, File catBase) {

    File dest = new File(catBase, srcResName);
    try {
      // Only copy if src is newer than desc.
      long srcLastModified = srcRes.getLastModified();
      long dstLastModified = dest.lastModified();

      if (srcLastModified < dstLastModified) {
        // Don't copy over it.
        logger.log(TreeLogger.SPAM, "Source is older than existing: "
            + dest.getAbsolutePath(), null);
        return;
      } else if (srcLastModified == dstLastModified) {
        // Exact same time; quietly don't overwrite.
        return;
      } else if (dest.exists()) {
        // Warn about the overwrite
        logger.log(TreeLogger.WARN, "Overwriting existing file '"
            + dest.getAbsolutePath() + "' with '" + srcRes.getLocation()
            + "', which has a newer timestamp");
      }

      // Make dest directories as required.
      File destParent = dest.getParentFile();
      if (destParent != null) {
        // No need to check mkdirs result because IOException later anyway.
        destParent.mkdirs();
      }

      Util.copy(srcRes.openContents(), new FileOutputStream(dest));
      dest.setLastModified(srcLastModified);

      logger.log(TreeLogger.TRACE, "Wrote: " + dest.getAbsolutePath(), null);
    } catch (IOException e) {
      logger.log(TreeLogger.WARN, "Failed to write: " + dest.getAbsolutePath(),
          e);
    } 
  }

  /**
   * Extracts a valid catalina base instance from the classpath. Does not
   * overwrite any existing files.
   */
  private String generateDefaultCatalinaBase(TreeLogger logger, File workDir) {
    logger = logger.branch(
        TreeLogger.TRACE,
        "Property 'catalina.base' not specified; checking for a standard catalina base image instead",
        null);

    // Recursively copies out files and directories
    String tomcatEtcDir = "com/google/gwt/dev/etc/tomcat/";
    Map<String, Resource> resourceMap = null;
    Throwable caught = null;
    try {
      resourceMap = getResourcesFor(logger, tomcatEtcDir);
    } catch (URISyntaxException e) {
      caught = e;
    } catch (IOException e) {
      caught = e;
    }

    File catBase = new File(workDir, "tomcat");
    if (resourceMap == null || resourceMap.isEmpty()) {
      logger.log(TreeLogger.WARN, "Could not find " + tomcatEtcDir, caught);
    } else {
      for (Entry<String, Resource> entry : resourceMap.entrySet()) {
        copyFileNoOverwrite(logger, entry.getKey(), entry.getValue(), catBase);
      }
    }

    return catBase.getAbsolutePath();
  }

  /**
   * Hacky, but fast.
   */
  private Map<String, Resource> getResourcesFor(TreeLogger logger,
      String tomcatEtcDir) throws URISyntaxException, IOException {
    ClassLoader contextClassLoader = this.getClass().getClassLoader();
    URL url = contextClassLoader.getResource(tomcatEtcDir);
    if (url == null) {
      return null;
    }
    String prefix = "";
    String urlString = url.toString();
    if (urlString.startsWith("jar:")) {
      assert urlString.toLowerCase(Locale.ENGLISH).contains(".jar!/"
          + tomcatEtcDir);
      urlString = urlString.substring(4, urlString.indexOf('!'));
      url = new URL(urlString);
      prefix = tomcatEtcDir;
    } else if (urlString.startsWith("zip:")) {
      assert urlString.toLowerCase(Locale.ENGLISH).contains(".zip!/"
          + tomcatEtcDir);
      urlString = urlString.substring(4, urlString.indexOf('!'));
      url = new URL(urlString);
      prefix = tomcatEtcDir;
    }
    ClassPathEntry entry = ResourceOracleImpl.createEntryForUrl(logger, url);
    assert (entry != null);
    ResourceOracleImpl resourceOracle = new ResourceOracleImpl(
        Collections.singletonList(entry));
    PathPrefixSet pathPrefixSet = new PathPrefixSet();
    PathPrefix pathPrefix = new PathPrefix(prefix, null, true);
    pathPrefixSet.add(pathPrefix);
    resourceOracle.setPathPrefixes(pathPrefixSet);
    ResourceOracleImpl.refresh(logger, resourceOracle);
    Map<String, Resource> resourceMap = resourceOracle.getResourceMap();
    return resourceMap;
  }

  private void publishAttributeToWebApp(TreeLogger logger,
      StandardContext webapp, String attrName, Object attrValue) {
    logger.log(TreeLogger.TRACE, "Adding attribute  '" + attrName
        + "' to web app '" + webapp.getName() + "'", null);
    webapp.getServletContext().setAttribute(attrName, attrValue);
  }

  /**
   * Publish the shell's tree logger as an attribute. This attribute is used to
   * find the logger out of the thin air within the shell servlet.
   */
  private void publishShellLoggerAttribute(TreeLogger logger,
      TreeLogger loggerToPublish, StandardContext webapp) {
    final String attr = "com.google.gwt.dev.shell.logger";
    publishAttributeToWebApp(logger, webapp, attr, loggerToPublish);
  }

  /**
   * Publish the shell's work dir as an attribute. This attribute is used to
   * find it out of the thin air within the shell servlet.
   */
  private void publishShellWorkDirsAttribute(TreeLogger logger,
      WorkDirs workDirs, StandardContext webapp) {
    final String attr = "com.google.gwt.dev.shell.workdirs";
    publishAttributeToWebApp(logger, webapp, attr, workDirs);
  }

  /**
   * Publish to the web app whether it should automatically generate resources.
   */
  private void publishShouldAutoGenerateResourcesAttribute(TreeLogger logger,
      boolean shouldAutoGenerateResources, StandardContext webapp) {
    publishAttributeToWebApp(logger, webapp,
        "com.google.gwt.dev.shell.shouldAutoGenerateResources",
        shouldAutoGenerateResources);
  }
}
