From 8a81bad1a27eb157108f63c6cc5d313a13b17be0 Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Fri, 27 Mar 2015 14:14:51 +0000
Subject: [PATCH] CR-6483 OPENDJ-1786 Automate integration of generated content
---
opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateRefEntriesMojo.java | 221 ++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 145 insertions(+), 76 deletions(-)
diff --git a/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateRefEntriesMojo.java b/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateRefEntriesMojo.java
index 1b5be78..fbd3c56 100644
--- a/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateRefEntriesMojo.java
+++ b/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateRefEntriesMojo.java
@@ -35,18 +35,20 @@
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
-import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
/**
* Generate DocBook RefEntry source documents for command-line tools man pages.
@@ -67,9 +69,6 @@
@Parameter(required = true)
private File outputDir;
- /** End of line. */
- public static final String EOL = System.getProperty("line.separator");
-
/**
* Writes a RefEntry file to the output directory for each tool.
* Files names correspond to script names: {@code man-<name>.xml}.
@@ -80,17 +79,29 @@
*/
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
- PrintStream out = System.out;
-
- // Set the magic property for generating DocBook XML.
- System.setProperty("org.forgerock.opendj.gendoc", "true");
-
// A Maven plugin classpath does not include project files.
// Prepare a ClassLoader capable of loading the command-line tools.
+ URLClassLoader toolsClassLoader = getBootToolsClassLoader();
+
+ if (!isOutputDirAvailable()) {
+ throw new MojoFailureException("Output directory " + outputDir.getPath() + " not available");
+ }
+
+ for (CommandLineTool tool : tools) {
+ generateManPageForTool(toolsClassLoader, tool);
+ }
+ }
+
+ /**
+ * Returns a ClassLoader capable of loading the command-line tools.
+ * @return A ClassLoader capable of loading the command-line tools.
+ * @throws MojoFailureException Failed to build classpath.
+ */
+ private URLClassLoader getBootToolsClassLoader() throws MojoFailureException {
URLClassLoader toolsClassLoader;
try {
List<String> runtimeClasspathElements = project.getRuntimeClasspathElements();
- List<URL> runtimeUrls = new LinkedList<URL>();
+ Set<URL> runtimeUrls = new LinkedHashSet<URL>();
for (String element : runtimeClasspathElements) {
runtimeUrls.add(new File(element).toURI().toURL());
}
@@ -103,53 +114,99 @@
throw new MojoFailureException("Failed to add element to classpath.", e);
}
debugClassPathElements(toolsClassLoader);
+ return toolsClassLoader;
+ }
- List<String> failures = new LinkedList<String>();
- for (CommandLineTool tool : tools) {
- final File manPage = new File(outputDir, "man-" + tool.getName() + ".xml");
- try {
- setSystemOut(refEntryFile(manPage.getPath()));
- } catch (FileNotFoundException e) {
- setSystemOut(out);
- failures.add(manPage.getPath());
- throw new MojoExecutionException("Failed to write " + manPage.getPath(), e);
+ /**
+ * Generate a RefEntry file to the output directory for a tool.
+ * The files name corresponds to the tool name: {@code man-<name>.xml}.
+ * @param toolsClassLoader The ClassLoader to run the tool.
+ * @param tool The tool to run in order to generate the page.
+ * @throws MojoExecutionException Failed to run the tool.
+ * @throws MojoFailureException Tool did not exit successfully.
+ */
+ private void generateManPageForTool(final URLClassLoader toolsClassLoader, final CommandLineTool tool)
+ throws MojoExecutionException, MojoFailureException {
+ final File manPage = new File(outputDir, "man-" + tool.getName() + ".xml");
+ final String toolScript = tool.getName();
+ final String toolSects = pathsToXIncludes(tool.getTrailingSectionPaths());
+ final String toolClass = tool.getApplication();
+ List<String> commands = new LinkedList<String>();
+ commands.add(getJavaCommand());
+ commands.addAll(getJavaArgs(toolScript, toolSects));
+ commands.add("-classpath");
+ commands.add(getClassPath(toolsClassLoader));
+ commands.add(toolClass);
+ commands.add(getUsageArgument(toolScript));
+ getLog().info("Writing man page: " + manPage.getPath());
+ try {
+ // Tools tend to use System.exit() so run them as separate processes.
+ ProcessBuilder builder = new ProcessBuilder(commands);
+ Process process = builder.start();
+ writeToFile(process.getInputStream(), manPage);
+ process.waitFor();
+ final int result = process.exitValue();
+ if (result != 0) {
+ throw new MojoFailureException("Failed to write page. Tool exit code: " + result);
}
+ } catch (InterruptedException e) {
+ throw new MojoExecutionException(toolClass + " interrupted", e);
+ } catch (IOException e) {
+ throw new MojoExecutionException(toolClass + " not found", e);
+ }
+ }
- // Set the properties for script name and list of trailing sections.
- System.setProperty("com.forgerock.opendj.ldap.tools.scriptName", tool.getName());
- final String xInclude = pathsToXIncludes(tool.getTrailingSectionPaths());
- System.setProperty("org.forgerock.opendj.gendoc.trailing", xInclude);
+ /**
+ * Returns true if the output directory is available.
+ * Attempts to create the directory if it does not exist.
+ * @return True if the output directory is available.
+ */
+ private boolean isOutputDirAvailable() {
+ return outputDir != null && (outputDir.exists() && outputDir.isDirectory() || outputDir.mkdirs());
+ }
+ /**
+ * Returns the path to the current Java executable.
+ * @return The path to the current Java executable.
+ */
+ private String getJavaCommand() {
+ return System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
+ }
+
+ /**
+ * Returns the Java args for running a tool.
+ * @param scriptName The name of the tool.
+ * @param trailingSections The man page sections to Xinclude.
+ * @return The Java args for running a tool.
+ */
+ private List<String> getJavaArgs(final String scriptName, final String trailingSections) {
+ List<String> args = new LinkedList<String>();
+ args.add("-Dorg.forgerock.opendj.gendoc=true");
+ args.add("-Dorg.opends.server.ServerRoot=" + System.getProperty("java.io.tmpdir"));
+ args.add("-Dcom.forgerock.opendj.ldap.tools.scriptName=" + scriptName);
+ args.add("-Dorg.forgerock.opendj.gendoc.trailing=" + trailingSections + "");
+ return args;
+ }
+
+ /**
+ * Returns the classpath for the class loader.
+ * @param classLoader Contains the URLs of the class path to return.
+ * @return The classpath for the class loader.
+ */
+ private String getClassPath(final URLClassLoader classLoader) {
+ final StringBuilder stringBuilder = new StringBuilder();
+ final URL[] urls = classLoader.getURLs();
+ for (int i = 0; i < urls.length; i++) {
+ if (i > 0) {
+ stringBuilder.append(File.pathSeparator);
+ }
try {
- final Class<?> toolClass = toolsClassLoader.loadClass(tool.getApplication());
- final Class[] argTypes = new Class[]{String[].class};
- final Method main = toolClass.getDeclaredMethod("main", argTypes);
- final String[] args = {"-?"};
- main.invoke(null, (Object) args);
- } catch (ClassNotFoundException e) {
- failures.add(manPage.getPath());
- throw new MojoExecutionException(tool.getApplication() + " not found", e);
- } catch (NoSuchMethodException e) {
- failures.add(manPage.getPath());
- throw new MojoExecutionException(tool.getApplication() + " has no main method.", e);
- } catch (IllegalAccessException e) {
- failures.add(manPage.getPath());
- throw new MojoExecutionException("Failed to run " + tool.getApplication() + ".main()", e);
- } catch (InvocationTargetException e) {
- failures.add(manPage.getPath());
- throw new MojoExecutionException("Failed to run " + tool.getApplication() + ".main()", e);
- } finally {
- setSystemOut(out);
+ stringBuilder.append(new File(urls[i].toURI()).getPath());
+ } catch (URISyntaxException e) {
+ getLog().info("Failed to add classpath element", e);
}
}
-
- final StringBuilder list = new StringBuilder();
- if (!failures.isEmpty()) {
- for (final String failure : failures) {
- list.append(failure).append(EOL);
- }
- throw new MojoFailureException("Failed to write the following RefEntry files: " + list);
- }
+ return stringBuilder.toString();
}
/**
@@ -173,26 +230,6 @@
}
/**
- * Returns a PrintStream to a file to which to write a RefEntry.
- * @param path Path to the file to be written.
- * @return PrintStream to a file to which to write a RefEntry.
- * @throws FileNotFoundException Failed to open the file for writing.
- */
- private PrintStream refEntryFile(final String path) throws FileNotFoundException {
- return new PrintStream(new BufferedOutputStream(new FileOutputStream(path)), true);
- }
-
- /**
- * Sets the System output stream.
- * @param out The stream to use.
- */
- private void setSystemOut(PrintStream out) {
- if (out != null) {
- System.setOut(out);
- }
- }
-
- /**
* Translates relative paths to XML files into XInclude elements.
*
* @param paths Paths to XInclude'd files, relative to the RefEntry.
@@ -208,8 +245,40 @@
final String nameSpace = "xinclude";
final StringBuilder result = new StringBuilder();
for (String path : paths) {
- result.append("<").append(nameSpace).append(":include href=\"").append(path).append("\" />").append(EOL);
+ result.append("<").append(nameSpace).append(":include href='").append(path).append("' />");
}
return result.toString();
}
+
+ /**
+ * Returns the usage argument.
+ * @param scriptName The name of the tool.
+ * @return The usage argument.
+ */
+ private String getUsageArgument(final String scriptName) {
+ return scriptName.equals("dsjavaproperties") ? "-H" : "-?";
+ }
+
+ /**
+ * Write the content of the input stream to the output file.
+ * @param input The input stream to write.
+ * @param output The file to write it to.
+ * @throws IOException Failed to write the content of the input stream.
+ */
+ private void writeToFile(final InputStream input, final File output) throws IOException {
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(output);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ writer.write(line);
+ writer.write(System.getProperty("line.separator"));
+ }
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
}
--
Gitblit v1.10.0