From 8a3867fa1e013a39345e0f43d8a56f0e8db2725f Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 20 Nov 2006 01:39:10 +0000
Subject: [PATCH] Update the command-line setup tool to provide the ability to populate the database with sample data, like the GUI version.

---
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java       |   69 ----
 opendj-sdk/opends/build.xml                                                           |   83 +++---
 opendj-sdk/opends/src/server/org/opends/server/util/CreateTemplate.java               |  119 +++++++++
 opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java             |  119 +++++++++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties |   25 +
 opendj-sdk/opends/src/server/org/opends/server/tools/InstallDS.java                   |  364 ++++++++++++++++++---------
 6 files changed, 537 insertions(+), 242 deletions(-)

diff --git a/opendj-sdk/opends/build.xml b/opendj-sdk/opends/build.xml
index 7ddff9b..a51f497 100644
--- a/opendj-sdk/opends/build.xml
+++ b/opendj-sdk/opends/build.xml
@@ -76,10 +76,11 @@
   <property name="dsml.gen.dir"     location="${build.dir}/dsml/gen"     />
   <property name="dsml.classes.dir" location="${build.dir}/dsml/classes" />
 
-	<!-- Properties for use with the Quick Setup.                      -->
-	<property name="quicksetup.src.dir"         location="src/quicksetup"             />
-	<property name="quicksetup.classes.dir"    location="${build.dir}/quicksetup/classes"    />
-	
+  <!-- Properties for use with the Quick Setup.                      -->
+  <property name="quicksetup.src.dir" location="src/quicksetup"       />
+  <property name="quicksetup.classes.dir"
+            location="${build.dir}/quicksetup/classes"                />
+
   <!-- Properties for code coverage testing.                            -->
   <property name="coverage.dir"         location="build/coverage"            />
   <property name="coverage.report.dir"  
@@ -230,18 +231,18 @@
 
     <taskdef resource="checkstyletask.properties"
          classpath="${checkstyle.dir}/checkstyle-all-4.1.jar" />
-  	
+
     <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
          failOnViolation="true">
       <fileset dir="${src.dir}" includes="**/*.java" />
       <formatter type="plain" />
     </checkstyle>
-  	
-  	<checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
-     	failOnViolation="true">
-	  <fileset dir="${quicksetup.src.dir}" includes="**/*.java" />
+
+    <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
+         failOnViolation="true">
+      <fileset dir="${quicksetup.src.dir}" includes="**/*.java" />
       <formatter type="plain" />
-     </checkstyle>
+    </checkstyle>
 
     <checkstyle config="${checkstyle.dir}/opends-doctarget-checkstyle.xml"
          failOnViolation="true">
@@ -294,34 +295,34 @@
     </javac>
   </target>
 
-	<!-- Compile the Quick Setup source files. -->
-	<target name="compilequicksetup"
-		depends="buildtools,compile"
-	    description="Compile the Quick Setup source files.">
-		
-	    <mkdir dir="${quicksetup.classes.dir}" />
-	    <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}" optimize="true"
-	    	debug="on" debuglevel="lines,source" source="1.5" target="1.5"
-	        deprecation="true" fork="true" memoryInitialSize="${MEM}"
-	        memoryMaximumSize="${MEM}">
-	        <compilerarg value="-Xlint:all" />
+  <!-- Compile the Quick Setup source files. -->
+  <target name="compilequicksetup" depends="buildtools,compile"
+          description="Compile the Quick Setup source files.">
 
-	    	<classpath>
-	        	<fileset dir="${build.dir}/build-tools">
-	            	<include name="build-tools.jar" />
-	            </fileset>
-	            <pathelement path="${classes.dir}"/>
-	        </classpath>
-	   	</javac>
-	   	<copy todir="${quicksetup.classes.dir}">
-	   		<fileset dir="${quicksetup.src.dir}" includes="**/*.properties, **/*.gif, **/*.png" />
-	   	</copy>
-	    <copy todir="${quicksetup.classes.dir}">
-	    	<fileset dir="${classes.dir}"
-	        	includes="**/DynamicConstants.class"/>
-	    </copy>
+    <mkdir dir="${quicksetup.classes.dir}" />
+    <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}"
+         optimize="true" debug="on" debuglevel="lines,source" source="1.5"
+         target="1.5" deprecation="true" fork="true" memoryInitialSize="${MEM}"
+         memoryMaximumSize="${MEM}">
+      <compilerarg value="-Xlint:all" />
+
+      <classpath>
+        <fileset dir="${build.dir}/build-tools">
+          <include name="build-tools.jar" />
+        </fileset>
+        <pathelement path="${classes.dir}"/>
+      </classpath>
+    </javac>
+    <copy todir="${quicksetup.classes.dir}">
+      <fileset dir="${quicksetup.src.dir}"
+               includes="**/*.properties, **/*.gif, **/*.png" />
+    </copy>
+    <copy todir="${quicksetup.classes.dir}">
+      <fileset dir="${classes.dir}"
+               includes="**/DynamicConstants.class **/CreateTemplate.class" />
+    </copy>
   </target>
