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

neil_a_wilson
31.40.2006 7dc2e6ceaaf74ff2cd8b6a8a3964097cffe1f475
Add initial MakeLDIF support for generating entries based on a template.  This
can be used to either write the generated entries to LDIF, or to import them
directly into the server. This code is not yet feature-complete, nor is it
100% compatible with the version of MakeLDIF provided with SLAMD, but it is
functional enough for use in a large number of situations.

OpenDS Issue Number: 588
37 files added
6 files modified
31925 ■■■■■ changed files
opends/build.xml 5 ●●●●● patch | view | raw | blame | history
opends/resource/MakeLDIF/cities 232 ●●●●● patch | view | raw | blame | history
opends/resource/MakeLDIF/example.template 34 ●●●●● patch | view | raw | blame | history
opends/resource/MakeLDIF/first.names 8605 ●●●●● patch | view | raw | blame | history
opends/resource/MakeLDIF/last.names 13419 ●●●●● patch | view | raw | blame | history
opends/resource/MakeLDIF/states 51 ●●●●● patch | view | raw | blame | history
opends/resource/MakeLDIF/streets 74 ●●●●● patch | view | raw | blame | history
opends/resource/bin/makeldif.bat 57 ●●●●● patch | view | raw | blame | history
opends/resource/bin/makeldif.sh 75 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/config/ConfigConstants.java 9 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ToolMessages.java 1029 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ImportLDIF.java 97 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/AttributeValueTag.java 272 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/Branch.java 450 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/DNTag.java 234 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/EntryWriter.java 68 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/FileTag.java 268 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/FirstNameTag.java 138 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/GUIDTag.java 164 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/IfAbsentTag.java 229 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/IfPresentTag.java 229 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/LastNameTag.java 138 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/MakeLDIF.java 424 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFException.java 95 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFInputStream.java 293 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFInputStreamThread.java 92 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/ParentDNTag.java 138 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/PresenceTag.java 218 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/RDNTag.java 172 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/RandomTag.java 696 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/SequentialTag.java 257 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/StaticTextTag.java 172 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/Tag.java 137 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TagResult.java 166 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/Template.java 393 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateEntry.java 332 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateFile.java 1759 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateLine.java 136 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateValue.java 108 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/UnderscoreDNTag.java 241 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/UnderscoreParentDNTag.java 146 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/AttributeType.java 50 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/LDIFImportConfig.java 23 ●●●●● patch | view | raw | blame | history
opends/build.xml
@@ -412,6 +412,7 @@
    <mkdir dir="${pdir}/config"          />
    <mkdir dir="${pdir}/config/schema"   />
    <mkdir dir="${pdir}/config/messages" />
    <mkdir dir="${pdir}/config/MakeLDIF" />
    <mkdir dir="${pdir}/db"              />
    <mkdir dir="${pdir}/changelogDb"     />
    <mkdir dir="${pdir}/ldif"            />
@@ -444,6 +445,10 @@
      <fileset dir="${resource.dir}/messages" />
    </copy>
    <copy todir="${pdir}/config/MakeLDIF">
      <fileset dir="${resource.dir}/MakeLDIF" />
    </copy>
    <copy todir="${pdir}/legal-notices">
      <fileset dir="${resource.dir}/legal-notices" />
    </copy>
opends/resource/MakeLDIF/cities
New file
@@ -0,0 +1,232 @@
Abilene
Albany
Albuquerque
Alexandria
Alpena
Altoona
Amarillo
Anchorage
Anniston
Ardmore
Atlanta
Augusta
Austin
Bakersfield
Baltimore
Bangor
Baton Rouge
Beaumont
Bend
Billings
Biloxi
Binghamton
Birmingham
Bismarck
Bloomington
Bluefield
Boise
Boston
Bowling Green
Bryan
Buffalo
Burlington
Butte
Cadillac
Casper
Cedar Rapids
Champaign
Charleston
Charlotte
Charlottesville
Chattanooga
Cheyenne
Chicago
Chico
Cincinnati
Clarksburg
Cleveland
College Station
Colorado Springs
Columbia
Columbus
Corpus Christi
Dallas
Davenport
Dayton
Denver
Des Moines
Detroit
Dothan
Duluth
Durham
Eau Claire
Elmira
El Paso
Erie
Eugene
Eureka
Evansville
Fairbanks
Fargo
Flint
Florence
Fort Myers
Fort Smith
Fort Wayne
Fort Worth
Fresno
Gainesville
Glendive
Grand Junction
Grand Rapids
Great Falls
Green Bay
Greenville
Hampton Roads
Harlingen
Harrisburg
Harrisonburg
Hartford
Hattiesburg
Helena
Honolulu
Houston
Huntington
Huntsville
Idaho Falls
Indianapolis
Jackson
Jacksonville
Jefferson City
Johnstown
Jonesboro
Joplin
Kansas City
Kirksville
Klamath Falls
Knoxville
La Crosse
Lafayette
Lake Charles
Lansing
Laredo
Las Vegas
Lawton
Lexington
Lima
Lincoln
Little Rock
Los Angeles
Louisville
Lubbock
Lynchburg
Macon
Madison
Mankato
Marquette
Mason City
Medford
Memphis
Meridian
Miami
Milwaukee
Minneapolis
Missoula
Mobile
Moline
Monroe
Monterey Bay Area
Montgomery
Naples
Nashville
New Haven
New Orleans
New York
North Platte
Odessa
Oklahoma City
Omaha
Orlando
Ottumwa
Paducah
Palm Springs
Panama City
Parkersburg
Pensacola
Peoria
Philadelphia
Phoenix
Pittsburgh
Pocatello
Port Arthur
Portland
Presque Isle
Providence
Pueblo
Quincy
Raleigh
Rapid City
Redding
Reno
Rhinelander
Richmond
Riverton
Roanoke
Rochester
Rockford
Sacramento
Saginaw
Saint Joseph
Saint Louis
Saint Paul
Salem
Salisbury
Salt Lake City
San Angelo
San Antonio
San Diego
Santa Barbara
Santa Fe
Savannah
Scranton
Seattle
Shreveport
Sioux City
Sioux Falls
South Bend
Spartanburg
Spokane
Springfield
Steubenville
Superior
Syracuse
Tallahassee
Tampa Bay
Terre Haute
Toledo
Topeka
Traverse City
Tucson
Tulsa
Tupelo
Tuscaloosa
Twin Falls
Tyler
Urbana
Utica
Victoria
Waterloo
Watertown
Wausau
Weston
West Palm Beach
Wheeling
Wichita
Wichita Falls
Wichita FallsLawton
Wilkes Barre
Wilmington
Winston
Youngstown
Yuma
Zanesville
opends/resource/MakeLDIF/example.template
New file
@@ -0,0 +1,34 @@
define suffix=dc=example,dc=com
define maildomain=example.com
define numusers=10001
branch: [suffix]
branch: ou=People,[suffix]
subordinateTemplate: person:[numusers]
template: person
rdnAttr: uid
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
givenName: <first>
sn: <last>
cn: {givenName} {sn}
initials: {givenName:1}<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}
employeeNumber: <sequential:0>
uid: user.{employeeNumber}
mail: {uid}@[maildomain]
userPassword: password
telephoneNumber: <random:telephone>
homePhone: <random:telephone>
pager: <random:telephone>
mobile: <random:telephone>
street: <random:numeric:5> <file:streets> Street
l: <file:cities>
st: <file:states>
postalCode: <random:numeric:5>
postalAddress: {cn}${street}${l}, {st}  {postalCode}
description: This is the description for {cn}.
opends/resource/MakeLDIF/first.names
New file
Diff too large
opends/resource/MakeLDIF/last.names
New file
Diff too large
opends/resource/MakeLDIF/states
New file
@@ -0,0 +1,51 @@
AL
AK
AZ
AR
CA
CO
CT
DE
DC
FL
GA
HI
ID
IL
IN
IA
KS
KY
LA
ME
MD
MA
MI
MN
MS
MO
MT
NE
NV
NH
NJ
NM
NY
NC
ND
OH
OK
OR
PA
RI
SC
SD
TN
TX
UT
VT
VA
WA
WV
WI
WY
opends/resource/MakeLDIF/streets
New file
@@ -0,0 +1,74 @@
Adams
Ash
Birch
Broadway
Cedar
Center
Central
Cherry
Chestnut
Church
College
Davis
Dogwood
East
Eighth
Eleventh
Elm
Fifteenth
Fifth
First
Forest
Fourteenth
Fourth
Franklin
Green
Hickory
Highland
Hill
Hillcrest
Jackson
Jefferson
Johnson
Lake
Lakeview
Laurel
Lee
Lincoln
Locust
Madison
Main
Maple
Meadow
Mill
Miller
Ninth
North
Oak
Park
Pine
Poplar
Railroad
Ridge
River
Second
Seventh
Sixth
South
Spring
Spruce
Sunset
Sycamore
Taylor
Tenth
Third
Thirteenth
Twelfth
Valley
Walnut
Washington
West
Williams
Willow
Wilson
Woodland
opends/resource/bin/makeldif.bat
New file
@@ -0,0 +1,57 @@
@echo off
rem CDDL HEADER START
rem
rem The contents of this file are subject to the terms of the
rem Common Development and Distribution License, Version 1.0 only
rem (the "License").  You may not use this file except in compliance
rem with the License.
rem
rem You can obtain a copy of the license at
rem trunk/opends/resource/legal-notices/OpenDS.LICENSE
rem or https://OpenDS.dev.java.net/OpenDS.LICENSE.
rem See the License for the specific language governing permissions
rem and limitations under the License.
rem
rem When distributing Covered Code, include this CDDL HEADER in each
rem file and include the License file at
rem trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
rem add the following below this CDDL HEADER, with the fields enclosed
rem by brackets "[]" replaced with your own identifying * information:
rem      Portions Copyright [yyyy] [name of copyright owner]
rem
rem CDDL HEADER END
rem
rem
rem      Portions Copyright 2006 Sun Microsystems, Inc.
setlocal
set DIR_HOME=%~dP0..
set INSTANCE_ROOT=%DIR_HOME%
if "%JAVA_BIN%" == "" goto noJavaBin
goto setClassPath
:noJavaBin
if "%JAVA_HOME%" == "" goto noJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
set JAVA_BIN="%JAVA_HOME%\bin\java.exe"
goto setClassPath
:noJavaHome
echo Error: JAVA_HOME environment variable is not set.
echo        Please set it to a valid Java 5 installation.
goto end
:setClassPath
FOR %%x in (%DIR_HOME%\lib\*.jar) DO call "%DIR_HOME%\bin\setcp.bat" %%x
cd %DIR_HOME%
%JAVA_BIN% %JAVA_ARGS% -classpath "%CLASSPATH%" org.opends.server.tools.makeldif.MakeLDIF --configClass org.opends.server.config.ConfigFileHandler --configFile %DIR_HOME%\config\config.ldif --resourcePath %DIR_HOME%\config\MakeLDIF %*
:end
opends/resource/bin/makeldif.sh
New file
@@ -0,0 +1,75 @@
#!/bin/sh
#
# 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.
# Capture the current working directory so that we can change to it later.
# Then apture the location of this script and the Directory Server instance
# root so that we can use them to create appropriate paths.
WORKING_DIR=`pwd`
cd `dirname $0`
SCRIPT_DIR=`pwd`
cd ..
INSTANCE_ROOT=`pwd`
export INSTANCE_ROOT
cd ${WORKING_DIR}
# See if JAVA_HOME is set.  If not, then see if there is a java executable in
# the path and try to figure it out.
if test -z "${JAVA_BIN}"
then
  if test -z "${JAVA_HOME}"
  then
    JAVA_BIN=`which java 2> /dev/null`
    if test $? -eq 0
    then
      export JAVA_BIN
    else
      echo "Please set JAVA_HOME to the root of a Java 5.0 installation."
      exit 1
    fi
  else
    JAVA_BIN=${JAVA_HOME}/bin/java
    export JAVA_BIN
  fi
fi
CLASSPATH=${INSTANCE_ROOT}/classes
for JAR in ${INSTANCE_ROOT}/lib/*.jar
do
    CLASSPATH=${CLASSPATH}:${JAR}
done
export CLASSPATH
${JAVA_BIN} ${JAVA_ARGS} org.opends.server.tools.makeldif.MakeLDIF \
     --configClass org.opends.server.config.ConfigFileHandler \
     --configFile ${INSTANCE_ROOT}/config/config.ldif \
     --resourcePath ${INSTANCE_ROOT}/config/MakeLDIF "${@}"
opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -3226,6 +3226,15 @@
  /**
   * The path to the directory that should serve as the MakeLDIF resource
   * directory.  It is relative to the server root.
   */
  public static final String PATH_MAKELDIF_RESOURCE_DIR =
       "config" + File.separator + "MakeLDIF";
  /**
   * The path to the directory containing the server schema definitions.  It is
   * relative to the server root.
   */
opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -2148,9 +2148,9 @@
  /**
   * The message ID for the message that will be used a requested include base
   * does not exist in the targeted backend.  This takes two arguments, which
   * are the specified include branch DN and the requested backend ID.
   * The message ID for the message that will be used if a requested include
   * base does not exist in the targeted backend.  This takes two arguments,
   * which are the specified include branch DN and the requested backend ID.
   */
  public static final int MSGID_LDIFIMPORT_INVALID_INCLUDE_BASE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 219;
@@ -5233,6 +5233,776 @@
  /**
   * The message ID for the message that will be used if an invalid number of
   * arguments were provided for a MakeLDIF tag.  This takes four arguments,
   * which are the name of the tag, the line number on which it appears, the
   * expected number of arguments, and the actual number of arguments.
   */
  public static final int MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 535;
  /**
   * The message ID for the message that will be used if an invalid number of
   * arguments were provided for a MakeLDIF tag, when a range of arguments are
   * allowed.  This takes five arguments, which are the name of the tag, the
   * line number on which it appears, the minimum number of expected arguments,
   * the maximum number of expected arguments, and the actual number of
   * arguments.
   */
  public static final int MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 536;
  /**
   * The message ID for the message that will be used if an undefined attribute
   * type is referenced in a template file.  This takes two arguments, which are
   * the name of the attribute type and the line number on which it appears.
   */
  public static final int MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 537;
  /**
   * The message ID for the message that will be used if an integer value is
   * below the allowed lower bound.  This takes four arguments, which are the
   * provided integer value, the lower bound, the tag name, and the line number
   * on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 538;
  /**
   * The message ID for the message that will be used if value cannot be parsed
   * as an integer.  This takes three arguments, which are the provided value,
   * the tag name, and the line number on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 539;
  /**
   * The message ID for the message that will be used if an integer value is
   * above the allowed upper bound.  This takes four arguments, which are the
   * provided integer value, the upper bound, the tag name, and the line number
   * on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_INTEGER_ABOVE_UPPER_BOUND =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 540;
  /**
   * The message ID for the message that will be used if a tag argument is an
   * empty string, which is not allowed.  This takes three arguments, which is
   * the position of the argument, the tag name, and the line number on which
   * it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_INVALID_EMPTY_STRING_ARGUMENT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 541;
  /**
   * The message ID for the message that will be used if a value cannot be
   * parsed as a Boolean.  This takes three arguments, which are the provided
   * value, the tag name, and the line number on which it appears in the
   * template file.
   */
  public static final int MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_BOOLEAN =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 542;
  /**
   * The message ID for the message that will be used if a branch references an
   * undefined subordinate template.  This takes two arguments, which are the DN
   * of the branch entry and the name of the undefined template.
   */
  public static final int MSGID_MAKELDIF_UNDEFINED_BRANCH_SUBORDINATE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 543;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to load a class for use as a tag.  This takes a single argument,
   * which is the name of the class.
   */
  public static final int MSGID_MAKELDIF_CANNOT_LOAD_TAG_CLASS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 544;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to instantiate a class for use as a tag.  This takes a single
   * argument, which is the name of the class.
   */
  public static final int MSGID_MAKELDIF_CANNOT_INSTANTIATE_TAG =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 545;
  /**
   * The message ID for the message that will be used if an attempt is made to
   * register a new tag with a conflicting name.  This takes two arguments,
   * which are the name of the class and the name of the tag.
   */
  public static final int MSGID_MAKELDIF_CONFLICTING_TAG_NAME =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 546;
  /**
   * The message ID for the message that will be used if a potential undefined
   * constant is used in the template file.  This takes two arguments, which are
   * the name of the constant and the line number on which it is used.
   */
  public static final int MSGID_MAKELDIF_WARNING_UNDEFINED_CONSTANT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_WARNING | 547;
  /**
   * The message ID for the message that will be used if a constant definition
   * does not include an equal sign.  This takes a single argument, which is the
   * line number on which it appears.
   */
  public static final int MSGID_MAKELDIF_DEFINE_MISSING_EQUALS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 548;
  /**
   * The message ID for the message that will be used if a constant definition
   * does not include a name.  This takes a single argument, which is the line
   * number on which it appears.
   */
  public static final int MSGID_MAKELDIF_DEFINE_NAME_EMPTY =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 549;
  /**
   * The message ID for the message that will be used if a constant definition
   * has a name that conflicts with another constant.  This takes two arguments,
   * which are the name of the constant and the line number on which the
   * conflict was detected.
   */
  public static final int MSGID_MAKELDIF_CONFLICTING_CONSTANT_NAME =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 550;
  /**
   * The message ID for the message that will be used if a constant definition
   * does not have a value.  This takes two arguments, which are the name of the
   * constant and the line number on which it is defined.
   */
  public static final int MSGID_MAKELDIF_WARNING_DEFINE_VALUE_EMPTY =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 551;
  /**
   * The message ID for the message that will be used if a branch definition
   * has a DN that conflicts with another branch.  This takes two arguments,
   * which are the branch DN and the line number on which the conflict was
   * detected.
   */
  public static final int MSGID_MAKELDIF_CONFLICTING_BRANCH_DN =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 552;
  /**
   * The message ID for the message that will be used if a template definition
   * has a name that conflicts with another template.  This takes two arguments,
   * which are the template name and the line number on which the conflict was
   * detected.
   */
  public static final int MSGID_MAKELDIF_CONFLICTING_TEMPLATE_NAME =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 553;
  /**
   * The message ID for the message that will be used if an unrecognized line
   * was found in the template file.  This takes two arguments, which are the
   * content of the line and the line number on which it was found.
   */
  public static final int MSGID_MAKELDIF_UNEXPECTED_TEMPLATE_FILE_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 554;
  /**
   * The message ID for the message that will be used if a template references
   * an undefined subordinate template.  This takes two arguments, which are the
   * name of the parent template and the name of the undefined subordinate
   * template.
   */
  public static final int MSGID_MAKELDIF_UNDEFINED_TEMPLATE_SUBORDINATE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 555;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to parse the branch DN.  This takes two arguments, which are the DN
   * string and the line number on which it appears.
   */
  public static final int MSGID_MAKELDIF_CANNOT_DECODE_BRANCH_DN =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 556;
  /**
   * The message ID for the message that will be used if a subordinate template
   * definition does not include a colon.  This takes two arguments, which are
   * the line number and the branch DN.
   */
  public static final int MSGID_MAKELDIF_BRANCH_SUBORDINATE_TEMPLATE_NO_COLON =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 557;
  /**
   * The message ID for the message that will be used if a subordinate template
   * specifies an invalid number of entries.  This takes four arguments, which
   * are the line number, the branch DN, the invalid number of entries, and the
   * subordinate template name.
   */
  public static final int
       MSGID_MAKELDIF_BRANCH_SUBORDINATE_INVALID_NUM_ENTRIES =
            CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 558;
  /**
   * The message ID for the message that will be used if there are zero entries
   * to be created for a subordinate template.  This takes three arguments,
   * which are the line number, the branch DN, and the subordinate template
   * name.
   */
  public static final int MSGID_MAKELDIF_BRANCH_SUBORDINATE_ZERO_ENTRIES =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_WARNING | 559;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to parse the number of entries for a subordinate template.  This
   * takes three arguments, which are the template name, the line number, and
   * the branch DN.
   */
  public static final int
       MSGID_MAKELDIF_BRANCH_SUBORDINATE_CANT_PARSE_NUMENTRIES =
            CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 560;
  /**
   * The message ID for the message that will be used if a subordinate template
   * definition does not include a colon.  This takes two arguments, which are
   * the line number and the template name.
   */
  public static final int
       MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_TEMPLATE_NO_COLON =
            CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 561;
  /**
   * The message ID for the message that will be used if a subordinate template
   * specifies an invalid number of entries.  This takes four arguments, which
   * are the line number, the template name, the invalid number of entries, and
   * the subordinate template name.
   */
  public static final int
       MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_INVALID_NUM_ENTRIES =
            CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 562;
  /**
   * The message ID for the message that will be used if there are zero entries
   * to be created for a subordinate template.  This takes three arguments,
   * which are the line number, the template name, and the subordinate template
   * name.
   */
  public static final int MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_ZERO_ENTRIES =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_WARNING | 563;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to parse the number of entries for a subordinate template.  This
   * takes three arguments, which are the subordinate template name, the line
   * number, and the template name.
   */
  public static final int
       MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_CANT_PARSE_NUMENTRIES =
            CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 564;
  /**
   * The message ID for the message that will be used if a template references
   * an undefined RDN attribute.  This takes two arguments, which are the
   * name of the parent template and the name of the undefined RDN attribute.
   */
  public static final int MSGID_MAKELDIF_TEMPLATE_MISSING_RDN_ATTR =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 565;
  /**
   * The message ID for the message that will be used if a branch definition has
   * an extra line with no colon to separate the attribute type from the value
   * pattern.  This takes two arguments, which are the line number in the
   * template file and the branch DN.
   */
  public static final int MSGID_MAKELDIF_NO_COLON_IN_BRANCH_EXTRA_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 566;
  /**
   * The message ID for the message that will be used if a branch definition has
   * an extra line with no attribute type .  This takes two arguments, which are
   * the line number in the  template file and the branch DN.
   */
  public static final int MSGID_MAKELDIF_NO_ATTR_IN_BRANCH_EXTRA_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 567;
  /**
   * The message ID for the message that will be used if a branch definition has
   * an extra line with no value.  This takes two arguments, which are the line
   * number in the  template file and the branch DN.
   */
  public static final int MSGID_MAKELDIF_NO_VALUE_IN_BRANCH_EXTRA_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_WARNING | 568;
  /**
   * The message ID for the message that will be used if a template definition
   * has a line with no colon to separate the attribute type from the value
   * pattern.  This takes two arguments, which are the line number in the
   * template file and the template name.
   */
  public static final int MSGID_MAKELDIF_NO_COLON_IN_TEMPLATE_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 569;
  /**
   * The message ID for the message that will be used if a template definition
   * has a line with no attribute type .  This takes two arguments, which are
   * the line number in the  template file and the template name.
   */
  public static final int MSGID_MAKELDIF_NO_ATTR_IN_TEMPLATE_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 570;
  /**
   * The message ID for the message that will be used if a template definition
   * has a line with no value.  This takes two arguments, which are the line
   * number in the  template file and the template name.
   */
  public static final int MSGID_MAKELDIF_NO_VALUE_IN_TEMPLATE_LINE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_WARNING | 571;
  /**
   * The message ID for the message that will be used if a template definition
   * references an undefined tag.  This takes two arguments, which are the name
   * of the tag and the line number on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_NO_SUCH_TAG =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 572;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to create a new tag instance.  This takes three arguments, which are
   * the tag name, the line number, and a message explaining the problem that
   * occurred.
   */
  public static final int MSGID_MAKELDIF_CANNOT_INSTANTIATE_NEW_TAG =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 573;
  /**
   * The message ID for the message that will be used as the description of the
   * configFile argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_CONFIG_FILE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 574;
  /**
   * The message ID for the message that will be used as the description of the
   * configClass argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_CONFIG_CLASS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 575;
  /**
   * The message ID for the message that will be used as the description of the
   * templateFile argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_TEMPLATE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 576;
  /**
   * The message ID for the message that will be used as the description of the
   * ldifFile argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_LDIF =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 577;
  /**
   * The message ID for the message that will be used as the description of the
   * randomSeed argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_SEED =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 578;
  /**
   * The message ID for the message that will be used as the description of the
   * help argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_HELP =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 579;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to initialize the command-line argument parser.  This takes a
   * single argument, which is a message explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_CANNOT_INITIALIZE_ARGS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 580;
  /**
   * The message ID for the message that will be used if an error occurs while
   * parsing the provided command-line arguments.  This takes a single argument,
   * which is a message explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_ERROR_PARSING_ARGS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 581;
  /**
   * The message ID for the message that will be used if an error occurs while
   * initializing the Directory Server JMX subsystem.  This takes two arguments,
   * which are the path to the Directory Server configuration file and a message
   * explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_CANNOT_INITIALIZE_JMX =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 582;
  /**
   * The message ID for the message that will be used if an error occurs while
   * initializing the Directory Server configuration.  This takes two
   * arguments, which are the path to the Directory Server configuration file
   * and a message explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_CANNOT_INITIALIZE_CONFIG =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 583;
  /**
   * The message ID for the message that will be used if an error occurs while
   * initializing the Directory Server schema.  This takes two arguments, which
   * are the path to the Directory Server configuration file and a message
   * explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_CANNOT_INITIALIZE_SCHEMA =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 584;
  /**
   * The message ID for the message that will be used if an I/O exception was
   * thrown while trying to load the template file.  This takes a single
   * argument, which is a message explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_IOEXCEPTION_DURING_PARSE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 585;
  /**
   * The message ID for the message that will be used if a non-I/O exception was
   * thrown while trying to load the template file.  This takes a single
   * argument, which is a message explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_EXCEPTION_DURING_PARSE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 586;
  /**
   * The message ID for the message that will be used if a value cannot be
   * parsed as a format string.  This takes three arguments, which are the
   * provided value, the tag name, and the line number on which it appears in
   * the  template file.
   */
  public static final int MSGID_MAKELDIF_TAG_INVALID_FORMAT_STRING =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 587;
  /**
   * The message ID for the message that will be used if a random tag does not
   * specify the random value type.  This takes a single argument, which is the
   * line number on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_NO_RANDOM_TYPE_ARGUMENT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 588;
  /**
   * The message ID for the message that will be used if a random tag will
   * always generate an empty value.  This takes a single argument, which is the
   * line number on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_WARNING_EMPTY_VALUE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_WARNING | 589;
  /**
   * The message ID for the message that will be used if a random tag has an
   * unknown random type.  This takes two arguments, which are the line number
   * on which it appears in the template file and the provided random type.
   */
  public static final int MSGID_MAKELDIF_TAG_UNKNOWN_RANDOM_TYPE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 590;
  /**
   * The message ID for the message that will be used as the description of the
   * resourcePath argument.  This does not take any arguments.
   */
  public static final int MSGID_MAKELDIF_DESCRIPTION_RESOURCE_PATH =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 591;
  /**
   * The message ID for the message that will be used if the specified temlate
   * file could not be found.  This takes a single argument, which is the
   * specified template file.
   */
  public static final int MSGID_MAKELDIF_COULD_NOT_FIND_TEMPLATE_FILE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 592;
  /**
   * The message ID for the message that will be used if the specified resource
   * directory does not exist.  This takes a single argument, which is the
   * specified resource directory.
   */
  public static final int MSGID_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 593;
  /**
   * The message ID for the message that will be used if the specified resource
   * directory exists but is not a directory.  This takes a single argument,
   * which is the specified resource directory.
   */
  public static final int MSGID_MAKELDIF_RESOURCE_DIRECTORY_NOT_DIRECTORY =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 594;
  /**
   * The message ID for the message that will be used if the specified tag
   * could not be found.  This takes three arguments, which are the file path,
   * the tag name, and the line number on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_CANNOT_FIND_FILE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 595;
  /**
   * The message ID for the message that will be used if an invalid file access
   * mode was specified.  This takes three arguments, which are the access mode,
   * the tag name, and the line number on which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_INVALID_FILE_ACCESS_MODE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 596;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to read the contents of a file.  This takes four arguments, which
   * are the file path, the tag name, the line number on which it appears in the
   * template file, and a message explaining the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_TAG_CANNOT_READ_FILE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 597;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to create the output LDIF file.  This takes two arguments, which are
   * the path to the LDIF file and a message explaining the problem that
   * occurred.
   */
  public static final int MSGID_MAKELDIF_UNABLE_TO_CREATE_LDIF =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 598;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to write to the output LDIF file.  This takes two arguments, which
   * are the path to the LDIF file and a message explaining the problem that
   * occurred.
   */
  public static final int MSGID_MAKELDIF_ERROR_WRITING_LDIF =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 599;
  /**
   * The message ID for the message that will be used to indicate the number of
   * entries that have been processed.  This takes a single argument, which is
   * the number of entries processed.
   */
  public static final int MSGID_MAKELDIF_PROCESSED_N_ENTRIES =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 600;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to write an entry.  This takes two arguments, which are the DN of
   * the entry and a message with information about the problem that occurred.
   */
  public static final int MSGID_MAKELDIF_CANNOT_WRITE_ENTRY =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 601;
  /**
   * The message ID for the message that will be used to indicate that all
   * processing has been completed.  This takes a single argument, which is the
   * number of entries processed.
   */
  public static final int MSGID_MAKELDIF_PROCESSING_COMPLETE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 602;
  /**
   * The message ID for the message that will be used as the description of the
   * templateFile argument.  This does not take any arguments.
   */
  public static final int MSGID_LDIFIMPORT_DESCRIPTION_TEMPLATE_FILE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 603;
  /**
   * The message ID for the message that will be used if both the ldifFile and
   * the templateFile arguments were provided.  This takes two arguments, which
   * are the long identifiers for the ldifFile and templateFile options.
   */
  public static final int MSGID_LDIFIMPORT_CONFLICTING_OPTIONS =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 604;
  /**
   * The message ID for the message that will be used if neither the ldifFile or
   * the templateFile arguments was provided.  This takes two arguments, which
   * are the long identifiers for the ldifFile and templateFile options.
   */
  public static final int MSGID_LDIFIMPORT_MISSING_REQUIRED_ARGUMENT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 605;
  /**
   * The message ID for the message that will be used if an error occurs while
   * attempting to initialize a MakeLDIF template file.  This takes two
   * arguments, which are the path to the template file and a message explaining
   * the problem that occurred.
   */
  public static final int MSGID_LDIFIMPORT_CANNOT_PARSE_TEMPLATE_FILE =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 606;
  /**
   * The message ID for the message that will be used if a template line has an
   * unclosed tag.  This takes a single argument, which is the line number on
   * which it appears in the template file.
   */
  public static final int MSGID_MAKELDIF_INCOMPLETE_TAG =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 607;
  /**
   * The message ID for the message that will be used if a branch definition
   * includes a tag that is not allowed for use in branches.  This takes two
   * arguments, which are the name of the tag and the line number on which it
   * appears in the template file.
   */
  public static final int MSGID_MAKELDIF_TAG_NOT_ALLOWED_IN_BRANCH =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 608;
  /**
   * The message ID for the message that will be used as the description of the
   * randomSeed argument.  This does not take any arguments.
   */
  public static final int MSGID_LDIFIMPORT_DESCRIPTION_RANDOM_SEED =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 609;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -5517,6 +6287,11 @@
                    "once to import from multiple LDIF files (the files " +
                    "will be processed in the order they are provided in " +
                    "the arguments).");
    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_TEMPLATE_FILE,
                    "Specifies the path to the MakeLDIF template file " +
                    "defining the data to be generated for the import.  This " +
                    "may not be used in conjunction with the --ldifFile " +
                    "option.");
    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_APPEND,
                    "Indicates that the import process should append to the " +
                    "existing database rather than overwriting it.");
