From be5173c6b9f258ae8a97796c718f5e61f99ceae0 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Thu, 05 Feb 2015 13:27:38 +0000
Subject: [PATCH] OPENDJ-1768 Add maven plugin to generate log reference
---
opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/package-info.java | 29 ++
opendj-logref-doc-maven-plugin/pom.xml | 47 ++++
opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/GenerateMessageFileMojo.java | 548 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 624 insertions(+), 0 deletions(-)
diff --git a/opendj-logref-doc-maven-plugin/pom.xml b/opendj-logref-doc-maven-plugin/pom.xml
new file mode 100644
index 0000000..196ffc5
--- /dev/null
+++ b/opendj-logref-doc-maven-plugin/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>opendj-project</artifactId>
+ <groupId>org.forgerock.opendj</groupId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>opendj-logref-doc-maven-plugin</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <name>OpenDJ Documentation LogRef Maven Plugin</name>
+ <description>
+ Generation of log references for admin and intallation guides of OpenDJ project.
+ </description>
+ <packaging>maven-plugin</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.forgerock.commons</groupId>
+ <artifactId>forgerock-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.forgerock.commons</groupId>
+ <artifactId>i18n-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.twdata.maven</groupId>
+ <artifactId>mojo-executor</artifactId>
+ <version>2.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>2.0</version>
+ </dependency>
+
+ <!-- dependencies to annotations -->
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>3.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/GenerateMessageFileMojo.java b/opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/GenerateMessageFileMojo.java
new file mode 100644
index 0000000..9230749
--- /dev/null
+++ b/opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/GenerateMessageFileMojo.java
@@ -0,0 +1,548 @@
+/*
+ * 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 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011-2015 ForgeRock AS
+ */
+package org.forgerock.maven;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+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.apache.maven.project.MavenProject;
+import org.forgerock.util.Utils;
+
+/**
+ * Generates xml files containing representations of messages found in properties files.
+ * <p>
+ * There is a single goal that generates xml files.
+ * <p>
+ */
+@Mojo(defaultPhase=LifecyclePhase.PRE_SITE, name="generate-xml-messages-doc")
+public class GenerateMessageFileMojo extends AbstractMojo {
+
+ /**
+ * The Maven Project.
+ */
+ @Parameter(property="project", readonly=true, required=true)
+ private MavenProject project;
+
+ /**
+ * The path to the directory containing the message properties files.
+ */
+ @Parameter(required=true)
+ private String messagesDirectory;
+
+ /**
+ * The path to the directory where xml reference files should be written.
+ * This path must be relative to ${project.build.directory}.
+ */
+ @Parameter(required=true)
+ private String outputDirectory;
+
+ /**
+ * A list which contains all file names, the extension is not needed.
+ */
+ @Parameter(required=true)
+ private List<String> messageFileNames;
+
+ /**
+ * The path and file name of the log message reference file path which will be copied in
+ * the output directory with generated log reference files.
+ */
+ @Parameter(required=true)
+ private String logMessageReferenceFilePath;
+
+ /**
+ * If the plugin is supposed to overwrite existing generated xml files.
+ */
+ @Parameter(required=true, defaultValue="false")
+ private boolean overwrite;
+
+ /** The end-of-line character for this platform. */
+ public static final String EOL = System.getProperty("line.separator");
+
+ /**
+ * The registry filename is the result of the concatenation of the location
+ * of where the source are generated, the package name and the
+ * DESCRIPTORS_REG value.
+ */
+ private static String REGISTRY_FILE_NAME;
+
+ /**
+ * One-line descriptions for log reference categories.
+ */
+ private static HashMap<String, String> CATEGORY_DESCRIPTIONS;
+
+ static {
+ CATEGORY_DESCRIPTIONS = new HashMap<String, String>();
+ CATEGORY_DESCRIPTIONS.put("ACCESS_CONTROL", "Access Control.");
+ CATEGORY_DESCRIPTIONS.put("ADMIN", "the administration framework.");
+ CATEGORY_DESCRIPTIONS.put("ADMIN_TOOL", "the tool like the offline" + " installer and uninstaller.");
+ CATEGORY_DESCRIPTIONS.put("BACKEND", "generic backends.");
+ CATEGORY_DESCRIPTIONS.put("CONFIG", "configuration handling.");
+ CATEGORY_DESCRIPTIONS.put("CORE", "the core server.");
+ CATEGORY_DESCRIPTIONS.put("DSCONFIG", "the dsconfig administration tool.");
+ CATEGORY_DESCRIPTIONS.put("EXTENSIONS", "server extensions for example,"
+ + " extended operations, SASL mechanisms, password storage"
+ + " schemes, password validators, and so on).");
+ CATEGORY_DESCRIPTIONS.put("JEB", "the JE backend.");
+ CATEGORY_DESCRIPTIONS.put("LOG", "the server loggers.");
+ CATEGORY_DESCRIPTIONS.put("PLUGIN", "plugin processing.");
+ CATEGORY_DESCRIPTIONS.put("PROTOCOL", "connection and protocol handling" + " (for example, ASN.1 and LDAP).");
+ CATEGORY_DESCRIPTIONS.put("QUICKSETUP", "quicksetup tools.");
+ CATEGORY_DESCRIPTIONS.put("RUNTIME_INFORMATION", "the runtime" + " information.");
+ CATEGORY_DESCRIPTIONS.put("SCHEMA", "the server schema elements.");
+ CATEGORY_DESCRIPTIONS.put("SYNC", "replication.");
+ CATEGORY_DESCRIPTIONS.put("TASK", "tasks.");
+ CATEGORY_DESCRIPTIONS.put("THIRD_PARTY", "third-party (including" + " user-defined) modules.");
+ CATEGORY_DESCRIPTIONS.put("TOOLS", "tools.");
+ CATEGORY_DESCRIPTIONS.put("USER_DEFINED", "user-defined modules.");
+ CATEGORY_DESCRIPTIONS.put("UTIL", "the general server utilities.");
+ CATEGORY_DESCRIPTIONS.put("VERSION", "version information.");
+ }
+
+ private static final String DESCRIPTORS_REG = "descriptors.reg";
+
+ /** Message giving formatting rules for string keys. */
+ public static String KEY_FORM_MSG = ".\n\nOpenDJ message property keys must be of the form\n\n"
+ + "\t\'[CATEGORY]_[SEVERITY]_[DESCRIPTION]_[ORDINAL]\'\n\n";
+
+ private static final String ERROR_SEVERITY_IDENTIFIER_STRING = "ERR_";
+ private static final String ERROR_SEVERITY_PRINTABLE = "ERROR";
+
+ /**
+ * Represents a log reference entry for an individual message.
+ */
+ private static class MessageRefEntry implements Comparable<MessageRefEntry> {
+ private Integer ordinal;
+ private String xmlId;
+ private String formatString;
+
+ /**
+ * Build log reference entry for an log message.
+ *
+ * @param msgPropKey
+ * @param category
+ * @param severity
+ * @param ordinal
+ * @param formatString
+ */
+ public MessageRefEntry(final String msgPropKey, final Integer ordinal, final String formatString) {
+ this.formatString = formatString;
+ this.ordinal = ordinal;
+ xmlId = getXmlId(msgPropKey);
+ }
+
+ private String getXmlId(final String messagePropertyKey) {
+ // XML IDs must be unique, and must begin with a letter ([A-Za-z])
+ // and may be followed by any number of letters, digits ([0-9]),
+ // hyphens ("-"), underscores ("_"), colons (":"), and periods
+ // (".").
+
+ final String invalidChars = "[^A-Za-z0-9\\-_:\\.]";
+ return messagePropertyKey.replaceAll(invalidChars, "-");
+ }
+
+ /**
+ * Return a DocBook XML <varlistentry> of this log reference
+ * entry. This implementation copies the message string verbatim, and
+ * does not interpret format specifiers.
+ *
+ * @return DocBook XML <varlistentry>.
+ */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(" <varlistentry xml:id=\"log-ref-").append(xmlId).append("\">").append(EOL);
+ if (ordinal != null) {
+ builder.append(" <term>ID: ").append(ordinal).append("</term>").append(EOL);
+ }
+ builder.append(" <listitem>").append(EOL);
+ builder.append(" <para>Severity: ").append(ERROR_SEVERITY_PRINTABLE).append("</para>").append(EOL);
+ builder.append(" <para>Message: ").append(formatString).append("</para>").append(EOL);
+ builder.append(" </listitem>").append(EOL);
+ builder.append(" </varlistentry>").append(EOL);
+
+ return builder.toString();
+ }
+
+ /**
+ * Calls {@link #toString()}.
+ */
+ public String toXML() {
+ return toString();
+ }
+
+ /**
+ * Compare message entries by unique identifier.
+ *
+ * @return See {@link java.lang.Comparable#compareTo(Object)}.
+ */
+ public int compareTo(MessageRefEntry mre) {
+ if (this.ordinal == null || mre.ordinal == null) {
+ return 0;
+ } else {
+ return this.ordinal.compareTo(mre.ordinal);
+ }
+ }
+ }
+
+ /** Represents a log reference list of messages for a category. */
+ private static class MessageRefCategory {
+ private String category;
+ private TreeSet<MessageRefEntry> messages;
+
+ MessageRefCategory(final String category, final TreeSet<MessageRefEntry> messages) {
+ this.category = category;
+ this.messages = messages;
+ }
+
+ /**
+ * Return a DocBook XML <variablelist> of this log reference
+ * category.
+ *
+ * @return DocBook XML <variablelist>
+ */
+ @Override
+ public String toString() {
+ StringBuilder entries = new StringBuilder();
+ for (MessageRefEntry entry : messages) {
+ entries.append(entry.toXML());
+ }
+ return getVariablelistHead() + entries + getVariablelistTail();
+ }
+
+ /**
+ * Calls {@link #toString()}.
+ */
+ public String toXML() {
+ return toString();
+ }
+
+ private String getXMLPreamble() {
+ DateFormat df = new SimpleDateFormat("yyyy");
+ Date now = new Date();
+ String year = df.format(now);
+
+ return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL + "<!--" + EOL + " ! CCPL HEADER START" + EOL
+ + " !" + EOL + " ! This work is licensed under the Creative Commons" + EOL
+ + " ! Attribution-NonCommercial-NoDerivs 3.0 Unported License." + EOL
+ + " ! To view a copy of this license, visit" + EOL
+ + " ! http://creativecommons.org/licenses/by-nc-nd/3.0/" + EOL
+ + " ! or send a letter to Creative Commons, 444 Castro Street," + EOL
+ + " ! Suite 900, Mountain View, California, 94041, USA." + EOL + " !" + EOL
+ + " ! See the License for the specific language governing permissions" + EOL
+ + " ! and limitations under the License." + EOL + " !" + EOL
+ + " ! If applicable, add the following below this CCPL HEADER, with the fields" + EOL
+ + " ! enclosed by brackets \"[]\" replaced with your own identifying information:" + EOL
+ + " ! Portions Copyright [yyyy] [name of copyright owner]" + EOL + " !" + EOL
+ + " ! CCPL HEADER END" + EOL + " !" + EOL + " ! Copyright " + year + " ForgeRock AS"
+ + EOL + " !" + EOL + "-->" + EOL;
+ }
+
+ private String getBaseElementAttrs() {
+ return "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'"
+ + " xmlns:xinclude='http://www.w3.org/2001/XInclude'";
+ }
+
+ private String getVariablelistHead() {
+ StringBuilder builder = new StringBuilder(getXMLPreamble());
+ builder.append(" <variablelist xml:id=\"log-ref-").append(this.category).append("\" ")
+ .append(getBaseElementAttrs()).append(">").append(EOL)
+ .append(" <title>Log Message Category: ").append(category).append("</title>").append(EOL);
+
+ return builder.toString();
+ }
+
+ private String getVariablelistTail() {
+ return " </variablelist>" + EOL;
+ }
+
+ }
+
+ private static class MessagePropertyKey implements Comparable<MessagePropertyKey> {
+ private String description;
+ private Integer ordinal;
+
+ /**
+ * Creates a message property key from a string value.
+ *
+ * @param keyString3
+ * from properties file
+ * @return MessagePropertyKey created from string
+ */
+ public static MessagePropertyKey parseString(String key) {
+ String description;
+ Integer ordinal = null;
+
+ int li = key.lastIndexOf("_");
+ if (li != -1) {
+ description = key.substring(0, li).toUpperCase();
+ } else {
+ throw new IllegalArgumentException("Incorrectly formatted key " + key);
+ }
+
+ try {
+ String ordString = key.substring(li + 1);
+ ordinal = Integer.parseInt(ordString);
+ } catch (Exception nfe) {
+ // Ignore exception, the message has no ordinal.
+ }
+ return new MessagePropertyKey(description, ordinal);
+ }
+
+ /**
+ * Creates a parameterized instance.
+ *
+ * @param description
+ * of this key
+ * @param ordinal
+ * of this key
+ */
+ public MessagePropertyKey(String description, Integer ordinal) {
+ this.description = description;
+ this.ordinal = ordinal;
+ }
+
+ /**
+ * Gets the ordinal of this key.
+ *
+ * @return ordinal of this key
+ */
+ public Integer getOrdinal() {
+ return this.ordinal;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ StringBuilder builder = new StringBuilder(description);
+ if (ordinal != null) {
+ builder.append("_").append(ordinal);
+ }
+
+ return builder.toString();
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(MessagePropertyKey k) {
+ if (ordinal == k.ordinal) {
+ return description.compareTo(k.description);
+ } else {
+ return ordinal.compareTo(k.ordinal);
+ }
+ }
+
+ }
+
+ /**
+ * For maven exec plugin execution. Generates for all included message files
+ * (sample.properties), a xml log ref file (log-ref-sample.xml)
+ *
+ * @throws Exception
+ */
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ String projectBuildDir = project.getBuild().getDirectory();
+
+ if (!outputDirectory.contains(projectBuildDir)) {
+ String errorMsg = String.format("outputDirectory parameter (%s) must be included "
+ + "in ${project.build.directory} (%s)", outputDirectory, projectBuildDir);
+ getLog().error(errorMsg);
+ throw new MojoExecutionException(errorMsg);
+ }
+
+ for (String messageFileName : messageFileNames) {
+ File source = new File(messagesDirectory, messageFileName + ".properties");
+ File dest = new File(outputDirectory, "log-ref-" + messageFileName.replace("_", "-") + ".xml");
+ try {
+ generateLogReferenceFile(source, dest, messageFileName.toUpperCase());
+ } catch (MojoExecutionException e) {
+ getLog().error("Impossible to generate " + dest.getAbsolutePath() + ": " + e.getMessage());
+ throw e;
+ }
+ }
+ copyLogMessageReferenceFile();
+ }
+
+
+ private void generateLogReferenceFile(File source, File dest, String globalCategory) throws MojoExecutionException {
+ PrintWriter destWriter = null;
+ try {
+ // Decide whether to generate messages based on modification times
+ // and print status messages.
+ if (!source.exists()) {
+ throw new Exception("file " + source.getName() + " does not exist");
+ }
+ if (!isOverwriteNeeded(source, dest)) {
+ return;
+ }
+
+ destWriter = new PrintWriter(dest, "UTF-8");
+ Properties properties = new Properties();
+ properties.load(new FileInputStream(source));
+ Map<MessagePropertyKey, String> errorMessages = loadErrorProperties(properties);
+ TreeSet<MessageRefEntry> messageRefEntries = new TreeSet<MessageRefEntry>();
+ Set<Integer> usedOrdinals = new HashSet<Integer>();
+
+ for (MessagePropertyKey msgKey : errorMessages.keySet()) {
+ String formatString = errorMessages.get(msgKey).replaceAll("<", "<");
+ Integer ordinal = msgKey.getOrdinal();
+ if (ordinal != null && usedOrdinals.contains(ordinal)) {
+ throw new Exception("The ordinal value \'" + ordinal + "\' in key " + msgKey
+ + " has been previously defined in " + source + KEY_FORM_MSG);
+ }
+ usedOrdinals.add(ordinal);
+ messageRefEntries.add(new MessageRefEntry(msgKey.toString(), msgKey.getOrdinal(), formatString));
+ }
+
+ destWriter.println(messageRefEntries.isEmpty() ?
+ "<!-- No message for this category -->"
+ : new MessageRefCategory(globalCategory, messageRefEntries).toXML());
+ getLog().info(dest.getPath() + " has been successfully generated");
+ getLog().debug("Message Generated: " + errorMessages.size());
+ } catch (Exception e) {
+ // Delete malformed file.
+ if (dest.exists()) {
+ dest.deleteOnExit();
+ }
+ throw new MojoExecutionException(e.getMessage());
+ } finally {
+ Utils.closeSilently(destWriter);
+ }
+ }
+
+
+ private Map<MessagePropertyKey, String> loadErrorProperties(Properties properties) throws Exception {
+ Map<MessagePropertyKey, String> errorMessage = new TreeMap<MessagePropertyKey, String>();
+ for (Object propO : properties.keySet()) {
+ String propKey = propO.toString();
+ try {
+ // Document only ERROR messages.
+ if (propKey.startsWith(ERROR_SEVERITY_IDENTIFIER_STRING)) {
+ MessagePropertyKey key = MessagePropertyKey.parseString(propKey);
+ String formatString = properties.getProperty(propKey);
+ errorMessage.put(key, formatString);
+ }
+ } catch (IllegalArgumentException iae) {
+ throw new Exception("invalid property key " + propKey + ": " + iae.getMessage() + KEY_FORM_MSG);
+ }
+ }
+
+ return errorMessage;
+ }
+
+
+ private boolean isOverwriteNeeded(File source, File dest) {
+ boolean needsOverwrite = this.overwrite || source.lastModified() > dest.lastModified();
+ if (dest.exists() && needsOverwrite) {
+ dest.delete();
+ getLog().info("Regenerating " + dest.getName() + " from " + source.getName());
+ } else if (dest.exists() && !needsOverwrite) {
+ // Fail fast - nothing to do.
+ getLog().info(dest.getName() + " is up to date");
+ return false;
+ } else {
+ File javaGenDir = dest.getParentFile();
+ if (!javaGenDir.exists()) {
+ javaGenDir.mkdirs();
+ }
+ }
+
+ return true;
+ }
+
+ private void copyLogMessageReferenceFile() throws MojoExecutionException {
+ File msgReferenceSourceFile = new File(logMessageReferenceFilePath);
+ File msgReferenceDestFile = new File(outputDirectory, msgReferenceSourceFile.getName());
+ if (!isOverwriteNeeded(msgReferenceSourceFile, msgReferenceDestFile)) {
+ return;
+ }
+ InputStream input = null;
+ OutputStream output = null;
+ try {
+ input = new FileInputStream(msgReferenceSourceFile);
+ output = new FileOutputStream(msgReferenceDestFile);
+ byte[] buf = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = input.read(buf)) > 0) {
+ output.write(buf, 0, bytesRead);
+ }
+ getLog().info("log message reference file has been successfully generated");
+ } catch (Exception e) {
+ throw new MojoExecutionException("Impossible to copy log reference message file into output directory: "
+ + e.getMessage());
+ } finally {
+ Utils.closeSilently(input, output);
+ }
+ }
+
+ /**
+ * Sets the file that will be generated containing declarations of messages
+ * from <code>source</code>.
+ *
+ * @param dest
+ * File destination
+ */
+ public void checkDestJava(File dest) throws Exception {
+ File descriptorsRegFile = new File(dest.getParentFile(), DESCRIPTORS_REG);
+
+ if (REGISTRY_FILE_NAME != null) {
+ // if REGISTRY_FILE_NAME is already set, ensure that we computed the
+ // same one
+ File prevDescriptorsRegFile = new File(REGISTRY_FILE_NAME);
+ if (!prevDescriptorsRegFile.equals(descriptorsRegFile)) {
+ throw new Exception("Error processing " + dest
+ + ": all messages must be located in the same package thus "
+ + "name of the source file should be "
+ + new File(prevDescriptorsRegFile.getParent(), dest.getName()));
+ }
+ } else {
+ REGISTRY_FILE_NAME = descriptorsRegFile.getCanonicalPath();
+ }
+ }
+
+}
diff --git a/opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/package-info.java b/opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/package-info.java
new file mode 100644
index 0000000..7840667
--- /dev/null
+++ b/opendj-logref-doc-maven-plugin/src/main/java/org/forgerock/maven/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/** Classes implementing the maven plugin to create a base schema that may be used during the upgrade process. */
+package org.forgerock.maven;
+
--
Gitblit v1.10.0