-	
+
   <!--
    ! Rebuild the Directory Server without destroying any existing configuration
    ! or data.  It will only overwrite the libraries, classes, and scripts, and
@@ -394,7 +395,7 @@
 
     <copy todir="${quicksetup.classes.dir}">
         <fileset dir="${classes.dir}"
-            includes="**/DynamicConstants.class"/>
+            includes="**/DynamicConstants.class **/CreateTemplate.class"/>
     </copy>
 
     <!-- Generate the quicksetup.jar file -->
@@ -674,9 +675,9 @@
     <preptestng file="${testng.dir}/testng.xml"
                 tofile="${unittest.resource.dir}/testng.xml"
                 grouplist="${test.groups}" 
-		packagelist="${test.packages}"
+                packagelist="${test.packages}"
                 classList="${test.classes}" 
-		methodList="${test.methods}" />
+                methodList="${test.methods}" />
 
 
 
@@ -691,7 +692,7 @@
 
   <!-- Execute Directory Server TestNG unit tests specified from CLI -->
   <target name="testcustom"
-	  depends="testinit,runtests"
+          depends="testinit,runtests"
           description="Execute the Directory Server TestNG unit tests specified from CLI.">
   </target>
 
@@ -722,7 +723,7 @@
 
   <!-- Execute the Directory Server TestNG unit tests specified from CLI in text mode with a coverage report. -->
   <target name="testcustomwithcoverage"
-	  depends="coverage,testcustom"
+          depends="coverage,testcustom"
           description="Execute the Directory Server TestNG unit tests specified from CLI in text mode with a coverage report.">
   </target>
 
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index 12110c7..c80d437 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -44,6 +44,7 @@
 import org.opends.quicksetup.i18n.ResourceProvider;
 import org.opends.quicksetup.ui.UIFactory;
 import org.opends.quicksetup.util.Utils;
+import org.opends.server.util.CreateTemplate;
 
 /**
  * This is an abstract class that is in charge of actually performing the
@@ -708,76 +709,18 @@
    */
   protected File createTemplateFile() throws InstallException
   {
-    File templateFile = null;
-    String baseDn = getUserData().getDataOptions().getBaseDn();
-    int nEntries = getUserData().getDataOptions().getNumberEntries();
     try
     {
-      templateFile = File.createTempFile("opends-template-file", ".template");
-      templateFile.deleteOnExit();
-    } catch (IOException ioe)
+      return CreateTemplate.createTemplateFile(
+                  getUserData().getDataOptions().getBaseDn(),
+                  getUserData().getDataOptions().getNumberEntries());
+    }
+    catch (IOException ioe)
     {
       String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
       throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
           failedMsg, ioe);
     }
-
-    StringBuffer buf = new StringBuffer();
-    buf.append("define suffix=" + baseDn);
-    if (nEntries > 0)
-    {
-      buf.append("\ndefine numusers=" + nEntries);
-    }
-
-    buf.append("\n").append("\nbranch: [suffix]").append("\n");
-    buf.append("\nbranch: ou=People,[suffix]");
-
-    if (nEntries > 0)
-    {
-      buf.append("\nsubordinateTemplate: person:[numusers]")
-      .append("\n")
-          .append("\ntemplate: person")
-          .append("\nrdnAttr: uid")
-          .append("\nobjectClass: top")
-          .append("\nobjectClass: person")
-          .append("\nobjectClass: organizationalPerson")
-          .append("\nobjectClass: inetOrgPerson")
-          .append("\ngivenName: <first>")
-          .append("\nsn: <last>")
-          .append("\ncn: {givenName} {sn}")
-          .append("\ninitials: {givenName:1}")
-          .append("<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}")
-          .append("\nemployeeNumber: <sequential:0>")
-          .append("\nuid: user.{employeeNumber}")
-          .append("\nmail: {uid}@maildomain.net")
-          .append("\nuserPassword: password")
-          .append("\ntelephoneNumber: <random:telephone>")
-          .append("\nhomePhone: <random:telephone>")
-          .append("\npager: <random:telephone>")
-          .append("\nmobile: <random:telephone>")
-          .append("\nstreet: <random:numeric:5> <file:streets> Street")
-          .append("\nl: <file:cities>")
-          .append("\nst: <file:states>")
-          .append("\npostalCode: <random:numeric:5>")
-          .append("\npostalAddress: {cn}${street}${l}, {st}  {postalCode}")
-          .append("\ndescription: This is the description for {cn}.");
-    }
-
-    String path = templateFile.getAbsolutePath();
-    try
-    {
-      Utils.createFile(path, buf.toString());
-    } catch (IOException ioe)
-    {
-      String[] arg =
-        { path };
-      String failedMsg =
-          getExceptionMsg("error-writing-to-temp-file", arg, ioe);
-      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
-          failedMsg, ioe);
-    }
-
-    return templateFile;
   }
 
   /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