@@ -5562,10 +6337,10 @@
                    "Specifies the path to a file into which rejected " +
                    "entries may be written if they are not accepted during " +
                    "the import process.");
    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE_REJECTS,
                    "Indicates whether to overwrite an existing rejects " +
                    "file when performing an LDIF import rather than " +
                    "appending to it.");
    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_RANDOM_SEED,
                    "Specifies the seed to use for the random number " +
                    "generator.  This  is only applicable when generating " +
                    "entries from a template.");
    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_SKIP_SCHEMA_VALIDATION,
                    "Indicates whether to skip schema validation during the " +
                    "import.");
@@ -5585,6 +6360,13 @@
    registerMessage(MSGID_LDIFIMPORT_ERROR_PARSING_ARGS,
                    "An error occurred while parsing the command-line " +
                    "arguments:  %s.");
    registerMessage(MSGID_LDIFIMPORT_CONFLICTING_OPTIONS,
                    "The %s and %s arguments are incompatible and may not be " +
                    "used together.");
    registerMessage(MSGID_LDIFIMPORT_MISSING_REQUIRED_ARGUMENT,
                    "Neither the %s or the %s argument was provided.  One " +
                    "of these arguments must be given to specify the source " +
                    "for the LDIF data to be imported.");
    registerMessage(MSGID_LDIFIMPORT_SERVER_BOOTSTRAP_ERROR,
                    "An unexpected error occurred while attempting to " +
                    "bootstrap the Directory Server client-side code:  %s.");
@@ -5633,6 +6415,9 @@
    registerMessage(MSGID_LDIFIMPORT_INVALID_INCLUDE_BASE,
                    "Provided include base DN \"%s\" is not handled by the " +
                    "backend with backend ID %s.");
    registerMessage(MSGID_LDIFIMPORT_CANNOT_PARSE_TEMPLATE_FILE,
                    "Unable to parse the specified file %s as a MakeLDIF " +
                    "template file:  %s.");
    registerMessage(MSGID_LDIFIMPORT_CANNOT_OPEN_REJECTS_FILE,
                    "An error occurred while trying to open the rejects " +
                    "file %s for writing:  %s.");
@@ -6962,6 +7747,236 @@
    registerMessage(MSGID_INSTALLDS_ERROR_READING_FROM_STDIN,
                    "ERROR:  Unexpected failure while reading from standard " +
                    "input:  %s.");
    registerMessage(MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT,
                    "Invalid number of arguments provided for tag %s on line " +
                    "number %d of the template file:  expected %d, got %d.");
    registerMessage(MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT,
                    "Invalid number of arguments provided for tag %s on line " +
                    "number %d of the template file:  expected between %d " +
                    "and %d, got %d.");
    registerMessage(MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE,
                    "Undefined attribute %s referenced on line %d of the " +
                    "template file.");
    registerMessage(MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND,
                    "Value %d is below the lowest allowed value of %d for " +
                    "tag %s on line %d of the template file.");
    registerMessage(MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER,
                    "Cannot parse value \"%s\" as an integer for tag %s on " +
                    "line %d of the template file.");
    registerMessage(MSGID_MAKELDIF_TAG_INTEGER_ABOVE_UPPER_BOUND,
                    "Value %d is above the largest allowed value of %d for " +
                    "tag %s on line %d of the template file.");
    registerMessage(MSGID_MAKELDIF_TAG_INVALID_EMPTY_STRING_ARGUMENT,
                    "Argument %d for tag %s on line number %d may not be an " +
                    "empty string.");
    registerMessage(MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_BOOLEAN,
                    "Cannot parse value \"%s\" as a Boolean value for tag %s " +
                    "on line %d of the template file.  The value must be " +
                    "either 'true' or 'false'.");
    registerMessage(MSGID_MAKELDIF_UNDEFINED_BRANCH_SUBORDINATE,
                    "The branch with entry DN %s references a subordinate " +
                    "template named %s which is not defined in the template " +
                    "file.");
    registerMessage(MSGID_MAKELDIF_CANNOT_LOAD_TAG_CLASS,
                    "Unable to load class %s for use as a MakeLDIF tag.");
    registerMessage(MSGID_MAKELDIF_CANNOT_INSTANTIATE_TAG,
                    "Cannot instantiate class %s as a MakeLDIF tag.");
    registerMessage(MSGID_MAKELDIF_CONFLICTING_TAG_NAME,
                    "Cannot register the tag defined in class %s because " +
                    "the tag name %s conflicts with the name of another " +
                    "tag that has already been registered.");
    registerMessage(MSGID_MAKELDIF_WARNING_UNDEFINED_CONSTANT,
                    "Possible reference to an undefined constant %s on line " +
                    "%d.");
    registerMessage(MSGID_MAKELDIF_DEFINE_MISSING_EQUALS,
                    "The constant definition on line %d is missing an " +
                    "equal sign to delimit the constant name from the value.");
    registerMessage(MSGID_MAKELDIF_DEFINE_NAME_EMPTY,
                    "The constant definition on line %d does not include a " +
                    "name for the constant.");
    registerMessage(MSGID_MAKELDIF_CONFLICTING_CONSTANT_NAME,
                    "The definition for constant %s on line %d conflicts " +
                    "with an earlier constant definition included in the " +
                    "template.");
    registerMessage(MSGID_MAKELDIF_WARNING_DEFINE_VALUE_EMPTY,
                    "Constant %s defined on line %d has not been assigned a " +
                    "value.");
    registerMessage(MSGID_MAKELDIF_CONFLICTING_BRANCH_DN,
                    "The branch definition %s starting on line %d conflicts " +
                    "with an earlier branch definition contained in the " +
                    "template file.");
    registerMessage(MSGID_MAKELDIF_CONFLICTING_TEMPLATE_NAME,
                    "The template definition %s starting on line %d " +
                    "conflicts with an earlier template definition contained " +
                    "in the template file.");
    registerMessage(MSGID_MAKELDIF_UNEXPECTED_TEMPLATE_FILE_LINE,
                    "Unexpected template line \"%s\" encountered on line %d " +
                    "of the template file.");
    registerMessage(MSGID_MAKELDIF_UNDEFINED_TEMPLATE_SUBORDINATE,
                    "The template named %s references a subordinate template " +
                    "named %s which is not defined in the template file.");
    registerMessage(MSGID_MAKELDIF_TEMPLATE_MISSING_RDN_ATTR,
                    "The template named %s includes RDN attribute %s that " +
                    "is not assigned a value in that template.");
    registerMessage(MSGID_MAKELDIF_CANNOT_DECODE_BRANCH_DN,
                    "Unable to decode branch DN \"%s\" on line %d of the " +
                    "template file.");
    registerMessage(MSGID_MAKELDIF_BRANCH_SUBORDINATE_TEMPLATE_NO_COLON,
                    "Subordinate template definition on line %d for branch " +
                    "%s is missing a colon to separate the template name " +
                    "from the number of entries.");
    registerMessage(MSGID_MAKELDIF_BRANCH_SUBORDINATE_INVALID_NUM_ENTRIES,
                    "Subordinate template definition on line %d for branch " +
                    "%s specified invalid number of entries %d for template " +
                    "%s.");
    registerMessage(MSGID_MAKELDIF_BRANCH_SUBORDINATE_ZERO_ENTRIES,
                    "Subordinate template definition on line %d for branch " +
                    "%s specifies that zero entries of type %s should be " +
                    "generated.");
    registerMessage(MSGID_MAKELDIF_BRANCH_SUBORDINATE_CANT_PARSE_NUMENTRIES,
                    "Unable to parse the number of entries for template %s " +
                    "as an integer for the subordinate template definition " +
                    "on line %d for branch %s.");
    registerMessage(MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_TEMPLATE_NO_COLON,
                    "Subordinate template definition on line %d for template " +
                    "%s is missing a colon to separate the template name " +
                    "from the number of entries.");
    registerMessage(MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_INVALID_NUM_ENTRIES,
                    "Subordinate template definition on line %d for template " +
                    "%s specified invalid number of entries %d for " +
                    "subordinate template %s.");
    registerMessage(MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_ZERO_ENTRIES,
                    "Subordinate template definition on line %d for template " +
                    "%s specifies that zero entries of type %s should be " +
                    "generated.");
    registerMessage(MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_CANT_PARSE_NUMENTRIES,
                    "Unable to parse the number of entries for template %s " +
                    "as an integer for the subordinate template definition " +
                    "on line %d for template %s.");
    registerMessage(MSGID_MAKELDIF_NO_COLON_IN_BRANCH_EXTRA_LINE,
                    "There is no colon to separate the attribute name from " +
                    "the value pattern on line %s of the template file in " +
                    "the definition for branch %s.");
    registerMessage(MSGID_MAKELDIF_NO_ATTR_IN_BRANCH_EXTRA_LINE,
                    "There is no attribute name before the colon on line %d " +
                    "of the template file in the definition for branch %s.");
    registerMessage(MSGID_MAKELDIF_NO_VALUE_IN_BRANCH_EXTRA_LINE,
                    "The value pattern for line %s of the template file in " +
                    "the definition for branch %s is empty.");
    registerMessage(MSGID_MAKELDIF_INCOMPLETE_TAG,
                    "Line %d of the template file contains an incomplete " +
                    "tag that starts with either '<' or '{' but does get " +
                    "closed.");
    registerMessage(MSGID_MAKELDIF_NO_COLON_IN_BRANCH_EXTRA_LINE,
                    "There is no colon to separate the attribute name from " +
                    "the value pattern on line %s of the template file in " +
                    "the definition for template %s.");
    registerMessage(MSGID_MAKELDIF_NO_ATTR_IN_TEMPLATE_LINE,
                    "There is no attribute name before the colon on line %d " +
                    "of the template file in the definition for template %s.");
    registerMessage(MSGID_MAKELDIF_NO_VALUE_IN_TEMPLATE_LINE,
                    "The value pattern for line %s of the template file in " +
                    "the definition for template %s is empty.");
    registerMessage(MSGID_MAKELDIF_NO_SUCH_TAG,
                    "An undefined tag %s is referenced on line %d of the " +
                    "template file.");
    registerMessage(MSGID_MAKELDIF_CANNOT_INSTANTIATE_NEW_TAG,
                    "An unexpected error occurred while trying to create a " +
                    "new instance of tag %s referenced on line %d of the " +
                    "template file:  %s.");
    registerMessage(MSGID_MAKELDIF_TAG_NOT_ALLOWED_IN_BRANCH,
                    "Tag %s referenced on line %d of the template file is " +
                    "not allowed for use in branch definitions.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_CONFIG_FILE,
                    "The path to the Directory Server configuration file.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_CONFIG_CLASS,
                    "The fully-qualified name of the Java class to use as " +
                    "the Directory Server configuration handler.  If this is " +
                    "not provided, then a default of " +
                    ConfigFileHandler.class.getName() + " will be used.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_RESOURCE_PATH,
                    "Specifies the path to look for MakeLDIF resources " +
                    "(e.g., data files) not found in the current working " +
                    "directory or template directory path.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_TEMPLATE,
                    "The path to the template file with information about " +
                    "the LDIF data to generate.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_LDIF,
                    "The path to the LDIF file to be written.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_SEED,
                    "The seed to use to initialize the random number " +
                    "generator.");
    registerMessage(MSGID_MAKELDIF_DESCRIPTION_HELP,
                    "Show this usgae information.");
    registerMessage(MSGID_MAKELDIF_CANNOT_INITIALIZE_ARGS,
                    "An unexpected error occurred while attempting to " +
                    "initialize the command-line arguments:  %s.");
    registerMessage(MSGID_MAKELDIF_ERROR_PARSING_ARGS,
                    "An error occurred while parsing the command-line " +
                    "arguments:  %s.");
    registerMessage(MSGID_MAKELDIF_CANNOT_INITIALIZE_JMX,
                    "An error occurred while attempting to initialize the " +
                    "Directory Server JMX subsystem based on the information " +
                    "in configuration file %s:  %s.");
    registerMessage(MSGID_MAKELDIF_CANNOT_INITIALIZE_CONFIG,
                    "An error occurred while attempting to process the " +
                    "Directory Server configuration file %s:  %s.");
    registerMessage(MSGID_MAKELDIF_CANNOT_INITIALIZE_SCHEMA,
                    "An error occurred while attempting to initialize the " +
                    "Directory Server schema based on the information in " +
                    "configuration file %s:  %s.");
    registerMessage(MSGID_MAKELDIF_IOEXCEPTION_DURING_PARSE,
                    "An error occurred while attempting to read the " +
                    "template file:  %s.");
    registerMessage(MSGID_MAKELDIF_EXCEPTION_DURING_PARSE,
                    "An error occurred while attempting to parse the " +
                    "template file:  %s.");
    registerMessage(MSGID_MAKELDIF_TAG_INVALID_FORMAT_STRING,
                    "Cannot parse value \"%s\" as an valid format string for " +
                    "tag %s on line %d of the template file.");
    registerMessage(MSGID_MAKELDIF_TAG_NO_RANDOM_TYPE_ARGUMENT,
                    "The random tag on line %d of the template file does " +
                    "not include an argument to specify the type of random " +
                    "value that should be generated.");
    registerMessage(MSGID_MAKELDIF_TAG_WARNING_EMPTY_VALUE,
                    "The value generated from the random tag on line %d of " +
                    "the template file will always be an empty string.");
    registerMessage(MSGID_MAKELDIF_TAG_UNKNOWN_RANDOM_TYPE,
                    "The random tag on line %d of the template file " +
                    "references an unknown random type of %s.");
    registerMessage(MSGID_MAKELDIF_COULD_NOT_FIND_TEMPLATE_FILE,
                    "Could not find template file %s.");
    registerMessage(MSGID_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY,
                    "The specified resource directory %s could not be found.");
    registerMessage(MSGID_MAKELDIF_RESOURCE_DIRECTORY_NOT_DIRECTORY,
                    "The specified resource directory %s exists but is not a " +
                    "directory.");
    registerMessage(MSGID_MAKELDIF_TAG_CANNOT_FIND_FILE,
                    "Cannot find file %s referenced by tag %s on line %d of " +
                    "the template file.");
    registerMessage(MSGID_MAKELDIF_TAG_INVALID_FILE_ACCESS_MODE,
                    "Invalid file access mode %s for tag %s on line %d of " +
                    "the template file.  It must be either \"sequential\" or " +
                    "\"random\".");
    registerMessage(MSGID_MAKELDIF_TAG_CANNOT_READ_FILE,
                    "An error occurred while trying to read file %s " +
                    "referenced by tag %s on line %d of the template file:  " +
                    "%s.");
    registerMessage(MSGID_MAKELDIF_UNABLE_TO_CREATE_LDIF,
                    "An error occurred while attempting to open LDIF file %s " +
                    "for writing:  %s.");
    registerMessage(MSGID_MAKELDIF_ERROR_WRITING_LDIF,
                    "An error occurred while writing data to LDIF file %s:  " +
                    "%s.");
    registerMessage(MSGID_MAKELDIF_PROCESSED_N_ENTRIES,
                    "Processed %d entries.");
    registerMessage(MSGID_MAKELDIF_CANNOT_WRITE_ENTRY,
                    "An error occurred while attempting to write entry %s to " +
                    "LDIF:  %s.");
    registerMessage(MSGID_MAKELDIF_PROCESSING_COMPLETE,
                    "LDIF processing complete.  %d entries written.");
  }
}
opends/src/server/org/opends/server/tools/ImportLDIF.java
@@ -28,9 +28,11 @@
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import org.opends.server.api.Backend;
import org.opends.server.api.plugin.PluginType;
@@ -45,6 +47,7 @@
import org.opends.server.core.InitializationException;
import org.opends.server.core.LockFileManager;
import org.opends.server.loggers.StartupErrorLogger;
import org.opends.server.tools.makeldif.TemplateFile;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
@@ -55,6 +58,7 @@
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.IntegerArgument;
import org.opends.server.util.args.StringArgument;
import static org.opends.server.config.ConfigConstants.*;
@@ -116,6 +120,7 @@
    BooleanArgument quietMode               = null;
    BooleanArgument replaceExisting         = null;
    BooleanArgument skipSchemaValidation    = null;
    IntegerArgument randomSeed              = null;
    StringArgument  backendID               = null;
    StringArgument  configClass             = null;
    StringArgument  configFile              = null;
