mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Mark Craig
29.53.2015 82213581b317d297f66ce52b4925f6b1963cf3d5
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ResultCode.java
@@ -196,9 +196,6 @@
    private static final Map<Integer, ResultCode> ELEMENTS = new LinkedHashMap<>();
    private static final List<ResultCode> IMMUTABLE_ELEMENTS = Collections.unmodifiableList(new ArrayList<ResultCode>(
            ELEMENTS.values()));
    /**
     * The result code that should only be used if the actual result code has
     * not yet been determined.
@@ -867,6 +864,9 @@
        return result;
    }
    private static final List<ResultCode> IMMUTABLE_ELEMENTS = Collections.unmodifiableList(new ArrayList<ResultCode>(
            ELEMENTS.values()));
    /**
     * Returns an unmodifiable list containing the set of available result codes
     * indexed on their integer value as defined in RFC 4511 section 4.1.9.
opendj-sdk/opendj-doc-maven-plugin/pom.xml
@@ -66,6 +66,11 @@
      <version>2.2.0</version>
    </dependency>
    <dependency>
      <groupId>com.thoughtworks.qdox</groupId>
      <artifactId>qdox</artifactId>
      <version>2.0-M3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.plugin-tools</groupId>
      <artifactId>maven-plugin-annotations</artifactId>
      <version>3.2</version>
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateResultCodeDocMojo.java
New file
@@ -0,0 +1,184 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at legal-notices/CDDLv1_0.txt.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2015 ForgeRock AS.
 */
package org.forgerock.opendj.maven.doc;
import static org.forgerock.opendj.maven.doc.Utils.*;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaType;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.forgerock.opendj.ldap.ResultCode;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * Generates documentation source for LDAP result codes based on
 * {@code org.forgerock.opendj.ldap.ResultCode}.
 * <br>
 * This implementation parses the source to match Javadoc comments with result codes.
 * It is assumed that the class's ResultCode fields are named with result code enum values,
 * and that those fields have Javadoc comments describing each result code.
 */