index ab7d1b9..59d2c03 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -18,6 +18,9 @@
 file containing data that should be added to\n    the Directory Server \
 database.  Multiple LDIF files may be provided by\n    using this option \
 multiple times.\n\
+-d {numEntries}  or   --sampleData {numEntries}\n    Specifies that the \
+database should be populated with the specified number\n\    of sample \
+entries.\n\
 -p {port}  or   --ldapPort {port}\n    Specifies the port on which the \
 Directory Server should listen for LDAP\n    communication.\n\
 -S  or   --skipPortCheck\n    Skip the check to determine whether the \
@@ -93,7 +96,7 @@
 directory-not-writable=You do not have write access on the directory {0}. \
 You must have file right access on the Installation directory.
 not-enough-disk-space=There is not enough free disk space under {0}.\nAt \
-least {1} megabytes of free disk space are required to install OpenDS.  
+least {1} megabytes of free disk space are required to install OpenDS.
 invalid-port-value-range=The LDAP Listener Port must be an integer between \
 {0} and {1}.
 cannot-bind-priviledged-port=Cannot bind to privileged port {0}.
@@ -102,7 +105,7 @@
 not-a-directory-manager-dn=The provided Administrative User DN is not a valid \
 DN.
 directory-manager-dn-is-config-dn=The provided Administrative User DN is \
-used for the configuration of the Directory Server. 
+used for the configuration of the Directory Server.
 not-equal-pwd=The passwords you have provided do not match.
 pwd-too-short=The minimum length required for the Administrative User \
 password is {0} characters.
@@ -152,9 +155,9 @@
 information-icon-tooltip=Information.
 
 #
-# Icon paths.  This is done to be able  to provide localizable icons (for 
+# Icon paths.  This is done to be able  to provide localizable icons (for
 # instance for those icons containing a text).  If there is not a localized
-# version of the icon it should be left as it is. 
+# version of the icon it should be left as it is.
 # The path specified here are the relative resource name to the images.
 #
 current-step-icon=images/currentstep.png
@@ -172,9 +175,9 @@
 #
 welcome-panel-title=Welcome
 # The following line contains some HTML tags.  translators should respect them.
-# Concerning the URL, depending on how works the product page translators 
-# have to modify it or not: if the server uses the locale of the browser to display 
-# a language there is no translation to be done but if we have specific URL for 
+# Concerning the URL, depending on how works the product page translators
+# have to modify it or not: if the server uses the locale of the browser to display
+# a language there is no translation to be done but if we have specific URL for
 # each language the URL must be localized.
 welcome-panel-instructions=The OpenDS QuickSetup tool will ask you for some \
 basic server and data configuration settings and will get your server up \
@@ -269,9 +272,9 @@
 #
 confirm-uninstall-panel-title=Confirm uninstall
 # The following line contains some HTML tags.  translators should respect them.
-# Concerning the URL, depending on how works the product page translators 
-# have to modify it or not: if the server uses the locale of the browser to display 
-# a language there is no translation to be done but if we have specific URL for 
+# Concerning the URL, depending on how works the product page translators
+# have to modify it or not: if the server uses the locale of the browser to display
+# a language there is no translation to be done but if we have specific URL for
 # each language the URL must be localized.
 confirm-uninstall-panel-instructions=The OpenDS Uninstall tool will \
 stop the OpenDS server if it is running and will delete all the user data \
@@ -362,4 +365,4 @@
 installstatus-installed=OpenDS Server Already Configured<br> \
 QuickSetup can only be used with OpenDS Servers that have not yet been \
 configured.  The current server:{0}
