// 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));
  }

  private 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() {
  }
}