@Mojo(name = "generate-result-code-doc", defaultPhase = LifecyclePhase.COMPILE)
public class GenerateResultCodeDocMojo extends AbstractMojo {
    /**
     * The Java file containing the source of the ResultCode class,
     * {@code org.forgerock.opendj.ldap.ResultCode}.
     * <br>
     * For example, {@code opendj-core/src/main/java/org/forgerock/opendj/ldap/ResultCode.java}.
     */
    @Parameter(required = true)
    private File resultCodeSource;
    /** The XML file to generate. */
    @Parameter(required = true)
    private File xmlFile;
    /**
     * Generates documentation source for LDAP result codes.
     *
     * @throws MojoExecutionException   Generation failed
     * @throws MojoFailureException     Not used
     */
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        final Map<String, Object> map = new HashMap<>();
        map.put("year", new SimpleDateFormat("yyyy").format(new Date()));
        // The overall explanation in the generated doc is the class comment.
        final JavaClass resultCodeClass;
        try {
            resultCodeClass = getJavaClass();
        } catch (IOException e) {
            throw new MojoExecutionException("Could not read " + resultCodeSource.getPath(), e);
        }
        map.put("classComment", cleanComment(resultCodeClass.getComment()));
        // Documentation for each result code comes from the Javadoc for the code,
        // and from the value and friendly name of the code.
        final Map<String, Object> comments = new HashMap<>();
        for (final JavaField field : resultCodeClass.getFields()) {
            final JavaType type = field.getType();
            if (type.getValue().equals("ResultCode")) {
                comments.put(field.getName(), cleanComment(field.getComment()));
            }
        }
        map.put("resultCodes", getResultCodesDoc(comments));
        final String template = "appendix-ldap-result-codes.ftl";
        try {
            writeStringToFile(applyTemplate(template, map), xmlFile);
        } catch (IOException e) {
            throw new MojoExecutionException("Could not write to " + xmlFile.getPath(), e);
        }
        getLog().info("Wrote " + xmlFile.getPath());
    }
    /**
     * Returns an object to access to the result code Java source.
     * @return An object to access to the result code Java source.
     * @throws IOException  Could not read the source
     */
    private JavaClass getJavaClass() throws IOException {
        final JavaProjectBuilder builder = new JavaProjectBuilder();
        builder.addSource(resultCodeSource);
        return builder.getClassByName("org.forgerock.opendj.ldap.ResultCode");
    }
    /**
     * Returns a clean string for use in generated documentation.
     * @param comment   The comment to clean.
     * @return A clean string for use in generated documentation.
     */
    private String cleanComment(String comment) {
        return stripCodeValueSentences(stripTags(convertLineSeparators(comment))).trim();
    }
    /**
     * Returns a string with line separators converted to spaces.
     * @param string    The string to convert.
     * @return A string with line separators converted to spaces.
     */
    private String convertLineSeparators(String string) {
        return string.replaceAll(System.lineSeparator(), " ");
    }
    /**
     * Returns a string with the HTML tags removed.
     * @param string    The string to strip.
     * @return A string with the HTML tags removed.
     */
    private String stripTags(String string) {
        return string.replaceAll("<[^>]*>", "");
    }
    /**
     * Returns a string with lines sentences of the following form removed:
     * This result code corresponds to the LDAP result code value of &#x7b;&#x40;code 0&#x7d;.
     * @param string    The string to strip.
     * @return A string with lines sentences of the matching form removed.
     */
    private String stripCodeValueSentences(String string) {
        return string
                .replaceAll("This result code corresponds to the LDAP result code value of \\{@code \\d+\\}.", "");
    }
    /**
     * Returns a list of documentation objects for all result codes.
     * @param comments  A map of field names to the clean comments.
     * @return A list of documentation objects for all result codes.
     */
    private List<Map<String, Object>> getResultCodesDoc(Map<String, Object> comments) {
        final List<Map<String, Object>> list = new LinkedList<>();
        if (comments == null || comments.isEmpty()) {
            return list;
        }
        for (ResultCode resultCode : ResultCode.values()) {
            final Map<String, Object> doc = new HashMap<>();
            doc.put("intValue", resultCode.intValue());
            doc.put("name", resultCode.getName());
            final Object comment = comments.get(resultCode.asEnum().toString());
            doc.put("comment", comment);
            list.add(doc);
        }
        return list;
    }
}
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java
@@ -25,10 +25,8 @@
package org.forgerock.opendj.maven.doc;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import static org.forgerock.opendj.maven.doc.Utils.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -36,13 +34,8 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.forgerock.opendj.ldap.schema.CoreSchemaSupportedLocales;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
@@ -77,12 +70,9 @@
        final String localeReference = getLocalesAndSubTypesDocumentation(currentLocale);
        final File localeReferenceFile = new File(outputDirectory, "sec-locales-subtypes.xml");
        try {
            createOutputDirectory();
            writeStringToFile(localeReference, localeReferenceFile);
        } catch (FileNotFoundException e) {
            throw new MojoFailureException("Failed to write doc reference file.", e);
        } catch (IOException e) {
            throw new MojoExecutionException("Failed to create output directory");
            throw new MojoExecutionException("Failed to write " + localeReferenceFile.getPath());
        }
    }