-installstatus-not-installed=The Directory Server is not installed.
\ No newline at end of file
+installstatus-not-installed=The Directory Server is not installed.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
index c0f0b5e..b76f13f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -7351,6 +7351,103 @@
 
 
   /**
+   * The message ID for the message that will be used as the description for the
+   * sampleData argument.  This does not take any arguments.
+   */
+  public static final int MSGID_INSTALLDS_DESCRIPTION_SAMPLE_DATA =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 753;
+
+
+
+  /**
+   * The message ID for the message that will be used as the heading when asking
+   * the user how to populate the database.  This does not take any arguments.
+   */
+  public static final int MSGID_INSTALLDS_HEADER_POPULATE_TYPE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 754;
+
+
+
+  /**
+   * The message ID for the message that will be used as the text for the
+   * populate option that will create only the base entry.  This does not take
+   * any arguments.
+   */
+  public static final int MSGID_INSTALLDS_POPULATE_OPTION_BASE_ONLY =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 755;
+
+
+
+  /**
+   * The message ID for the message that will be used as the text for the
+   * populate option that will leave the database emtpy.  This does not take any
+   * arguments.
+   */
+  public static final int MSGID_INSTALLDS_POPULATE_OPTION_LEAVE_EMPTY =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 756;
+
+
+
+  /**
+   * The message ID for the message that will be used as the text for the
+   * populate option that will import data from LDIF.  This does not take any
+   * arguments.
+   */
+  public static final int MSGID_INSTALLDS_POPULATE_OPTION_IMPORT_LDIF =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 757;
+
+
+
+  /**
+   * The message ID for the message that will be used as the text for the
+   * populate option that will create only the base entry.  This does not take
+   * any arguments.
+   */
+  public static final int MSGID_INSTALLDS_POPULATE_OPTION_GENERATE_SAMPLE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 758;
+
+
+
+  /**
+   * The message ID for the message that will be used as the text for the prompt
+   * asking the user how to populate the database.  This does not take any
+   * arguments.
+   */
+  public static final int MSGID_INSTALLDS_PROMPT_POPULATE_CHOICE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 759;
+
+
+
+  /**
+   * The message ID for the message that will be used to indicate that the
+   * specified LDIF file does not exist.  This takes a single argument, which is
+   * the specified LDIF file.
+   */
+  public static final int MSGID_INSTALLDS_NO_SUCH_LDIF_FILE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 780;
+
+
+
+  /**
+   * The message ID for the message that will be used as the prompt for the
+   * number of entries to generate.  This does not take any arguments.
+   */
+  public static final int MSGID_INSTALLDS_PROMPT_NUM_ENTRIES =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 781;
+
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs when
+   * trying to create the template for generating sample data.  This takes a
+   * single argument, which is a message explaining the problem that occurred.
+   */
+  public static final int MSGID_INSTALLDS_CANNOT_CREATE_TEMPLATE_FILE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 782;
+
+
+
+  /**
    * Associates a set of generic messages with the message IDs defined in this
    * class.
    */
@@ -8873,6 +8970,9 @@
                     "should be added to the Directory Server database.  " +
                     "Multiple LDIF files may be provided by using this " +
                     "option multiple times.");
+    registerMessage(MSGID_INSTALLDS_DESCRIPTION_SAMPLE_DATA,
+                    "Specifies that the database should be populated with " +
+                    "the specified number of sample entries.");
     registerMessage(MSGID_INSTALLDS_DESCRIPTION_LDAPPORT,
                     "Specifies the port on which the Directory Server should " +
                     "listen for LDAP communication.");
@@ -8995,6 +9095,25 @@
     registerMessage(MSGID_INSTALLDS_ERROR_READING_FROM_STDIN,
                     "ERROR:  Unexpected failure while reading from standard " +
                     "input:  %s.");
