// Copyright (C) 2009 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.google.gerrit.launcher;

import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/** Main class for a JAR file to run code from "WEB-INF/lib". */
public final class GerritLauncher {
  private static final String pkg = "com.google.gerrit.pgm";
  public static final String NOT_ARCHIVED = "NOT_ARCHIVED";

  public static void main(final String argv[]) throws Exception {
    System.exit(mainImpl(argv));
  }

  public static int mainImpl(final String argv[]) throws Exception {
    if (argv.length == 0) {
      File me;
      try {
        me = getDistributionArchive();
      } catch (FileNotFoundException e) {
        me = null;
      }

      String jar = me != null ? me.getName() : "gerrit.war";
      System.err.println("Gerrit Code Review " + getVersion(me));
      System.err.println("usage: java -jar " + jar + " command [ARG ...]");
      System.err.println();
      System.err.println("The most commonly used commands are:");
      System.err.println("  init           Initialize a Gerrit installation");
      System.err.println("  reindex        Rebuild the secondary index");
      System.err.println("  daemon         Run the Gerrit network daemons");
      System.err.println("  gsql           Run the interactive query console");
      System.err.println("  version        Display the build version number");
      System.err.println();
      System.err.println("  ls             List files available for cat");
      System.err.println("  cat FILE       Display a file from the archive");
      System.err.println();
      return 1;
    }

    // Special cases, a few global options actually are programs.
    //
    if ("-v".equals(argv[0]) || "--version".equals(argv[0])) {
      argv[0] = "version";
    } else if ("-p".equals(argv[0]) || "--cat".equals(argv[0])) {
      argv[0] = "cat";
    } else if ("-l".equals(argv[0]) || "--ls".equals(argv[0])) {
      argv[0] = "ls";
    }

    // Run the application class
    //
    final ClassLoader cl = libClassLoader();
    Thread.currentThread().setContextClassLoader(cl);
    return invokeProgram(cl, argv);
  }

  private static String getVersion(final File me) {
    if (me == null) {
      return "";
    }

    try {
      final JarFile jar = new JarFile(me);
      try {
        Manifest mf = jar.getManifest();
        Attributes att = mf.getMainAttributes();
        String val = att.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
        return val != null ? val : "";
      } finally {
        jar.close();
      }
    } catch (IOException e) {
      return "";
    }
  }