@@ -127,6 +132,7 @@
    StringArgument  includeFilterStrings    = null;
    StringArgument  ldifFiles               = null;
    StringArgument  rejectFile              = null;
    StringArgument  templateFile            = null;
    // Create the command-line argument parser for use with this program.
@@ -154,12 +160,19 @@
      ldifFiles =
           new StringArgument("ldiffile", 'l', "ldifFile", true, true, true,
           new StringArgument("ldiffile", 'l', "ldifFile", false, true, true,
                              "{ldifFile}", null, null,
                              MSGID_LDIFIMPORT_DESCRIPTION_LDIF_FILE);
      argParser.addArgument(ldifFiles);
      templateFile =
           new StringArgument("templatefile", 't', "templateFile", false, false,
                              true, "{templateFile}", null, null,
                              MSGID_LDIFIMPORT_DESCRIPTION_TEMPLATE_FILE);
      argParser.addArgument(templateFile);
      append =
           new BooleanArgument("append", 'a', "append",
                               MSGID_LDIFIMPORT_DESCRIPTION_APPEND);
@@ -234,6 +247,13 @@
      argParser.addArgument(overwriteRejects);
      randomSeed =
           new IntegerArgument("randomseed", 'S', "randomSeed", false, false,
                               true, "{seed}", 0, null, false, 0, false, 0,
                               MSGID_LDIFIMPORT_DESCRIPTION_RANDOM_SEED);
      argParser.addArgument(randomSeed);
      skipSchemaValidation =
           new BooleanArgument("skipschema", 's', "skipSchemaValidation",
                    MSGID_LDIFIMPORT_DESCRIPTION_SKIP_SCHEMA_VALIDATION);
@@ -296,6 +316,29 @@
    }
    // Make sure that either the "ldifFile" argument or the "templateFile"
    // argument was provided, but not both.
    if (ldifFiles.isPresent())
    {
      if (templateFile.isPresent())
      {
        int    msgID   = MSGID_LDIFIMPORT_CONFLICTING_OPTIONS;
        String message = getMessage(msgID, ldifFiles.getLongIdentifier(),
                                    templateFile.getLongIdentifier());
        System.err.println(message);
        return 1;
      }
    }
    else if (! templateFile.isPresent())
    {
      int    msgID   = MSGID_LDIFIMPORT_MISSING_REQUIRED_ARGUMENT;
      String message = getMessage(msgID, ldifFiles.getLongIdentifier(),
                                  templateFile.getLongIdentifier());
      System.err.println(message);
      return 1;
    }
    // Perform the initial bootstrap of the Directory Server and process the
    // configuration.
    DirectoryServer directoryServer = DirectoryServer.getInstance();
@@ -758,9 +801,57 @@
    }
    // See if the data should be read from LDIF files or generated via MakeLDIF.
    LDIFImportConfig importConfig;
    if (ldifFiles.isPresent())
    {
      ArrayList<String> fileList = new ArrayList<String>(ldifFiles.getValues());
      importConfig = new LDIFImportConfig(fileList);
    }
    else
    {
      Random random;
      if (randomSeed.isPresent())
      {
        try
        {
          random = new Random(randomSeed.getIntValue());
        }
        catch (Exception e)
        {
          random = new Random();
        }
      }
      else
      {
        random = new Random();
      }
      String resourcePath = DirectoryServer.getServerRoot() + File.separator +
                            PATH_MAKELDIF_RESOURCE_DIR;
      TemplateFile tf = new TemplateFile(resourcePath, random);
      ArrayList<String> warnings = new ArrayList<String>();
      try
      {
        tf.parse(templateFile.getValue(), warnings);
      }
      catch (Exception e)
      {
        int msgID = MSGID_LDIFIMPORT_CANNOT_PARSE_TEMPLATE_FILE;
        String message = getMessage(msgID, templateFile.getValue(),
                                    e.getMessage());
        logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                 message, msgID);
        return 1;
      }
      importConfig = new LDIFImportConfig(tf);
    }
    // Create the LDIF import configuration to use when reading the LDIF.
    ArrayList<String> fileList = new ArrayList<String>(ldifFiles.getValues());
    LDIFImportConfig importConfig = new LDIFImportConfig(fileList);
    importConfig.setAppendToExistingData(append.isPresent());
    importConfig.setReplaceExistingEntries(replaceExisting.isPresent());
    importConfig.setCompressed(isCompressed.isPresent());
opends/src/server/org/opends/server/tools/makeldif/AttributeValueTag.java
New file
@@ -0,0 +1,272 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.InitializationException;
import org.opends.server.types.AttributeType;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a tag that is used to reference the value of a specified
 * attribute already defined in the entry.
 */
