// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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.

import static java.util.Comparator.comparing;

import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.util.Context;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;

/**
 * Output a jar file containing all classes on the platform classpath of the given JDK release.
 *
 * <p>usage: DumpPlatformClassPath <release version> <output jar>
 */
public class DumpPlatformClassPath {

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.err.println("usage: DumpPlatformClassPath <release version> <output jar>");
      System.exit(1);
    }
    int release = Integer.parseInt(args[0]);
    Path output = Paths.get(args[1]);

    Map<String, byte[]> entries = new HashMap<>();

    // Legacy JDK 8 bootclasspath handling.
    // TODO(cushon): make sure this has test coverage.
    Path javaHome = Paths.get(System.getProperty("java.home"));
    if (javaHome.endsWith("jre")) {
      javaHome = javaHome.getParent();
    }
    for (String jar :
        Arrays.asList("rt.jar", "resources.jar", "jsse.jar", "jce.jar", "charsets.jar")) {
      Path path = javaHome.resolve("jre/lib").resolve(jar);
      if (!Files.exists(path)) {
        continue;
      }
      try (JarFile jf = new JarFile(path.toFile())) {
        jf.stream()
            .forEachOrdered(
                entry -> {
                  try {
                    entries.put(entry.getName(), toByteArray(jf.getInputStream(entry)));
                  } catch (IOException e) {
                    throw new UncheckedIOException(e);
                  }
                });
      }
    }

    if (!entries.isEmpty()) {
      // If we found a JDK 8 bootclasspath (rt.jar, etc.) then we're done.
      //
      // However JDK 8 only contains bootclasspath API information for the current release,
      // so we're always going to get a JDK 8 API level regardless of what the user requested.
      // Emit a warning if they wanted to target a different version.
      if (release != 8) {
        System.err.printf(
            "warning: ignoring release %s on --host_javabase=%s\n",
            release, System.getProperty("java.version"));
      }
    } else {
      // JDK > 8 --host_javabase bootclasspath handling.
      // The default --host_javabase is currently JDK 10.

      // Set up a compilation with --release to initialize a filemanager
      Context context = new Context();
      JavacTool.create()
          .getTask(
              /* out = */ null,
              /* fileManager = */ null,
              /* diagnosticListener = */ null,
              /* options = */ Arrays.asList("--release", String.valueOf(release)),
              /* classes = */ null,
              /* compilationUnits = */ null,
              context);
      JavaFileManager fileManager = context.get(JavaFileManager.class);

      for (JavaFileObject fileObject :
          fileManager.list(
              StandardLocation.PLATFORM_CLASS_PATH,
              "",
              EnumSet.of(Kind.CLASS),
              /* recurse= */ true)) {
        String binaryName =
            fileManager.inferBinaryName(StandardLocation.PLATFORM_CLASS_PATH, fileObject);
        entries.put(
            binaryName.replace('.', '/') + ".class", toByteArray(fileObject.openInputStream()));
      }

      // Include the jdk.unsupported module for compatibility with JDK 8.
      // (see: https://bugs.openjdk.java.net/browse/JDK-8206937)
      // `--release 8` only provides access to supported APIs, which excludes e.g. sun.misc.Unsafe.
      Path module =
          FileSystems.getFileSystem(URI.create("jrt:/")).getPath("modules/jdk.unsupported");
      Files.walkFileTree(
          module,
          new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes attrs)
                throws IOException {
              String name = path.getFileName().toString();
              if (name.endsWith(".class") && !name.equals("module-info.class")) {
                entries.put(module.relativize(path).toString(), Files.readAllBytes(path));
              }
              return super.visitFile(path, attrs);
            }
          });
    }

    try (OutputStream os = Files.newOutputStream(output);
        BufferedOutputStream bos = new BufferedOutputStream(os, 65536);
        JarOutputStream jos = new JarOutputStream(bos)) {
      entries.entrySet().stream()
          .sorted(comparing(Map.Entry::getKey))
          .forEachOrdered(
              entry -> {
                try {
                  addEntry(jos, entry.getKey(), entry.getValue());
                } catch (IOException e) {
                  throw new UncheckedIOException(e);
                }
              });
    }
  }

  // Use a fixed timestamp for deterministic jar output.
  private static final long FIXED_TIMESTAMP =
      new GregorianCalendar(2010, 0, 1, 0, 0, 0).getTimeInMillis();

  private static void addEntry(JarOutputStream jos, String name, byte[] bytes) throws IOException {
    JarEntry je = new JarEntry(name);
    je.setTime(FIXED_TIMESTAMP);
    je.setMethod(ZipEntry.STORED);
    je.setSize(bytes.length);
    CRC32 crc = new CRC32();
    crc.update(bytes);
    je.setCrc(crc.getValue());
    jos.putNextEntry(je);
    jos.write(bytes);
  }

  private static byte[] toByteArray(InputStream is) throws IOException {
    byte[] buffer = new byte[8192];
    ByteArrayOutputStream boas = new ByteArrayOutputStream();
    while (true) {
      int r = is.read(buffer);
      if (r == -1) {
        break;
      }
      boas.write(buffer, 0, r);
    }
    return boas.toByteArray();
  }
}