  private static int invokeProgram(final ClassLoader loader,
      final String[] origArgv) throws Exception {
    String name = origArgv[0];
    final String[] argv = new String[origArgv.length - 1];
    System.arraycopy(origArgv, 1, argv, 0, argv.length);

    Class<?> clazz;
    try {
      try {
        String cn = name;
        if (cn.equals(cn.toLowerCase())) {
          StringBuilder buf = new StringBuilder();
          buf.append(Character.toUpperCase(cn.charAt(0)));
          for (int i = 1; i < cn.length(); i++) {
            if (cn.charAt(i) == '-' && i + 1 < cn.length()) {
              i++;
              buf.append(Character.toUpperCase(cn.charAt(i)));
            } else {
              buf.append(cn.charAt(i));
            }
          }
          cn = buf.toString();
        }
        clazz = Class.forName(pkg + "." + cn, true, loader);
      } catch (ClassNotFoundException cnfe) {
        if (name.equals(name.toLowerCase())) {
          clazz = Class.forName(pkg + "." + name, true, loader);
        } else {
          throw cnfe;
        }
      }
    } catch (ClassNotFoundException cnfe) {
      System.err.println("fatal: unknown command " + name);
      System.err.println("      (no " + pkg + "." + name + ")");
      return 1;
    }

    final Method main;
    try {
      main = clazz.getMethod("main", argv.getClass());
    } catch (SecurityException | NoSuchMethodException e) {
      System.err.println("fatal: unknown command " + name);
      return 1;
    }

    final Object res;
    try {
      if ((main.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
        res = main.invoke(null, new Object[] {argv});
      } else {
        res = main.invoke(clazz.newInstance(), new Object[] {argv});
      }
    } catch (InvocationTargetException ite) {
      if (ite.getCause() instanceof Exception) {
        throw (Exception) ite.getCause();
      } else if (ite.getCause() instanceof Error) {
        throw (Error) ite.getCause();
      } else {
        throw ite;
      }
    }
    if (res instanceof Number) {
      return ((Number) res).intValue();
    } else {
      return 0;
    }
  }

  private static ClassLoader libClassLoader() throws IOException {
    final File path;
    try {
      path = getDistributionArchive();
    } catch (FileNotFoundException e) {
      if (NOT_ARCHIVED.equals(e.getMessage())) {
        return useDevClasspath();
      }
      throw e;
    }

    final SortedMap<String, URL> jars = new TreeMap<String, URL>();
    try {
      final ZipFile zf = new ZipFile(path);
      try {
        final Enumeration<? extends ZipEntry> e = zf.entries();
        while (e.hasMoreElements()) {
          final ZipEntry ze = e.nextElement();
          if (ze.isDirectory()) {
            continue;
          } else if (ze.getName().startsWith("WEB-INF/lib/")) {
            extractJar(zf, ze, jars);
          } else if (ze.getName().startsWith("WEB-INF/pgm-lib/")) {
            extractJar(zf, ze, jars);
          }
        }
      } finally {
        zf.close();
      }
    } catch (IOException e) {
      throw new IOException("Cannot obtain libraries from " + path, e);
    }

    if (jars.isEmpty()) {
      return GerritLauncher.class.getClassLoader();
    }

    // The extension API needs to be its own ClassLoader, along
    // with a few of its dependencies. Try to construct this first.
    List<URL> extapi = new ArrayList<URL>();
    move(jars, "gerrit-extension-api-", extapi);
    move(jars, "guice-", extapi);
    move(jars, "javax.inject-1.jar", extapi);
    move(jars, "aopalliance-1.0.jar", extapi);
    move(jars, "guice-servlet-", extapi);
    move(jars, "tomcat-servlet-api-", extapi);

    ClassLoader parent = ClassLoader.getSystemClassLoader();
    if (!extapi.isEmpty()) {
      parent = new URLClassLoader(
          extapi.toArray(new URL[extapi.size()]),
          parent);
    }
    return new URLClassLoader(
        jars.values().toArray(new URL[jars.size()]),
        parent);
  }

  private static void extractJar(ZipFile zf, ZipEntry ze,
      SortedMap<String, URL> jars) throws IOException {
    File tmp = createTempFile(safeName(ze), ".jar");
    FileOutputStream out = new FileOutputStream(tmp);
    try {
      InputStream in = zf.getInputStream(ze);
      try {
        byte[] buf = new byte[4096];
        int n;
        while ((n = in.read(buf, 0, buf.length)) > 0) {
          out.write(buf, 0, n);
        }
      } finally {
        in.close();
      }
    } finally {
      out.close();
    }

    String name = ze.getName();
    jars.put(
        name.substring(name.lastIndexOf('/'), name.length()),
        tmp.toURI().toURL());
  }

  private static void move(SortedMap<String, URL> jars,
      String prefix,
      List<URL> extapi) {
    SortedMap<String, URL> matches = jars.tailMap(prefix);
    if (!matches.isEmpty()) {
      String first = matches.firstKey();
      if (first.startsWith(prefix)) {
        extapi.add(jars.remove(first));
      }
    }
  }

  private static String safeName(final ZipEntry ze) {
    // Try to derive the name of the temporary file so it
    // doesn't completely suck. Best if we can make it
    // match the name it was in the archive.
    //
    String name = ze.getName();
    if (name.contains("/")) {
      name = name.substring(name.lastIndexOf('/') + 1);
    }
    if (name.contains(".")) {
      name = name.substring(0, name.lastIndexOf('.'));
    }
    if (name.isEmpty()) {
      name = "code";
    }
    return name;
  }

  private volatile static File myArchive;
  private volatile static File myHome;

  /**
   * Locate the JAR/WAR file we were launched from.
   *
   * @return local path of the Gerrit WAR file.
   * @throws FileNotFoundException if the code cannot guess the location.
   */
  public static File getDistributionArchive() throws FileNotFoundException {
    if (myArchive == null) {
      myArchive = locateMyArchive();
    }
    return myArchive;
  }

  private static File locateMyArchive() throws FileNotFoundException {
    final ClassLoader myCL = GerritLauncher.class.getClassLoader();
    final String myName =
        GerritLauncher.class.getName().replace('.', '/') + ".class";

    final URL myClazz = myCL.getResource(myName);
    if (myClazz == null) {
      throw new FileNotFoundException("Cannot find JAR: no " + myName);
    }

    // ZipFile may have the path of our JAR hiding within itself.
    //
    try {
      JarFile jar = ((JarURLConnection) myClazz.openConnection()).getJarFile();
      File path = new File(jar.getName());
      if (path.isFile()) {
        return path;
      }
    } catch (Exception e) {
      // Nope, that didn't work. Try a different method.
      //
    }

    // Maybe this is a local class file, running under a debugger?
    //
    if ("file".equals(myClazz.getProtocol())) {
      final File path = new File(myClazz.getPath());
      if (path.isFile() && path.getParentFile().isDirectory()) {
        throw new FileNotFoundException(NOT_ARCHIVED);
      }
    }

    // The CodeSource might be able to give us the source as a stream.
    // If so, copy it to a local file so we have random access to it.
    //
    final CodeSource src =
        GerritLauncher.class.getProtectionDomain().getCodeSource();
    if (src != null) {
      try {
        final InputStream in = src.getLocation().openStream();
        try {
          final File tmp = createTempFile("gerrit_", ".zip");
          final FileOutputStream out = new FileOutputStream(tmp);
          try {
            final byte[] buf = new byte[4096];
            int n;
            while ((n = in.read(buf, 0, buf.length)) > 0) {
              out.write(buf, 0, n);
            }
          } finally {
            out.close();
          }
          return tmp;
        } finally {
          in.close();
        }
      } catch (IOException e) {
        // Nope, that didn't work.
        //
      }
    }

    throw new FileNotFoundException("Cannot find local copy of JAR");
  }

  private static boolean temporaryDirectoryFound;
  private static File temporaryDirectory;

  /**
   * Creates a temporary file within the application's unpack location.
   * <p>
   * The launcher unpacks the nested JAR files into a temporary directory,
   * allowing the classes to be loaded from local disk with standard Java APIs.
   * This method constructs a new temporary file in the same directory.
   * <p>
   * The method first tries to create {@code prefix + suffix} within the
   * directory under the assumption that a given {@code prefix + suffix}
   * combination is made at most once per JVM execution. If this fails (e.g. the
   * named file already exists) a mangled unique name is used and returned
   * instead, with the unique string appearing between the prefix and suffix.
   * <p>
   * Files created by this method will be automatically deleted by the JVM when
   * it terminates. If the returned file is converted into a directory by the
   * caller, the caller must arrange for the contents to be deleted before the
   * directory is.
   * <p>
   * If supported by the underlying operating system, the temporary directory
   * which contains these temporary files is accessible only by the user running
   * the JVM.
   *
   * @param prefix prefix of the file name.
   * @param suffix suffix of the file name.
   * @return the path of the temporary file. The returned object exists in the
   *         filesystem as a file; caller may need to delete and recreate as a
   *         directory if a directory was preferred.
   * @throws IOException the file could not be created.
   */
  public static synchronized File createTempFile(String prefix, String suffix)
      throws IOException {
    if (!temporaryDirectoryFound) {
      final File d = File.createTempFile("gerrit_", "_app", tmproot());
      if (d.delete() && d.mkdir()) {
        // Try to lock the directory down to be accessible by us.
        // We first have to remove all permissions, then add back
        // only the owner permissions.
        //
        d.setWritable(false, false /* all */);
        d.setReadable(false, false /* all */);
        d.setExecutable(false, false /* all */);

        d.setWritable(true, true /* owner only */);
        d.setReadable(true, true /* owner only */);
        d.setExecutable(true, true /* owner only */);

        d.deleteOnExit();
        temporaryDirectory = d;
      }
      temporaryDirectoryFound = true;
    }

    if (temporaryDirectory != null) {
      // If we have a private directory and this name has not yet
      // been used within the private directory, create it as-is.
      //
      final File tmp = new File(temporaryDirectory, prefix + suffix);
      if (tmp.createNewFile()) {
        tmp.deleteOnExit();
        return tmp;
      }
    }

    if (!prefix.endsWith("_")) {
      prefix += "_";
    }

    final File tmp = File.createTempFile(prefix, suffix, temporaryDirectory);
    tmp.deleteOnExit();
    return tmp;
  }

  /**
   * Provide path to a working directory
   *
   * @return local path of the working directory or null if cannot be determined
   */
  public static File getHomeDirectory() {
    if (myHome == null) {
      myHome = locateHomeDirectory();
    }
    return myHome;
  }


  private static File tmproot() {
    File tmp;
    String gerritTemp = System.getenv("GERRIT_TMP");
    if (gerritTemp != null && gerritTemp.length() > 0) {
      tmp = new File(gerritTemp);
    } else {
      tmp = new File(getHomeDirectory(), "tmp");
    }
    if (!tmp.exists() && !tmp.mkdirs()) {
      System.err.println("warning: cannot create " + tmp.getAbsolutePath());
      System.err.println("warning: using system temporary directory instead");
      return null;
    }

    // Try to clean up any stale empty directories. Assume any empty
    // directory that is older than 7 days is one of these dead ones
    // that we can clean up.
    //
    final File[] tmpEntries = tmp.listFiles();
    if (tmpEntries != null) {
      final long now = System.currentTimeMillis();
      final long expired = now - MILLISECONDS.convert(7, DAYS);
      for (final File tmpEntry : tmpEntries) {
        if (tmpEntry.isDirectory() && tmpEntry.lastModified() < expired) {
          final String[] all = tmpEntry.list();
          if (all == null || all.length == 0) {
            tmpEntry.delete();
          }
        }
      }
    }

    try {
      return tmp.getCanonicalFile();
    } catch (IOException e) {
      return tmp;
    }
  }

  private static File locateHomeDirectory() {
    // Try to find the user's home directory. If we can't find it
    // return null so the JVM's default temporary directory is used
    // instead. This is probably /tmp or /var/tmp.
    //
    String userHome = System.getProperty("user.home");
    if (userHome == null || "".equals(userHome)) {
      userHome = System.getenv("HOME");
      if (userHome == null || "".equals(userHome)) {
        System.err.println("warning: cannot determine home directory");
        System.err.println("warning: using system temporary directory instead");
        return null;
      }
    }

    // Ensure the home directory exists. If it doesn't, try to make it.
    //
    final File home = new File(userHome);
    if (!home.exists()) {
      if (home.mkdirs()) {
        System.err.println("warning: created " + home.getAbsolutePath());
      } else {
        System.err.println("warning: " + home.getAbsolutePath() + " not found");
        System.err.println("warning: using system temporary directory instead");
        return null;
      }
    }

    // Use $HOME/.gerritcodereview/tmp for our temporary file area.
    //
    final File gerrithome = new File(home, ".gerritcodereview");
    if (!gerrithome.exists() && !gerrithome.mkdirs()) {
      System.err.println("warning: cannot create " + gerrithome.getAbsolutePath());
      System.err.println("warning: using system temporary directory instead");
      return null;
    }
    try {
      return gerrithome.getCanonicalFile();
    } catch (IOException e) {
      return gerrithome;
    }
  }

  /**
   * Locate the path of the {@code buck-out} directory in a source tree.
   *
   * @throws FileNotFoundException if the directory cannot be found.
   */
  public static File getDeveloperBuckOut() throws FileNotFoundException {
    // Find ourselves in the CLASSPATH, we should be a loose class file.
    Class<GerritLauncher> self = GerritLauncher.class;
    URL u = self.getResource(self.getSimpleName() + ".class");
    if (u == null) {
      throw new FileNotFoundException("Cannot find class " + self.getName());
    } else if (!"file".equals(u.getProtocol())) {
      throw new FileNotFoundException("Cannot find extract path from " + u);
    }

    // Pop up to the top level classes folder that contains us.
    File dir = new File(u.getPath());
    String myName = self.getName();
    for (;;) {
      int dot = myName.lastIndexOf('.');
      if (dot < 0) {
        dir = dir.getParentFile();
        break;
      }
      myName = myName.substring(0, dot);
      dir = dir.getParentFile();
    }

    dir = popdir(u, dir, "classes");
    dir = popdir(u, dir, "eclipse");
    if ("buck-out".equals(dir.getName())) {
      return dir;
    }
    throw new FileNotFoundException("Cannot find buck-out from " + u);
  }

  private static File popdir(URL u, File dir, String name)
      throws FileNotFoundException {
    if (dir.getName().equals(name)) {
      return dir.getParentFile();
    }
    throw new FileNotFoundException("Cannot find buck-out from " + u);
  }

  private static ClassLoader useDevClasspath()
      throws MalformedURLException, FileNotFoundException {
    File out = getDeveloperBuckOut();
    List<URL> dirs = new ArrayList<URL>();
    dirs.add(new File(new File(out, "eclipse"), "classes").toURI().toURL());
    ClassLoader cl = GerritLauncher.class.getClassLoader();
    for (URL u : ((URLClassLoader) cl).getURLs()) {
      if (includeJar(u)) {
        dirs.add(u);
      }
    }
    return new URLClassLoader(
        dirs.toArray(new URL[dirs.size()]),
        ClassLoader.getSystemClassLoader().getParent());
  }

  private static boolean includeJar(URL u) {
    String path = u.getPath();
    return path.endsWith(".jar")
        && !path.endsWith("-src.jar")
        && !path.contains("/buck-out/gen/lib/gwt/");
  }

  private GerritLauncher() {
  }
}
