From 707c42dc201fef98865f2c2db666df801378e69e Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 19 Nov 2013 13:50:58 +0000
Subject: [PATCH] OPENDJ-1075 Port server make-ldif tool to the SDK CR-2603
---
opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools.properties | 29 +++
opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ConsoleApplication.java | 15 +
opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java | 256 ++++++++++++++++++++++++++++++++
opendj-sdk/opendj3/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/MakeLDIFTestCase.java | 130 ++++++++++++++++
4 files changed, 426 insertions(+), 4 deletions(-)
diff --git a/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ConsoleApplication.java b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ConsoleApplication.java
index 98e0b0b..a1d38f6 100755
--- a/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ConsoleApplication.java
+++ b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ConsoleApplication.java
@@ -49,13 +49,13 @@
* a console-based application.
*/
abstract class ConsoleApplication {
- private final PrintStream err = new PrintStream(System.err);
+ private final PrintStream err;
private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
private final InputStream in = System.in;
- private final PrintStream out = new PrintStream(System.out);
+ private final PrintStream out;
private final Console console = System.console();
@@ -63,7 +63,16 @@
* Creates a new console application instance.
*/
ConsoleApplication() {
- // Nothing to do.
+ this(System.out, System.err);
+ }
+
+ /**
+ * Creates a new console application instance with
+ * provided standard and error out streams.
+ */
+ ConsoleApplication(PrintStream out, PrintStream err) {
+ this.out = out;
+ this.err = err;
}
/**
diff --git a/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java
new file mode 100644
index 0000000..9f64f90
--- /dev/null
+++ b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java
@@ -0,0 +1,256 @@
+/*
+ * 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 2006-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2013 ForgeRock AS
+ */
+package com.forgerock.opendj.ldap.tools;
+
+import static com.forgerock.opendj.ldap.tools.ToolConstants.*;
+import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
+import static com.forgerock.opendj.ldap.tools.Utils.*;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldif.EntryGenerator;
+import org.forgerock.opendj.ldif.LDIFEntryWriter;
+
+/**
+ * Program that generate LDIF content based on a template.
+ */
+public final class MakeLDIF extends ConsoleApplication {
+
+ private static final int EXIT_CODE_SUCCESS = 0;
+ private static final int EXIT_CODE_FAILURE = 1;
+
+ /** The total number of entries that have been written. */
+ private long numberOfEntriesWritten;
+
+ /**
+ * Main method for MakeLDIF tool.
+ *
+ * @param args
+ * The command-line arguments provided to this program.
+ */
+ public static void main(final String[] args) {
+ final int retCode = new MakeLDIF().run(args);
+ System.exit(filterExitCode(retCode));
+ }
+
+ /** Run Make LDIF with provided command-line arguments. */
+ int run(final String[] args) {
+ final LocalizableMessage toolDescription = INFO_MAKELDIF_TOOL_DESCRIPTION.get();
+ final ArgumentParser argParser = new ArgumentParser(MakeLDIF.class.getName(), toolDescription,
+ false, true, 1, 1, "template-file-path");
+
+ BooleanArgument showUsage;
+ IntegerArgument randomSeed;
+ StringArgument ldifFile;
+ StringArgument resourcePath;
+ StringArgument constants;
+ try {
+ resourcePath = new StringArgument("resourcepath", 'r', "resourcePath", false, false, true,
+ INFO_PATH_PLACEHOLDER.get(), null, null, INFO_MAKELDIF_DESCRIPTION_RESOURCE_PATH.get());
+ resourcePath.setHidden(true);
+ argParser.addArgument(resourcePath);
+
+ ldifFile = new StringArgument("ldiffile", OPTION_SHORT_OUTPUT_LDIF_FILENAME,
+ OPTION_LONG_OUTPUT_LDIF_FILENAME, false, false, true, INFO_FILE_PLACEHOLDER.get(),
+ null, null, INFO_MAKELDIF_DESCRIPTION_LDIF.get());
+ argParser.addArgument(ldifFile);
+
+ randomSeed = new IntegerArgument("randomseed", OPTION_SHORT_RANDOM_SEED, OPTION_LONG_RANDOM_SEED, false,
+ false, true, INFO_SEED_PLACEHOLDER.get(), 0, null, INFO_MAKELDIF_DESCRIPTION_SEED.get());
+ argParser.addArgument(randomSeed);
+
+ constants = new StringArgument("constant", 'c', "constant", false, true, true, INFO_FILE_PLACEHOLDER.get(),
+ null, null, INFO_MAKELDIF_DESCRIPTION_LDIF.get());
+ argParser.addArgument(constants);
+
+ showUsage = new BooleanArgument("help", OPTION_SHORT_HELP, OPTION_LONG_HELP,
+ INFO_MAKELDIF_DESCRIPTION_HELP.get());
+ argParser.addArgument(showUsage);
+ argParser.setUsageArgument(showUsage, getOutputStream());
+ } catch (ArgumentException ae) {
+ println(ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
+ return EXIT_CODE_FAILURE;
+ }
+
+ // Parse the command-line arguments provided to the program.
+ try {
+ argParser.parseArguments(args);
+ } catch (ArgumentException ae) {
+ println(ERR_ERROR_PARSING_ARGS.get(ae.getMessage()));
+ println(argParser.getUsageMessage());
+ return EXIT_CODE_FAILURE;
+ }
+
+ if (argParser.usageOrVersionDisplayed()) {
+ return 0;
+ }
+ final String templatePath = argParser.getTrailingArguments().get(0);
+ return run(templatePath, resourcePath, ldifFile, randomSeed, constants);
+ }
+
+ /** Run Make LDIF with provided arguments. */
+ private int run(final String templatePath, final StringArgument resourcePath,
+ final StringArgument ldifFile, final IntegerArgument randomSeedArg, final StringArgument constants) {
+ EntryGenerator generator = null;
+ LDIFEntryWriter writer = null;
+ try {
+ generator = createGenerator(templatePath, resourcePath, randomSeedArg, constants);
+ if (generator == null) {
+ return EXIT_CODE_FAILURE;
+ }
+
+ if (generator.hasWarning()) {
+ for (LocalizableMessage warn : generator.getWarnings()) {
+ println(warn);
+ }
+ }
+
+ if (ldifFile.isPresent()) {
+ try {
+ writer = new LDIFEntryWriter(new BufferedWriter(new FileWriter(new File(ldifFile.getValue()))));
+ } catch (IOException e) {
+ println(ERR_MAKELDIF_UNABLE_TO_CREATE_LDIF.get(ldifFile.getValue(), e.getMessage()));
+ return EXIT_CODE_FAILURE;
+ }
+ } else {
+ writer = new LDIFEntryWriter(getOutputStream());
+ }
+
+ if (!generateEntries(generator, writer, ldifFile)) {
+ return EXIT_CODE_FAILURE;
+ }
+
+ println(INFO_MAKELDIF_PROCESSING_COMPLETE.get(numberOfEntriesWritten));
+
+ } finally {
+ closeIfNotNull(generator, writer);
+ }
+
+ return EXIT_CODE_SUCCESS;
+ }
+
+ /**
+ * Returns the initialized generator, or null if a problem occurs.
+ */
+ private EntryGenerator createGenerator(final String templatePath, final StringArgument resourcePath,
+ final IntegerArgument randomSeedArg, final StringArgument constants) {
+ final EntryGenerator generator = new EntryGenerator(templatePath);
+
+ if (resourcePath.isPresent()) {
+ final File resourceDir = new File(resourcePath.getValue());
+ if (!resourceDir.exists()) {
+ println(ERR_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY.get(resourcePath.getValue()));
+ generator.close();
+ return null;
+ }
+ generator.setResourcePath(resourcePath.getValue());
+ }
+
+ if (randomSeedArg.isPresent()) {
+ try {
+ generator.setRandomSeed(randomSeedArg.getIntValue());
+ } catch (ArgumentException ae) {
+ println(ERR_ERROR_PARSING_ARGS.get(ae.getMessage()));
+ generator.close();
+ return null;
+ }
+ }
+
+ if (constants.isPresent()) {
+ if (!addConstantsToGenerator(constants, generator)) {
+ generator.close();
+ return null;
+ }
+ }
+
+ // Force initialization of generator
+ try {
+ generator.hasNext();
+ } catch (IOException e) {
+ println(ERR_MAKELDIF_EXCEPTION_DURING_PARSE.get(e.getMessage()));
+ generator.close();
+ return null;
+ }
+
+ return generator;
+ }
+
+ /**
+ * Returns true if all constants are added to generator, false otherwise.
+ */
+ private boolean addConstantsToGenerator(StringArgument constants, EntryGenerator generator) {
+ for (final String constant : constants.getValues()) {
+ final String[] chunks = constant.split("=");
+ if (chunks.length != 2) {
+ println(ERR_CONSTANT_ARG_CANNOT_DECODE.get(constant));
+ return false;
+ }
+ generator.setConstant(chunks[0], chunks[1]);
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if generation is successfull, false otherwise.
+ */
+ private boolean generateEntries(final EntryGenerator generator, final LDIFEntryWriter writer,
+ final StringArgument ldifFile) {
+ try {
+ while (generator.hasNext()) {
+ final Entry entry = generator.readEntry();
+ try {
+ writer.writeEntry(entry);
+ } catch (IOException e) {
+ println(ERR_MAKELDIF_ERROR_WRITING_LDIF.get(ldifFile.getValue(), e.getMessage()));
+ return false;
+ }
+ if ((++numberOfEntriesWritten % 1000) == 0) {
+ println(INFO_MAKELDIF_PROCESSED_N_ENTRIES.get(numberOfEntriesWritten));
+ }
+ }
+ } catch (Exception e) {
+ println(ERR_MAKELDIF_EXCEPTION_DURING_PROCESSING.get(e.getMessage()));
+ return false;
+ }
+ return true;
+ }
+
+ private MakeLDIF() {
+ // nothing to do
+ }
+
+ // To allow tests
+ MakeLDIF(PrintStream out, PrintStream err) {
+ super(out, err);
+ }
+
+}
diff --git a/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools.properties b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools.properties
index 8f7902e..d630efb 100755
--- a/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools.properties
+++ b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools.properties
@@ -117,7 +117,6 @@
INFO_TIME_IN_HOURS_MINUTES_SECONDS=%d hours, %d minutes, %d seconds
INFO_TIME_IN_DAYS_HOURS_MINUTES_SECONDS=%d days, %d hours, %d minutes, %d \
seconds
-INFO_ARGPARSER_USAGE=Usage:
INFO_SUBCMDPARSER_WHERE_OPTIONS_INCLUDE=Command options:
ERR_MENU_BAD_CHOICE_SINGLE=Invalid response. Please enter a valid \
menu option
@@ -472,3 +471,31 @@
files and report the differences in LDIF format
INFO_LDIFSEARCH_TOOL_DESCRIPTION=This utility can be used to perform search \
operations against entries contained in an LDIF file
+ #
+ # MakeLDIF tool
+ #
+INFO_MAKELDIF_TOOL_DESCRIPTION=This utility can be used to generate LDIF \
+ data based on a definition in a template file
+INFO_SEED_PLACEHOLDER={seed}
+INFO_PATH_PLACEHOLDER={path}
+INFO_MAKELDIF_DESCRIPTION_LDIF=The path to the LDIF file to be written
+INFO_MAKELDIF_DESCRIPTION_SEED=The seed to use to initialize the random \
+ number generator
+INFO_MAKELDIF_DESCRIPTION_HELP=Show this usage information
+INFO_MAKELDIF_DESCRIPTION_RESOURCE_PATH=Path to look for \
+ MakeLDIF resources (e.g., data files)
+ERR_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY=The specified resource \
+ directory %s could not be found
+INFO_MAKELDIF_PROCESSED_N_ENTRIES=Processed %d entries
+INFO_MAKELDIF_PROCESSING_COMPLETE=LDIF processing complete. %d entries \
+ written
+ERR_MAKELDIF_EXCEPTION_DURING_PARSE=An error occurred while \
+ parsing template file : %s
+ERR_MAKELDIF_UNABLE_TO_CREATE_LDIF=An error occurred while \
+ attempting to open LDIF file %s for writing: %s
+ERR_MAKELDIF_ERROR_WRITING_LDIF=An error occurred while writing data \
+ to LDIF file %s: %s
+ERR_MAKELDIF_EXCEPTION_DURING_PROCESSING=An error occurred while \
+ processing : %s
+ERR_CONSTANT_ARG_CANNOT_DECODE=Unable to parse a constant argument, \
+ expecting name=value but got %s
diff --git a/opendj-sdk/opendj3/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/MakeLDIFTestCase.java b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/MakeLDIFTestCase.java
new file mode 100644
index 0000000..d5b84fc
--- /dev/null
+++ b/opendj-sdk/opendj3/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/MakeLDIFTestCase.java
@@ -0,0 +1,130 @@
+/*
+ * 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 2013 ForgeRock AS.
+ */
+package com.forgerock.opendj.ldap.tools;
+
+import static org.fest.assertions.Assertions.*;
+
+import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.forgerock.opendj.util.StaticUtils;
+
+@SuppressWarnings("javadoc")
+public class MakeLDIFTestCase extends ToolsTestCase {
+
+ @DataProvider(name = "validArguments")
+ Object[][] createValidArguments() throws Exception {
+ Object[][] data = new Object[][] {
+ { args("-c", "numusers=1", "example.template"),
+ // 2 base entries + users
+ expectedErrOutput(INFO_MAKELDIF_PROCESSING_COMPLETE.get(3)) },
+
+ { args("-c", "numusers=5", "example.template"),
+ // 2 base entries + users
+ expectedErrOutput(INFO_MAKELDIF_PROCESSING_COMPLETE.get(7)) },
+ };
+ return data;
+ }
+
+ @DataProvider(name = "invalidArguments")
+ Object[][] createInValidArguments() throws Exception {
+ Object[][] data = new Object[][] {
+ { // check that usage is written to output when arguments are invalid
+ args(),
+ expectedErrOutput(INFO_MAKELDIF_TOOL_DESCRIPTION.get()) },
+
+ { // check that there is an argument error when no arg provided
+ args(),
+ expectedErrOutput(ERR_ERROR_PARSING_ARGS.get("")) },
+
+ { args("-r", "unknown/path" , "example.template"),
+ expectedErrOutput(ERR_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY.get("unknown/path")) },
+
+ { args("-o", "unknown/path" , "example.template"),
+ expectedErrOutput(ERR_MAKELDIF_UNABLE_TO_CREATE_LDIF.get("unknown/path", "")) },
+
+ { args("-s", "non-numeric" , "example.template"),
+ expectedErrOutput(ERR_ERROR_PARSING_ARGS.get("")) },
+ };
+ return data;
+ }
+
+ @Test(dataProvider = "validArguments")
+ public void testRunValidArguments(String[] arguments, LocalizableMessage expectedErrOutput)
+ throws Exception {
+ run(arguments, true, expectedErrOutput);
+ }
+
+ @Test(dataProvider = "invalidArguments")
+ public void testRunInvalidArguments(String[] arguments, LocalizableMessage expectedErrOutput)
+ throws Exception {
+ run(arguments, false, expectedErrOutput);
+ }
+
+ private void run(String[] arguments, boolean expectsResults, LocalizableMessage expectedErrOutput)
+ throws UnsupportedEncodingException {
+ PrintStream outStream = null;
+ PrintStream errStream = null;
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ outStream = new PrintStream(out);
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ errStream = new PrintStream(err);
+
+ MakeLDIF makeLDIF = new MakeLDIF(outStream, errStream);
+ makeLDIF.run(arguments);
+
+ if (expectsResults) {
+ assertThat(out.size()).isGreaterThan(0);
+ } else {
+ assertThat(out.size()).isEqualTo(0);
+ }
+
+ assertThat(err.toString("UTF-8")).contains(Utils.wrapText(expectedErrOutput, Utils.MAX_LINE_WIDTH));
+ } finally {
+ StaticUtils.closeSilently(outStream, errStream);
+ }
+ }
+
+ /** Arguments passed to the command */
+ private String[] args(String...arguments) {
+ return arguments;
+ }
+
+ /** A message the error output is expected to contain. */
+ private LocalizableMessage expectedErrOutput(LocalizableMessage val) {
+ return val;
+ }
+
+
+}
--
Gitblit v1.10.0