@@ -102,74 +92,9 @@
        return applyTemplate("sec-locales-subtypes.ftl", map);
    }
    /**
     * Create the output directory if it does not exist.
     * @throws IOException  Failed to create the directory.
     */
    private void createOutputDirectory() throws IOException {
        if (outputDirectory != null && !outputDirectory.exists()) {
            if (!outputDirectory.mkdirs()) {
                throw new IOException("Failed to create output directory.");
            }
        }
    }
    /**
     * Writes a string to a file.
     * @param string    The string to write.
     * @param file      The file to write to.
     * @throws FileNotFoundException The file did not exist, or could not be created for writing.
     */
    private void writeStringToFile(final String string, final File file) throws FileNotFoundException {
        PrintWriter printWriter = new PrintWriter(file);
        printWriter.print(string);
        printWriter.close();
    }
    private final Map<String, String> localeTagsToOids =
            CoreSchemaSupportedLocales.getJvmSupportedLocaleNamesToOids();
    /** FreeMarker template configuration. */
    private Configuration configuration;
    /**
     * Returns a FreeMarker configuration for applying templates.
     * @return A FreeMarker configuration for applying templates.
     */
    private Configuration getConfiguration() {
        if (configuration == null) {
            configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setClassForTemplateLoading(GenerateSchemaDocMojo.class, "/templates");
            configuration.setDefaultEncoding("UTF-8");
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
        }
        return configuration;
    }
    /**
     * Returns the String result from applying a FreeMarker template.
     * @param template The name of a template file found in {@code resources/templates/}.
     * @param map      The map holding the data to use in the template.
     * @return The String result from applying a FreeMarker template.
     */
    private String applyTemplate(final String template, final Map<String, Object> map) {
        // FreeMarker requires a configuration to find the template.
        configuration = getConfiguration();
        // FreeMarker takes the data and a Writer to process the template.
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Writer writer = new OutputStreamWriter(outputStream);
        try {
            Template configurationTemplate = configuration.getTemplate(template);
            configurationTemplate.process(map, writer);
            return outputStream.toString();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            org.forgerock.util.Utils.closeSilently(writer, outputStream);
        }
    }
    /** Container for documentation regarding a locale. */
    private class LocaleDoc {
        String tag;
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/Utils.java
@@ -27,16 +27,23 @@
import static org.forgerock.util.Utils.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
@@ -44,6 +51,7 @@
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -96,9 +104,7 @@
        if (original == null) {
            throw new IOException("Could not read input to copy.");
        }
        if (!copy.exists() && !copy.createNewFile()) {
            throw new IOException("Failed to create " + copy);
        }
        createFile(copy);
        OutputStream outputStream = new FileOutputStream(copy);
        int bytesRead;
        byte[] buffer = new byte[4096];
@@ -108,6 +114,32 @@
        closeSilently(original, outputStream);
    }
    /**
     * Writes a string to a file.
     * @param string    The string to write
     * @param file      The file to write to
     * @throws IOException  The file did not exist, or could not be created for writing.
     */
    static void writeStringToFile(final String string, final File file) throws IOException {
        createFile(file);
        PrintWriter printWriter = new PrintWriter(file);
        printWriter.print(string);
        printWriter.close();
    }
    /**
     * Creates a file including parent directories if it does not yet exist.
     * @param file          The file to create
     * @throws IOException  Failed to create the file
     */
    private static void createFile(File file) throws IOException {
        if (!file.exists()) {
            createDirectory(file.getParent());
            if (!file.createNewFile()) {
                throw new IOException("Failed to create " + file.getPath());
            }
        }
    }
    /**
     * Returns the classpath for the class loader and its parent.
@@ -171,6 +203,47 @@
        debugClassPathElements(classLoader.getParent(), log);
    }
    /** FreeMarker template configuration. */
    static Configuration configuration;
    /**
     * Returns a FreeMarker configuration for applying templates.
     * @return A FreeMarker configuration for applying templates.
     */
    static Configuration getConfiguration() {
        if (configuration == null) {
            configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setClassForTemplateLoading(Utils.class, "/templates");
            configuration.setDefaultEncoding("UTF-8");
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
        }
        return configuration;
    }
    /**
     * Returns the String result from applying a FreeMarker template.
     * @param template The name of a template file found in {@code resources/templates/}.
     * @param map      The map holding the data to use in the template.
     * @return The String result from applying a FreeMarker template.
     */
    static String applyTemplate(final String template, final Map<String, Object> map) {
        // FreeMarker requires a configuration to find the template.
        configuration = getConfiguration();
        // FreeMarker takes the data and a Writer to process the template.
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Writer writer = new OutputStreamWriter(outputStream);
        try {
            Template configurationTemplate = configuration.getTemplate(template);
            configurationTemplate.process(map, writer);
            return outputStream.toString();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            org.forgerock.util.Utils.closeSilently(writer, outputStream);
        }
    }
    private Utils() {
        // Not used.
    }
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/templates/appendix-ldap-result-codes.ftl
New file
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! You can also obtain a copy of the license at legal-notices/CC-BY-NC-ND.txt.
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright ${year} ForgeRock AS.
  !
