Path: blob/trunk/java/src/dev/selenium/tools/javadoc/JavadocJarMaker.java
1865 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617package dev.selenium.tools.javadoc;1819import static java.nio.charset.StandardCharsets.UTF_8;2021import com.github.bazelbuild.rules_jvm_external.zip.StableZipEntry;22import java.io.File;23import java.io.IOException;24import java.io.InputStream;25import java.io.OutputStream;26import java.io.StringWriter;27import java.io.UncheckedIOException;28import java.io.Writer;29import java.nio.file.Files;30import java.nio.file.Path;31import java.nio.file.Paths;32import java.util.ArrayList;33import java.util.Comparator;34import java.util.HashSet;35import java.util.List;36import java.util.Locale;37import java.util.Set;38import java.util.stream.Collectors;39import java.util.stream.Stream;40import java.util.zip.ZipEntry;41import java.util.zip.ZipInputStream;42import java.util.zip.ZipOutputStream;43import javax.tools.DocumentationTool;44import javax.tools.JavaFileObject;45import javax.tools.StandardJavaFileManager;46import javax.tools.StandardLocation;47import javax.tools.ToolProvider;48import org.openqa.selenium.io.TemporaryFilesystem;4950public class JavadocJarMaker {5152public static void main(String[] args) throws IOException {53Set<Path> sourceJars = new HashSet<>();54Path out = null;55Set<Path> classpath = new HashSet<>();5657int argCount = args.length;58for (int i = 0; i < argCount; i++) {59String flag = args[i];60String next = args[++i];6162switch (flag) {63case "--cp":64classpath.add(Paths.get(next));65break;6667case "--in":68sourceJars.add(Paths.get(next));69break;7071case "--out":72out = Paths.get(next);73break;74}75}7677if (sourceJars.isEmpty()) {78throw new IllegalArgumentException(79"At least one input just must be specified via the --in flag");80}8182if (out == null) {83throw new IllegalArgumentException(84"The output jar location must be specified via the --out flag");85}8687TemporaryFilesystem tmpFS = TemporaryFilesystem.getDefaultTmpFS();88Set<File> tempDirs = new HashSet<>();89File dir = tmpFS.createTempDir("javadocs", "");90tempDirs.add(dir);9192DocumentationTool tool = ToolProvider.getSystemDocumentationTool();93try (StandardJavaFileManager fileManager =94tool.getStandardFileManager(null, Locale.getDefault(), UTF_8)) {95fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, List.of(dir));96fileManager.setLocation(97StandardLocation.CLASS_PATH,98classpath.stream().map(Path::toFile).collect(Collectors.toSet()));99100Set<JavaFileObject> sources = new HashSet<>();101Set<String> topLevelPackages = new HashSet<>();102103File unpackTo = tmpFS.createTempDir("unpacked-sources", "");104tempDirs.add(unpackTo);105Set<String> fileNames = new HashSet<>();106readSourceFiles(107unpackTo.toPath(), fileManager, sourceJars, sources, topLevelPackages, fileNames);108109// True if we're just exporting a set of modules110if (sources.isEmpty()) {111try (OutputStream os = Files.newOutputStream(out);112ZipOutputStream zos = new ZipOutputStream(os)) {113// It's enough to just create the thing114}115return;116}117118List<String> options = new ArrayList<>();119if (!classpath.isEmpty()) {120options.add("-cp");121options.add(122classpath.stream()123.map(String::valueOf)124.collect(Collectors.joining(File.pathSeparator)));125}126options.addAll(127List.of(128"-html5",129"--frames",130"-notimestamp",131"-use",132"-quiet",133"-Xdoclint:-missing",134"-encoding",135"UTF8"));136137File outputTo = tmpFS.createTempDir("output-dir", "");138tempDirs.add(outputTo);139Path outputToPath = outputTo.toPath();140141options.addAll(List.of("-d", outputTo.getAbsolutePath()));142143sources.forEach(obj -> options.add(obj.getName()));144145Writer writer = new StringWriter();146DocumentationTool.DocumentationTask task =147tool.getTask(writer, fileManager, null, null, options, sources);148Boolean result = task.call();149if (result == null || !result) {150System.err.println("javadoc " + String.join(" ", options));151System.err.println(writer);152return;153}154155try (OutputStream os = Files.newOutputStream(out);156ZipOutputStream zos = new ZipOutputStream(os);157Stream<Path> walk = Files.walk(outputToPath)) {158walk.sorted(Comparator.naturalOrder())159.forEachOrdered(160path -> {161if (path.equals(outputToPath)) {162return;163}164165try {166if (Files.isDirectory(path)) {167String name = outputToPath.relativize(path) + "/";168ZipEntry entry = new StableZipEntry(name);169zos.putNextEntry(entry);170zos.closeEntry();171} else {172String name = outputToPath.relativize(path).toString();173ZipEntry entry = new StableZipEntry(name);174zos.putNextEntry(entry);175try (InputStream is = Files.newInputStream(path)) {176is.transferTo(zos);177}178zos.closeEntry();179}180} catch (IOException e) {181throw new UncheckedIOException(e);182}183});184}185}186187tempDirs.forEach(tmpFS::deleteTempDir);188}189190private static void readSourceFiles(191Path unpackTo,192StandardJavaFileManager fileManager,193Set<Path> sourceJars,194Set<JavaFileObject> sources,195Set<String> topLevelPackages,196Set<String> fileNames)197throws IOException {198199for (Path jar : sourceJars) {200if (!Files.exists(jar)) {201continue;202}203204try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(jar))) {205for (ZipEntry entry = zis.getNextEntry(); entry != null; entry = zis.getNextEntry()) {206String name = entry.getName();207if (!name.endsWith(".java")) {208continue;209}210211Path target = unpackTo.resolve(name).normalize();212if (!target.startsWith(unpackTo)) {213throw new IOException("Attempt to write out of working directory");214}215216Files.createDirectories(target.getParent());217try (OutputStream out = Files.newOutputStream(target)) {218zis.transferTo(out);219}220221fileManager.getJavaFileObjects(target).forEach(sources::add);222223String[] segments = name.split("/");224if (segments.length > 0 && !"META-INF".equals(segments[0])) {225topLevelPackages.add(segments[0]);226}227228fileNames.add(name);229}230}231}232}233}234235236