| /******************************************************************************* |
| * Copyright (c) 2013, 2015 IBH SYSTEMS GmbH and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBH SYSTEMS GmbH - initial API and implementation |
| * Obeo - Fix bug #440546 |
| *******************************************************************************/ |
| package org.eclipse.tycho.extras.docbundle; |
| |
| import java.io.File; |
| import java.io.PrintStream; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Set; |
| |
| import org.apache.commons.exec.OS; |
| import org.apache.maven.execution.MavenSession; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.logging.Log; |
| import org.apache.maven.toolchain.Toolchain; |
| import org.apache.maven.toolchain.ToolchainManager; |
| import org.codehaus.plexus.util.cli.CommandLineUtils; |
| import org.codehaus.plexus.util.cli.Commandline; |
| import org.codehaus.plexus.util.cli.DefaultConsumer; |
| import org.eclipse.osgi.util.ManifestElement; |
| import org.eclipse.tycho.core.osgitools.BundleReader; |
| import org.eclipse.tycho.core.osgitools.OsgiManifest; |
| |
| public class JavadocRunner { |
| private File output; |
| |
| private ToolchainManager toolchainManager; |
| |
| private MavenSession session; |
| |
| private Set<File> sourceFolders = Collections.<File> emptySet(); |
| |
| private Set<File> manifestFiles = Collections.<File> emptySet(); |
| |
| private Log log; |
| |
| private JavadocOptions options; |
| |
| private File buildDirectory; |
| |
| private BundleReader bundleReader; |
| |
| private Collection<String> classPath = Collections.<String> emptyList(); |
| |
| private String lineSeparator = System.getProperty("line.separator"); |
| |
| private DocletArtifactsResolver docletArtifactsResolver; |
| |
| private PackageNameMatcher includeMatcher; |
| |
| private PackageNameMatcher excludeMatcher; |
| |
| public JavadocRunner() { |
| } |
| |
| public void setBundleReader(final BundleReader bundleReader) { |
| this.bundleReader = bundleReader; |
| } |
| |
| public void setBuildDirectory(final File buildDirectory) { |
| this.buildDirectory = buildDirectory; |
| } |
| |
| public void setOptions(final JavadocOptions options) { |
| this.options = options; |
| if (this.options == null) { |
| this.options = new JavadocOptions(); |
| } |
| } |
| |
| public void setLog(final Log log) { |
| this.log = log; |
| } |
| |
| public void setSession(final MavenSession session) { |
| this.session = session; |
| } |
| |
| public void setOutput(final File output) { |
| this.output = output; |
| } |
| |
| public void run() throws Exception { |
| this.output.mkdirs(); |
| this.buildDirectory.mkdirs(); |
| |
| final File optionsFile = new File(this.buildDirectory, "javadoc.options.txt"); |
| final Commandline cli = createCommandLine(optionsFile.getAbsolutePath()); |
| |
| try (PrintStream ps = new PrintStream(optionsFile)) { |
| ps.print(createOptionsFileContent()); |
| ps.close(); |
| |
| this.log.info("Calling: " + cli); |
| final int rc = CommandLineUtils.executeCommandLine(cli, new DefaultConsumer(), new DefaultConsumer()); |
| if (rc != 0) { |
| if (!this.options.isIgnoreError()) { |
| throw new MojoExecutionException("Failed to execute javadoc - rc = " + rc); |
| } else { |
| this.log.info("execution failed with rc = " + rc); |
| } |
| } |
| } |
| } |
| |
| /* VisibleForTesting */Commandline createCommandLine(String optionsFileAbsolutePath) { |
| Commandline cli = new Commandline(); |
| cli.setExecutable(getExecutable()); |
| cli.setWorkingDirectory(this.output); |
| cli.createArg().setValue("@" + optionsFileAbsolutePath); |
| addJvmArgs(cli); |
| return cli; |
| } |
| |
| /* VisibleForTesting */String createOptionsFileContent() throws Exception { |
| |
| // initialize include/exclude filters |
| if (options != null) { |
| if (!options.getIncludes().isEmpty()) { |
| includeMatcher = PackageNameMatcher.compile(options.getIncludes()); |
| this.log.info("Including packages matching " + includeMatcher); |
| } |
| if (!options.getExcludes().isEmpty()) { |
| excludeMatcher = PackageNameMatcher.compile(options.getExcludes()); |
| this.log.info("Excluding packages matching " + excludeMatcher); |
| } |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| addSourcePaths(sb); |
| addClassPath(sb); |
| addDoclet(sb); |
| addDocletPaths(sb); |
| addEncoding(sb); |
| addArguments(sb); |
| |
| final int count = addPackages(sb); |
| if (count <= 0) { |
| this.log.warn("No packages found"); |
| } |
| |
| return sb.toString(); |
| } |
| |
| private void addEncoding(final StringBuilder sb) { |
| if (this.options.getEncoding() != null) { |
| sb.append("-encoding ").append(this.options.getEncoding()).append(lineSeparator); |
| } |
| } |
| |
| private void addDoclet(final StringBuilder sb) { |
| if (this.options.getDoclet() == null) { |
| return; |
| } |
| sb.append("-doclet ").append(this.options.getDoclet()).append(lineSeparator); |
| } |
| |
| private void addDocletPaths(final StringBuilder sb) throws MojoExecutionException { |
| Set<String> resolvedArtifactJars = docletArtifactsResolver.resolveArtifacts(this.options.getDocletArtifacts()); |
| addPathArgument(sb, "-docletpath", resolvedArtifactJars); |
| } |
| |
| private void addClassPath(final StringBuilder sb) { |
| addPathArgument(sb, "-classpath", this.classPath); |
| } |
| |
| private void addArguments(final StringBuilder sb) { |
| for (final String argument : this.options.getAdditionalArguments()) { |
| sb.append(argument).append(lineSeparator); |
| } |
| } |
| |
| private void addJvmArgs(final Commandline cli) { |
| |
| for (final String arg : this.options.getJvmOptions()) { |
| cli.createArg().setValue("-J" + arg); |
| } |
| } |
| |
| private int addPackages(final StringBuilder sb) throws Exception { |
| int count = 0; |
| |
| for (final File manifestFile : this.manifestFiles) { |
| if (!manifestFile.canRead()) { |
| this.log.debug("No readable manifest: " + manifestFile); |
| continue; |
| } |
| |
| final OsgiManifest bundle = this.bundleReader.loadManifest(manifestFile); |
| count += addPackages(sb, bundle.getManifestElements("Export-Package")); |
| } |
| return count; |
| } |
| |
| private int addPackages(final StringBuilder sb, final ManifestElement[] manifestElements) { |
| if (manifestElements == null) { |
| return 0; |
| } |
| |
| for (final ManifestElement ele : manifestElements) { |
| final String pkg = ele.getValue(); |
| |
| final boolean include = includeMatcher != null ? includeMatcher.matches(pkg) : true; |
| final boolean exclude = excludeMatcher != null ? excludeMatcher.matches(pkg) : false; |
| |
| if (include && !exclude) { |
| sb.append(pkg).append(lineSeparator); |
| } |
| } |
| |
| return manifestElements.length; |
| } |
| |
| private void addPath(final StringBuilder sb, final Collection<?> path) { |
| boolean first = true; |
| for (final Object ele : path) { |
| if (ele == null) { |
| continue; |
| } |
| // convert black slashes to forward slashes for javadoc |
| final String pathEle = ele.toString().replace('\\', '/'); |
| if (!first) { |
| sb.append(File.pathSeparator); |
| } else { |
| first = false; |
| } |
| sb.append(pathEle); |
| } |
| } |
| |
| private void addSourcePaths(final StringBuilder sb) { |
| addPathArgument(sb, "-sourcepath", this.sourceFolders); |
| } |
| |
| private void addPathArgument(final StringBuilder sb, final String arg, final Collection<?> path) { |
| if (path.isEmpty()) { |
| return; |
| } |
| sb.append(arg); |
| sb.append(" '"); |
| addPath(sb, path); |
| sb.append("'" + lineSeparator); |
| } |
| |
| protected String getExecutable() { |
| log.debug("Find javadoc executable"); |
| |
| if (this.options.getExecutable() != null) { |
| // prefer the specific one |
| log.debug("Using specified javadoc: " + options.getExecutable()); |
| return this.options.getExecutable(); |
| } |
| |
| log.debug("Toolchain manager: " + toolchainManager); |
| |
| if (this.toolchainManager != null) { |
| // try the toolchain |
| final Toolchain tc = this.toolchainManager.getToolchainFromBuildContext("jdk", this.session); |
| log.debug("Toolchain: " + tc); |
| |
| if (tc != null) { |
| final String exe = tc.findTool("javadoc"); |
| log.debug("Toolchain Tool: " + exe); |
| if (exe != null) { |
| return exe; |
| } |
| } |
| } |
| |
| String javaHome = System.getProperty("java.home"); |
| String javadocFromJavaHome; |
| |
| // derive path to javac from java.home similar to org.codehaus.plexus.compiler.javac.JavacCompiler.getJavacExecutable() in plexus-compiler-javac |
| if (OS.isFamilyMac()) { |
| javadocFromJavaHome = javaHome + File.separator + "bin" + File.separator + "javadoc"; |
| } else { |
| javadocFromJavaHome = javaHome + File.separator + ".." + File.separator + "bin" + File.separator |
| + "javadoc"; |
| } |
| |
| if (OS.isFamilyWindows()) { |
| javadocFromJavaHome += ".exe"; |
| } |
| |
| log.debug("Testing javadoc from java.home = " + javadocFromJavaHome); |
| |
| if (new File(javadocFromJavaHome).canExecute()) { |
| return javadocFromJavaHome; |
| } |
| |
| log.debug("Using path fallback"); |
| |
| // fall back |
| return "javadoc"; |
| } |
| |
| public void setToolchainManager(final ToolchainManager toolchainManager) { |
| this.toolchainManager = toolchainManager; |
| } |
| |
| public void setSourceFolders(final Set<File> sourceFolders) { |
| this.sourceFolders = sourceFolders; |
| } |
| |
| public void setClassPath(final Collection<String> classPath) { |
| this.classPath = classPath; |
| } |
| |
| public void setManifestFiles(Set<File> manifestFiles) { |
| this.manifestFiles = manifestFiles; |
| } |
| |
| public void setDocletArtifactsResolver(DocletArtifactsResolver docletArtifactsResolver) { |
| this.docletArtifactsResolver = docletArtifactsResolver; |
| } |
| } |