+    registerMessage(MSGID_INSTALLDS_HEADER_POPULATE_TYPE,
+                    "Options for populating the database:");
+    registerMessage(MSGID_INSTALLDS_POPULATE_OPTION_BASE_ONLY,
+                    "Only create the base entry");
+    registerMessage(MSGID_INSTALLDS_POPULATE_OPTION_LEAVE_EMPTY,
+                    "Leave the database empty");
+    registerMessage(MSGID_INSTALLDS_POPULATE_OPTION_IMPORT_LDIF,
+                    "Import data from an LDIF file");
+    registerMessage(MSGID_INSTALLDS_POPULATE_OPTION_GENERATE_SAMPLE,
+                    "Load automatically-generated sample data");
+    registerMessage(MSGID_INSTALLDS_PROMPT_POPULATE_CHOICE,
+                    "Database population selection:");
+    registerMessage(MSGID_INSTALLDS_NO_SUCH_LDIF_FILE,
+                    "ERROR:  The specified LDIF file %s does not exist.");
+    registerMessage(MSGID_INSTALLDS_PROMPT_NUM_ENTRIES,
+                    "Please specify the number of user entries to generate:");
+    registerMessage(MSGID_INSTALLDS_CANNOT_CREATE_TEMPLATE_FILE,
+                    "ERROR:  Cannot create the template file for generating " +
+                    "sample data:  %s.");
 
 
     registerMessage(MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/InstallDS.java b/opendj-sdk/opends/src/server/org/opends/server/tools/InstallDS.java
index a473c96..9358d71 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/InstallDS.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/InstallDS.java
@@ -41,6 +41,7 @@
 import org.opends.server.types.DN;
 import org.opends.server.types.ExistingFileBehavior;
 import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.util.CreateTemplate;
 import org.opends.server.util.LDIFWriter;
 import org.opends.server.util.PasswordReader;
 import org.opends.server.util.args.ArgumentException;
@@ -99,6 +100,35 @@
 
 
   /**
+   * The value that indicates that only the base entry should be created.
+   */
+  private static final int POPULATE_TYPE_BASE_ONLY = 1;
+
+
+
+  /**
+   * The value that indicates that the database should be left empty.
+   */
+  private static final int POPULATE_TYPE_LEAVE_EMPTY = 2;
+
+
+
+  /**
+   * The value that indicates that data should be imported from an LDIF file.
+   */
+  private static final int POPULATE_TYPE_IMPORT_FROM_LDIF = 3;
+
+
+
+  /**
+   * The value that indicates that the database should be populated with sample
+   * data.
+   */
+  private static final int POPULATE_TYPE_GENERATE_SAMPLE_DATA = 4;
+
+
+
+  /**
    * Invokes the <CODE>installMain</CODE> method with the provided arguments.
    *
    * @param  args  The command-line arguments to use for this program.
@@ -159,6 +189,7 @@
     BooleanArgument   skipPortCheck;
     FileBasedArgument rootPWFile;
     IntegerArgument   ldapPort;
+    IntegerArgument   sampleData;
     StringArgument    baseDN;
     StringArgument    configClass;
     StringArgument    configFile;
@@ -217,6 +248,12 @@
                                       MSGID_INSTALLDS_DESCRIPTION_IMPORTLDIF);
       argParser.addArgument(importLDIF);
 
+      sampleData = new IntegerArgument("sampledata", 'd', "sampleData", false,
+                                       false, true, "{numEntries}", 0, null,
+                                       true, 0, false, 0,
+                                       MSGID_INSTALLDS_DESCRIPTION_SAMPLE_DATA);
+      argParser.addArgument(sampleData);
+
       ldapPort = new IntegerArgument("ldapport", 'p', "ldapPort", false, false,
                                      true, "{port}", 389, null, true, 1, true,
                                      65535,
@@ -277,6 +314,36 @@
     }
 
 
+    // Make sure that the user didn't provide conflicting arguments.
+    if (addBaseEntry.isPresent())
+    {
+      if (importLDIF.isPresent())
+      {
+        int    msgID   = MSGID_TOOL_CONFLICTING_ARGS;
+        String message = getMessage(msgID, addBaseEntry.getLongIdentifier(),
+                                    importLDIF.getLongIdentifier());
+        System.err.println(wrapText(message, MAX_LINE_WIDTH));
+        return 1;
+      }
+      else if (sampleData.isPresent())
+      {
+        int    msgID   = MSGID_TOOL_CONFLICTING_ARGS;
+        String message = getMessage(msgID, addBaseEntry.getLongIdentifier(),
+                                    sampleData.getLongIdentifier());
+        System.err.println(wrapText(message, MAX_LINE_WIDTH));
+        return 1;
+      }
+    }
+    else if (importLDIF.isPresent() && sampleData.isPresent())
+    {
+      int    msgID   = MSGID_TOOL_CONFLICTING_ARGS;
+      String message = getMessage(msgID, importLDIF.getLongIdentifier(),
+                                  sampleData.getLongIdentifier());
+      System.err.println(wrapText(message, MAX_LINE_WIDTH));
+      return 1;
+    }
+
+
     // Make sure the path to the configuration file was given.
     String configFileName;
     if (configFile.isPresent())
@@ -357,128 +424,6 @@
     }
 
 
-    // Determine the directory base DN.
-    LinkedList<DN> baseDNs;
-    if (baseDN.isPresent())
-    {
-      baseDNs = new LinkedList<DN>();
-      for (String s : baseDN.getValues())
-      {
-        try
-        {
-          baseDNs.add(DN.decode(s));
-        }
-        catch (Exception e)
-        {
-          int    msgID   = MSGID_INSTALLDS_CANNOT_PARSE_DN;
-          String message = getMessage(msgID, s, e.getMessage());
-          System.err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-    }
-    else if (silentInstall.isPresent())
-    {
-      try
-      {
-        baseDNs = new LinkedList<DN>();
-        baseDNs.add(DN.decode(baseDN.getDefaultValue()));
-      }
-      catch (Exception e)
-      {
-        int    msgID   = MSGID_INSTALLDS_CANNOT_PARSE_DN;
-        String message = getMessage(msgID, baseDN.getDefaultValue(),
-                                    e.getMessage());
-        System.err.println(wrapText(message, MAX_LINE_WIDTH));
-        return 1;
-      }
-    }
-    else
-    {
-      int    msgID   = MSGID_INSTALLDS_PROMPT_BASEDN;
-      String message = getMessage(msgID);
-
-      baseDNs = new LinkedList<DN>();
-      baseDNs.add(promptForDN(message, baseDN.getDefaultValue()));
-    }
-
-
-    // Determine whether to import data from LDIF.
-    LinkedList<String> ldifFiles;
-    if (silentInstall.isPresent())
-    {
-      if (importLDIF.isPresent())
-      {
-        ldifFiles = importLDIF.getValues();
-      }
-      else
-      {
-        ldifFiles = null;
-      }
-    }
-    else if (importLDIF.isPresent())
-    {
-      ldifFiles = importLDIF.getValues();
-    }
-    else if (! baseDN.isPresent())
-    {
-      int     msgID          = MSGID_INSTALLDS_PROMPT_IMPORT;
-      String  message        = getMessage(msgID);
-      boolean importFromLDIF = promptForBoolean(message, false);
-
-      if (importFromLDIF)
-      {
-        msgID   = MSGID_INSTALLDS_PROMPT_IMPORT_FILE;
-        message = getMessage(msgID);
-
-        ldifFiles = new LinkedList<String>();
-        ldifFiles.add(promptForString(message, null));
-      }
-      else
-      {
-        ldifFiles = null;
-      }
-    }
-    else
-    {
-      ldifFiles = null;
-    }
-
-
-
-    // Determine whether to add the base entry.
-    boolean addBase;
-    if (addBaseEntry.isPresent())
-    {
-      addBase = true;
-
-      if ((ldifFiles != null) && (! ldifFiles.isEmpty()))
-      {
-        int msgID = MSGID_INSTALLDS_TWO_CONFLICTING_ARGUMENTS;
-        String message = getMessage(msgID, addBaseEntry.getLongIdentifier(),
-                                    importLDIF.getLongIdentifier());
-        System.err.println(wrapText(message, MAX_LINE_WIDTH));
-        return 1;
-      }
-    }
-    else if (silentInstall.isPresent() ||
-             ((ldifFiles != null) && (! ldifFiles.isEmpty())))
-    {
-      addBase = false;
-    }
-    else if (baseDN.isPresent())
-    {
-      addBase = false;
-    }
-    else
-    {
-      int    msgID   = MSGID_INSTALLDS_PROMPT_ADDBASE;
-      String message = getMessage(msgID, baseDNs.getFirst().toString());
-
-      addBase = promptForBoolean(message, true);
-    }
-
-
     // Determine the LDAP port number.
     int ldapPortNumber;
     if (silentInstall.isPresent() || ldapPort.isPresent())
@@ -619,6 +564,137 @@
     }
 
 
+    // Determine the directory base DN.
+    LinkedList<DN> baseDNs;
+    if (baseDN.isPresent())
+    {
+      baseDNs = new LinkedList<DN>();
+      for (String s : baseDN.getValues())
+      {
+        try
+        {
+          baseDNs.add(DN.decode(s));
+        }
+        catch (Exception e)
+        {
+          int    msgID   = MSGID_INSTALLDS_CANNOT_PARSE_DN;
+          String message = getMessage(msgID, s, e.getMessage());
+          System.err.println(wrapText(message, MAX_LINE_WIDTH));
+          return 1;
+        }
+      }
+    }
+    else if (silentInstall.isPresent())
+    {
+      try
+      {
+        baseDNs = new LinkedList<DN>();
+        baseDNs.add(DN.decode(baseDN.getDefaultValue()));
+      }
+      catch (Exception e)
+      {
+        int    msgID   = MSGID_INSTALLDS_CANNOT_PARSE_DN;
+        String message = getMessage(msgID, baseDN.getDefaultValue(),
+                                    e.getMessage());
+        System.err.println(wrapText(message, MAX_LINE_WIDTH));
+        return 1;
+      }
+    }
+    else
+    {
+      int    msgID   = MSGID_INSTALLDS_PROMPT_BASEDN;
+      String message = getMessage(msgID);
+
+      baseDNs = new LinkedList<DN>();
+      baseDNs.add(promptForDN(message, baseDN.getDefaultValue()));
+    }
+
+
+    // Determine how to populate the database.
+    int                populateType = POPULATE_TYPE_LEAVE_EMPTY;
+    int                numUsers     = -1;
+    LinkedList<String> ldifFiles    = null;
+    if (addBaseEntry.isPresent())
+    {
+      populateType = POPULATE_TYPE_BASE_ONLY;
+    }
+    else if (importLDIF.isPresent())
+    {
+      ldifFiles    = importLDIF.getValues();
+      populateType = POPULATE_TYPE_IMPORT_FROM_LDIF;
+    }
+    else if (sampleData.isPresent())
+    {
+      try
+      {
+        numUsers     = sampleData.getIntValue();
+        populateType = POPULATE_TYPE_GENERATE_SAMPLE_DATA;
+      }
+      catch (Exception e)
+      {
+        // This should never happen.
+        e.printStackTrace();
+        return 1;
+      }
+    }
+    else if (silentInstall.isPresent())
+    {
+      populateType = POPULATE_TYPE_LEAVE_EMPTY;
+    }
+    else
+    {
+      int msgID = MSGID_INSTALLDS_HEADER_POPULATE_TYPE;
+      System.out.println(wrapText(getMessage(msgID), MAX_LINE_WIDTH));
+
+      msgID = MSGID_INSTALLDS_POPULATE_OPTION_BASE_ONLY;
+      System.out.println(wrapText("1.  " + getMessage(msgID), MAX_LINE_WIDTH));
+
+      msgID = MSGID_INSTALLDS_POPULATE_OPTION_LEAVE_EMPTY;
+      System.out.println(wrapText("2.  " + getMessage(msgID), MAX_LINE_WIDTH));
+
+      msgID = MSGID_INSTALLDS_POPULATE_OPTION_IMPORT_LDIF;
+      System.out.println(wrapText("3.  " + getMessage(msgID), MAX_LINE_WIDTH));
+
+      msgID = MSGID_INSTALLDS_POPULATE_OPTION_GENERATE_SAMPLE;
+      System.out.println(wrapText("4.  " + getMessage(msgID), MAX_LINE_WIDTH));
+
+      msgID = MSGID_INSTALLDS_PROMPT_POPULATE_CHOICE;
+      populateType = promptForInteger(getMessage(msgID), 1, 1, 4);
+      System.out.println();
+
+      if (populateType == POPULATE_TYPE_IMPORT_FROM_LDIF)
+      {
+        ldifFiles = new LinkedList<String>();
+        while (true)
+        {
+          msgID = MSGID_INSTALLDS_PROMPT_IMPORT_FILE;
+          String message = getMessage(msgID);
+          String path    = promptForString(message, "");
+          if (new File(path).exists())
+          {
+            ldifFiles.add(path);
+            System.out.println();
+            break;
+          }
+          else
+          {
+            msgID   = MSGID_INSTALLDS_NO_SUCH_LDIF_FILE;
+            message = getMessage(msgID, path);
+            System.err.println(wrapText(message, MAX_LINE_WIDTH));
+            System.err.println();
+          }
+        }
+      }
+      else if (populateType == POPULATE_TYPE_GENERATE_SAMPLE_DATA)
+      {
+        msgID = MSGID_INSTALLDS_PROMPT_NUM_ENTRIES;
+        String message = getMessage(msgID);
+        numUsers = promptForInteger(message, 2000, 0, Integer.MAX_VALUE);
+        System.out.println();
+      }
+    }
+
+
     // At this point, we should be able to invoke the ConfigureDS utility to
     // apply the requested configuration.
     ArrayList<String> argList = new ArrayList<String>();
@@ -662,8 +738,8 @@
     }
 
 
-    // If we should import data or add the base entry, then do so now.
-    if (addBase)
+    // If we need to create a base LDIF file or a template file, then do so now.
+    if (populateType == POPULATE_TYPE_BASE_ONLY)
     {
       // Create a temporary LDIF file that will hold the entry to add.
       if (! silentInstall.isPresent())
@@ -692,8 +768,8 @@
         if (ldifFiles == null)
         {
           ldifFiles = new LinkedList<String>();
-          ldifFiles.add(ldifFilePath);
         }
+        ldifFiles.add(ldifFilePath);
       }
       catch (Exception e)
       {
@@ -704,6 +780,27 @@
         return 1;
       }
     }
+    else if (populateType == POPULATE_TYPE_GENERATE_SAMPLE_DATA)
+    {
+      try
+      {
+        File templateFile = CreateTemplate.createTemplateFile(
+                                 baseDNs.getFirst().toString(), numUsers);
+        if (ldifFiles == null)
+        {
+          ldifFiles = new LinkedList<String>();
+        }
+        ldifFiles.add(templateFile.getAbsolutePath());
+      }
+      catch (Exception e)
+      {
+        int    msgID   = MSGID_INSTALLDS_CANNOT_CREATE_TEMPLATE_FILE;
+        String message = getMessage(msgID, String.valueOf(e));
+
+        System.err.println(wrapText(message, MAX_LINE_WIDTH));
+        return 1;
+      }
+    }
 
     if ((ldifFiles != null) && (! ldifFiles.isEmpty()))
     {
@@ -724,11 +821,24 @@
 
       for (String s : ldifFiles)
       {
-        argList.add("-l");
+        if (populateType == POPULATE_TYPE_GENERATE_SAMPLE_DATA)
+        {
+          argList.add("-t");
+        }
+        else
+        {
+          argList.add("-l");
+        }
         argList.add(s);
       }
 
-      if (addBase)
+      if (populateType == POPULATE_TYPE_GENERATE_SAMPLE_DATA)
+      {
+        argList.add("-S");
+        argList.add("0");
+      }
+
+      if (populateType == POPULATE_TYPE_BASE_ONLY)
       {
         argList.add("-q");
       }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/CreateTemplate.java b/opendj-sdk/opends/src/server/org/opends/server/util/CreateTemplate.java
new file mode 100644
index 0000000..dfb05a7
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/CreateTemplate.java
@@ -0,0 +1,119 @@
+/*
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  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
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.util;
+
+
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.LinkedList;
+
+
+
+/**
+ * This class may be used to generate a MakeLDIF template with a specified base
+ * DN and number of user entries.
+ */
+public class CreateTemplate
+{
+  /**
+   * Creates a MakeLDIF template file using the provided information.
+   *
+   * @param  baseDN      The base DN for the data in the template file.
+   * @param  numEntries  The number of user entries the template file should
+   *                     create.
+   *
+   * @return  The {@code File} object that references the created template file.
+   *
+   * @throws  IOException  If a problem occurs while writing the template file.
+   */
+  public static File createTemplateFile(String baseDN, int numEntries)
+         throws IOException
+  {
+    File templateFile = File.createTempFile("opends-install", ".template");
+    templateFile.deleteOnExit();
+
+    LinkedList<String> lines = new LinkedList<String>();
+    lines.add("define suffix=" + baseDN);
+
+    if (numEntries > 0)
+    {
+      lines.add("define numusers=" + numEntries);
+    }
+
+    lines.add("");
+    lines.add("branch: [suffix]");
+    lines.add("");
+    lines.add("branch: ou=People,[suffix]");
+
+    if (numEntries > 0)
+    {
+      lines.add("subordinateTemplate: person:[numusers]");
+      lines.add("");
+      lines.add("template: person");
+      lines.add("rdnAttr: uid");
+      lines.add("objectClass: top");
+      lines.add("objectClass: person");
+      lines.add("objectClass: organizationalPerson");
+      lines.add("objectClass: inetOrgPerson");
+      lines.add("givenName: <first>");
+      lines.add("sn: <last>");
+      lines.add("cn: {givenName} {sn}");
+      lines.add("initials: {givenName:1}" +
+                "<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}");
+      lines.add("employeeNumber: <sequential:0>");
+      lines.add("uid: user.{employeeNumber}");
+      lines.add("mail: {uid}@maildomain.net");
+      lines.add("userPassword: password");
+      lines.add("telephoneNumber: <random:telephone>");
+      lines.add("homePhone: <random:telephone>");
+      lines.add("pager: <random:telephone>");
+      lines.add("mobile: <random:telephone>");
+      lines.add("street: <random:numeric:5> <file:streets> Street");
+      lines.add("l: <file:cities>");
+      lines.add("st: <file:states>");
+      lines.add("postalCode: <random:numeric:5>");
+      lines.add("postalAddress: {cn}${street}${l}, {st}  {postalCode}");
+      lines.add("description: This is the description for {cn}.");
+    }
+
+    BufferedWriter writer = new BufferedWriter(new FileWriter(templateFile));
+    for (String line : lines)
+    {
+      writer.write(line);
+      writer.newLine();
+    }
+
+    writer.flush();
+    writer.close();
+
+    return templateFile;
+  }
+}
+

--
Gitblit v1.10.0