001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2015 ForgeRock AS.
025 */
026package org.forgerock.opendj.maven.doc;
027
028import static org.forgerock.opendj.maven.doc.Utils.*;
029
030import org.apache.maven.plugin.AbstractMojo;
031import org.apache.maven.plugin.MojoExecutionException;
032import org.apache.maven.plugin.MojoFailureException;
033import org.apache.maven.plugins.annotations.LifecyclePhase;
034import org.apache.maven.plugins.annotations.Mojo;
035import org.apache.maven.plugins.annotations.Parameter;
036import org.apache.maven.project.MavenProject;
037
038import java.io.File;
039import java.io.IOException;
040import java.io.InputStream;
041import java.util.LinkedList;
042import java.util.List;
043
044/**
045 * Generates the configuration reference, a set of HTML documents describing the server configuration.
046 */
047@Mojo(name = "generate-config-ref", defaultPhase = LifecyclePhase.PRE_SITE)
048public class GenerateConfigurationReferenceMojo extends AbstractMojo {
049    /**
050     * The Maven Project.
051     */
052    @Parameter(property = "project", readonly = true, required = true)
053    private MavenProject project;
054
055    /**
056     * The path to the directory where the configuration reference should be written.
057     * This path must be under {@code ${project.build.directory} }.
058     */
059    @Parameter(defaultValue = "${project.build.directory}/site/configref")
060    private String outputDirectory;
061
062    /**
063     * Generates the configuration reference under the output directory.
064     * @throws MojoExecutionException   Generation failed
065     * @throws MojoFailureException     Not used
066     */
067    @Override
068    public void execute() throws MojoExecutionException, MojoFailureException {
069        createOutputDirectory();
070        generateConfigRef();
071        try {
072            copyResources();
073        } catch (IOException e) {
074            throw new MojoExecutionException("Failed to copy resource files.", e);
075        }
076    }
077
078    /**
079     * Creates the output directory where the configuration reference is written.
080     * @throws MojoExecutionException   The output directory is not under {@code ${project.build.directory} }
081     *                                  or could not be created.
082     */
083    private void createOutputDirectory() throws MojoExecutionException {
084        String projectBuildDir = project.getBuild().getDirectory();
085
086        if (!outputDirectory.contains(projectBuildDir)) {
087            String errorMsg = String.format(
088                    "The outputDirectory (%s) must be under the ${project.build.directory} (%s).",
089                    outputDirectory,
090                    projectBuildDir);
091            getLog().error(errorMsg);
092            throw new MojoExecutionException(errorMsg);
093        }
094
095        try {
096            createDirectory(outputDirectory);
097        } catch (IOException e) {
098            getLog().error(e.getMessage());
099            throw new MojoExecutionException(e.getMessage(), e);
100        }
101    }
102
103    /**
104     * Runs the configuration reference generator class.
105     * @throws MojoExecutionException   Failed to run the generator
106     */
107    private void generateConfigRef() throws MojoExecutionException {
108        String generatorClass = "org.opends.server.admin.doc.ConfigGuideGeneration";
109        List<String> commands = new LinkedList<>();
110        try {
111            commands.add(getJavaCommand());
112            commands.add("-classpath");
113            commands.add(getClassPath(getRuntimeClassLoader(project, getLog())));
114            commands.add("-DGenerationDir=" + outputDirectory);
115            commands.add(generatorClass);
116        } catch (Exception e) {
117            throw new MojoExecutionException("Failed to set the classpath.", e);
118        }
119
120        try {
121            ProcessBuilder builder = new ProcessBuilder(commands);
122            Process process = builder.start();
123            process.waitFor();
124            final int result = process.exitValue();
125            if (result != 0) {
126                final StringBuilder message = new StringBuilder();
127                message.append("Failed to generate the config ref. Exit code: ").append(result).append(EOL)
128                        .append("To debug the problem, run the following command and connect your IDE:").append(EOL);
129                commands.add(1, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000");
130                for (String arg: commands) {
131                    message.append(arg).append(' ');
132                }
133                message.append(EOL);
134                throw new MojoExecutionException(message.toString());
135            }
136        }  catch (InterruptedException e) {
137            throw new MojoExecutionException(generatorClass + " interrupted", e);
138        } catch (IOException e) {
139            throw new MojoExecutionException(generatorClass + " not found", e);
140        }
141    }
142
143    /** List of static file resources needed by the configuration reference. */
144    private static String[] resourceFiles = {
145        "duration-syntax.html",
146        "opendj-config.css",
147        "opendj_logo_sm.png",
148        "pageaction.gif",
149        "tab_deselected.jpg",
150        "tab_selected.gif"
151    };
152
153    /**
154     * Copies static files needed by the configuration reference.
155     * @throws IOException  Failed to read a resource or to write a file
156     */
157    private void copyResources() throws IOException {
158        for (String file : resourceFiles) {
159            InputStream original = this.getClass().getResourceAsStream("/config-ref/" + file);
160            File copy = new File(outputDirectory, file);
161            copyInputStreamToFile(original, copy);
162        }
163    }
164}