public class AttributeValueTag
       extends Tag
{
  // The attribute type that specifies which value should be used.
  private AttributeType attributeType;
  // The maximum number of characters to include from the value.
  private int numCharacters;
  /**
   * Creates a new instance of this attribute value tag.
   */
  public AttributeValueTag()
  {
    attributeType = null;
    numCharacters = 0;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "AttributeValue";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    String lowerName = toLowerCase(arguments[0]);
    attributeType = DirectoryServer.getAttributeType(lowerName, true);
    if (! branch.hasAttribute(attributeType))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE;
      String message = getMessage(msgID, arguments[0], lineNumber);
      throw new InitializationException(msgID, message);
    }
    if (arguments.length == 2)
    {
      try
      {
        numCharacters = Integer.parseInt(arguments[1]);
        if (numCharacters < 0)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
          String message = getMessage(msgID, numCharacters, 0, getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[1], getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
    }
    else
    {
      numCharacters = 0;
    }
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    String lowerName = toLowerCase(arguments[0]);
    attributeType = DirectoryServer.getAttributeType(lowerName, true);
    if (! template.hasAttribute(attributeType))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE;
      String message = getMessage(msgID, arguments[0], lineNumber);
      throw new InitializationException(msgID, message);
    }
    if (arguments.length == 2)
    {
      try
      {
        numCharacters = Integer.parseInt(arguments[1]);
        if (numCharacters < 0)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
          String message = getMessage(msgID, numCharacters, 0, getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[1], getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
    }
    else
    {
      numCharacters = 0;
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    TemplateValue v = templateEntry.getValue(attributeType);
    if (v == null)
    {
      // This is fine -- we just won't append anything.
      return TagResult.SUCCESS_RESULT;
    }
    if (numCharacters > 0)
    {
      String valueString = v.getValue().toString();
      if (valueString.length() > numCharacters)
      {
        templateValue.append(valueString.substring(0, numCharacters));
      }
      else
      {
        templateValue.append(valueString);
      }
    }
    else
    {
      templateValue.getValue().append(v.getValue());
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/Branch.java
New file
@@ -0,0 +1,450 @@
/*
 * 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.tools.makeldif;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a branch that should be included in the resulting LDIF.  A
 * branch may or may not have subordinate entries.
 */
public class Branch
{
  // The DN for this branch entry.
  private DN branchDN;
  // The number of entries that should be created below this branch for each
  // subordinate template.
  private int[] numEntriesPerTemplate;
  // The names of the subordinate templates for this branch.
  private String[] subordinateTemplateNames;
  // The set of subordinate templates for this branch.
  private Template[] subordinateTemplates;
  // The template file in which this branch appears.
  private TemplateFile templateFile;
  // The set of template lines that correspond to the RDN components.
  private TemplateLine[] rdnLines;
  // The set of extra lines that should be included in this branch entry.
  private TemplateLine[] extraLines;
  /**
   * Creates a new branch with the provided information.
   *
   * @param  templateFile  The template file in which this branch appears.
   * @param  branchDN      The DN for this branch entry.
   */
  public Branch(TemplateFile templateFile, DN branchDN)
  {
    this(templateFile, branchDN, new String[0], new int[0],
         new TemplateLine[0]);
  }
  /**
   * Creates a new branch with the provided information.
   *
   * @param  templateFile              The template file in which this branch
   *                                   appears.
   * @param  branchDN                  The DN for this branch entry.
   * @param  subordinateTemplateNames  The names of the subordinate templates
   *                                   used to generate entries below this
   *                                   branch.
   * @param  numEntriesPerTemplate     The number of entries that should be
   *                                   created below this branch for each
   *                                   subordinate template.
   * @param  extraLines                The set of extra lines that should be
   *                                   included in this branch entry.
   */
  public Branch(TemplateFile templateFile, DN branchDN,
                String[] subordinateTemplateNames, int[] numEntriesPerTemplate,
                TemplateLine[] extraLines)
  {
    this.templateFile             = templateFile;
    this.branchDN                 = branchDN;
    this.subordinateTemplateNames = subordinateTemplateNames;
    this.numEntriesPerTemplate    = numEntriesPerTemplate;
    this.extraLines               = extraLines;
    subordinateTemplates = null;
    // Get the RDN template lines based just on the entry DN.
    Entry entry = createEntry(branchDN);
    ArrayList<String>       warnings = new ArrayList<String>();
    ArrayList<TemplateLine> lineList = new ArrayList<TemplateLine>();
    for (String ocName : entry.getObjectClasses().values())
    {
      try
      {
        String[] valueStrings = new String[] { ocName };
        Tag[] tags = new Tag[1];
        tags[0] = new StaticTextTag();
        tags[0].initializeForBranch(templateFile, this, valueStrings, 0,
                                    warnings);
        TemplateLine l =
             new TemplateLine(DirectoryServer.getObjectClassAttributeType(), 0,
                              tags);
        lineList.add(l);
      }
      catch (Exception e)
      {
        // This should never happen.
        e.printStackTrace();
      }
    }
    for (List<Attribute> attrList : entry.getUserAttributes().values())
    {
      for (Attribute a : attrList)
      {
        for (AttributeValue v : a.getValues())
        {
          try
          {
            String[] valueStrings = new String[] { v.getStringValue() };
            Tag[] tags = new Tag[1];
            tags[0] = new StaticTextTag();
            tags[0].initializeForBranch(templateFile, this, valueStrings, 0,
                                        warnings);
            lineList.add(new TemplateLine(a.getAttributeType(), 0, tags));
          }
          catch (Exception e)
          {
            // This should never happen.
            e.printStackTrace();
          }
        }
      }
    }
    for (List<Attribute> attrList : entry.getOperationalAttributes().values())
    {
      for (Attribute a : attrList)
      {
        for (AttributeValue v : a.getValues())
        {
          try
          {
            String[] valueStrings = new String[] { v.getStringValue() };
            Tag[] tags = new Tag[1];
            tags[0] = new StaticTextTag();
            tags[0].initializeForBranch(templateFile, this, valueStrings, 0,
                                        warnings);
            lineList.add(new TemplateLine(a.getAttributeType(), 0, tags));
          }
          catch (Exception e)
          {
            // This should never happen.
            e.printStackTrace();
          }
        }
      }
    }
    rdnLines = new TemplateLine[lineList.size()];
    lineList.toArray(rdnLines);
  }
  /**
   * Performs any necessary processing to ensure that the branch initialization
   * is completed.  In particular, it should make sure that all referenced
   * subordinate templates actually exist in the template file.
   *
   * @param  templates  The set of templates defined in the template file.
   *
   * @throws  MakeLDIFException  If any of the subordinate templates are not
   *                             defined in the template file.
   */
  public void completeBranchInitialization(Map<String,Template> templates)
         throws MakeLDIFException
  {
    if (subordinateTemplateNames == null)
    {
      subordinateTemplateNames = new String[0];
      subordinateTemplates     = new Template[0];
    }
    else
    {
      subordinateTemplates = new Template[subordinateTemplateNames.length];
      for (int i=0; i < subordinateTemplates.length; i++)
      {
        subordinateTemplates[i] =
             templates.get(toLowerCase(subordinateTemplateNames[i]));
        if (subordinateTemplates[i] == null)
        {
          int    msgID   = MSGID_MAKELDIF_UNDEFINED_BRANCH_SUBORDINATE;
          String message = getMessage(msgID, subordinateTemplateNames[i],
                                      branchDN.toString());
          throw new MakeLDIFException(msgID, message);
        }
      }
    }
  }
  /**
   * Retrieves the DN for this branch entry.
   *
   * @return  The DN for this branch entry.
   */
  public DN getBranchDN()
  {
    return branchDN;
  }
  /**
   * Retrieves the names of the subordinate templates for this branch.
   *
   * @return  The names of the subordinate templates for this branch.
   */
  public String[] getSubordinateTemplateNames()
  {
    return subordinateTemplateNames;
  }
  /**
   * Retrieves the set of subordinate templates used to generate entries below
   * this branch.  Note that the subordinate templates will not be available
   * until the <CODE>completeBranchInitialization</CODE> method has been called.
   *
   * @return  The set of subordinate templates used to generate entries below
   *          this branch.
   */
  public Template[] getSubordinateTemplates()
  {
    return subordinateTemplates;
  }
  /**
   * Retrieves the number of entries that should be created below this branch
   * for each subordinate template.
   *
   * @return  The number of entries that should be created below this branch for
   *          each subordinate template.
   */
  public int[] getNumEntriesPerTemplate()
  {
    return numEntriesPerTemplate;
  }
  /**
   * Adds a new subordinate template to this branch.  Note that this should not
   * be used after <CODE>completeBranchInitialization</CODE> has been called.
   *
   * @param  name        The name of the template to use to generate the
   *                     entries.
   * @param  numEntries  The number of entries to create based on the template.
   */
  public void addSubordinateTemplate(String name, int numEntries)
  {
    String[] newNames  = new String[subordinateTemplateNames.length+1];
    int[]    newCounts = new int[numEntriesPerTemplate.length+1];
    System.arraycopy(subordinateTemplateNames, 0, newNames, 0,
                     subordinateTemplateNames.length);
    System.arraycopy(numEntriesPerTemplate, 0, newCounts, 0,
                     numEntriesPerTemplate.length);
    newNames[subordinateTemplateNames.length] = name;
    newCounts[numEntriesPerTemplate.length]   = numEntries;
    subordinateTemplateNames = newNames;
    numEntriesPerTemplate    = newCounts;
  }
  /**
   * Retrieves the set of extra lines that should be included in this branch
   * entry.
   *
   * @return  The set of extra lines that should be included in this branch
   *          entry.
   */
  public TemplateLine[] getExtraLines()
  {
    return extraLines;
  }
  /**
   * Adds the provided template line to the set of extra lines for this branch.
   *
   * @param  line  The line to add to the set of extra lines for this branch.
   */
  public void addExtraLine(TemplateLine line)
  {
    TemplateLine[] newExtraLines = new TemplateLine[extraLines.length+1];
    System.arraycopy(extraLines, 0, newExtraLines, 0, extraLines.length);
    newExtraLines[extraLines.length] = line;
    extraLines = newExtraLines;
  }
  /**
   * Indicates whether this branch contains a reference to the specified
   * attribute type, either in the RDN components of the DN or in the extra
   * lines.
   *
   * @param  attributeType  The attribute type for which to make the
   *                        determination.
   *
   * @return  <CODE>true</CODE> if the branch does contain the specified
   *          attribute type, or <CODE>false</CODE> if it does not.
   */
  public boolean hasAttribute(AttributeType attributeType)
  {
    if (branchDN.getRDN().hasAttributeType(attributeType))
    {
      return true;
    }
    for (TemplateLine l : extraLines)
    {
      if (l.getAttributeType().equals(attributeType))
      {
        return true;
      }
    }
    return false;
  }
  /**
   * Writes the entry for this branch, as well as all appropriate subordinate
   * entries.
   *
   * @param  entryWriter  The entry writer to which the entries should be
   *                      written.
   *
   * @return  The result that indicates whether processing should continue.
   *
   * @throws  IOException  If a problem occurs while attempting to write to the
   *                       LDIF writer.
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public TagResult writeEntries(EntryWriter entryWriter)
         throws IOException, MakeLDIFException
  {
    // Create a new template entry and populate it based on the RDN attributes
    // and extra lines.
    TemplateEntry entry = new TemplateEntry(this);
    for (TemplateLine l : rdnLines)
    {
      TagResult r = l.generateLine(entry);
      if (! (r.keepProcessingEntry() && r.keepProcessingParent() &&
             r.keepProcessingTemplateFile()))
      {
        return r;
      }
    }
    for (TemplateLine l : extraLines)
    {
      TagResult r = l.generateLine(entry);
      if (! (r.keepProcessingEntry() && r.keepProcessingParent() &&
             r.keepProcessingTemplateFile()))
      {
        return r;
      }
    }
    if (! entryWriter.writeEntry(entry.toEntry()))
    {
      return TagResult.STOP_PROCESSING;
    }
    for (int i=0; i < subordinateTemplates.length; i++)
    {
      TagResult r =
           subordinateTemplates[i].writeEntries(entryWriter, branchDN,
                                                numEntriesPerTemplate[i]);
      if (! (r.keepProcessingParent() && r.keepProcessingTemplateFile()))
      {
        if (r.keepProcessingTemplateFile())
        {
          // We don't want to propagate a "stop processing parent" all the way
          // up the chain.
          return TagResult.SUCCESS_RESULT;
        }
        return r;
      }
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/DNTag.java
New file
@@ -0,0 +1,234 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import org.opends.server.types.DN;
import org.opends.server.types.RDN;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include the DN of the current entry
 * in the attribute value.
 */
public class DNTag
       extends Tag
{
  // The number of DN components to include.
  private int numComponents;
  /**
   * Creates a new instance of this DN tag.
   */
  public DNTag()
  {
    numComponents = 0;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "DN";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed for this tag.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  private void initializeInternal(TemplateFile templateFile, String[] arguments,
                                  int lineNumber)
          throws InitializationException
  {
    if (arguments.length == 0)
    {
      numComponents = 0;
    }
    else if (arguments.length == 1)
    {
      try
      {
        numComponents = Integer.parseInt(arguments[0]);
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[0], getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
    }
    else
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0, 1,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    DN dn = templateEntry.getDN();
    if ((dn == null) || dn.isNullDN())
    {
      return TagResult.SUCCESS_RESULT;
    }
    if (numComponents == 0)
    {
      dn.toString(templateValue.getValue());
    }
    else if (numComponents > 0)
    {
      RDN[] rdnComps = dn.getRDNComponents();
      int count = Math.min(numComponents, rdnComps.length);
      rdnComps[0].toString(templateValue.getValue());
      for (int i=1; i < count; i++)
      {
        templateValue.append(",");
        rdnComps[i].toString(templateValue.getValue());
      }
    }
    else
    {
      RDN[] rdnComps = dn.getRDNComponents();
      int count = Math.min(Math.abs(numComponents), rdnComps.length);
      rdnComps[rdnComps.length-count].toString(templateValue.getValue());
      for (int i=1; i < count; i++)
      {
        templateValue.append(",");
        rdnComps[rdnComps.length-count+i].toString(templateValue.getValue());
      }
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/EntryWriter.java
New file
@@ -0,0 +1,68 @@
/*
 * 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.tools.makeldif;
import java.io.IOException;
import org.opends.server.types.Entry;
/**
 * This interface defines a method that may be used to write entries generated
 * through the MakeLDIF utility.
 */
public interface EntryWriter
{
  /**
   * Writes the provided entry to the appropriate target.
   *
   * @param  entry  The entry to be written.
   *
   * @return  <CODE>true</CODE> if the entry writer will accept additional
   *          entries, or <CODE>false</CODE> if no more entries should be
   *         written.
   *
   * @throws  IOException  If a problem occurs while writing the entry to its
   *                       intended destination.
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public boolean writeEntry(Entry entry)
         throws IOException, MakeLDIFException;
  /**
   * Notifies the entry writer that no more entries will be provided and that
   * any associated cleanup may be performed.
   */
  public void closeEntryWriter();
}
opends/src/server/org/opends/server/tools/makeldif/FileTag.java
New file
@@ -0,0 +1,268 @@
/*
 * 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.tools.makeldif;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Random;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used provide values from a text file.  The
 * file should have one value per line.  Access to the values may be either at
 * random or in sequential order.
 */
public class FileTag
       extends Tag
{
  // Indicates whether the values should be selected sequentially or at random.
  private boolean sequential;
  // The file containing the data.
  private File dataFile;
  // The index used for sequential access.
  private int nextIndex;
  // The random number generator for this tag.
  private Random random;
  // The array of lines read from the file.
  private String[] fileLines;
  /**
   * Creates a new instance of this file tag.
   */
  public FileTag()
  {
    sequential = false;
    dataFile   = null;
    nextIndex  = 0;
    random     = null;
    fileLines  = null;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "File";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber, warnings);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber, warnings);
  }
  /**
   * Performs any initialization for this tag that may be needed.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  private void initializeInternal(TemplateFile templateFile, String[] arguments,
                                  int lineNumber, List<String> warnings)
          throws InitializationException
  {
    random = templateFile.getRandom();
    // There must be at least one argument, and possibly two.
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    // The first argument should be the path to the file.
    dataFile = templateFile.getFile(arguments[0]);
    if ((dataFile == null) || (! dataFile.exists()))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_FIND_FILE;
      String message = getMessage(msgID, arguments[0], getName(), lineNumber);
      throw new InitializationException(msgID, message);
    }
    // If there is a second argument, then it should be either "sequential" or
    // "random".  If there isn't one, then we should assume "random".
    if (arguments.length == 2)
    {
      if (arguments[1].equalsIgnoreCase("sequential"))
      {
        sequential = true;
        nextIndex  = 0;
      }
      else if (arguments[1].equalsIgnoreCase("random"))
      {
        sequential = false;
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_TAG_INVALID_FILE_ACCESS_MODE;
        String message = getMessage(msgID, arguments[1], getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
    }
    else
    {
      sequential = false;
    }
    // See if the file has already been read into memory.  If not, then read it.
    try
    {
      fileLines = templateFile.getFileLines(dataFile);
    }
    catch (IOException ioe)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_READ_FILE;
      String message = getMessage(msgID, arguments[0], getName(), lineNumber,
                                  String.valueOf(ioe));
      throw new InitializationException(msgID, message, ioe);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    if (sequential)
    {
      templateValue.append(fileLines[nextIndex++]);
      if (nextIndex >= fileLines.length)
      {
        nextIndex = 0;
      }
    }
    else
    {
      templateValue.append(fileLines[random.nextInt(fileLines.length)]);
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/FirstNameTag.java
New file
@@ -0,0 +1,138 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include a first name in the
 * attribute value.
 */
public class FirstNameTag
       extends Tag
{
  // The template file with which this tag is associated.
  private TemplateFile templateFile;
  /**
   * Creates a new instance of this first name tag.
   */
  public FirstNameTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "First";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return false;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    this.templateFile = templateFile;
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    templateValue.append(templateFile.getFirstName());
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/GUIDTag.java
New file
@@ -0,0 +1,164 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import java.util.UUID;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include a GUID in the attribute
 * value.
 */
public class GUIDTag
       extends Tag
{
  /**
   * Creates a new instance of this GUID tag.
   */
  public GUIDTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "GUID";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    templateValue.append(UUID.randomUUID().toString());
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/IfAbsentTag.java
New file
@@ -0,0 +1,229 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.InitializationException;
import org.opends.server.types.AttributeType;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a tag that is used to base presence of one attribute on
 * the absence of another attribute and/or attribute value.
 */
public class IfAbsentTag
       extends Tag
{
  // The attribute type for which to make the determination.
  private AttributeType attributeType;
  // The value for which to make the determination.
  private String assertionValue;
  /**
   * Creates a new instance of this ifabsent tag.
   */
  public IfAbsentTag()
  {
    attributeType  = null;
    assertionValue = null;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "IfAbsent";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    String lowerName = toLowerCase(arguments[0]);
    AttributeType t = DirectoryServer.getAttributeType(lowerName, true);
    if (! branch.hasAttribute(t))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE;
      String message = getMessage(msgID, arguments[0], lineNumber);
      throw new InitializationException(msgID, message);
    }
    if (arguments.length == 2)
    {
      assertionValue = arguments[1];
    }
    else
    {
      assertionValue = null;
    }
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    String lowerName = toLowerCase(arguments[0]);
    AttributeType t = DirectoryServer.getAttributeType(lowerName, true);
    if (! template.hasAttribute(t))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE;
      String message = getMessage(msgID, arguments[0], lineNumber);
      throw new InitializationException(msgID, message);
    }
    if (arguments.length == 2)
    {
      assertionValue = arguments[1];
    }
    else
    {
      assertionValue = null;
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    List<TemplateValue> values = templateEntry.getValues(attributeType);
    if ((values == null) || values.isEmpty())
    {
      return TagResult.SUCCESS_RESULT;
    }
    if (assertionValue == null)
    {
      return TagResult.OMIT_FROM_ENTRY;
    }
    else
    {
      for (TemplateValue v : values)
      {
        if (assertionValue.equals(v.getValue().toString()))
        {
          return TagResult.OMIT_FROM_ENTRY;
        }
      }
      return TagResult.SUCCESS_RESULT;
    }
  }
}
opends/src/server/org/opends/server/tools/makeldif/IfPresentTag.java
New file
@@ -0,0 +1,229 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.InitializationException;
import org.opends.server.types.AttributeType;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a tag that is used to base presence of one attribute on
 * the presence of another attribute and/or attribute value.
 */
public class IfPresentTag
       extends Tag
{
  // The attribute type for which to make the determination.
  private AttributeType attributeType;
  // The value for which to make the determination.
  private String assertionValue;
  /**
   * Creates a new instance of this ifpresent tag.
   */
  public IfPresentTag()
  {
    attributeType  = null;
    assertionValue = null;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "IfPresent";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    String lowerName = toLowerCase(arguments[0]);
    AttributeType t = DirectoryServer.getAttributeType(lowerName, true);
    if (! branch.hasAttribute(t))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE;
      String message = getMessage(msgID, arguments[0], lineNumber);
      throw new InitializationException(msgID, message);
    }
    if (arguments.length == 2)
    {
      assertionValue = arguments[1];
    }
    else
    {
      assertionValue = null;
    }
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if ((arguments.length < 1) || (arguments.length > 2))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    String lowerName = toLowerCase(arguments[0]);
    AttributeType t = DirectoryServer.getAttributeType(lowerName, true);
    if (! template.hasAttribute(t))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNDEFINED_ATTRIBUTE;
      String message = getMessage(msgID, arguments[0], lineNumber);
      throw new InitializationException(msgID, message);
    }
    if (arguments.length == 2)
    {
      assertionValue = arguments[1];
    }
    else
    {
      assertionValue = null;
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    List<TemplateValue> values = templateEntry.getValues(attributeType);
    if ((values == null) || values.isEmpty())
    {
      return TagResult.OMIT_FROM_ENTRY;
    }
    if (assertionValue == null)
    {
      return TagResult.SUCCESS_RESULT;
    }
    else
    {
      for (TemplateValue v : values)
      {
        if (assertionValue.equals(v.getValue().toString()))
        {
          return TagResult.SUCCESS_RESULT;
        }
      }
      return TagResult.OMIT_FROM_ENTRY;
    }
  }
}
opends/src/server/org/opends/server/tools/makeldif/LastNameTag.java
New file
@@ -0,0 +1,138 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include a last name in the
 * attribute value.
 */
public class LastNameTag
       extends Tag
{
  // The template file with which this tag is associated.
  private TemplateFile templateFile;
  /**
   * Creates a new instance of this last name tag.
   */
  public LastNameTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "Last";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return false;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    this.templateFile = templateFile;
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    templateValue.append(templateFile.getLastName());
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/MakeLDIF.java
New file
@@ -0,0 +1,424 @@
/*
 * 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.tools.makeldif;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Random;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Entry;
import org.opends.server.types.ExistingFileBehavior;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.util.LDIFWriter;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.IntegerArgument;
import org.opends.server.util.args.StringArgument;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a program that can be used to generate LDIF content based
 * on a template.
 */
public class MakeLDIF
       implements EntryWriter
{
  /**
   * The fully-qualified name of this class for debugging purposes.
   */
  private static final String CLASS_NAME =
       "org.opends.server.tools.makeldif.MakeLDIF";
  /**
   * The position at which to wrap long lines of console output.
   */
  public static final int MAX_LINE_WIDTH = 79;
  // The LDIF writer that will be used to write the entries.
  private LDIFWriter ldifWriter;
  // The total number of entries that have been written.
  private long entriesWritten;
  /**
   * Invokes the <CODE>makeLDIFMain</CODE> method with the provided set of
   * arguments.
   *
   * @param  args  The command-line arguments provided for this program.
   */
  public static void main(String[] args)
  {
    MakeLDIF makeLDIF = new MakeLDIF();
    int returnCode = makeLDIF.makeLDIFMain(args);
    if (returnCode != 0)
    {
      System.exit(returnCode);
    }
  }
  /**
   * Creates a new instance of this utility.  It should just be used for
   * invoking the <CODE>makeLDIFMain</CODE> method.
   */
  public MakeLDIF()
  {
    ldifWriter     = null;
    entriesWritten = 0L;
  }
  /**
   * Processes the provided set of command-line arguments and begins generating
   * the LDIF content.
   *
   * @param  args  The command-line arguments provided for this program.
   *
   * @return  A result code of zero if all processing completed properly, or
   *          a nonzero result if a problem occurred.
   */
  public int makeLDIFMain(String[] args)
  {
    // Create and initialize the argument parser for this program.
    ArgumentParser  argParser = new ArgumentParser(CLASS_NAME, false);
    BooleanArgument showUsage;
    IntegerArgument randomSeed;
    StringArgument  configClass;
    StringArgument  configFile;
    StringArgument  templatePath;
    StringArgument  ldifFile;
    StringArgument  resourcePath;
    try
    {
      configFile = new StringArgument("configfile", 'c', "configFile", true,
                                      false, true, "{configFile}", null, null,
                                      MSGID_MAKELDIF_DESCRIPTION_CONFIG_FILE);
      argParser.addArgument(configFile);
      configClass = new StringArgument("configclass", 'C', "configClass", false,
                                       false, true, "{configClass}", null, null,
                                       MSGID_MAKELDIF_DESCRIPTION_CONFIG_CLASS);
      argParser.addArgument(configClass);
      resourcePath =
           new StringArgument("resourcepath", 'r', "resourcePath", true, false,
                              true, "{path}", null, null,
                              MSGID_MAKELDIF_DESCRIPTION_RESOURCE_PATH);
      argParser.addArgument(resourcePath);
      templatePath = new StringArgument("templatefile", 't', "templateFile",
                                        true, false, true, "{file}", null, null,
                                        MSGID_MAKELDIF_DESCRIPTION_TEMPLATE);
      argParser.addArgument(templatePath);
      ldifFile = new StringArgument("ldiffile", 'o', "ldifFile", true, false,
                                    true, "{file}", null, null,
                                    MSGID_MAKELDIF_DESCRIPTION_LDIF);
      argParser.addArgument(ldifFile);
      randomSeed = new IntegerArgument("randomseed", 's', "randomSeed", false,
                                       false, true, "{seed}", 0, null,
                                       MSGID_MAKELDIF_DESCRIPTION_SEED);
      argParser.addArgument(randomSeed);
      showUsage = new BooleanArgument("help", 'H', "help",
                                      MSGID_MAKELDIF_DESCRIPTION_HELP);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
    }
    catch (ArgumentException ae)
    {
      int msgID = MSGID_MAKELDIF_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // Parse the command-line arguments provided to the program.
    try
    {
      argParser.parseArguments(args);
    }
    catch (ArgumentException ae)
    {
      int    msgID   = MSGID_MAKELDIF_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.err.println(argParser.getUsage());
      return 1;
    }
    // If we should just display usage information, then print it and exit.
    if (showUsage.isPresent())
    {
      return 0;
    }
    // Initialize the Directory Server configuration handler using the
    // information that was provided.
    DirectoryServer directoryServer = DirectoryServer.getInstance();
    directoryServer.bootstrapClient();
    try
    {
      directoryServer.initializeJMX();
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_INITIALIZE_JMX;
      String message = getMessage(msgID,
                                  String.valueOf(configFile.getValue()),
                                  e.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    try
    {
      directoryServer.initializeConfiguration(configClass.getValue(),
                                              configFile.getValue());
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_INITIALIZE_CONFIG;
      String message = getMessage(msgID,
                                  String.valueOf(configFile.getValue()),
                                  e.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    try
    {
      directoryServer.initializeSchema();
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_INITIALIZE_SCHEMA;
      String message = getMessage(msgID,
                                  String.valueOf(configFile.getValue()),
                                  e.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // Create the random number generator that will be used for the generation
    // process.
    Random random;
    if (randomSeed.isPresent())
    {
      try
      {
        random = new Random(randomSeed.getIntValue());
      }
      catch (Exception e)
      {
        random = new Random();
      }
    }
    else
    {
      random = new Random();
    }
    // If a resource path was provided, then make sure it's acceptable.
    File resourceDir = new File(resourcePath.getValue());
    if (! resourceDir.exists())
    {
      int    msgID   = MSGID_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY;
      String message = getMessage(msgID, resourcePath.getValue());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // Load and parse the template file.
    LinkedList<String> warnings = new LinkedList<String>();
    TemplateFile templateFile = new TemplateFile(resourcePath.getValue(),
                                                 random);
    try
    {
      templateFile.parse(templatePath.getValue(), warnings);
    }
    catch (IOException ioe)
    {
      int    msgID   = MSGID_MAKELDIF_IOEXCEPTION_DURING_PARSE;
      String message = getMessage(msgID, ioe.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_EXCEPTION_DURING_PARSE;
      String message = getMessage(msgID, e.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // If there were any warnings, then print them.
    if (! warnings.isEmpty())
    {
      for (String s : warnings)
      {
        System.err.println(wrapText(s, MAX_LINE_WIDTH));
      }
    }
    // Create the LDIF writer that will be used to actually write the LDIF.
    LDIFExportConfig exportConfig =
         new LDIFExportConfig(ldifFile.getValue(),
                              ExistingFileBehavior.OVERWRITE);
    try
    {
      ldifWriter = new LDIFWriter(exportConfig);
    }
    catch (IOException ioe)
    {
      int    msgID   = MSGID_MAKELDIF_UNABLE_TO_CREATE_LDIF;
      String message = getMessage(msgID, ldifFile.getValue(),
                                  String.valueOf(ioe));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // Generate the LDIF content.
    try
    {
      templateFile.generateLDIF(this);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_ERROR_WRITING_LDIF;
      String message = getMessage(msgID, ldifFile.getValue(),
                                  String.valueOf(e));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    finally
    {
      try
      {
        ldifWriter.close();
      } catch (Exception e) {}
    }
    // If we've gotten here, then everything was successful.
    return 0;
  }
  /**
   * Writes the provided entry to the appropriate target.
   *
   * @param  entry  The entry to be written.
   *
   * @return  <CODE>true</CODE> if the entry writer will accept more entries, or
   *          <CODE>false</CODE> if not.
   *
   * @throws  IOException  If a problem occurs while writing the entry to its
   *                       intended destination.
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public boolean writeEntry(Entry entry)
         throws IOException, MakeLDIFException
  {
    try
    {
      ldifWriter.writeEntry(entry);
      if ((++entriesWritten % 1000) == 0)
      {
        int    msgID   = MSGID_MAKELDIF_PROCESSED_N_ENTRIES;
        String message = getMessage(msgID, entriesWritten);
        System.out.println(wrapText(message, MAX_LINE_WIDTH));
      }
      return true;
    }
    catch (IOException ioe)
    {
      throw ioe;
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_WRITE_ENTRY;
      String message = getMessage(msgID, String.valueOf(entry.getDN()),
                                  String.valueOf(e));
      throw new MakeLDIFException(msgID, message, e);
    }
  }
  /**
   * Notifies the entry writer that no more entries will be provided and that
   * any associated cleanup may be performed.
   */
  public void closeEntryWriter()
  {
    int    msgID   = MSGID_MAKELDIF_PROCESSING_COMPLETE;
    String message = getMessage(msgID, entriesWritten);
    System.out.println(wrapText(message, MAX_LINE_WIDTH));
  }
}
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFException.java
New file
@@ -0,0 +1,95 @@
/*
 * 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.tools.makeldif;
/**
 * This class defines an exception that can be thrown if a problem occurs during
 * MakeLDIF processing.
 */
public class MakeLDIFException
       extends Exception
{
  /**
   * The serial version identifier required to satisfy the compiler because this
   * class extends <CODE>java.lang.Exception</CODE>, which implements the
   * <CODE>java.io.Serializable</CODE> interface.  This value was generated
   * using the <CODE>serialver</CODE> command-line utility included with the
   * Java SDK.
   */
  private static final long serialVersionUID = -918795152848233269L;
  // The unique identifier for the message.
  private int msgID;
  /**
   * Creates a new MakeLDIF exception with the provided information.
   *
   * @param  msgID    The unique identifier for the message.
   * @param  message  The message for this exception.
   */
  public MakeLDIFException(int msgID, String message)
  {
    super(message);
    this.msgID = msgID;
  }
  /**
   * Creates a new MakeLDIF exception with the provided information.
   *
   * @param  msgID    The unique identifier for the message.
   * @param  message  The message for this exception.
   * @param  cause    The underlying cause for this exception.
   */
  public MakeLDIFException(int msgID, String message, Throwable cause)
  {
    super(message, cause);
    this.msgID = msgID;
  }
  /**
   * Retrieves the unique identifier for the message.
   *
   * @return  The unique identifier for the message.
   */
  public int getMessageID()
  {
    return msgID;
  }
}
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFInputStream.java
New file
@@ -0,0 +1,293 @@
/*
 * 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.tools.makeldif;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.opends.server.types.Entry;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.util.LDIFException;
import org.opends.server.util.LDIFWriter;
/**
 * This class creates an input stream that can be used to read entries generated
 * by MakeLDIF as if they were being read from another source like a file.  It
 * has a fixed-size queue that dictates how many entries may be held in memory
 * at any given time.
 */
public class MakeLDIFInputStream
       extends InputStream
       implements EntryWriter
{
  // Indicates whether all of the entries have been generated.
  private boolean allGenerated;
  // Indicates whether this input stream has been closed.
  private boolean closed;
  // The byte array output stream that will be used to convert entries to byte
  // arrays with their LDIF representations.
  private ByteArrayOutputStream entryOutputStream;
  // The byte array that will hold the LDIF representation of the next entry to
  // be read.
  private ByteBuffer entryBytes;
  // The IOException that should be thrown the next time a read is requested.
  private IOException ioException;
  // The LDIF writer that will be used to write the entries to LDIF.
  private LDIFWriter ldifWriter;
  // The queue used to hold generated entries until they can be read.
  private LinkedBlockingQueue<Entry> entryQueue;
  // The background thread being used to actually generate the entries.
  private MakeLDIFInputStreamThread generatorThread;
  // The template file to use to generate the entries.
  private TemplateFile templateFile;
  /**
   * Creates a new MakeLDIF input stream that will generate entries based on the
   * provided template file.
   *
   * @param  templateFile  The template file to use to generate the entries.
   */
  public MakeLDIFInputStream(TemplateFile templateFile)
  {
    this.templateFile = templateFile;
    allGenerated = false;
    closed       = false;
    entryQueue   = new LinkedBlockingQueue<Entry>(10);
    ioException  = null;
    entryBytes   = null;
    entryOutputStream = new ByteArrayOutputStream(8192);
    LDIFExportConfig exportConfig = new LDIFExportConfig(entryOutputStream);
    try
    {
      ldifWriter = new LDIFWriter(exportConfig);
    }
    catch (IOException ioe)
    {
      // This should never happen.
      ioException = ioe;
    }
    generatorThread = new MakeLDIFInputStreamThread(this, templateFile);
    generatorThread.start();
  }
  /**
   * {@inheritDoc}
   */
  public void close()
  {
    closed      = true;
    ioException = null;
  }
  /**
   * {@inheritDoc}
   */
  public int read()
         throws IOException
  {
    if (closed)
    {
      return -1;
    }
    else if (ioException != null)
    {
      throw ioException;
    }
    if ((entryBytes == null) || (! entryBytes.hasRemaining()))
    {
      if (! getNextEntry())
      {
        closed = true;
        return -1;
      }
    }
    return (0xFF & entryBytes.get());
  }
  /**
   * {@inheritDoc}
   */
  public int read(byte[] b, int off, int len)
         throws IOException
  {
    if (closed)
    {
      return -1;
    }
    else if (ioException != null)
    {
      throw ioException;
    }
    if ((entryBytes == null) || (! entryBytes.hasRemaining()))
    {
      if (! getNextEntry())
      {
        closed = true;
        return -1;
      }
    }
    int bytesRead = Math.min(len, entryBytes.remaining());
    entryBytes.get(b, off, bytesRead);
    return bytesRead;
  }
  /**
   * {@inheritDoc}
   */
  public boolean writeEntry(Entry entry)
         throws IOException, MakeLDIFException
  {
    while (! closed)
    {
      try
      {
        if (entryQueue.offer(entry, 500, TimeUnit.MILLISECONDS))
        {
          return true;
        }
      } catch (InterruptedException ie) {}
    }
    return false;
  }
  /**
   * {@inheritDoc}
   */
  public void closeEntryWriter()
  {
    allGenerated = true;
  }
  /**
   * Sets the I/O exception that should be thrown on any subsequent calls to
   * <CODE>available</CODE> or <CODE>read</CODE>.
   *
   * @param  ioException   The I/O exception that should be thrown.
   */
  void setIOException(IOException ioException)
  {
    this.ioException = ioException;
  }
  /**
   * Retrieves the next entry and puts it in the entry byte buffer.
   *
   * @return  <CODE>true</CODE> if the next entry is available, or
   *          <CODE>false</CODE> if there are no more entries or if the input
   *          stream has been closed.
   */
  private boolean getNextEntry()
  {
    Entry entry = entryQueue.poll();
    while (entry == null)
    {
      if (closed)
      {
        return false;
      }
      else if (allGenerated)
      {
        entry = entryQueue.poll();
        if (entry == null)
        {
          return false;
        }
      }
      else
      {
        try
        {
          entry = entryQueue.poll(500, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ie) {}
      }
    }
    try
    {
      entryOutputStream.reset();
      ldifWriter.writeEntry(entry);
      ldifWriter.flush();
      entryBytes = ByteBuffer.wrap(entryOutputStream.toByteArray());
    }
    catch (LDIFException le)
    {
      // This should never happen.
      ioException = new IOException(le.getMessage());
      return false;
    }
    catch (IOException ioe)
    {
      // Neither should this.
      ioException = ioe;
      return false;
    }
    return true;
  }
}
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFInputStreamThread.java
New file
@@ -0,0 +1,92 @@
/*
 * 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.tools.makeldif;
import java.io.IOException;
import org.opends.server.api.DirectoryThread;
/**
 * This class defines a thread that will be used in conjunction with the
 * MakeLDIF input stream to actually generate the data.
 */
class MakeLDIFInputStreamThread
      extends DirectoryThread
{
  // The MakeLDIF input stream that this thread is feeding.
  private MakeLDIFInputStream inputStream;
  // The template file to use to generate the entries.
  private TemplateFile templateFile;
  /**
   * Creates a new instance of this MakeLDIF input stream thread that will feed
   * the provided input strema.
   *
   * @param  inputStream   The MakeLDIF input stream that this thread will feed.
   * @param  templateFile  The template file to use to generate the entries.
   */
  public MakeLDIFInputStreamThread(MakeLDIFInputStream inputStream,
                                   TemplateFile templateFile)
  {
    super("MakeLDIF Input Stream Thread");
    this.inputStream  = inputStream;
    this.templateFile = templateFile;
  }
  /**
   * Operates in a loop, generating entries and feeding them to the input stream
   * until either all entries have been generated or the input stream is closed.
   */
  public void run()
  {
    try
    {
      templateFile.generateLDIF(inputStream);
    }
    catch (MakeLDIFException mle)
    {
      inputStream.setIOException(new IOException(mle.getMessage()));
      inputStream.closeEntryWriter();
    }
    catch (IOException ioe)
    {
      inputStream.setIOException(ioe);
      inputStream.closeEntryWriter();
    }
  }
}
opends/src/server/org/opends/server/tools/makeldif/ParentDNTag.java
New file
@@ -0,0 +1,138 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import org.opends.server.types.DN;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include the DN of the parent entry
 * in the attribute value.
 */
public class ParentDNTag
       extends Tag
{
  /**
   * Creates a new instance of this parent DN tag.
   */
  public ParentDNTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "ParentDN";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return false;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    DN parentDN = templateEntry.getParentDN();
    if ((parentDN == null) || parentDN.isNullDN())
    {
      return TagResult.SUCCESS_RESULT;
    }
    parentDN.toString(templateValue.getValue());
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/PresenceTag.java
New file
@@ -0,0 +1,218 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import java.util.Random;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to indicate that a value should only be
 * included in a percentage of the entries.
 */
public class PresenceTag
       extends Tag
{
  // The percentage of the entries in which this attribute value should appear.
  private int percentage;
  // The random number generator for this tag.
  private Random random;
  /**
   * Creates a new instance of this presence tag.
   */
  public PresenceTag()
  {
    percentage = 100;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "Presence";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments,  lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments,  lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed for this tag.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  private void initializeInternal(TemplateFile templateFile, String[] arguments,
                                  int lineNumber)
          throws InitializationException
  {
    random = templateFile.getRandom();
    if (arguments.length != 1)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    try
    {
      percentage = Integer.parseInt(arguments[0]);
      if (percentage < 0)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
        String message = getMessage(percentage, 0, getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
      else if (percentage > 100)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_ABOVE_UPPER_BOUND;
        String message = getMessage(percentage, 100, getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
    }
    catch (NumberFormatException nfe)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
      String message = getMessage(msgID, arguments[0], getName(), lineNumber);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    int intValue = random.nextInt(100);
    if (intValue < percentage)
    {
      return TagResult.SUCCESS_RESULT;
    }
    else
    {
      return TagResult.OMIT_FROM_ENTRY;
    }
  }
}
opends/src/server/org/opends/server/tools/makeldif/RDNTag.java
New file
@@ -0,0 +1,172 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import org.opends.server.types.DN;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include the RDN of the current entry
 * in the attribute value.
 */
public class RDNTag
       extends Tag
{
  /**
   * Creates a new instance of this RDN tag.
   */
  public RDNTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "RDN";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    DN dn = templateEntry.getDN();
    if ((dn == null) || dn.isNullDN())
    {
      return TagResult.SUCCESS_RESULT;
    }
    else
    {
      dn.getRDN().toString(templateValue.getValue());
      return TagResult.SUCCESS_RESULT;
    }
  }
}
opends/src/server/org/opends/server/tools/makeldif/RandomTag.java
New file
@@ -0,0 +1,696 @@
/*
 * 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.tools.makeldif;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Random;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a tag that may be used to generate random values.  It has
 * a number of subtypes based on the type of information that should be
 * generated, including:
 * <UL>
 *   <LI>alpha:length</LI>
 *   <LI>alpha:minlength:maxlength</LI>
 *   <LI>numeric:length</LI>
 *   <LI>numeric:minvalue:maxvalue</LI>
 *   <LI>numeric:minvalue:maxvalue:format</LI>
 *   <LI>alphanumeric:length</LI>
 *   <LI>alphanumeric:minlength:maxlength</LI>
 *   <LI>chars:characters:length</LI>
 *   <LI>chars:characters:minlength:maxlength</LI>
 *   <LI>hex:length</LI>
 *   <LI>hex:minlength:maxlength</LI>
 *   <LI>base64:length</LI>
 *   <LI>base64:minlength:maxlength</LI>
 *   <LI>month</LI>
 *   <LI>month:maxlength</LI>
 *   <LI>telephone</LI>
 * </UL>
 */
public class RandomTag
       extends Tag
{
  /**
   * The value that indicates that the value is to be generated from a fixed
   * number of characters from a given character set.
   */
  public static final int RANDOM_TYPE_CHARS_FIXED = 1;
  /**
   * The value that indicates that the value is to be generated from a variable
   * number of characters from a given character set.
   */
  public static final int RANDOM_TYPE_CHARS_VARIABLE = 2;
  /**
   * The value that indicates that the value should be a random number.
   */
  public static final int RANDOM_TYPE_NUMERIC = 3;
  /**
   * The value that indicates that the value should be a random month.
   */
  public static final int RANDOM_TYPE_MONTH = 4;
  /**
   * The value that indicates that the value should be a telephone number.
   */
  public static final int RANDOM_TYPE_TELEPHONE = 5;
  /**
   * The character set that will be used for alphabetic characters.
   */
  public static final char[] ALPHA_CHARS =
       "abcdefghijklmnopqrstuvwxyz".toCharArray();
  /**
   * The character set that will be used for numeric characters.
   */
  public static final char[] NUMERIC_CHARS = "01234567890".toCharArray();
  /**
   * The character set that will be used for alphanumeric characters.
   */
  public static final char[] ALPHANUMERIC_CHARS =
       "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
  /**
   * The character set that will be used for hexadecimal characters.
   */
  public static final char[] HEX_CHARS = "01234567890abcdef".toCharArray();
  /**
   * The character set that will be used for base64 characters.
   */
  public static final char[] BASE64_CHARS =
       ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
        "01234567890+/").toCharArray();
  /**
   * The set of month names that will be used.
   */
  public static final String[] MONTHS =
  {
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December"
  };
  // The character set that should be used to generate the values.
  private char[] characterSet;
  // The decimal format used to format numeric values.
  private DecimalFormat decimalFormat;
  // The number of characters between the minimum and maximum length
  // (inclusive).
  private int lengthRange;
  // The maximum number of characters to include in the value.
  private int maxLength;
  // The minimum number of characters to include in the value.
  private int minLength;
  // The type of random value that should be generated.
  private int randomType;
  // The maximum numeric value that should be generated.
  private long maxValue;
  // The minimum numeric value that should be generated.
  private long minValue;
  // The number of values between the minimum and maximum value (inclusive).
  private long valueRange;
  // The random number generator for this tag.
  private Random random;
  /**
   * Creates a new instance of this random tag.
   */
  public RandomTag()
  {
    characterSet  = null;
    decimalFormat = null;
    lengthRange   = 1;
    maxLength     = 0;
    minLength     = 0;
    randomType    = 0;
    maxValue      = 0L;
    minValue      = 0L;
    valueRange    = 1L;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "Random";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber, warnings);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber, warnings);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * either a branch or template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  private void initializeInternal(TemplateFile templateFile, String[] arguments,
                                  int lineNumber, List<String> warnings)
          throws InitializationException
  {
    random = templateFile.getRandom();
    // There must be at least one argument, to specify the type of random value
    // to generate.
    if ((arguments == null) || (arguments.length == 0))
    {
      int    msgID   = MSGID_MAKELDIF_TAG_NO_RANDOM_TYPE_ARGUMENT;
      String message = getMessage(msgID, lineNumber);
      throw new InitializationException(msgID, message);
    }
    int numArgs = arguments.length;
    String randomTypeString = toLowerCase(arguments[0]);
    if (randomTypeString.equals("alpha"))
    {
      characterSet = ALPHA_CHARS;
      decodeLength(arguments, 1, lineNumber, warnings);
    }
    else if (randomTypeString.equals("numeric"))
    {
      if (numArgs == 2)
      {
        randomType   = RANDOM_TYPE_CHARS_FIXED;
        characterSet = NUMERIC_CHARS;
        try
        {
          minLength = Integer.parseInt(arguments[1]);
          if (minLength < 0)
          {
            int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
            String message = getMessage(msgID, minLength, 0, getName(),
                                        lineNumber);
            throw new InitializationException(msgID, message);
          }
          else if (minLength == 0)
          {
            int    msgID   = MSGID_MAKELDIF_TAG_WARNING_EMPTY_VALUE;
            String message = getMessage(msgID, lineNumber);
            warnings.add(message);
          }
        }
        catch (NumberFormatException nfe)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
          String message = getMessage(msgID, arguments[1], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message, nfe);
        }
      }
      else if ((numArgs == 3) || (numArgs == 4))
      {
        randomType = RANDOM_TYPE_NUMERIC;
        if (numArgs == 4)
        {
          try
          {
            decimalFormat = new DecimalFormat(arguments[3]);
          }
          catch (Exception e)
          {
            int    msgID   = MSGID_MAKELDIF_TAG_INVALID_FORMAT_STRING;
            String message = getMessage(msgID, arguments[3], getName(),
                                        lineNumber);
            throw new InitializationException(msgID, message, e);
          }
        }
        else
        {
          decimalFormat = null;
        }
        try
        {
          minValue = Long.parseLong(arguments[1]);
        }
        catch (NumberFormatException nfe)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
          String message = getMessage(msgID, arguments[1], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message, nfe);
        }
        try
        {
          maxValue = Long.parseLong(arguments[2]);
          if (maxValue < minValue)
          {
            int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
            String message = getMessage(msgID, maxValue, minValue, getName(),
                                        lineNumber);
            throw new InitializationException(msgID, message);
          }
          valueRange = maxValue - minValue + 1;
        }
        catch (NumberFormatException nfe)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
          String message = getMessage(msgID, arguments[2], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message, nfe);
        }
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
        String message = getMessage(msgID, getName(), lineNumber, 2, 4,
                                    numArgs);
        throw new InitializationException(msgID, message);
      }
    }
    else if (randomTypeString.equals("alphanumeric"))
    {
      characterSet = ALPHANUMERIC_CHARS;
      decodeLength(arguments, 1, lineNumber, warnings);
    }
    else if (randomTypeString.equals("chars"))
    {
      if ((numArgs < 3) || (numArgs > 4))
      {
        int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
        String message = getMessage(msgID, getName(), lineNumber, 3, 4,
                                    numArgs);
        throw new InitializationException(msgID, message);
      }
      characterSet = arguments[1].toCharArray();
      decodeLength(arguments, 2, lineNumber, warnings);
    }
    else if (randomTypeString.equals("hex"))
    {
      characterSet = HEX_CHARS;
      decodeLength(arguments, 1, lineNumber, warnings);
    }
    else if (randomTypeString.equals("base64"))
    {
      characterSet = BASE64_CHARS;
      decodeLength(arguments, 1, lineNumber, warnings);
    }
    else if (randomTypeString.equals("month"))
    {
      randomType = RANDOM_TYPE_MONTH;
      if (numArgs == 1)
      {
        maxLength = 0;
      }
      else if (numArgs == 2)
      {
        try
        {
          maxLength = Integer.parseInt(arguments[1]);
          if (maxLength <= 0)
          {
            int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
            String message = getMessage(msgID, maxLength, 1, getName(),
                                        lineNumber);
            throw new InitializationException(msgID, message);
          }
        }
        catch (NumberFormatException nfe)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
          String message = getMessage(msgID, arguments[1], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message, nfe);
        }
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
        String message = getMessage(msgID, getName(), lineNumber, 1, 2,
                                    numArgs);
        throw new InitializationException(msgID, message);
      }
    }
    else if (randomTypeString.equals("telephone"))
    {
      randomType    = RANDOM_TYPE_TELEPHONE;
    }
    else
    {
      int    msgID   = MSGID_MAKELDIF_TAG_UNKNOWN_RANDOM_TYPE;
      String message = getMessage(msgID, lineNumber, randomTypeString);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Decodes the information in the provided argument list as either a single
   * integer specifying the number of characters, or two integers specifying the
   * minimum and maximum number of characters.
   *
   * @param  arguments   The set of arguments to be processed.
   * @param  startPos    The position at which the first legth value should
   *                     appear in the argument list.
   * @param  lineNumber  The line number on which the tag appears in the
   *                     template file.
   * @param  warnings    A list into which any appropriate warning messages may
   *                     be placed.
   */
  private void decodeLength(String[] arguments, int startPos, int lineNumber,
                            List<String> warnings)
          throws InitializationException
  {
    int numArgs = arguments.length - startPos + 1;
    if (numArgs == 2)
    {
      // There is a fixed number of characters in the value.
      randomType = RANDOM_TYPE_CHARS_FIXED;
      try
      {
        minLength = Integer.parseInt(arguments[startPos]);
        if (minLength < 0)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
          String message = getMessage(msgID, minLength, 0, getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
        else if (minLength == 0)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_WARNING_EMPTY_VALUE;
          String message = getMessage(msgID, lineNumber);
          warnings.add(message);
        }
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[startPos], getName(),
                                    lineNumber);
        throw new InitializationException(msgID, message, nfe);
      }
    }
    else if (numArgs == 3)
    {
      // There are minimum and maximum lengths.
      randomType = RANDOM_TYPE_CHARS_VARIABLE;
      try
      {
        minLength = Integer.parseInt(arguments[startPos]);
        if (minLength < 0)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
          String message = getMessage(msgID, minLength, 0, getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[startPos], getName(),
                                    lineNumber);
        throw new InitializationException(msgID, message, nfe);
      }
      try
      {
        maxLength   = Integer.parseInt(arguments[startPos+1]);
        lengthRange = maxLength - minLength + 1;
        if (maxLength < minLength)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_INTEGER_BELOW_LOWER_BOUND;
          String message = getMessage(msgID, maxLength, minLength, getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
        else if (maxLength == 0)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_WARNING_EMPTY_VALUE;
          String message = getMessage(msgID, getName(), lineNumber);
          warnings.add(message);
        }
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[startPos+1], getName(),
                                    lineNumber);
        throw new InitializationException(msgID, message, nfe);
      }
    }
    else
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, startPos+1,
                                  startPos+2, numArgs);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    StringBuilder buffer = templateValue.getValue();
    switch (randomType)
    {
      case RANDOM_TYPE_CHARS_FIXED:
        for (int i=0; i < minLength; i++)
        {
          buffer.append(characterSet[random.nextInt(characterSet.length)]);
        }
        break;
      case RANDOM_TYPE_CHARS_VARIABLE:
        int numChars = random.nextInt(lengthRange) + minLength;
        for (int i=0; i < numChars; i++)
        {
          buffer.append(characterSet[random.nextInt(characterSet.length)]);
        }
        break;
      case RANDOM_TYPE_NUMERIC:
        long randomValue =
          ((random.nextLong() & 0x7FFFFFFFFFFFFFFFL) % valueRange) + minValue;
        if (decimalFormat == null)
        {
          buffer.append(randomValue);
        }
        else
        {
          buffer.append(decimalFormat.format(randomValue));
        }
        break;
      case RANDOM_TYPE_MONTH:
        String month = MONTHS[random.nextInt(MONTHS.length)];
        if ((maxLength == 0) || (month.length() <= maxLength))
        {
          buffer.append(month);
        }
        else
        {
          buffer.append(month.substring(0, maxLength));
        }
        break;
      case RANDOM_TYPE_TELEPHONE:
        for (int i=0; i < 3; i++)
        {
          buffer.append(NUMERIC_CHARS[random.nextInt(NUMERIC_CHARS.length)]);
        }
        buffer.append('-');
        for (int i=0; i < 3; i++)
        {
          buffer.append(NUMERIC_CHARS[random.nextInt(NUMERIC_CHARS.length)]);
        }
        buffer.append('-');
        for (int i=0; i < 4; i++)
        {
          buffer.append(NUMERIC_CHARS[random.nextInt(NUMERIC_CHARS.length)]);
        }
        break;
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/SequentialTag.java
New file
@@ -0,0 +1,257 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include a sequentially-incrementing
 * integer in the generated values.
 */
public class SequentialTag
       extends Tag
{
  // Indicates whether to reset for each parent.
  private boolean resetOnNewParents;
  // The initial value in the sequence.
  private int initialValue;
  // The next value in the sequence.
  private int nextValue;
  /**
   * Creates a new instance of this sequential tag.
   */
  public SequentialTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "Sequential";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed for this tag.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  private void initializeInternal(TemplateFile templateFile, String[] arguments,
                                  int lineNumber)
          throws InitializationException
  {
    switch (arguments.length)
    {
      case 0:
        initialValue      = 0;
        nextValue         = 0;
        resetOnNewParents = true;
        break;
      case 1:
        try
        {
          initialValue = Integer.parseInt(arguments[0]);
        }
        catch (NumberFormatException nfe)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
          String message = getMessage(msgID, arguments[0], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
        nextValue         = initialValue;
        resetOnNewParents = true;
        break;
      case 2:
        try
        {
          initialValue = Integer.parseInt(arguments[0]);
        }
        catch (NumberFormatException nfe)
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
          String message = getMessage(msgID, arguments[0], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
        if (arguments[1].equalsIgnoreCase("true"))
        {
          resetOnNewParents = true;
        }
        else if (arguments[1].equalsIgnoreCase("false"))
        {
          resetOnNewParents = false;
        }
        else
        {
          int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_BOOLEAN;
          String message = getMessage(msgID, arguments[1], getName(),
                                      lineNumber);
          throw new InitializationException(msgID, message);
        }
        nextValue = initialValue;
        break;
      default:
        int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
        String message = getMessage(msgID, getName(), lineNumber, 0, 2,
                                    arguments.length);
        throw new InitializationException(msgID, message);
    }
  }
  /**
   * Performs any initialization for this tag that may be needed when starting
   * to generate entries below a new parent.
   *
   * @param  parentEntry  The entry below which the new entries will be
   *                      generated.
   */
  public void initializeForParent(TemplateEntry parentEntry)
  {
    if (resetOnNewParents)
    {
      nextValue = initialValue;
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    templateValue.getValue().append(nextValue++);
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/StaticTextTag.java
New file
@@ -0,0 +1,172 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to hold static text (i.e., text that
 * appears outside of any tag).
 */
public class StaticTextTag
       extends Tag
{
  // The static text to include in the LDIF.
  private String text;
  /**
   * Creates a new instance of this static text tag.
   */
  public StaticTextTag()
  {
    text = "";
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "StaticText";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 1)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    text = arguments[0];
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 1)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 1,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
    text = arguments[0];
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    templateValue.append(text);
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/Tag.java
New file
@@ -0,0 +1,137 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
/**
 * This class defines a tag that may be used in a template line.  It can be used
 * to generate content in the resulting LDIF.
 */
public abstract class Tag
{
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public abstract String getName();
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public abstract boolean allowedInBranch();
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    // No implementation required by default.
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public abstract void initializeForTemplate(TemplateFile templateFile,
                                             Template template,
                                             String[] arguments, int lineNumber,
                                             List<String> warnings)
         throws InitializationException;
  /**
   * Performs any initialization for this tag that may be needed when starting
   * to generate entries below a new parent.
   *
   * @param  parentEntry  The entry below which the new entries will be
   *                      generated.
   */
  public void initializeForParent(TemplateEntry parentEntry)
  {
    // No implementation required by default.
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public abstract TagResult generateValue(TemplateEntry templateEntry,
                                          TemplateValue templateValue);
}
opends/src/server/org/opends/server/tools/makeldif/TagResult.java
New file
@@ -0,0 +1,166 @@
/*
 * 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.tools.makeldif;
/**
 * This class defines a data structure that provides information about the
 * result of tag processing.
 */
public class TagResult
{
  /**
   * A tag result in which all components have a value of <CODE>true</CODE>.
   */
  public static final TagResult SUCCESS_RESULT =
       new TagResult(true, true, true, true);
  /**
   * A tag result that indicates the value should not be included in the entry,
   * but all other processing should continue.
   */
  public static final TagResult OMIT_FROM_ENTRY =
       new TagResult(false, true, true, true);
  /**
   * A tag result in whihc all components have a value of <CODE>false</CODE>.
   */
  public static final TagResult STOP_PROCESSING =
       new TagResult(false, false, false, false);
  // Indicates whether to keep processing the associated line.
  private boolean keepProcessingLine;
  // Indicates whether to keep processing the associated entry.
  private boolean keepProcessingEntry;
  // Indicates whether to keep processing entries below the associated parent.
  private boolean keepProcessingParent;
  // Indicates whether to keep processing entries for the template file.
  private boolean keepProcessingTemplateFile;
  /**
   * Creates a new tag result object with the provided information.
   *
   * @param  keepProcessingLine          Indicates whether to continue
   *                                     processing for the current line.  If
   *                                     not, then the line will not be included
   *                                     in the entry.
   * @param  keepProcessingEntry         Indicates whether to continue
   *                                     processing for the current entry.  If
   *                                     not, then the entry will not be
   *                                     included in the data.
   * @param  keepProcessingParent        Indicates whether to continue
   *                                     processing entries below the current
   *                                     parent in the template file.
   * @param  keepProcessingTemplateFile  Indicates whether to continue
   *                                     processing entries for the template
   *                                     file.
   */
  public TagResult(boolean keepProcessingLine, boolean keepProcessingEntry,
                   boolean keepProcessingParent,
                   boolean keepProcessingTemplateFile)
  {
    this.keepProcessingLine         = keepProcessingLine;
    this.keepProcessingEntry        = keepProcessingEntry;
    this.keepProcessingParent       = keepProcessingParent;
    this.keepProcessingTemplateFile = keepProcessingTemplateFile;
  }
  /**
   * Indicates whether to continue processing for the current line.  If this is
   * <CODE>false</CODE>, then the current line will not be included in the
   * entry.  It will have no impact on whehter the entry itself is included in
   * the generated LDIF.
   *
   * @return  <CODE>true</CODE> if the line should be included in the entry, or
   *          <CODE>false</CODE> if not.
   */
  public boolean keepProcessingLine()
  {
    return keepProcessingLine;
  }
  /**
   * Indicates whether to continue processing for the current entry.  If this is
   * <CODE>false</CODE>, then the current entry will not be included in the
   * generated LDIF, and processing will resume with the next entry below the
   * current parent.
   *
   * @return  <CODE>true</CODE> if the entry should be included in the
   *          generated LDIF, or <CODE>false</CODE> if not.
   */
  public boolean keepProcessingEntry()
  {
    return keepProcessingEntry;
  }
  /**
   * Indicates whether to continue processing entries below the current parent.
   * If this is <CODE>false</CODE>, then the current entry will not be included,
   * and processing will resume below the next parent in the template file.
   *
   * @return  <CODE>true</CODE> if processing for the current parent should
   *          continue, or <CODE>false</CODE> if not.
   */
  public boolean keepProcessingParent()
  {
    return keepProcessingParent;
  }
  /**
   * Indicates whether to keep processing entries for the template file.  If
   * this is <CODE>false</CODE>, then LDIF processing will end immediately (and
   * the current entry will not be included).
   *
   * @return  <CODE>true</CODE> if processing for the template file should
   *          continue, or <CODE>false</CODE> if not.
   */
  public boolean keepProcessingTemplateFile()
  {
    return keepProcessingTemplateFile;
  }
}
opends/src/server/org/opends/server/tools/makeldif/Template.java
New file
@@ -0,0 +1,393 @@
/*
 * 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.tools.makeldif;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a template, which is a pattern that may be used to
 * generate entries.  A template may be used either below a branch or below
 * another template.
 */
public class Template
{
  // The attribute types that are used in the RDN for entries generated using
  // this template.
  private AttributeType[] rdnAttributes;
  // The number of entries to create for each subordinate template.
  private int[] numEntriesPerTemplate;
  // The name for this template.
  private String name;
  // The names of the subordinate templates below this template.
  private String[] subordinateTemplateNames;
  // The subordinate templates below this template.
  private Template[] subordinateTemplates;
  // The template file that contains this template.
  private TemplateFile templateFile;
  // The set of template lines for this template.
  private TemplateLine[] templateLines;
  /**
   * Creates a new template with the provided information.
   *
   * @param  templateFile              The template file that contains this
   *                                   template.
   * @param  name                      The name for this template.
   * @param  rdnAttributes             The set of attribute types that are used
   *                                   in the RDN for entries generated using
   *                                   this template.
   * @param  subordinateTemplateNames  The names of the subordinate templates
   *                                   below this template.
   * @param  numEntriesPerTemplate     The number of entries to create below
   *                                   each subordinate template.
   */
  public Template(TemplateFile templateFile, String name,
                  AttributeType[] rdnAttributes,
                  String[] subordinateTemplateNames,
                  int[] numEntriesPerTemplate)
  {
    this.templateFile             = templateFile;
    this.name                     = name;
    this.rdnAttributes            = rdnAttributes;
    this.subordinateTemplateNames = subordinateTemplateNames;
    this.numEntriesPerTemplate    = numEntriesPerTemplate;
    templateLines        = new TemplateLine[0];
    subordinateTemplates = null;
  }
  /**
   * Creates a new template with the provided information.
   *
   * @param  templateFile              The template file that contains this
   *                                   template.
   * @param  name                      The name for this template.
   * @param  rdnAttributes             The set of attribute types that are used
   *                                   in the RDN for entries generated using
   *                                   this template.
   * @param  subordinateTemplateNames  The names of the subordinate templates
   *                                   below this template.
   * @param  numEntriesPerTemplate     The number of entries to create below
   *                                   each subordinate template.
   * @param  templateLines             The set of template lines for this
   *                                   template.
   */
  public Template(TemplateFile templateFile, String name,
                  AttributeType[] rdnAttributes,
                  String[] subordinateTemplateNames,
                  int[] numEntriesPerTemplate, TemplateLine[] templateLines)
  {
    this.templateFile             = templateFile;
    this.name                     = name;
    this.rdnAttributes            = rdnAttributes;
    this.subordinateTemplateNames = subordinateTemplateNames;
    this.numEntriesPerTemplate    = numEntriesPerTemplate;
    this.templateLines            = templateLines;
    subordinateTemplates = null;
  }
  /**
   * Performs any necessary processing to ensure that the template
   * initialization is completed.  In particular, it should make sure that all
   * referenced subordinate templates actually exist in the template file, and
   * that all of the RDN attributes are contained in the template lines.
   *
   * @param  templates  The set of templates defined in the template file.
   *
   * @throws  MakeLDIFException  If any of the subordinate templates are not
   *                             defined in the template file.
   */
  public void completeTemplateInitialization(Map<String,Template> templates)
         throws MakeLDIFException
  {
    // Make sure that all of the specified subordinate templates exist.
    if (subordinateTemplateNames == null)
    {
      subordinateTemplateNames = new String[0];
      subordinateTemplates     = new Template[0];
    }
    else
    {
      subordinateTemplates = new Template[subordinateTemplateNames.length];
      for (int i=0; i < subordinateTemplates.length; i++)
      {
        subordinateTemplates[i] =
             templates.get(toLowerCase(subordinateTemplateNames[i]));
        if (subordinateTemplates[i] == null)
        {
          int    msgID   = MSGID_MAKELDIF_UNDEFINED_TEMPLATE_SUBORDINATE;
          String message = getMessage(msgID, subordinateTemplateNames[i], name);
          throw new MakeLDIFException(msgID, message);
        }
      }
    }
    // Make sure that all of the RDN attributes are defined.
    HashSet<AttributeType> rdnAttrs =
         new HashSet<AttributeType>(rdnAttributes.length);
    for (AttributeType t : rdnAttributes)
    {
      rdnAttrs.add(t);
    }
    for (TemplateLine l : templateLines)
    {
      if (rdnAttrs.remove(l.getAttributeType()))
      {
        if (rdnAttrs.isEmpty())
        {
          break;
        }
      }
    }
    if (! rdnAttrs.isEmpty())
    {
      AttributeType t       = rdnAttrs.iterator().next();
      int           msgID   = MSGID_MAKELDIF_TEMPLATE_MISSING_RDN_ATTR;
      String        message = getMessage(msgID, name, t.getNameOrOID());
      throw new MakeLDIFException(msgID, message);
    }
  }
  /**
   * Retrieves the name for this template.
   *
   * @return  The name for this template.
   */
  public String getName()
  {
    return name;
  }
  /**
   * Retrieves the set of attribute types that are used in the RDN for entries
   * generated using this template.
   *
   * @return  The set of attribute types that are used in the RDN for entries
   *          generated using this template.
   */
  public AttributeType[] getRDNAttributes()
  {
    return rdnAttributes;
  }
  /**
   * Retrieves the names of the subordinate templates used to generate entries
   * below entries created by this template.
   *
   * @return  The names of the subordinate templates used to generate entries
   *          below entries created by this template.
   */
  public String[] getSubordinateTemplateNames()
  {
    return subordinateTemplateNames;
  }
  /**
   * Retrieves the subordinate templates used to generate entries below entries
   * created by this template.
   *
   * @return  The subordinate templates used to generate entries below entries
   *          created by this template.
   */
  public Template[] getSubordinateTemplates()
  {
    return subordinateTemplates;
  }
  /**
   * Retrieves the number of entries that should be created for each subordinate
   * template.
   *
   * @return  The number of entries that should be created for each subordinate
   *          template.
   */
  public int[] getNumEntriesPerTemplate()
  {
    return numEntriesPerTemplate;
  }
  /**
   * Retrieves the set of template lines for this template.
   *
   * @return  The set of template lines for this template.
   */
  public TemplateLine[] getTemplateLines()
  {
    return templateLines;
  }
  /**
   * Adds the provided template line to this template.
   *
   * @param  line  The template line to add to this template.
   */
  public void addTemplateLine(TemplateLine line)
  {
    TemplateLine[] newTemplateLines = new TemplateLine[templateLines.length+1];
    System.arraycopy(templateLines, 0, newTemplateLines, 0,
                     templateLines.length);
    newTemplateLines[templateLines.length] = line;
    templateLines = newTemplateLines;
  }
  /**
   * Indicates whether this template contains any template lines that reference
   * the provided attribute type.
   *
   * @param  attributeType  The attribute type for which to make the
   *                        determination.
   *
   * @return  <CODE>true</CODE> if this template contains one or more template
   *          lines that reference the provided attribute type, or
   *          <CODE>false</CODE> if not.
   */
  public boolean hasAttribute(AttributeType attributeType)
  {
    for (TemplateLine l : templateLines)
    {
      if (l.getAttributeType().equals(attributeType))
      {
        return true;
      }
    }
    return false;
  }
  /**
   * Writes the entry for this template, as well as all appropriate subordinate
   * entries.
   *
   * @param  entryWriter  The entry writer that will be used to write the
   *                      entries.
   * @param  parentDN     The DN of the entry below which the subordinate
   *                      entries should be generated.
   * @param  count        The number of entries to generate based on this
   *                      template.
   *
   * @return  The result that indicates whether processing should continue.
   *
   * @throws  IOException  If a problem occurs while attempting to write to the
   *                       LDIF writer.
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public TagResult writeEntries(EntryWriter entryWriter, DN parentDN, int count)
         throws IOException, MakeLDIFException
  {
    for (int i=0; i < count; i++)
    {
      templateFile.nextFirstAndLastNames();
      TemplateEntry templateEntry = new TemplateEntry(this, parentDN);
      for (TemplateLine l : templateLines)
      {
        TagResult r = l.generateLine(templateEntry);
        if (! (r.keepProcessingEntry() && r.keepProcessingParent() &&
               r.keepProcessingTemplateFile()))
        {
          return r;
        }
      }
      Entry entry = templateEntry.toEntry();
      if (! entryWriter.writeEntry(entry))
      {
        return TagResult.STOP_PROCESSING;
      }
      for (int j=0; j < subordinateTemplates.length; j++)
      {
        TagResult r =
             subordinateTemplates[j].writeEntries(entryWriter, entry.getDN(),
                                                  numEntriesPerTemplate[j]);
        if (! (r.keepProcessingParent() && r.keepProcessingTemplateFile()))
        {
          if (r.keepProcessingTemplateFile())
          {
            // We don't want to propagate a "stop processing parent" all the
            // way up the chain.
            return TagResult.SUCCESS_RESULT;
          }
          return r;
        }
      }
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/TemplateEntry.java
New file
@@ -0,0 +1,332 @@
/*
 * 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.tools.makeldif;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.RDN;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines an entry that is generated using a MakeLDIF branch or
 * template.
 */
public class TemplateEntry
{
  // The branch used to generate this entry (if it is associated with a branch).
  private Branch branch;
  // The DN for this template entry, if it is known.
  private DN dn;
  // The DN of the parent entry for this template entry, if it is available.
  private DN parentDN;
  // The set of attributes associated with this template entry, mapped from the
  // lowercase name of the attribute to the list of generated values.
  private LinkedHashMap<AttributeType,ArrayList<TemplateValue>> attributes;
  // The template used to generate this entry (if it is associated with a
  // template).
  private Template template;
  /**
   * Creates a new template entry that will be associated with the provided
   * branch.
   *
   * @param  branch  The branch to use when creating this template entry.
   */
  public TemplateEntry(Branch branch)
  {
    this.branch = branch;
    dn         = branch.getBranchDN();
    template   = null;
    parentDN   = null;
    attributes = new LinkedHashMap<AttributeType,ArrayList<TemplateValue>>();
  }
  /**
   * Creates a new template entry that will be associated with the provided
   * template.
   *
   * @param  template  The template used to generate this entry.
   * @param  parentDN  The DN of the parent entry for this template entry.
   */
  public TemplateEntry(Template template, DN parentDN)
  {
    this.template = template;
    this.parentDN = parentDN;
    dn         = null;
    branch     = null;
    attributes = new LinkedHashMap<AttributeType,ArrayList<TemplateValue>>();
  }
  /**
   * Retrieves the branch used to generate this entry.
   *
   * @return  The branch used to generate this entry, or <CODE>null</CODE> if it
   *          is associated with a template instead of a branch.
   */
  public Branch getBranch()
  {
    return branch;
  }
  /**
   * Retrieves the template used to generate this entry.
   *
   * @return  The template used to generate this entry, or <CODE>null</CODE> if
   *          it is associated with a branch instead of a template.
   */
  public Template getTemplate()
  {
    return template;
  }
  /**
   * Retrieves the DN of the parent entry for this template entry.
   *
   * @return  The DN of the parent entry for this template entry, or
   *          <CODE>null</CODE> if there is no parent DN.
   */
  public DN getParentDN()
  {
    return parentDN;
  }
  /**
   * Retrieves teh DN for this template entry, if it is known.
   *
   * @return  The DN for this template entry if it is known, or
   *          <CODE>null</CODE> if it cannot yet be determined.
   */
  public DN getDN()
  {
    if (dn == null)
    {
      AttributeType[]  rdnAttributes = template.getRDNAttributes();
      String[]         rdnNames      = new String[rdnAttributes.length];
      AttributeValue[] rdnValues     = new AttributeValue[rdnAttributes.length];
      for (int i=0; i < rdnAttributes.length; i++)
      {
        TemplateValue v = getValue(rdnAttributes[i]);
        if (v == null)
        {
          return null;
        }
        rdnNames[i]  = rdnAttributes[i].getNameOrOID();
        rdnValues[i] = new AttributeValue(rdnAttributes[i],
                                          v.getValue().toString());
      }
      RDN[] parentComponents = parentDN.getRDNComponents();
      RDN[] dnComponents = new RDN[parentComponents.length+1];
      dnComponents[0] = new RDN(rdnAttributes, rdnNames, rdnValues);
      System.arraycopy(parentComponents, 0, dnComponents, 1,
                       parentComponents.length);
      dn = new DN(dnComponents);
    }
    return dn;
  }
  /**
   * Indicates whether this entry contains one or more values for the specified
   * attribute type.
   *
   * @param  attributeType  The attribute type for which to make the
   *                        determination.
   *
   * @return  <CODE>true</CODE> if this entry contains one or more values for
   *          the specified attribute type, or <CODE>false</CODE> if not.
   */
  public boolean hasAttribute(AttributeType attributeType)
  {
    return attributes.containsKey(attributeType);
  }
  /**
   * Retrieves the value for the specified attribute, if defined.  If the
   * specified attribute has multiple values, then the first will be returned.
   *
   * @param  attributeType  The attribute type for which to retrieve the value.
   *
   * @return  The value for the specified attribute, or <CODE>null</CODE> if
   *          there are no values for that attribute type.
   */
  public TemplateValue getValue(AttributeType attributeType)
  {
    ArrayList<TemplateValue> valueList = attributes.get(attributeType);
    if ((valueList == null) || valueList.isEmpty())
    {
      return null;
    }
    else
    {
      return valueList.get(0);
    }
  }
  /**
   * Retrieves the set of values for the specified attribute, if defined.
   *
   * @param  attributeType  The attribute type for which to retrieve the set of
   *                        values.
   *
   * @return  The set of values for the specified attribute, or
   *          <CODE>null</CODE> if there are no values for that attribute type.
   */
  public List<TemplateValue> getValues(AttributeType attributeType)
  {
    ArrayList<TemplateValue> valueList = attributes.get(attributeType);
    return valueList;
  }
  /**
   * Adds the provided template value to this entry.
   *
   * @param  value  The value to add to this entry.
   */
  public void addValue(TemplateValue value)
  {
    ArrayList<TemplateValue> valueList =
         attributes.get(value.getAttributeType());
    if (valueList == null)
    {
      valueList = new ArrayList<TemplateValue>();
      valueList.add(value);
      attributes.put(value.getAttributeType(), valueList);
    }
    else
    {
      valueList.add(value);
    }
  }
  /**
   * Retrieves this template entry as an <CODE>Entry</CODE> object.
   *
   * @return  The <CODE>Entry</CODE> object for this template entry.
   */
  public Entry toEntry()
  {
    // Process all of the attributes for this entry.
    LinkedHashMap<ObjectClass,String> objectClasses =
         new LinkedHashMap<ObjectClass,String>();
    LinkedHashMap<AttributeType,List<Attribute>> userAttributes =
         new LinkedHashMap<AttributeType,List<Attribute>>();
    LinkedHashMap<AttributeType,List<Attribute>> operationalAttributes =
         new LinkedHashMap<AttributeType,List<Attribute>>();
    for (AttributeType t : attributes.keySet())
    {
      ArrayList<TemplateValue> valueList = attributes.get(t);
      if (t.isObjectClassType())
      {
        for (TemplateValue v : valueList)
        {
          String ocName = toLowerCase(v.getValue().toString());
          ObjectClass oc = DirectoryServer.getObjectClass(ocName, true);
          objectClasses.put(oc, ocName);
        }
      }
      else if (t.isOperational())
      {
        LinkedHashSet<AttributeValue> values =
             new LinkedHashSet<AttributeValue>();
        for (TemplateValue v : valueList)
        {
          values.add(new AttributeValue(t, v.getValue().toString()));
        }
        ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
        attrList.add(new Attribute(t, t.getNameOrOID(), values));
        operationalAttributes.put(t, attrList);
      }
      else
      {
        LinkedHashSet<AttributeValue> values =
             new LinkedHashSet<AttributeValue>();
        for (TemplateValue v : valueList)
        {
          values.add(new AttributeValue(t, v.getValue().toString()));
        }
        ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
        attrList.add(new Attribute(t, t.getNameOrOID(), values));
        userAttributes.put(t, attrList);
      }
    }
    return new Entry(getDN(), objectClasses, userAttributes,
                     operationalAttributes);
  }
}
opends/src/server/org/opends/server/tools/makeldif/TemplateFile.java
New file
@@ -0,0 +1,1759 @@
/*
 * 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.tools.makeldif;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.InitializationException;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a template file, which is a collection of constant
 * definitions, branches, and templates.
 */
public class TemplateFile
{
  /**
   * The name of the file holding the list of first names.
   */
  public static final String FIRST_NAME_FILE = "first.names";
  /**
   * The name of the file holding the list of last names.
   */
  public static final String LAST_NAME_FILE = "last.names";
  // A map of the contents of various text files used during the parsing
  // process, mapped from absolute path to the array of lines in the file.
  private HashMap<String,String[]> fileLines;
  // The index of the next first name value that should be used.
  private int firstNameIndex;
  // The index of the next last name value that should be used.
  private int lastNameIndex;
  // A counter used to keep track of the number of times that the larger of the
  // first/last name list has been completed.
  private int nameLoopCounter;
  // A counter that will be used in case we have exhausted all possible first
  // and last name combinations.
  private int nameUniquenessCounter;
  // The set of branch definitions for this template file.
  private LinkedHashMap<DN,Branch> branches;
  // The set of constant definitions for this template file.
  private LinkedHashMap<String,String> constants;
  // The set of registered tags for this template file.
  private LinkedHashMap<String,Tag> registeredTags;
  // The set of template definitions for this template file.
  private LinkedHashMap<String,Template> templates;
  // The random number generator for this template file.
  private Random random;
  // The next first name that should be used.
  private String firstName;
  // The next last name that should be used.
  private String lastName;
  // The resource path to use for filesystem elements that cannot be found
  // anywhere else.
  private String resourcePath;
  // The path to the directory containing the template file, if available.
  private String templatePath;
  // The set of first names to use when generating the LDIF.
  private String[] firstNames;
  // The set of last names to use when generating the LDIF.
  private String[] lastNames;
  /**
   * Creates a new, empty template file structure.
   *
   * @param  resourcePath  The path to the directory that may contain additional
   *                       resource files needed during the LDIF generation
   *                       process.
   */
  public TemplateFile(String resourcePath)
  {
    this(resourcePath, new Random());
  }
  /**
   * Creates a new, empty template file structure.
   *
   *
   * @param  resourcePath  The path to the directory that may contain additional
   *                       resource files needed during the LDIF generation
   *                       process.
   * @param  random        The random number generator for this template file.
   */
  public TemplateFile(String resourcePath, Random random)
  {
    this.resourcePath = resourcePath;
    this.random       = random;
    fileLines             = new HashMap<String,String[]>();
    branches              = new LinkedHashMap<DN,Branch>();
    constants             = new LinkedHashMap<String,String>();
    registeredTags        = new LinkedHashMap<String,Tag>();
    templates             = new LinkedHashMap<String,Template>();
    templatePath          = null;
    firstNames            = new String[0];
    lastNames             = new String[0];
    firstName             = null;
    lastName              = null;
    firstNameIndex        = 0;
    lastNameIndex         = 0;
    nameLoopCounter       = 0;
    nameUniquenessCounter = 1;
    registerDefaultTags();
    try
    {
      readNameFiles();
    }
    catch (IOException ioe)
    {
      // FIXME -- What to do here?
      ioe.printStackTrace();
      firstNames = new String[] { "John" };
      lastNames  = new String[] { "Doe" };
    }
  }
  /**
   * Retrieves the set of tags that have been registered.  They will be in the
   * form of a mapping between the name of the tag (in all lowercase characters)
   * and the corresponding tag implementation.
   *
   * @return  The set of tags that have been registered.
   */
  public Map<String,Tag> getTags()
  {
    return registeredTags;
  }
  /**
   * Retrieves the tag with the specified name.
   *
   * @param  lowerName  The name of the tag to retrieve, in all lowercase
   *                    characters.
   *
   * @return  The requested tag, or <CODE>null</CODE> if no such tag has been
   *          registered.
   */
  public Tag getTag(String lowerName)
  {
    return registeredTags.get(lowerName);
  }
  /**
   * Registers the specified class as a tag that may be used in templates.
   *
   * @param  tagClass  The fully-qualified name of the class to register as a
   *                   tag.
   *
   * @throws  MakeLDIFException  If a problem occurs while attempting to
   *                             register the specified tag.
   */
  public void registerTag(String tagClass)
         throws MakeLDIFException
  {
    Class c;
    try
    {
      c = Class.forName(tagClass);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_LOAD_TAG_CLASS;
      String message = getMessage(msgID, tagClass);
      throw new MakeLDIFException(msgID, message, e);
    }
    Tag t;
    try
    {
      t = (Tag) c.newInstance();
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_INSTANTIATE_TAG;
      String message = getMessage(msgID, tagClass);
      throw new MakeLDIFException(msgID, message, e);
    }
    String lowerName = toLowerCase(t.getName());
    if (registeredTags.containsKey(lowerName))
    {
      int    msgID   = MSGID_MAKELDIF_CONFLICTING_TAG_NAME;
      String message = getMessage(msgID, tagClass, t.getName());
      throw new MakeLDIFException(msgID, message);
    }
    else
    {
      registeredTags.put(lowerName, t);
    }
  }
  /**
   * Registers the set of tags that will always be available for use in
   * templates.
   */
  private void registerDefaultTags()
  {
    Class[] defaultTagClasses = new Class[]
    {
      AttributeValueTag.class,
      DNTag.class,
      FileTag.class,
      FirstNameTag.class,
      GUIDTag.class,
      IfAbsentTag.class,
      IfPresentTag.class,
      LastNameTag.class,
      ParentDNTag.class,
      PresenceTag.class,
      RandomTag.class,
      RDNTag.class,
      SequentialTag.class,
      StaticTextTag.class,
      UnderscoreDNTag.class,
      UnderscoreParentDNTag.class
    };
    for (Class c : defaultTagClasses)
    {
      try
      {
        Tag t = (Tag) c.newInstance();
        registeredTags.put(toLowerCase(t.getName()), t);
      }
      catch (Exception e)
      {
        // This should never happen.
        e.printStackTrace();
      }
    }
  }
  /**
   * Retrieves the set of constants defined for this template file.
   *
   * @return  The set of constants defined for this template file.
   */
  public Map<String,String> getConstants()
  {
    return constants;
  }
  /**
   * Retrieves the value of the constant with the specified name.
   *
   * @param  lowerName  The name of the constant to retrieve, in all lowercase
   *                    characters.
   *
   * @return  The value of the constant with the specified name, or
   *          <CODE>null</CODE> if there is no such constant.
   */
  public String getConstant(String lowerName)
  {
    return constants.get(lowerName);
  }
  /**
   * Registers the provided constant for use in the template.
   *
   * @param  name   The name for the constant.
   * @param  value  The value for the constant.
   */
  public void registerConstant(String name, String value)
  {
    constants.put(toLowerCase(name), value);
  }
  /**
   * Retrieves the set of branches defined in this template file.
   *
   * @return  The set of branches defined in this template file.
   */
  public Map<DN,Branch> getBranches()
  {
    return branches;
  }
  /**
   * Retrieves the branch registered with the specified DN.
   *
   * @param  branchDN  The DN for which to retrieve the corresponding branch.
   *
   * @return  The requested branch, or <CODE>null</CODE> if no such branch has
   *          been registered.
   */
  public Branch getBranch(DN branchDN)
  {
    return branches.get(branchDN);
  }
  /**
   * Registers the provided branch in this template file.
   *
   * @param  branch  The branch to be registered.
   */
  public void registerBranch(Branch branch)
  {
    branches.put(branch.getBranchDN(), branch);
  }
  /**
   * Retrieves the set of templates defined in this template file.
   *
   * @return  The set of templates defined in this template file.
   */
  public Map<String,Template> getTemplates()
  {
    return templates;
  }
  /**
   * Retrieves the template with the specified name.
   *
   * @param  lowerName  The name of the template to retrieve, in all lowercase
   *                    characters.
   *
   * @return  The requested template, or <CODE>null</CODE> if there is no such
   *          template.
   */
  public Template getTemplate(String lowerName)
  {
    return templates.get(lowerName);
  }
  /**
   * Registers the provided template for use in this template file.
   *
   * @param  template  The template to be registered.
   */
  public void registerTemplate(Template template)
  {
    templates.put(toLowerCase(template.getName()), template);
  }
  /**
   * Retrieves the random number generator for this template file.
   *
   * @return  The random number generator for this template file.
   */
  public Random getRandom()
  {
    return random;
  }
  /**
   * Reads the contents of the first and last name files into the appropriate
   * arrays and sets up the associated index pointers.
   *
   * @throws  IOException  If a problem occurs while reading either of the
   *                       files.
   */
  private void readNameFiles()
          throws IOException
  {
    File f = getFile(FIRST_NAME_FILE);
    ArrayList<String> nameList = new ArrayList<String>();
    BufferedReader reader = new BufferedReader(new FileReader(f));
    while (true)
    {
      String line = reader.readLine();
      if (line == null)
      {
        break;
      }
      else
      {
        nameList.add(line);
      }
    }
    reader.close();
    firstNames = new String[nameList.size()];
    nameList.toArray(firstNames);
    f = getFile(LAST_NAME_FILE);
    nameList = new ArrayList<String>();
    reader = new BufferedReader(new FileReader(f));
    while (true)
    {
      String line = reader.readLine();
      if (line == null)
      {
        break;
      }
      else
      {
        nameList.add(line);
      }
    }
    reader.close();
    lastNames = new String[nameList.size()];
    nameList.toArray(lastNames);
  }
  /**
   * Updates the first and last name indexes to choose new values.  The
   * algorithm used is designed to ensure that the combination of first and last
   * names will never be repeated.  It depends on the number of first names and
   * the number of last names being relatively prime.  This method should be
   * called before beginning generation of each template entry.
   */
  public void nextFirstAndLastNames()
  {
    firstName = firstNames[firstNameIndex++];
    lastName  = lastNames[lastNameIndex++];
    // If we've already exhausted every possible combination, then append an
    // integer to the last name.
    if (nameUniquenessCounter > 1)
    {
      lastName += nameUniquenessCounter;
    }
    if (firstNameIndex >= firstNames.length)
    {
      // We're at the end of the first name list, so start over.  If the first
      // name list is larger than the last name list, then we'll also need to
      // set the last name index to the next loop counter position.
      firstNameIndex = 0;
      if (firstNames.length > lastNames.length)
      {
        lastNameIndex = ++nameLoopCounter;
        if (lastNameIndex >= lastNames.length)
        {
          lastNameIndex = 0;
          nameUniquenessCounter++;
        }
      }
    }
    else if (lastNameIndex >= lastNames.length)
    {
      // We're at the end of the last name list, so start over.  If the last
      // name list is larger than the first name list, then we'll also need to
      // set the first name index to the next loop counter position.
      lastNameIndex = 0;
      if (lastNames.length > firstNames.length)
      {
        firstNameIndex = ++nameLoopCounter;
        if (firstNameIndex >= firstNames.length)
        {
          firstNameIndex = 0;
          nameUniquenessCounter++;
        }
      }
    }
  }
  /**
   * Retrieves the first name value that should be used for the current entry.
   *
   * @return  The first name value that should be used for the current entry.
   */
  public String getFirstName()
  {
    return firstName;
  }
  /**
   * Retrieves the last name value that should be used for the current entry.
   *
   * @return  The last name value that should be used for the current entry.
   */
  public String getLastName()
  {
    return lastName;
  }
  /**
   * Parses the contents of the specified file as a MakeLDIF template file
   * definition.
   *
   * @param  filename  The name of the file containing the template data.
   * @param  warnings  A list into which any warnings identified may be placed.
   *
   * @throws  IOException  If a problem occurs while attempting to read data
   *                       from the specified file.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   any of the MakeLDIF components.
   *
   * @throws  MakeLDIFException  If any other problem occurs while parsing the
   *                             template file.
   */
  public void parse(String filename, List<String> warnings)
         throws IOException, InitializationException, MakeLDIFException
  {
    ArrayList<String> fileLines = new ArrayList<String>();
    templatePath = null;
    File f = getFile(filename);
    if ((f == null) || (! f.exists()))
    {
      int    msgID   = MSGID_MAKELDIF_COULD_NOT_FIND_TEMPLATE_FILE;
      String message = getMessage(msgID, filename);
      throw new IOException(message);
    }
    else
    {
      templatePath = f.getParentFile().getAbsolutePath();
    }
    BufferedReader reader = new BufferedReader(new FileReader(f));
    while (true)
    {
      String line = reader.readLine();
      if (line == null)
      {
        break;
      }
      else
      {
        fileLines.add(line);
      }
    }
    reader.close();
    String[] lines = new String[fileLines.size()];
    fileLines.toArray(lines);
    parse(lines, warnings);
  }
  /**
   * Parses the data read from the provided input stream as a MakeLDIF template
   * file definition.
   *
   * @param  inputStream  The input stream from which to read the template file
   *                      data.
   * @param  warnings     A list into which any warnings identified may be
   *                      placed.
   *
   * @throws  IOException  If a problem occurs while attempting to read data
   *                       from the provided input stream.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   any of the MakeLDIF components.
   *
   * @throws  MakeLDIFException  If any other problem occurs while parsing the
   *                             template file.
   */
  public void parse(InputStream inputStream, List<String> warnings)
         throws IOException, InitializationException, MakeLDIFException
  {
    ArrayList<String> fileLines = new ArrayList<String>();
    BufferedReader reader =
         new BufferedReader(new InputStreamReader(inputStream));
    while (true)
    {
      String line = reader.readLine();
      if (line == null)
      {
        break;
      }
      else
      {
        fileLines.add(line);
      }
    }
    reader.close();
    String[] lines = new String[fileLines.size()];
    fileLines.toArray(lines);
    parse(lines, warnings);
  }
  /**
   * Parses the provided data as a MakeLDIF template file definition.
   *
   * @param  lines  The lines that make up the template file.
   * @param  warnings  A list into which any warnings identified may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   any of the MakeLDIF components.
   *
   * @throws  MakeLDIFException  If any other problem occurs while parsing the
   *                             template file.
   */
  public void parse(String[] lines, List<String> warnings)
         throws InitializationException, MakeLDIFException
  {
    // Create temporary variables that will be used to hold the data read.
    LinkedHashMap<String,Tag> templateFileIncludeTags =
         new LinkedHashMap<String,Tag>();
    LinkedHashMap<String,String> templateFileConstants =
         new LinkedHashMap<String,String>();
    LinkedHashMap<DN,Branch> templateFileBranches =
         new LinkedHashMap<DN,Branch>();
    LinkedHashMap<String,Template> templateFileTemplates =
         new LinkedHashMap<String,Template>();
    for (int lineNumber=0; lineNumber < lines.length; lineNumber++)
    {
      String line = lines[lineNumber];
      // See if there are any constant definitions in the line that need to be
      // replaced.  We'll do that first before any further processing.
      int closePos = line.lastIndexOf(']');
      if (closePos > 0)
      {
        StringBuilder lineBuffer = new StringBuilder(line);
        int openPos = line.lastIndexOf('[', closePos);
        if (openPos >= 0)
        {
          String constantName =
               toLowerCase(line.substring(openPos+1, closePos));
          String constantValue = templateFileConstants.get(constantName);
          if (constantValue == null)
          {
            int    msgID   = MSGID_MAKELDIF_WARNING_UNDEFINED_CONSTANT;
            String message = getMessage(msgID, constantName, lineNumber);
            warnings.add(message);
          }
          else
          {
            lineBuffer.replace(openPos, closePos+1, constantValue);
          }
        }
        line = lineBuffer.toString();
      }
      String lowerLine = toLowerCase(line);
      if ((line.length() == 0) || line.startsWith("#"))
      {
        // This is a comment or a blank line, so we'll ignore it.
        continue;
      }
      else if (lowerLine.startsWith("include "))
      {
        // This should be an include definition.  The next element should be the
        // name of the class.  Load and instantiate it and make sure there are
        // no conflicts.
        String className = line.substring(8).trim();
        Class tagClass;
        try
        {
          tagClass = Class.forName(className);
        }
        catch (Exception e)
        {
          int    msgID   = MSGID_MAKELDIF_CANNOT_LOAD_TAG_CLASS;
          String message = getMessage(msgID, className);
          throw new MakeLDIFException(msgID, message, e);
        }
        Tag tag;
        try
        {
          tag = (Tag) tagClass.newInstance();
        }
        catch (Exception e)
        {
          int    msgID   = MSGID_MAKELDIF_CANNOT_INSTANTIATE_TAG;
          String message = getMessage(msgID, className);
          throw new MakeLDIFException(msgID, message, e);
        }
        String lowerName = toLowerCase(tag.getName());
        if (registeredTags.containsKey(lowerName) ||
            templateFileIncludeTags.containsKey(lowerName))
        {
          int    msgID   = MSGID_MAKELDIF_CONFLICTING_TAG_NAME;
          String message = getMessage(msgID, className, tag.getName());
          throw new MakeLDIFException(msgID, message);
        }
        templateFileIncludeTags.put(lowerName, tag);
      }
      else if (lowerLine.startsWith("define "))
      {
        // This should be a constant definition.  The rest of the line should
        // contain the constant name, an equal sign, and the constant value.
        int equalPos = line.indexOf('=', 7);
        if (equalPos < 0)
        {
          int    msgID   = MSGID_MAKELDIF_DEFINE_MISSING_EQUALS;
          String message = getMessage(msgID, lineNumber);
          throw new MakeLDIFException(msgID, message);
        }
        String name  = line.substring(7, equalPos).trim();
        if (name.length() == 0)
        {
          int    msgID   = MSGID_MAKELDIF_DEFINE_NAME_EMPTY;
          String message = getMessage(msgID, lineNumber);
          throw new MakeLDIFException(msgID, message);
        }
        String lowerName = toLowerCase(name);
        if (templateFileConstants.containsKey(lowerName))
        {
          int    msgID   = MSGID_MAKELDIF_CONFLICTING_CONSTANT_NAME;
          String message = getMessage(msgID, name, lineNumber);
          throw new MakeLDIFException(msgID, message);
        }
        String value = line.substring(equalPos+1);
        if (value.length() == 0)
        {
          int    msgID   = MSGID_MAKELDIF_WARNING_DEFINE_VALUE_EMPTY;
          String message = getMessage(msgID, name, lineNumber);
          warnings.add(message);
        }
        templateFileConstants.put(lowerName, value);
      }
      else if (lowerLine.startsWith("branch: "))
      {
        int startLineNumber = lineNumber;
        ArrayList<String> lineList = new ArrayList<String>();
        lineList.add(line);
        while (true)
        {
          lineNumber++;
          if (lineNumber >= lines.length)
          {
            break;
          }
          line = lines[lineNumber];
          if (line.length() == 0)
          {
            break;
          }
          else
          {
            // See if there are any constant definitions in the line that need
            // to be replaced.  We'll do that first before any further
            // processing.
            closePos = line.lastIndexOf(']');
            if (closePos > 0)
            {
              StringBuilder lineBuffer = new StringBuilder(line);
              int openPos = line.lastIndexOf('[', closePos);
              if (openPos >= 0)
              {
                String constantName =
                     toLowerCase(line.substring(openPos+1, closePos));
                String constantValue = templateFileConstants.get(constantName);
                if (constantValue == null)
                {
                  int    msgID   = MSGID_MAKELDIF_WARNING_UNDEFINED_CONSTANT;
                  String message = getMessage(msgID, constantName, lineNumber);
                  warnings.add(message);
                }
                else
                {
                  lineBuffer.replace(openPos, closePos+1, constantValue);
                }
              }
              line = lineBuffer.toString();
            }
            lineList.add(line);
          }
        }
        String[] branchLines = new String[lineList.size()];
        lineList.toArray(branchLines);
        Branch b = parseBranchDefinition(branchLines, lineNumber,
                                         templateFileIncludeTags,
                                         templateFileConstants, warnings);
        DN branchDN = b.getBranchDN();
        if (templateFileBranches.containsKey(branchDN))
        {
          int    msgID   = MSGID_MAKELDIF_CONFLICTING_BRANCH_DN;
          String message = getMessage(msgID, String.valueOf(branchDN),
                                      startLineNumber);
          throw new MakeLDIFException(msgID, message);
        }
        else
        {
          templateFileBranches.put(branchDN, b);
        }
      }
      else if (lowerLine.startsWith("template: "))
      {
        int startLineNumber = lineNumber;
        ArrayList<String> lineList = new ArrayList<String>();
        lineList.add(line);
        while (true)
        {
          lineNumber++;
          if (lineNumber >= lines.length)
          {
            break;
          }
          line = lines[lineNumber];
          if (line.length() == 0)
          {
            break;
          }
          else
          {
            // See if there are any constant definitions in the line that need
            // to be replaced.  We'll do that first before any further
            // processing.
            closePos = line.lastIndexOf(']');
            if (closePos > 0)
            {
              StringBuilder lineBuffer = new StringBuilder(line);
              int openPos = line.lastIndexOf('[', closePos);
              if (openPos >= 0)
              {
                String constantName =
                     toLowerCase(line.substring(openPos+1, closePos));
                String constantValue = templateFileConstants.get(constantName);
                if (constantValue == null)
                {
                  int    msgID   = MSGID_MAKELDIF_WARNING_UNDEFINED_CONSTANT;
                  String message = getMessage(msgID, constantName, lineNumber);
                  warnings.add(message);
                }
                else
                {
                  lineBuffer.replace(openPos, closePos+1, constantValue);
                }
              }
              line = lineBuffer.toString();
            }
            lineList.add(line);
          }
        }
        String[] templateLines = new String[lineList.size()];
        lineList.toArray(templateLines);
        Template t = parseTemplateDefinition(templateLines, lineNumber,
                                             templateFileIncludeTags,
                                             templateFileConstants, warnings);
        String lowerName = toLowerCase(t.getName());
        if (templateFileTemplates.containsKey(lowerName))
        {
          int    msgID   = MSGID_MAKELDIF_CONFLICTING_TEMPLATE_NAME;
          String message = getMessage(msgID, String.valueOf(t.getName()),
                                      startLineNumber);
          throw new MakeLDIFException(msgID, message);
        }
        else
        {
          templateFileTemplates.put(lowerName, t);
        }
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_UNEXPECTED_TEMPLATE_FILE_LINE;
        String message = getMessage(msgID, line, lineNumber);
        throw new MakeLDIFException(msgID, message);
      }
    }
    // If we've gotten here, then we're almost done.  We just need to finalize
    // the branch and template definitions and then update the template file
    // variables.
    for (Branch b : templateFileBranches.values())
    {
      b.completeBranchInitialization(templateFileTemplates);
    }
    for (Template t : templateFileTemplates.values())
    {
      t.completeTemplateInitialization(templateFileTemplates);
    }
    registeredTags.putAll(templateFileIncludeTags);
    constants.putAll(templateFileConstants);
    branches.putAll(templateFileBranches);
    templates.putAll(templateFileTemplates);
  }
  /**
   * Parses the information contained in the provided set of lines as a MakeLDIF
   * branch definition.
   *
   * @param  branchLines      The set of lines containing the branch definition.
   * @param  startLineNumber  The line number in the template file on which the
   *                          first of the branch lines appears.
   * @param  tags             The set of defined tags from the template file.
   *                          Note that this does not include the tags that are
   *                          always registered by default.
   * @param  constants        The set of constants defined in the template file.
   * @param  warnings         A list into which any warnings identified may be
   *                          placed.
   *
   * @return  The decoded branch definition.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   any of the branch elements.
   *
   * @throws  MakeLDIFException  If some other problem occurs during processing.
   */
  private Branch parseBranchDefinition(String[] branchLines,
                                       int startLineNumber,
                                       LinkedHashMap<String,Tag> tags,
                                       LinkedHashMap<String,String> constants,
                                       List<String> warnings)
          throws InitializationException, MakeLDIFException
  {
    // The first line must be "branch: " followed by the branch DN.
    String dnString = branchLines[0].substring(8).trim();
    DN branchDN;
    try
    {
      branchDN = DN.decode(dnString);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_DECODE_BRANCH_DN;
      String message = getMessage(msgID, dnString, startLineNumber);
      throw new MakeLDIFException(msgID, message);
    }
    // Create a new branch that will be used for the verification process.
    Branch branch = new Branch(this, branchDN);
    for (int i=1; i < branchLines.length; i++)
    {
      String line       = branchLines[i];
      String lowerLine  = toLowerCase(line);
      int    lineNumber = startLineNumber + i;
      if (lowerLine.startsWith("#"))
      {
        // It's a comment, so we should ignore it.
        continue;
      }
      else if (lowerLine.startsWith("subordinatetemplate: "))
      {
        // It's a subordinate template, so we'll want to parse the name and the
        // number of entries.
        int colonPos = line.indexOf(':', 21);
        if (colonPos <= 21)
        {
          int    msgID   = MSGID_MAKELDIF_BRANCH_SUBORDINATE_TEMPLATE_NO_COLON;
          String message = getMessage(msgID, lineNumber, dnString);
          throw new MakeLDIFException(msgID, message);
        }
        String templateName = line.substring(21, colonPos).trim();
        int numEntries;
        try
        {
          numEntries = Integer.parseInt(line.substring(colonPos+1).trim());
          if (numEntries < 0)
          {
            int msgID = MSGID_MAKELDIF_BRANCH_SUBORDINATE_INVALID_NUM_ENTRIES;
            String message = getMessage(msgID, lineNumber, dnString, numEntries,
                                        templateName);
            throw new MakeLDIFException(msgID, message);
          }
          else if (numEntries == 0)
          {
            int    msgID   = MSGID_MAKELDIF_BRANCH_SUBORDINATE_ZERO_ENTRIES;
            String message = getMessage(msgID, lineNumber, dnString,
                                        templateName);
            warnings.add(message);
          }
          branch.addSubordinateTemplate(templateName, numEntries);
        }
        catch (NumberFormatException nfe)
        {
          int msgID = MSGID_MAKELDIF_BRANCH_SUBORDINATE_CANT_PARSE_NUMENTRIES;
          String message = getMessage(msgID, templateName, lineNumber,
                                      dnString);
          throw new MakeLDIFException(msgID, message);
        }
      }
      else
      {
        TemplateLine templateLine = parseTemplateLine(line, lowerLine,
                                                      lineNumber, branch, null,
                                                      tags, warnings);
        branch.addExtraLine(templateLine);
      }
    }
    return branch;
  }
  /**
   * Parses the information contained in the provided set of lines as a MakeLDIF
   * template definition.
   *
   * @param  templateLines    The set of lines containing the template
   *                          definition.
   * @param  startLineNumber  The line number in the template file on which the
   *                          first of the template lines appears.
   * @param  tags             The set of defined tags from the template file.
   *                          Note that this does not include the tags that are
   *                          always registered by default.
   * @param  constants        The set of constants defined in the template file.
   * @param  warnings         A list into which any warnings identified may be
   *                          placed.
   *
   * @return  The decoded template definition.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   any of the template elements.
   *
   * @throws  MakeLDIFException  If some other problem occurs during processing.
   */
  private Template parseTemplateDefinition(String[] templateLines,
                                           int startLineNumber,
                                           LinkedHashMap<String,Tag> tags,
                                           LinkedHashMap<String,String>
                                                constants,
                                           List<String> warnings)
          throws InitializationException, MakeLDIFException
  {
    // The first line must be "template: " followed by the template name.
    String templateName = templateLines[0].substring(10).trim();
    // The next line may start with either "extends: ", "rdnAttr: ", or
    // "subordinateTemplate: ".  Keep reading until we find something that's
    // not one of those.
    int                arrayLineNumber    = 1;
    String             parentTemplateName = null;
    AttributeType[]    rdnAttributes      = null;
    ArrayList<String>  subTemplateNames   = new ArrayList<String>();
    ArrayList<Integer> entriesPerTemplate = new ArrayList<Integer>();
    for ( ; arrayLineNumber < templateLines.length; arrayLineNumber++)
    {
      int    lineNumber = startLineNumber + arrayLineNumber;
      String line       = templateLines[arrayLineNumber];
      String lowerLine  = toLowerCase(line);
      if (lowerLine.startsWith("#"))
      {
        // It's a comment.  Ignore it.
        continue;
      }
      else if (lowerLine.startsWith("extends: "))
      {
        parentTemplateName = line.substring(9).trim();
      }
      else if (lowerLine.startsWith("rdnattr: "))
      {
        // This is the set of RDN attributes.  If there are multiple, they may
        // be separated by plus signs.
        ArrayList<AttributeType> attrList = new ArrayList<AttributeType>();
        String rdnAttrNames = lowerLine.substring(9).trim();
        StringTokenizer tokenizer = new StringTokenizer(rdnAttrNames, "+");
        while (tokenizer.hasMoreTokens())
        {
          attrList.add(DirectoryServer.getAttributeType(tokenizer.nextToken(),
                                                        true));
        }
        rdnAttributes = new AttributeType[attrList.size()];
        attrList.toArray(rdnAttributes);
      }
      else if (lowerLine.startsWith("subordinatetemplate: "))
      {
        // It's a subordinate template, so we'll want to parse the name and the
        // number of entries.
        int colonPos = line.indexOf(':', 21);
        if (colonPos <= 21)
        {
          int msgID = MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_TEMPLATE_NO_COLON;
          String message = getMessage(msgID, lineNumber, templateName);
          throw new MakeLDIFException(msgID, message);
        }
        String subTemplateName = line.substring(21, colonPos).trim();
        int numEntries;
        try
        {
          numEntries = Integer.parseInt(line.substring(colonPos+1).trim());
          if (numEntries < 0)
          {
            int msgID = MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_INVALID_NUM_ENTRIES;
            String message = getMessage(msgID, lineNumber, templateName,
                                        numEntries, subTemplateName);
            throw new MakeLDIFException(msgID, message);
          }
          else if (numEntries == 0)
          {
            int    msgID   = MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_ZERO_ENTRIES;
            String message = getMessage(msgID, lineNumber, templateName,
                                        subTemplateName);
            warnings.add(message);
          }
          subTemplateNames.add(subTemplateName);
          entriesPerTemplate.add(numEntries);
        }
        catch (NumberFormatException nfe)
        {
          int msgID = MSGID_MAKELDIF_TEMPLATE_SUBORDINATE_CANT_PARSE_NUMENTRIES;
          String message = getMessage(msgID, subTemplateName, lineNumber,
                                      templateName);
          throw new MakeLDIFException(msgID, message);
        }
      }
      else
      {
        // It's something we don't recognize, so it must be a template line.
        break;
      }
    }
    // Create a new template that will be used for the verification process.
    String[] subordinateTemplateNames = new String[subTemplateNames.size()];
    subTemplateNames.toArray(subordinateTemplateNames);
    int[] numEntriesPerTemplate = new int[entriesPerTemplate.size()];
    for (int i=0; i < numEntriesPerTemplate.length; i++)
    {
      numEntriesPerTemplate[i] = entriesPerTemplate.get(i);
    }
    Template template = new Template(this, templateName, rdnAttributes,
                                     subordinateTemplateNames,
                                     numEntriesPerTemplate);
    for ( ; arrayLineNumber < templateLines.length; arrayLineNumber++)
    {
      String line       = templateLines[arrayLineNumber];
      String lowerLine  = toLowerCase(line);
      int    lineNumber = startLineNumber + arrayLineNumber;
      if (lowerLine.startsWith("#"))
      {
        // It's a comment, so we should ignore it.
        continue;
      }
      else
      {
        TemplateLine templateLine = parseTemplateLine(line, lowerLine,
                                                      lineNumber, null,
                                                      template, tags, warnings);
        template.addTemplateLine(templateLine);
      }
    }
    return template;
  }
  /**
   * Parses the provided line as a template line.  Note that exactly one of the
   * branch or template arguments must be non-null and the other must be null.
   *
   * @param  line        The text of the template line.
   * @param  lowerLine   The template line in all lowercase characters.
   * @param  lineNumber  The line number on which the template line appears.
   * @param  branch      The branch with which the template line is associated.
   * @param  template    The template with which the template line is
   *                     associated.
   * @param  tags        The set of defined tags from the template file.  Note
   *                     that this does not include the tags that are always
   *                     registered by default.
   * @param  warnings    A list into which any warnings identified may be
   *                     placed.
   *
   * @return  The template line that has been parsed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   any of the template elements.
   *
   * @throws  MakeLDIFException  If some other problem occurs during processing.
   */
  private TemplateLine parseTemplateLine(String line, String lowerLine,
                                         int lineNumber, Branch branch,
                                         Template template,
                                         LinkedHashMap<String,Tag> tags,
                                         List<String> warnings)
          throws InitializationException, MakeLDIFException
  {
    // The first component must be the attribute type, followed by a colon.
    int colonPos = lowerLine.indexOf(':');
    if (colonPos < 0)
    {
      if (branch == null)
      {
        int    msgID   = MSGID_MAKELDIF_NO_COLON_IN_TEMPLATE_LINE;
        String message = getMessage(msgID, lineNumber, template.getName());
        throw new MakeLDIFException(msgID, message);
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_NO_COLON_IN_BRANCH_EXTRA_LINE;
        String message = getMessage(msgID, lineNumber,
                                    String.valueOf(branch.getBranchDN()));
        throw new MakeLDIFException(msgID, message);
      }
    }
    else if (colonPos == 0)
    {
      if (branch == null)
      {
        int    msgID   = MSGID_MAKELDIF_NO_ATTR_IN_TEMPLATE_LINE;
        String message = getMessage(msgID, lineNumber, template.getName());
        throw new MakeLDIFException(msgID, message);
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_NO_ATTR_IN_BRANCH_EXTRA_LINE;
        String message = getMessage(msgID, lineNumber,
                                    String.valueOf(branch.getBranchDN()));
        throw new MakeLDIFException(msgID, message);
      }
    }
    AttributeType attributeType =
         DirectoryServer.getAttributeType(lowerLine.substring(0, colonPos),
                                          true);
    // First, find the position of the first non-blank character in the line.
    int length = line.length();
    int pos    = colonPos + 1;
    while ((pos < length) && (lowerLine.charAt(pos) == ' '))
    {
      pos++;
    }
    if (pos >= length)
    {
      // We've hit the end of the line with no value.  We'll allow it, but add a
      // warning.
      if (branch == null)
      {
        int    msgID   = MSGID_MAKELDIF_NO_VALUE_IN_TEMPLATE_LINE;
        String message = getMessage(msgID, lineNumber, template.getName());
        warnings.add(message);
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_NO_VALUE_IN_BRANCH_EXTRA_LINE;
        String message = getMessage(msgID, lineNumber,
                                    String.valueOf(branch.getBranchDN()));
        warnings.add(message);
      }
    }
    // Define constants that specify what we're currently parsing.
    final int PARSING_STATIC_TEXT     = 0;
    final int PARSING_REPLACEMENT_TAG = 1;
    final int PARSING_ATTRIBUTE_TAG   = 2;
    int phase = PARSING_STATIC_TEXT;
    ArrayList<Tag> tagList = new ArrayList<Tag>();
    StringBuilder buffer = new StringBuilder();
    for ( ; pos < length; pos++)
    {
      char c = line.charAt(pos);
      switch (phase)
      {
        case PARSING_STATIC_TEXT:
          switch (c)
          {
            case '<':
              if (buffer.length() > 0)
              {
                StaticTextTag t = new StaticTextTag();
                String[] args = new String[] { buffer.toString() };
                t.initializeForBranch(this, branch, args, lineNumber,
                                      warnings);
                tagList.add(t);
                buffer = new StringBuilder();
              }
              phase = PARSING_REPLACEMENT_TAG;
              break;
            case '{':
              if (buffer.length() > 0)
              {
                StaticTextTag t = new StaticTextTag();
                String[] args = new String[] { buffer.toString() };
                t.initializeForBranch(this, branch, args, lineNumber,
                                      warnings);
                tagList.add(t);
                buffer = new StringBuilder();
              }
              phase = PARSING_ATTRIBUTE_TAG;
              break;
            default:
              buffer.append(c);
          }
          break;
        case PARSING_REPLACEMENT_TAG:
          switch (c)
          {
            case '>':
              Tag t = parseReplacementTag(buffer.toString(), branch, template,
                                          lineNumber, tags, warnings);
              tagList.add(t);
              buffer = new StringBuilder();
              phase = PARSING_STATIC_TEXT;
              break;
            default:
              buffer.append(c);
              break;
          }
          break;
        case PARSING_ATTRIBUTE_TAG:
          switch (c)
          {
              case '}':
              Tag t = parseAttributeTag(buffer.toString(), branch, template,
                                        lineNumber, warnings);
              tagList.add(t);
              buffer = new StringBuilder();
              phase = PARSING_STATIC_TEXT;
              break;
            default:
              buffer.append(c);
              break;
          }
          break;
      }
    }
    if (phase == PARSING_STATIC_TEXT)
    {
      if (buffer.length() > 0)
      {
        StaticTextTag t = new StaticTextTag();
        String[] args = new String[] { buffer.toString() };
        t.initializeForBranch(this, branch, args, lineNumber, warnings);
        tagList.add(t);
      }
    }
    else
    {
      int    msgID   = MSGID_MAKELDIF_INCOMPLETE_TAG;
      String message = getMessage(msgID, lineNumber);
      throw new InitializationException(msgID, message);
    }
    Tag[] tagArray = new Tag[tagList.size()];
    tagList.toArray(tagArray);
    return new TemplateLine(attributeType, lineNumber, tagArray);
  }
  /**
   * Parses the provided string as a replacement tag.  Exactly one of the branch
   * or template must be null, and the other must be non-null.
   *
   * @param  tagString   The string containing the encoded tag.
   * @param  branch      The branch in which this tag appears.
   * @param  template    The template in which this tag appears.
   * @param  lineNumber  The line number on which this tag appears in the
   *                     template file.
   * @param  tags        The set of defined tags from the template file.  Note
   *                     that this does not include the tags that are always
   *                     registered by default.
   * @param  warnings    A list into which any warnings identified may be
   *                     placed.
   *
   * @return  The replacement tag parsed from the provided string.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the tag.
   *
   * @throws  MakeLDIFException  If some other problem occurs during processing.
   */
  private Tag parseReplacementTag(String tagString, Branch branch,
                                  Template template, int lineNumber,
                                  LinkedHashMap<String,Tag> tags,
                                  List<String> warnings)
          throws InitializationException, MakeLDIFException
  {
    // The components of the replacement tag will be separated by colons, with
    // the first being the tag name and the remainder being arguments.
    StringTokenizer tokenizer = new StringTokenizer(tagString, ":");
    String          tagName      = tokenizer.nextToken().trim();
    String          lowerTagName = toLowerCase(tagName);
    Tag t = getTag(lowerTagName);
    if (t == null)
    {
      t = tags.get(lowerTagName);
      if (t == null)
      {
        int    msgID   = MSGID_MAKELDIF_NO_SUCH_TAG;
        String message = getMessage(msgID, tagName, lineNumber);
        throw new MakeLDIFException(msgID, message);
      }
    }
    ArrayList<String> argList = new ArrayList<String>();
    while (tokenizer.hasMoreTokens())
    {
      argList.add(tokenizer.nextToken().trim());
    }
    String[] args = new String[argList.size()];
    argList.toArray(args);
    Tag newTag;
    try
    {
      newTag = t.getClass().newInstance();
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_MAKELDIF_CANNOT_INSTANTIATE_NEW_TAG;
      String message = getMessage(msgID, tagName, lineNumber,
                                  String.valueOf(e));
      throw new MakeLDIFException(msgID, message, e);
    }
    if (branch == null)
    {
      newTag.initializeForTemplate(this, template, args, lineNumber, warnings);
    }
    else
    {
      if (newTag.allowedInBranch())
      {
        newTag.initializeForBranch(this, branch, args, lineNumber, warnings);
      }
      else
      {
        int    msgID   = MSGID_MAKELDIF_TAG_NOT_ALLOWED_IN_BRANCH;
        String message = getMessage(msgID, newTag.getName(), lineNumber);
        throw new MakeLDIFException(msgID, message);
      }
    }
    return newTag;
  }
  /**
   * Parses the provided string as an attribute tag.  Exactly one of the branch
   * or template must be null, and the other must be non-null.
   *
   * @param  tagString   The string containing the encoded tag.
   * @param  branch      The branch in which this tag appears.
   * @param  template    The template in which this tag appears.
   * @param  lineNumber  The line number on which this tag appears in the
   *                     template file.
   * @param  warnings    A list into which any warnings identified may be
   *                     placed.
   *
   * @return  The attribute tag parsed from the provided string.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the tag.
   *
   * @throws  MakeLDIFException  If some other problem occurs during processing.
   */
  private Tag parseAttributeTag(String tagString, Branch branch,
                                Template template, int lineNumber,
                                List<String> warnings)
          throws InitializationException, MakeLDIFException
  {
    // The attribute tag must have at least one argument, which is the name of
    // the attribute to reference.  It may have a second argument, which is the
    // number of characters to use from the attribute value.  The arguments will
    // be delimited by colons.
    StringTokenizer   tokenizer = new StringTokenizer(tagString, ":");
    ArrayList<String> argList   = new ArrayList<String>();
    while (tokenizer.hasMoreTokens())
    {
      argList.add(tokenizer.nextToken());
    }
    String[] args = new String[argList.size()];
    argList.toArray(args);
    AttributeValueTag tag = new AttributeValueTag();
    if (branch == null)
    {
      tag.initializeForTemplate(this, template, args, lineNumber, warnings);
    }
    else
    {
      tag.initializeForBranch(this, branch, args, lineNumber, warnings);
    }
    return tag;
  }
  /**
   * Retrieves a File object based on the provided path.  If the given path is
   * absolute, then that absolute path will be used.  If it is relative, then it
   * will first be evaluated relative to the current working directory.  If that
   * path doesn't exist, then it will be evaluated relative to the resource
   * path.  If that path doesn't exist, then it will be evaluated relative to
   * the directory containing the template file.
   *
   * @param  path  The path provided for the file.
   *
   * @return  The File object for the specified path, or <CODE>null</CODE> if
   *          the specified file could not be found.
   */
  public File getFile(String path)
  {
    // First, see if the file exists using the given path.  This will work if
    // the file is absolute, or it's relative to the current working directory.
    File f = new File(path);
    if (f.exists())
    {
      return f;
    }
    // If the provided path was absolute, then use it anyway, even though we
    // couldn't find the file.
    if (f.isAbsolute())
    {
      return f;
    }
    // Try a path relative to the resource directory.
    String newPath = resourcePath + File.separator + path;
    f = new File(newPath);
    if (f.exists())
    {
      return f;
    }
    // Try a path relative to the template directory, if it's available.
    if (templatePath != null)
    {
      newPath = templatePath = File.separator + path;
      f = new File(newPath);
      if (f.exists())
      {
        return f;
      }
    }
    return null;
  }
  /**
   * Retrieves the lines of the specified file as a string array.  If the result
   * is already cached, then it will be used.  If the result is not cached, then
   * the file data will be cached so that the contents can be re-used if there
   * are multiple references to the same file.
   *
   * @param  file  The file for which to retrieve the contents.
   *
   * @return  An array containing the lines of the specified file.
   *
   * @throws  IOException  If a problem occurs while reading the file.
   */
  public String[] getFileLines(File file)
         throws IOException
  {
    String absolutePath = file.getAbsolutePath();
    String[] lines = fileLines.get(absolutePath);
    if (lines == null)
    {
      ArrayList<String> lineList = new ArrayList<String>();
      BufferedReader reader = new BufferedReader(new FileReader(file));
      while (true)
      {
        String line = reader.readLine();
        if (line == null)
        {
          break;
        }
        else
        {
          lineList.add(line);
        }
      }
      reader.close();
      lines = new String[lineList.size()];
      lineList.toArray(lines);
      lineList.clear();
      fileLines.put(absolutePath, lines);
    }
    return lines;
  }
  /**
   * Generates the LDIF content and writes it to the provided LDIF writer.
   *
   * @param  entryWriter  The entry writer that should be used to write the
   *                      entries.
   *
   * @return  The result that indicates whether processing should continue.
   *
   * @throws  IOException  If an error occurs while writing to the LDIF file.
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public TagResult generateLDIF(EntryWriter entryWriter)
         throws IOException, MakeLDIFException
  {
    for (Branch b : branches.values())
    {
      TagResult result = b.writeEntries(entryWriter);
      if (! (result.keepProcessingTemplateFile()))
      {
        return result;
      }
    }
    entryWriter.closeEntryWriter();
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/TemplateLine.java
New file
@@ -0,0 +1,136 @@
/*
 * 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.tools.makeldif;
import org.opends.server.types.AttributeType;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a line that may appear in a template or branch.  It may
 * contain any number of tags to be evaluated.
 */
public class TemplateLine
{
  // The attribute type for this template line.
  private AttributeType attributeType;
  // The line number on which this template line appears in the template file.
  private int lineNumber;
  // The set of tags for this template line.
  private Tag[] tags;
  /**
   * Creates a new template line with the provided information.
   *
   * @param  attributeType  The attribute type for this template line.
   * @param  lineNumber     The line number on which this template line appears
   *                        in the template file.
   * @param  tags           The set of tags for this template line.
   */
  public TemplateLine(AttributeType attributeType, int lineNumber, Tag[] tags)
  {
    this.attributeType = attributeType;
    this.lineNumber    = lineNumber;
    this.tags          = tags;
  }
  /**
   * Retrieves the attribute type for this template line.
   *
   * @return  The attribute type for this template line.
   */
  public AttributeType getAttributeType()
  {
    return attributeType;
  }
  /**
   * Retrieves the line number on which this template line appears in the
   * template file.
   *
   * @return  The line number on which this template line appears in the
   *          template file.
   */
  public int getLineNumber()
  {
    return lineNumber;
  }
  /**
   * Retrieves the set of tags for this template line.
   *
   * @return  The set of tags for this template line.
   */
  public Tag[] getTags()
  {
    return tags;
  }
  /**
   * Generates the content for this template line and places it in the provided
   * template entry.
   *
   * @param  templateEntry  The template entry being generated.
   *
   * @return  The result of generating the template line.
   */
  public TagResult generateLine(TemplateEntry templateEntry)
  {
    TemplateValue value = new TemplateValue(this);
    for (Tag t : tags)
    {
      TagResult result = t.generateValue(templateEntry, value);
      if (! (result.keepProcessingLine() && result.keepProcessingEntry() &&
             result.keepProcessingParent() &&
             result.keepProcessingTemplateFile()))
      {
        return result;
      }
    }
    templateEntry.addValue(value);
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/TemplateValue.java
New file
@@ -0,0 +1,108 @@
/*
 * 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.tools.makeldif;
import org.opends.server.types.AttributeType;
/**
 * This class defines a value generated from a template line.
 */
public class TemplateValue
{
  // The generated template value.
  private StringBuilder templateValue;
  // The template line used to generate this value.
  private TemplateLine templateLine;
  /**
   * Creates a new template value with the provided information.
   *
   * @param  templateLine  The template line used to generate this value.
   */
  public TemplateValue(TemplateLine templateLine)
  {
    this.templateLine = templateLine;
    templateValue = new StringBuilder();
  }
  /**
   * Retrieves the template line used to generate this value.
   *
   * @return  The template line used to generate this value.
   */
  public TemplateLine getTemplateLine()
  {
    return templateLine;
  }
  /**
   * Retrieves the attribute type for this template value.
   *
   * @return  The attribute type for this template value.
   */
  public AttributeType getAttributeType()
  {
    return templateLine.getAttributeType();
  }
  /**
   * Retrieves the generated value.
   *
   * @return  The generated value.
   */
  public StringBuilder getValue()
  {
    return templateValue;
  }
  /**
   * Appends the provided string to this template value.
   *
   * @param  s  The string to append to the template value.
   */
  public void append(String s)
  {
    templateValue.append(s);
  }
}
opends/src/server/org/opends/server/tools/makeldif/UnderscoreDNTag.java
New file
@@ -0,0 +1,241 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import org.opends.server.types.DN;
import org.opends.server.types.RDN;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include the DN of the current entry
 * in the attribute value, with underscores in place of the commas.
 */
public class UnderscoreDNTag
       extends Tag
{
  // The number of DN components to include.
  private int numComponents;
  /**
   * Creates a new instance of this DN tag.
   */
  public UnderscoreDNTag()
  {
    numComponents = 0;
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "_DN";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return true;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a branch definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  branch        The branch in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForBranch(TemplateFile templateFile, Branch branch,
                                  String[] arguments, int lineNumber,
                                  List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    initializeInternal(templateFile, arguments, lineNumber);
  }
  /**
   * Performs any initialization for this tag that may be needed for this tag.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  private void initializeInternal(TemplateFile templateFile, String[] arguments,
                                  int lineNumber)
          throws InitializationException
  {
    if (arguments.length == 0)
    {
      numComponents = 0;
    }
    else if (arguments.length == 1)
    {
      try
      {
        numComponents = Integer.parseInt(arguments[0]);
      }
      catch (NumberFormatException nfe)
      {
        int    msgID   = MSGID_MAKELDIF_TAG_CANNOT_PARSE_AS_INTEGER;
        String message = getMessage(msgID, arguments[0], getName(), lineNumber);
        throw new InitializationException(msgID, message);
      }
    }
    else
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0, 1,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    DN dn = templateEntry.getDN();
    if ((dn == null) || dn.isNullDN())
    {
      return TagResult.SUCCESS_RESULT;
    }
    if (numComponents == 0)
    {
      RDN[] rdnComps = dn.getRDNComponents();
      rdnComps[0].toString(templateValue.getValue());
      for (int i=1; i < rdnComps.length; i++)
      {
        templateValue.append("_");
        rdnComps[i].toString(templateValue.getValue());
      }
    }
    else if (numComponents > 0)
    {
      RDN[] rdnComps = dn.getRDNComponents();
      int count = Math.min(numComponents, rdnComps.length);
      rdnComps[0].toString(templateValue.getValue());
      for (int i=1; i < count; i++)
      {
        templateValue.append("_");
        rdnComps[i].toString(templateValue.getValue());
      }
    }
    else
    {
      RDN[] rdnComps = dn.getRDNComponents();
      int count = Math.min(Math.abs(numComponents), rdnComps.length);
      rdnComps[rdnComps.length-count].toString(templateValue.getValue());
      for (int i=1; i < count; i++)
      {
        templateValue.append("_");
        rdnComps[rdnComps.length-count+i].toString(templateValue.getValue());
      }
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/tools/makeldif/UnderscoreParentDNTag.java
New file
@@ -0,0 +1,146 @@
/*
 * 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.tools.makeldif;
import java.util.List;
import org.opends.server.core.InitializationException;
import org.opends.server.types.DN;
import org.opends.server.types.RDN;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
/**
 * This class defines a tag that is used to include the DN of the parent entry
 * in the attribute value, with underscores in place of commas.
 */
public class UnderscoreParentDNTag
       extends Tag
{
  /**
   * Creates a new instance of this underscore parent DN tag.
   */
  public UnderscoreParentDNTag()
  {
    // No implementation required.
  }
  /**
   * Retrieves the name for this tag.
   *
   * @return  The name for this tag.
   */
  public String getName()
  {
    return "_ParentDN";
  }
  /**
   * Indicates whether this tag is allowed for use in the extra lines for
   * branches.
   *
   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
   *          or <CODE>false</CODE> if not.
   */
  public boolean allowedInBranch()
  {
    return false;
  }
  /**
   * Performs any initialization for this tag that may be needed while parsing
   * a template definition.
   *
   * @param  templateFile  The template file in which this tag is used.
   * @param  template      The template in which this tag is used.
   * @param  arguments     The set of arguments provided for this tag.
   * @param  lineNumber    The line number on which this tag appears in the
   *                       template file.
   * @param  warnings      A list into which any appropriate warning messages
   *                       may be placed.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   this tag.
   */
  public void initializeForTemplate(TemplateFile templateFile,
                                    Template template, String[] arguments,
                                    int lineNumber, List<String> warnings)
         throws InitializationException
  {
    if (arguments.length != 0)
    {
      int    msgID   = MSGID_MAKELDIF_TAG_INVALID_ARGUMENT_COUNT;
      String message = getMessage(msgID, getName(), lineNumber, 0,
                                  arguments.length);
      throw new InitializationException(msgID, message);
    }
  }
  /**
   * Generates the content for this tag by appending it to the provided tag.
   *
   * @param  templateEntry  The entry for which this tag is being generated.
   * @param  templateValue  The template value to which the generated content
   *                        should be appended.
   *
   * @return  The result of generating content for this tag.
   */
  public TagResult generateValue(TemplateEntry templateEntry,
                                 TemplateValue templateValue)
  {
    DN parentDN = templateEntry.getParentDN();
    if ((parentDN == null) || parentDN.isNullDN())
    {
      return TagResult.SUCCESS_RESULT;
    }
    RDN[] rdnComps = parentDN.getRDNComponents();
    rdnComps[0].toString(templateValue.getValue());
    for (int i=1; i < rdnComps.length; i++)
    {
      templateValue.append("_");
      rdnComps[i].toString(templateValue.getValue());
    }
    return TagResult.SUCCESS_RESULT;
  }
}
opends/src/server/org/opends/server/types/AttributeType.java
@@ -85,6 +85,9 @@
  // "no-user-modification".
  private boolean isNoUserModification;
  // Indicates whether this attribute type is the objectclass type.
  private boolean isObjectClassType;
  // Indicates whether this attribute type is declared "obsolete".
  private boolean isObsolete;
@@ -202,6 +205,22 @@
    this.extraProperties         =
         new ConcurrentHashMap<String,
                               CopyOnWriteArrayList<String>>(0);
    isObjectClassType = false;
    if ((oid != null) && oid.equals(OBJECTCLASS_ATTRIBUTE_TYPE_OID))
    {
      isObjectClassType = true;
    }
    else
    {
      for (String lowerName : typeNames.keySet())
      {
        if (lowerName.equals(OBJECTCLASS_ATTRIBUTE_TYPE_NAME))
        {
          isObjectClassType = true;
        }
      }
    }
  }
@@ -377,6 +396,22 @@
    {
      this.substringMatchingRule = substringMatchingRule;
    }
    isObjectClassType = false;
    if ((oid != null) && oid.equals(OBJECTCLASS_ATTRIBUTE_TYPE_OID))
    {
      isObjectClassType = true;
    }
    else
    {
      for (String lowerName : typeNames.keySet())
      {
        if (lowerName.equals(OBJECTCLASS_ATTRIBUTE_TYPE_NAME))
        {
          isObjectClassType = true;
        }
      }
    }
  }
@@ -1130,20 +1165,7 @@
  {
    assert debugEnter(CLASS_NAME, "isObjectClassType");
    if ((oid != null) && oid.equals(OBJECTCLASS_ATTRIBUTE_TYPE_OID))
    {
      return true;
    }
    for (String lowerName : typeNames.keySet())
    {
      if (lowerName.equals(OBJECTCLASS_ATTRIBUTE_TYPE_NAME))
      {
        return true;
      }
    }
    return false;
    return isObjectClassType;
  }
opends/src/server/org/opends/server/types/LDIFImportConfig.java
@@ -46,6 +46,8 @@
import java.util.zip.GZIPInputStream;
import org.opends.server.core.DirectoryException;
import org.opends.server.tools.makeldif.MakeLDIFInputStream;
import org.opends.server.tools.makeldif.TemplateFile;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.messages.MessageHandler.*;
@@ -137,6 +139,10 @@
  // The set of attribute types that should be included in the import.
  private Set<AttributeType> includeAttributes;
  // The MakeLDIF template file that should be used to generate
  // entries (instead of having them read from a file).
  private TemplateFile templateFile;
  /**
@@ -247,6 +253,23 @@
  /**
   * Creates a new LDIF import configuration that will generate
   * entries using the given MakeLDIF template file rather than
   * reading them from an existing LDIF file.
   *
   * @param  templateFile  The template file to use to generate the
   *                       entries.
   */
  public LDIFImportConfig(TemplateFile templateFile)
  {
    this(new MakeLDIFInputStream(templateFile));
    assert debugConstructor(CLASS_NAME, String.valueOf(templateFile));
  }
  /**
   * Retrieves the reader that should be used to read the LDIF data.
   * Note that if the LDIF file is compressed and/or encrypted, then
   * that must be indicated before this method is called for the first