// 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.nio.charset.StandardCharsets.UTF_8;
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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
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";

  private static ClassLoader daemonClassLoader;

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

  /**
   * Invokes a proram.
   *
   * <p>Creates a new classloader to load and run the program class. To reuse a classloader across
   * calls (e.g. from tests), use {@link #invokeProgram(ClassLoader, String[])}.
   *
   * @param argv arguments, as would be passed to {@code gerrit.war}. The first argument is the
   *     program name.
   * @return program return code.
   * @throws Exception if any error occurs.
   */
  public static int mainImpl(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("  passwd          Set or change password in secure.config");

      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(isProlog(programClassName(argv[0])));
    Thread.currentThread().setContextClassLoader(cl);
    return invokeProgram(cl, argv);
  }

  public static void daemonStart(String[] argv) throws Exception {
    if (daemonClassLoader != null) {
      throw new IllegalStateException("daemonStart can be called only once per JVM instance");
    }
    final ClassLoader cl = libClassLoader(false);
    Thread.currentThread().setContextClassLoader(cl);

    daemonClassLoader = cl;

    String[] daemonArgv = new String[argv.length + 1];
    daemonArgv[0] = "daemon";
    for (int i = 0; i < argv.length; i++) {
      daemonArgv[i + 1] = argv[i];
    }
    int res = invokeProgram(cl, daemonArgv);
    if (res != 0) {
      throw new Exception("Unexpected return value: " + res);
    }
  }

  public static void daemonStop(String[] argv) throws Exception {
    if (daemonClassLoader == null) {
      throw new IllegalStateException("daemonStop can be called only after call to daemonStop");
    }
    String[] daemonArgv = new String[argv.length + 2];
    daemonArgv[0] = "daemon";
    daemonArgv[1] = "--stop-only";
    for (int i = 0; i < argv.length; i++) {
      daemonArgv[i + 2] = argv[i];
    }
    int res = invokeProgram(daemonClassLoader, daemonArgv);
    if (res != 0) {
      throw new Exception("Unexpected return value: " + res);
    }
  }

  private static boolean isProlog(String cn) {
    return "PrologShell".equals(cn) || "Rulec".equals(cn);
  }

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

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

  /**
   * Invokes a proram in the provided {@code ClassLoader}.
   *
   * @param loader classloader to load program class from.
   * @param origArgv arguments, as would be passed to {@code gerrit.war}. The first argument is the
   *     program name.
   * @return program return code.
   * @throws Exception if any error occurs.
   */
  public static int invokeProgram(ClassLoader loader, 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 = programClassName(name);
        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.getConstructor(new Class<?>[] {}).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();
    }
    return 0;
  }

  private static String programClassName(String cn) {
    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));
        }
      }
      return buf.toString();
    }
    return cn;
  }

  private static ClassLoader libClassLoader(boolean prologCompiler) 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<>();
    try (ZipFile zf = new ZipFile(path)) {
      final Enumeration<? extends ZipEntry> e = zf.entries();
      while (e.hasMoreElements()) {
        final ZipEntry ze = e.nextElement();
        if (ze.isDirectory()) {
          continue;
        }

        String name = ze.getName();
        if (name.startsWith("WEB-INF/lib/")) {
          extractJar(zf, ze, jars);
        } else if (name.startsWith("WEB-INF/pgm-lib/")) {
          // Some Prolog tools are restricted.
          if (prologCompiler || !name.startsWith("WEB-INF/pgm-lib/prolog-")) {
            extractJar(zf, ze, jars);
          }
        }
      }
    } 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<>();
    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 = URLClassLoader.newInstance(extapi.toArray(new URL[extapi.size()]), parent);
    }
    return URLClassLoader.newInstance(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");
    try (OutputStream out = Files.newOutputStream(tmp.toPath());
        InputStream in = zf.getInputStream(ze)) {
      byte[] buf = new byte[4096];
      int n;
      while ((n = in.read(buf, 0, buf.length)) > 0) {
        out.write(buf, 0, n);
      }
    }

    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(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 static volatile File myArchive;
  private static volatile File myHome;

  private static final Map<Path, FileSystem> zipFileSystems = new HashMap<>();

  /**
   * 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, IOException {
    File result = myArchive;
    if (result == null) {
      synchronized (GerritLauncher.class) {
        result = myArchive;
        if (result != null) {
          return result;
        }
        result = locateMyArchive();
        myArchive = result;
      }
    }
    return result;
  }

  public static synchronized FileSystem getZipFileSystem(Path zip) throws IOException {
    // FileSystems canonicalizes the path, so we should too.
    zip = zip.toRealPath();
    FileSystem zipFs = zipFileSystems.get(zip);
    if (zipFs == null) {
      zipFs = newZipFileSystem(zip);
      zipFileSystems.put(zip, zipFs);
    }
    return zipFs;
  }

  public static FileSystem newZipFileSystem(Path zip) throws IOException {
    return FileSystems.newFileSystem(
        URI.create("jar:" + zip.toUri()), Collections.<String, String>emptyMap());
  }

  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 (InputStream in = src.getLocation().openStream()) {
        final File tmp = createTempFile("gerrit_", ".zip");
        try (OutputStream out = Files.newOutputStream(tmp.toPath())) {
          final byte[] buf = new byte[4096];
          int n;
          while ((n = in.read(buf, 0, buf.length)) > 0) {
            out.write(buf, 0, n);
          }
        }
        return tmp;
      } 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 (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;
    }
  }

  /**
   * Check whether the process is running in Eclipse.
   *
   * <p>Unlike {@link #getDeveloperEclipseOut()}, this method checks the actual runtime stack, not
   * the classpath.
   *
   * @return true if any thread has a stack frame in {@code org.eclipse.jdt}.
   */
  public static boolean isRunningInEclipse() {
    return Thread.getAllStackTraces()
        .values()
        .stream()
        .flatMap(Arrays::stream)
        .anyMatch(e -> e.getClassName().startsWith("org.eclipse.jdt."));
  }

  /**
   * Locate the path of the {@code eclipse-out} directory in a source tree.
   *
   * <p>Unlike {@link #isRunningInEclipse()}, this method only inspects files relative to the
   * classpath, not the runtime stack.
   *
   * @return local path of the {@code eclipse-out} directory in a source tree.
   * @throws FileNotFoundException if the directory cannot be found.
   */
  public static Path getDeveloperEclipseOut() throws FileNotFoundException {
    return resolveInSourceRoot("eclipse-out");
  }

  public static boolean isJdk9OrLater() {
    return Double.parseDouble(System.getProperty("java.class.version")) >= 53.0;
  }

  public static String getJdkVersionPostJdk8() {
    // 9.0.4 => 9
    return System.getProperty("java.version").substring(0, 1);
  }

  public static Properties loadBuildProperties(Path propPath) throws IOException {
    Properties properties = new Properties();
    try (InputStream in = Files.newInputStream(propPath)) {
      properties.load(in);
    } catch (NoSuchFileException e) {
      // Ignore; will be run from PATH, with a descriptive error if it fails.
    }
    return properties;
  }

  static final String SOURCE_ROOT_RESOURCE = "/com/google/gerrit/launcher/workspace-root.txt";

  /**
   * Locate a path in the source tree.
   *
   * @return local path of the {@code name} directory in a source tree.
   * @throws FileNotFoundException if the directory cannot be found.
   */
  public static Path resolveInSourceRoot(String name) throws FileNotFoundException {

    // Find ourselves in the classpath, as a loose class file or jar.
    Class<GerritLauncher> self = GerritLauncher.class;

    // If the build system provides us with a source root, use that.
    try (InputStream stream = self.getResourceAsStream(SOURCE_ROOT_RESOURCE)) {
      if (stream != null) {
        try (Scanner scan = new Scanner(stream, UTF_8.name()).useDelimiter("\n")) {
          if (scan.hasNext()) {
            Path p = Paths.get(scan.next());
            if (!Files.exists(p)) {
              throw new FileNotFoundException("source root not found: " + p);
            }
            return p;
          }
        }
      }
    } catch (IOException e) {
      // not Bazel, then.
    }

    URL u = self.getResource(self.getSimpleName() + ".class");
    if (u == null) {
      throw new FileNotFoundException("Cannot find class " + self.getName());
    } else if ("jar".equals(u.getProtocol())) {
      String p = u.getPath();
      try {
        u = new URL(p.substring(0, p.indexOf('!')));
      } catch (MalformedURLException e) {
        FileNotFoundException fnfe = new FileNotFoundException("Not a valid jar file: " + u);
        fnfe.initCause(e);
        throw fnfe;
      }
    }
    if (!"file".equals(u.getProtocol())) {
      throw new FileNotFoundException("Cannot extract path from " + u);
    }

    // Pop up to the top-level source folder by looking for .buckconfig.
    Path dir = Paths.get(u.getPath());
    while (!Files.isRegularFile(dir.resolve("WORKSPACE"))) {
      Path parent = dir.getParent();
      if (parent == null) {
        throw new FileNotFoundException("Cannot find source root from " + u);
      }
      dir = parent;
    }

    Path ret = dir.resolve(name);
    if (!Files.exists(ret)) {
      throw new FileNotFoundException(name + " not found in source root " + dir);
    }
    return ret;
  }

  private static ClassLoader useDevClasspath() throws IOException {
    Path out = getDeveloperEclipseOut();
    List<URL> dirs = new ArrayList<>();
    dirs.add(out.resolve("classes").toUri().toURL());
    ClassLoader cl = GerritLauncher.class.getClassLoader();

    if (isJdk9OrLater()) {
      Path rootPath = resolveInSourceRoot(".").normalize();

      Properties properties = loadBuildProperties(rootPath.resolve(".bazel_path"));
      Path outputBase = Paths.get(properties.getProperty("output_base"));

      Path runtimeClasspath =
          rootPath.resolve("bazel-bin/tools/eclipse/main_classpath_collect.runtime_classpath");
      for (String f : Files.readAllLines(runtimeClasspath, UTF_8)) {
        URL url;
        if (f.startsWith("external")) {
          url = outputBase.resolve(f).toUri().toURL();
        } else {
          url = rootPath.resolve(f).toUri().toURL();
        }
        if (includeJar(url)) {
          dirs.add(url);
        }
      }
    } else {
      for (URL u : ((URLClassLoader) cl).getURLs()) {
        if (includeJar(u)) {
          dirs.add(u);
        }
      }
    }
    return URLClassLoader.newInstance(
        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("/com/google/gerrit");
  }

  private GerritLauncher() {}
}
