Path: blob/master/test/langtools/tools/lib/toolbox/JavadocTask.java
41149 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package toolbox;2425import java.io.File;26import java.io.IOException;27import java.io.PrintWriter;28import java.nio.file.Path;29import java.nio.file.Paths;30import java.util.ArrayList;31import java.util.Arrays;32import java.util.Collections;33import java.util.HashMap;34import java.util.List;35import java.util.Map;36import java.util.stream.Collectors;37import java.util.stream.Stream;3839import javax.tools.DocumentationTool.DocumentationTask;40import javax.tools.DocumentationTool;41import javax.tools.JavaFileManager;42import javax.tools.JavaFileManager.Location;43import javax.tools.JavaFileObject;44import javax.tools.StandardJavaFileManager;45import javax.tools.StandardLocation;46import javax.tools.ToolProvider;4748import jdk.javadoc.internal.api.JavadocTool;4950/**51* A task to configure and run the documentation tool, javadoc.52*/53public class JavadocTask extends AbstractTask<JavadocTask> {54private boolean includeStandardOptions;55private List<Path> classpath;56private List<Path> sourcepath;57private Path outdir;58private List<String> options;59private List<String> classes;60private List<String> files;61private List<JavaFileObject> fileObjects;62private JavaFileManager fileManager;6364private JavadocTool jdtool;65private StandardJavaFileManager internalFileManager;66private Class<?> docletClass = null; // use the standard doclet by default6768/**69* Creates a task to execute {@code javadoc} using API mode.70* @param toolBox the {@code ToolBox} to use71*/72public JavadocTask(ToolBox toolBox) {73super(toolBox, Task.Mode.API);74}7576/**77* Creates a task to execute {@code javadoc} in a specified mode.78* @param toolBox the {@code ToolBox} to use79* @param mode the mode to be used80*/81public JavadocTask(ToolBox toolBox, Task.Mode mode) {82super(toolBox, mode);83}8485/**86* Sets the classpath.87* @param classpath the classpath88* @return this task object89*/90public JavadocTask classpath(String classpath) {91this.classpath = Stream.of(classpath.split(File.pathSeparator))92.filter(s -> !s.isEmpty())93.map(s -> Paths.get(s))94.collect(Collectors.toList());95return this;96}9798/**99* Sets the classpath.100* @param classpath the classpath101* @return this task object102*/103public JavadocTask classpath(Path... classpath) {104this.classpath = Arrays.asList(classpath);105return this;106}107108/**109* Sets the classpath.110* @param classpath the classpath111* @return this task object112*/113public JavadocTask classpath(List<Path> classpath) {114this.classpath = classpath;115return this;116}117118/**119* Sets the sourcepath.120* @param sourcepath the sourcepath121* @return this task object122*/123public JavadocTask sourcepath(String sourcepath) {124this.sourcepath = Stream.of(sourcepath.split(File.pathSeparator))125.filter(s -> !s.isEmpty())126.map(s -> Paths.get(s))127.collect(Collectors.toList());128return this;129}130131/**132* Sets the sourcepath.133* @param sourcepath the sourcepath134* @return this task object135*/136public JavadocTask sourcepath(Path... sourcepath) {137this.sourcepath = Arrays.asList(sourcepath);138return this;139}140141/**142* Sets the sourcepath.143* @param sourcepath the sourcepath144* @return this task object145*/146public JavadocTask sourcepath(List<Path> sourcepath) {147this.sourcepath = sourcepath;148return this;149}150151/**152* Sets the output directory.153* @param outdir the output directory154* @return this task object155*/156public JavadocTask outdir(String outdir) {157this.outdir = Paths.get(outdir);158return this;159}160161/**162* Sets the output directory.163* @param outdir the output directory164* @return this task object165*/166public JavadocTask outdir(Path outdir) {167this.outdir = outdir;168return this;169}170171/**172* Sets the options.173* @param options the options174* @return this task object175*/176public JavadocTask options(String... options) {177this.options = Arrays.asList(options);178return this;179}180181/**182* Sets the options.183* @param options the options184* @return this task object185*/186public JavadocTask options(List<String> options) {187this.options = options;188return this;189}190191/**192* Sets the files to be documented.193* @param files the files194* @return this task object195*/196public JavadocTask files(String... files) {197this.files = Arrays.asList(files);198return this;199}200201/**202* Sets the files to be documented.203* @param files the files204* @return this task object205*/206public JavadocTask files(Path... files) {207this.files = Stream.of(files)208.map(Path::toString)209.collect(Collectors.toList());210return this;211}212213/**214* Sets the files to be documented.215* @param files the files216* @return this task object217*/218public JavadocTask files(List<Path> files) {219this.files = files.stream()220.map(Path::toString)221.collect(Collectors.toList());222return this;223}224225/**226* Sets the sources to be documented.227* Each source string is converted into an in-memory object that228* can be passed directly to the tool.229* @param sources the sources230* @return this task object231*/232public JavadocTask sources(String... sources) {233fileObjects = Stream.of(sources)234.map(s -> new ToolBox.JavaSource(s))235.collect(Collectors.toList());236return this;237}238239/**240* Sets the file manager to be used by this task.241* @param fileManager the file manager242* @return this task object243*/244public JavadocTask fileManager(JavaFileManager fileManager) {245this.fileManager = fileManager;246return this;247}248249/**250* Sets the doclet class to be invoked by javadoc.251* Note: this is applicable only in API mode.252* @param docletClass the user specified doclet253* @return this task object254*/255public JavadocTask docletClass(Class<?> docletClass) {256this.docletClass = docletClass;257return this;258}259260/**261* {@inheritDoc}262* @return the name "javadoc"263*/264@Override265public String name() {266return "javadoc";267}268269/**270* Calls the javadoc tool with the arguments as currently configured.271* @return a Result object indicating the outcome of the execution272* and the content of any output written to stdout, stderr, or the273* main stream by the tool.274*/275@Override276public Task.Result run() {277if (mode == Task.Mode.EXEC)278return runExec();279280AbstractTask.WriterOutput direct = new AbstractTask.WriterOutput();281// The following are to catch output to System.out and System.err,282// in case these are used instead of the primary (main) stream283AbstractTask.StreamOutput sysOut = new AbstractTask.StreamOutput(System.out, System::setOut);284AbstractTask.StreamOutput sysErr = new AbstractTask.StreamOutput(System.err, System::setErr);285int rc;286Map<Task.OutputKind, String> outputMap = new HashMap<>();287try {288switch (mode == null ? Task.Mode.API : mode) {289case API:290rc = runAPI(direct.pw);291break;292case CMDLINE:293rc = runCommand(direct.pw);294break;295default:296throw new IllegalStateException();297}298} catch (IOException e) {299toolBox.out.println("Exception occurred: " + e);300rc = 99;301} finally {302outputMap.put(Task.OutputKind.STDOUT, sysOut.close());303outputMap.put(Task.OutputKind.STDERR, sysErr.close());304outputMap.put(Task.OutputKind.DIRECT, direct.close());305}306return checkExit(new Task.Result(toolBox, this, rc, outputMap));307}308309private int runAPI(PrintWriter pw) throws IOException {310try {311jdtool = (JavadocTool) ToolProvider.getSystemDocumentationTool();312jdtool = new JavadocTool();313314if (fileManager == null)315fileManager = internalFileManager = jdtool.getStandardFileManager(null, null, null);316if (outdir != null)317setLocationFromPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT,318Collections.singletonList(outdir));319if (classpath != null)320setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);321if (sourcepath != null)322setLocationFromPaths(StandardLocation.SOURCE_PATH, sourcepath);323List<String> allOpts = new ArrayList<>();324if (options != null)325allOpts.addAll(options);326327Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);328DocumentationTask task = jdtool.getTask(pw,329fileManager,330null, // diagnostic listener; should optionally collect diags331docletClass,332allOpts,333allFiles);334return ((DocumentationTask) task).call() ? 0 : 1;335} finally {336if (internalFileManager != null)337internalFileManager.close();338}339}340341private void setLocationFromPaths(Location location, List<Path> files) throws IOException {342if (!(fileManager instanceof StandardJavaFileManager))343throw new IllegalStateException("not a StandardJavaFileManager");344((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);345}346347private int runCommand(PrintWriter pw) {348List<String> args = getAllArgs();349String[] argsArray = args.toArray(new String[args.size()]);350return jdk.javadoc.internal.tool.Main.execute(argsArray, pw);351}352353private Task.Result runExec() {354List<String> args = new ArrayList<>();355Path javadoc = toolBox.getJDKTool("javadoc");356args.add(javadoc.toString());357if (includeStandardOptions) {358args.addAll(toolBox.split(System.getProperty("test.tool.vm.opts"), " +"));359}360args.addAll(getAllArgs());361362String[] argsArray = args.toArray(new String[args.size()]);363ProcessBuilder pb = getProcessBuilder();364pb.command(argsArray);365try {366return runProcess(toolBox, this, pb.start());367} catch (IOException | InterruptedException e) {368throw new Error(e);369}370}371372private List<String> getAllArgs() {373List<String> args = new ArrayList<>();374if (options != null)375args.addAll(options);376if (outdir != null) {377args.add("-d");378args.add(outdir.toString());379}380if (classpath != null) {381args.add("-classpath");382args.add(toSearchPath(classpath));383}384if (sourcepath != null) {385args.add("-sourcepath");386args.add(toSearchPath(sourcepath));387}388if (classes != null)389args.addAll(classes);390if (files != null)391args.addAll(files);392393return args;394}395396private String toSearchPath(List<Path> files) {397return files.stream()398.map(Path::toString)399.collect(Collectors.joining(File.pathSeparator));400}401402private Iterable<? extends JavaFileObject> joinFiles(403List<String> files, List<JavaFileObject> fileObjects) {404if (files == null)405return fileObjects;406if (internalFileManager == null)407internalFileManager = jdtool.getStandardFileManager(null, null, null);408Iterable<? extends JavaFileObject> filesAsFileObjects =409internalFileManager.getJavaFileObjectsFromStrings(files);410if (fileObjects == null)411return filesAsFileObjects;412List<JavaFileObject> combinedList = new ArrayList<>();413for (JavaFileObject o : filesAsFileObjects)414combinedList.add(o);415combinedList.addAll(fileObjects);416return combinedList;417}418}419420421