/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions Copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2015 ForgeRock AS.
|
*/
|
package org.forgerock.opendj.maven;
|
|
import java.io.BufferedReader;
|
import java.io.BufferedWriter;
|
import java.io.File;
|
import java.io.FileReader;
|
import java.io.FileWriter;
|
import java.io.IOException;
|
import java.util.LinkedList;
|
import java.util.List;
|
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;
|
|
/**
|
* Concatenates the contents of the files in the schema directory to create a
|
* base schema that may be used during the upgrade process. Each element will
|
* also include the X-SCHEMA-FILE extension to indicate the source schema file.
|
* <p>
|
* There is a single goal that generates the base schema.
|
* <p>
|
*/
|
@Mojo(name = "concat", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
|
public final class ConcatSchemaMojo extends AbstractMojo {
|
|
/**
|
* The Maven Project.
|
*/
|
@Parameter(property = "project", required = true, readonly = true)
|
private MavenProject project;
|
|
/**
|
* The path to the directory containing the schema files.
|
*/
|
@Parameter(required = true, defaultValue = "${basedir}/resource/schema")
|
private String schemaDirectory;
|
|
/**
|
* The directory path of the concatenated schema file to create. Must be in ${project.build.directory}
|
*/
|
@Parameter(required = true)
|
private String outputDirectory;
|
|
/**
|
* The file name of the concatenated schema file to create.
|
*/
|
@Parameter(required = true)
|
private String outputFile;
|
|
/** {@inheritDoc} */
|
@Override
|
public void execute() throws MojoExecutionException, MojoFailureException {
|
String projectBuildDir = project.getBuild().getDirectory();
|
String outputFilePath = outputDirectory + System.getProperty("file.separator") + outputFile;
|
|
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);
|
}
|
getLog().info(String.format("Concatenating all ldif files from directory: %s", schemaDirectory));
|
getLog().info(String.format("Concatenated file: %s", outputFilePath));
|
|
new File(outputFilePath).getParentFile().mkdirs();
|
|
// Get a sorted list of the files in the schema directory.
|
TreeSet<String> schemaFileNames = new TreeSet<>();
|
for (File f : new File(schemaDirectory).listFiles()) {
|
if (f.isFile()) {
|
schemaFileNames.add(f.getName());
|
}
|
}
|
|
// Create a set of lists that will hold the schema elements read from the files.
|
LinkedList<String> attributeTypes = new LinkedList<>();
|
LinkedList<String> objectClasses = new LinkedList<>();
|
LinkedList<String> nameForms = new LinkedList<>();
|
LinkedList<String> ditContentRules = new LinkedList<>();
|
LinkedList<String> ditStructureRules = new LinkedList<>();
|
LinkedList<String> matchingRuleUses = new LinkedList<>();
|
LinkedList<String> ldapSyntaxes = new LinkedList<>();
|
int curLineNumber = 0;
|
|
// Open each of the files in order and read the elements that they contain,
|
// appending them to the appropriate lists.
|
for (String name : schemaFileNames) {
|
// Read the contents of the file into a list with one schema element per
|
// list element.
|
LinkedList<StringBuilder> lines = new LinkedList<>();
|
try {
|
BufferedReader reader = new BufferedReader(new FileReader(new File(schemaDirectory, name)));
|
String line = reader.readLine();
|
while (line != null) {
|
curLineNumber++;
|
if (line.length() > 0 && !line.startsWith("#")) {
|
if (line.startsWith(" ")) {
|
lines.getLast().append(line.substring(1));
|
} else {
|
lines.add(new StringBuilder(line));
|
}
|
}
|
line = reader.readLine();
|
}
|
reader.close();
|
} catch (Exception e) {
|
getLog().error(String.format(
|
"Error while reading schema file %s at line %d: %s", name, curLineNumber, e.getMessage()));
|
throw new MojoExecutionException(e.getMessage(), e);
|
}
|
|
// Iterate through each line in the list. Find the colon and get the
|
// attribute name at the beginning. If it's someting that we don't
|
// recognize, then skip it. Otherwise, add the X-SCHEMA-FILE extension
|
// and add it to the appropriate schema element list.
|
for (StringBuilder buffer : lines) {
|
// Get the line and add the X-SCHEMA-FILE extension to the end of it.
|
// All of them should end with " )" but some might have the parenthesis
|
// crammed up against the last character so deal with that as well.
|
String line = buffer.toString().trim();
|
if (line.endsWith(" )")) {
|
line = line.substring(0, line.length() - 1) + "X-SCHEMA-FILE '" + name + "' )";
|
} else if (line.endsWith(")")) {
|
line = line.substring(0, line.length() - 1) + " X-SCHEMA-FILE '" + name + "' )";
|
} else {
|
continue;
|
}
|
|
String lowerLine = line.toLowerCase();
|
if (lowerLine.startsWith("attributetypes:")) {
|
attributeTypes.add(line);
|
} else if (lowerLine.startsWith("objectclasses:")) {
|
objectClasses.add(line);
|
} else if (lowerLine.startsWith("nameforms:")) {
|
nameForms.add(line);
|
} else if (lowerLine.startsWith("ditcontentrules:")) {
|
ditContentRules.add(line);
|
} else if (lowerLine.startsWith("ditstructurerules:")) {
|
ditStructureRules.add(line);
|
} else if (lowerLine.startsWith("matchingruleuse:")) {
|
matchingRuleUses.add(line);
|
} else if (lowerLine.startsWith("ldapsyntaxes:")) {
|
ldapSyntaxes.add(line);
|
}
|
}
|
}
|
|
// Write the resulting output to the merged schema file.
|
try {
|
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilePath));
|
writer.write("dn: cn=schema");
|
writer.newLine();
|
writer.write("objectClass: top");
|
writer.newLine();
|
writer.write("objectClass: ldapSubentry");
|
writer.newLine();
|
writer.write("objectClass: subschema");
|
writer.newLine();
|
|
writeSchemaElements(ldapSyntaxes, writer);
|
writeSchemaElements(attributeTypes, writer);
|
writeSchemaElements(objectClasses, writer);
|
writeSchemaElements(nameForms, writer);
|
writeSchemaElements(ditContentRules, writer);
|
writeSchemaElements(ditStructureRules, writer);
|
writeSchemaElements(matchingRuleUses, writer);
|
|
writer.close();
|
} catch (Exception e) {
|
getLog().error(
|
String.format("Error while writing concatenated schema file %s: %s", outputFile, e.getMessage()));
|
throw new MojoExecutionException(e.getMessage(), e);
|
}
|
}
|
|
private void writeSchemaElements(List<String> schemaElements, BufferedWriter writer) throws IOException {
|
for (String line : schemaElements) {
|
writer.write(line);
|
writer.newLine();
|
}
|
}
|
|
}
|