-->
<#-- Comment text comes from the Javadoc, so the language is English. -->
<appendix xml:id="appendix-ldap-result-codes"
          xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://docbook.org/ns/docbook
                              http://docbook.org/xml/5.0/xsd/docbook.xsd"
          xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>LDAP Result Codes</title>
 <para>
  ${classComment}
 </para>
 <indexterm>
  <primary>LDAP</primary>
  <secondary>Result codes</secondary>
 </indexterm>
 <table pgwide="1">
  <title>OpenDJ LDAP Result Codes</title>
  <tgroup cols="3">
   <colspec colnum="1" colwidth="1*" />
   <colspec colnum="2" colwidth="2*" />
   <colspec colnum="3" colwidth="3*" />
   <thead>
    <row>
     <entry>Result Code</entry>
     <entry>Name</entry>
     <entry>Description</entry>
    </row>
   </thead>
   <tbody>
    <#list resultCodes as resultCode>
    <row valign="top">
     <entry>
      <para>
       ${resultCode.intValue}
      </para>
     </entry>
     <entry>
      <para>
       ${resultCode.name}
      </para>
     </entry>
     <entry>
      <para>
       ${resultCode.comment}
      </para>
     </entry>
    </row>
    </#list>
   </tbody>
  </tgroup>
 </table>
</appendix>
opendj-sdk/opendj-server-legacy/pom.xml
@@ -1950,6 +1950,18 @@
                  </messageFileNames>
                </configuration>
              </execution>
              <execution>
                <id>generate-result-code-doc</id>
                <phase>pre-site</phase>
                <goals>
                  <goal>generate-result-code-doc</goal>
                </goals>
                <configuration>
                  <resultCodeSource>../opendj-core/src/main/java/org/forgerock/opendj/ldap/ResultCode.java</resultCodeSource>
                  <xmlFile>${project.build.directory}/docbkx-sources/reference/appendix-ldap-result-codes.xml</xmlFile>
                </configuration>
              </execution>
            </executions>
          </plugin>
opendj-sdk/opendj-server-legacy/src/main/docbkx/reference/index.xml
@@ -194,6 +194,14 @@
 <xinclude:include href="../shared/glossary.xml" />
 <xinclude:include href="appendix-rest2ldap.xml" />
 <xinclude:include href="appendix-ldap-result-codes.xml">
  <xinclude:fallback>
   <appendix>
    <title>LDAP Result Codes Missing</title>
    <para>The generated LDAP result codes appendix is missing.</para>
   </appendix>
  </xinclude:fallback>
 </xinclude:include>
 <xinclude:include href='appendix-file-layout.xml' />
 <xinclude:include href='appendix-ports-used.xml' />
 <xinclude:include href='appendix-standards.xml' />
opendj-sdk/pom.xml
@@ -196,6 +196,26 @@
      </plugin>
      <plugin>
        <groupId>org.forgerock.opendj</groupId>
        <artifactId>opendj-doc-maven-plugin</artifactId>
        <version>${project.version}</version>
        <inherited>false</inherited>
        <executions>
          <execution>
            <id>generate-result-code-doc</id>
            <phase>pre-site</phase>
            <goals>
              <goal>generate-result-code-doc</goal>
            </goals>
            <configuration>
              <resultCodeSource>opendj-core/src/main/java/org/forgerock/opendj/ldap/ResultCode.java</resultCodeSource>
              <xmlFile>${project.build.directory}/docbkx-sources/dev-guide/appendix-ldap-result-codes.xml</xmlFile>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.forgerock.commons</groupId>
        <artifactId>forgerock-doc-maven-plugin</artifactId>
        <inherited>false</inherited>
opendj-sdk/src/main/docbkx/dev-guide/index.xml
@@ -131,6 +131,14 @@
  </xinclude:include>
 </reference>
 <xinclude:include href="appendix-ldap-result-codes.xml">
  <xinclude:fallback>
   <appendix>
    <title>LDAP Result Codes Missing</title>
    <para>The generated LDAP result codes appendix is missing.</para>
   </appendix>
  </xinclude:fallback>
 </xinclude:include>
 <xinclude:include href="../shared/glossary.xml" />
 <index />