001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.tools.makeldif;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.io.File;
033    import java.io.IOException;
034    import java.util.LinkedList;
035    import java.util.Random;
036    
037    import org.opends.server.core.DirectoryServer;
038    import org.opends.server.types.Entry;
039    import org.opends.server.types.ExistingFileBehavior;
040    import org.opends.server.types.LDIFExportConfig;
041    import org.opends.server.util.LDIFWriter;
042    import org.opends.server.util.args.ArgumentException;
043    import org.opends.server.util.args.ArgumentParser;
044    import org.opends.server.util.args.BooleanArgument;
045    import org.opends.server.util.args.IntegerArgument;
046    import org.opends.server.util.args.StringArgument;
047    
048    import static org.opends.messages.ToolMessages.*;
049    import static org.opends.server.util.ServerConstants.*;
050    import static org.opends.server.util.StaticUtils.*;
051    import static org.opends.server.tools.ToolConstants.*;
052    
053    
054    
055    /**
056     * This class defines a program that can be used to generate LDIF content based
057     * on a template.
058     */
059    public class MakeLDIF
060           implements EntryWriter
061    {
062      /**
063       * The fully-qualified name of this class.
064       */
065      private static final String CLASS_NAME =
066           "org.opends.server.tools.makeldif.MakeLDIF";
067    
068    
069    
070      // The LDIF writer that will be used to write the entries.
071      private LDIFWriter ldifWriter;
072    
073      // The total number of entries that have been written.
074      private long entriesWritten;
075    
076    
077    
078      /**
079       * Invokes the <CODE>makeLDIFMain</CODE> method with the provided set of
080       * arguments.
081       *
082       * @param  args  The command-line arguments provided for this program.
083       */
084      public static void main(String[] args)
085      {
086        MakeLDIF makeLDIF = new MakeLDIF();
087        int returnCode = makeLDIF.makeLDIFMain(args);
088        if (returnCode != 0)
089        {
090          System.exit(filterExitCode(returnCode));
091        }
092      }
093    
094    
095    
096      /**
097       * Creates a new instance of this utility.  It should just be used for
098       * invoking the <CODE>makeLDIFMain</CODE> method.
099       */
100      public MakeLDIF()
101      {
102        ldifWriter     = null;
103        entriesWritten = 0L;
104      }
105    
106    
107    
108      /**
109       * Processes the provided set of command-line arguments and begins generating
110       * the LDIF content.
111       *
112       * @param  args  The command-line arguments provided for this program.
113       *
114       * @return  A result code of zero if all processing completed properly, or
115       *          a nonzero result if a problem occurred.
116       */
117      public int makeLDIFMain(String[] args)
118      {
119        // Create and initialize the argument parser for this program.
120        Message toolDescription = INFO_MAKELDIF_TOOL_DESCRIPTION.get();
121        ArgumentParser  argParser = new ArgumentParser(CLASS_NAME, toolDescription,
122                                                       false);
123        BooleanArgument showUsage;
124        IntegerArgument randomSeed;
125        StringArgument  configClass;
126        StringArgument  configFile;
127        StringArgument  templatePath;
128        StringArgument  ldifFile;
129        StringArgument  resourcePath;
130    
131        try
132        {
133          configFile = new StringArgument("configfile", 'c', "configFile", true,
134                                          false, true,
135                                          INFO_CONFIGFILE_PLACEHOLDER.get(), null,
136                                          null,
137                                          INFO_DESCRIPTION_CONFIG_FILE.get());
138          configFile.setHidden(true);
139          argParser.addArgument(configFile);
140    
141    
142          configClass = new StringArgument("configclass", OPTION_SHORT_CONFIG_CLASS,
143                                           OPTION_LONG_CONFIG_CLASS, false,
144                                           false, true,
145                                           INFO_CONFIGCLASS_PLACEHOLDER.get(), null,
146                                           null,
147                                           INFO_DESCRIPTION_CONFIG_CLASS.get());
148          configClass.setHidden(true);
149          argParser.addArgument(configClass);
150    
151    
152          resourcePath =
153               new StringArgument("resourcepath", 'r', "resourcePath", true, false,
154                                  true, INFO_PATH_PLACEHOLDER.get(), null, null,
155                                  INFO_MAKELDIF_DESCRIPTION_RESOURCE_PATH.get());
156          resourcePath.setHidden(true);
157          argParser.addArgument(resourcePath);
158    
159    
160          templatePath =
161                  new StringArgument("templatefile", 't', "templateFile",
162                                     true, false, true, INFO_FILE_PLACEHOLDER.get(),
163                                     null, null,
164                                     INFO_MAKELDIF_DESCRIPTION_TEMPLATE.get());
165          argParser.addArgument(templatePath);
166    
167    
168          ldifFile = new StringArgument("ldiffile", 'o', "ldifFile", true, false,
169                                        true, INFO_FILE_PLACEHOLDER.get(), null,
170                                        null, INFO_MAKELDIF_DESCRIPTION_LDIF.get());
171          argParser.addArgument(ldifFile);
172    
173    
174          randomSeed = new IntegerArgument("randomseed", OPTION_SHORT_RANDOM_SEED,
175                                           OPTION_LONG_RANDOM_SEED, false,
176                                           false, true, INFO_SEED_PLACEHOLDER.get(),
177                                           0, null,
178                                           INFO_MAKELDIF_DESCRIPTION_SEED.get());
179          argParser.addArgument(randomSeed);
180    
181    
182          showUsage = new BooleanArgument("help", OPTION_SHORT_HELP,
183                                          OPTION_LONG_HELP,
184                                          INFO_MAKELDIF_DESCRIPTION_HELP.get());
185          argParser.addArgument(showUsage);
186          argParser.setUsageArgument(showUsage);
187        }
188        catch (ArgumentException ae)
189        {
190          Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
191          System.err.println(wrapText(message, MAX_LINE_WIDTH));
192          return 1;
193        }
194    
195    
196        // Parse the command-line arguments provided to the program.
197        try
198        {
199          argParser.parseArguments(args);
200        }
201        catch (ArgumentException ae)
202        {
203          Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
204          System.err.println(wrapText(message, MAX_LINE_WIDTH));
205          System.err.println(argParser.getUsage());
206          return 1;
207        }
208    
209    
210        // If we should just display usage or version information,
211        // then print it and exit.
212        if (argParser.usageOrVersionDisplayed())
213        {
214          return 0;
215        }
216    
217    
218        // Initialize the Directory Server configuration handler using the
219        // information that was provided.
220        DirectoryServer directoryServer = DirectoryServer.getInstance();
221        directoryServer.bootstrapClient();
222    
223        try
224        {
225          directoryServer.initializeJMX();
226        }
227        catch (Exception e)
228        {
229          Message message = ERR_MAKELDIF_CANNOT_INITIALIZE_JMX.get(
230                  String.valueOf(configFile.getValue()), e.getMessage());
231          System.err.println(wrapText(message, MAX_LINE_WIDTH));
232          return 1;
233        }
234    
235        try
236        {
237          directoryServer.initializeConfiguration(configClass.getValue(),
238                                                  configFile.getValue());
239        }
240        catch (Exception e)
241        {
242          Message message = ERR_MAKELDIF_CANNOT_INITIALIZE_CONFIG.get(
243                  String.valueOf(configFile.getValue()), e.getMessage());
244          System.err.println(wrapText(message, MAX_LINE_WIDTH));
245          return 1;
246        }
247    
248        try
249        {
250          directoryServer.initializeSchema();
251        }
252        catch (Exception e)
253        {
254          Message message = ERR_MAKELDIF_CANNOT_INITIALIZE_SCHEMA.get(
255                  String.valueOf(configFile.getValue()), e.getMessage());
256          System.err.println(wrapText(message, MAX_LINE_WIDTH));
257          return 1;
258        }
259    
260    
261        // Create the random number generator that will be used for the generation
262        // process.
263        Random random;
264        if (randomSeed.isPresent())
265        {
266          try
267          {
268            random = new Random(randomSeed.getIntValue());
269          }
270          catch (Exception e)
271          {
272            random = new Random();
273          }
274        }
275        else
276        {
277          random = new Random();
278        }
279    
280    
281        // If a resource path was provided, then make sure it's acceptable.
282        File resourceDir = new File(resourcePath.getValue());
283        if (! resourceDir.exists())
284        {
285          Message message = ERR_MAKELDIF_NO_SUCH_RESOURCE_DIRECTORY.get(
286                  resourcePath.getValue());
287          System.err.println(wrapText(message, MAX_LINE_WIDTH));
288          return 1;
289        }
290    
291    
292        // Load and parse the template file.
293        LinkedList<Message> warnings = new LinkedList<Message>();
294        TemplateFile templateFile = new TemplateFile(resourcePath.getValue(),
295                                                     random);
296        try
297        {
298          templateFile.parse(templatePath.getValue(), warnings);
299        }
300        catch (IOException ioe)
301        {
302          Message message = ERR_MAKELDIF_IOEXCEPTION_DURING_PARSE.get(
303                  ioe.getMessage());
304          System.err.println(wrapText(message, MAX_LINE_WIDTH));
305          return 1;
306        }
307        catch (Exception e)
308        {
309          Message message = ERR_MAKELDIF_EXCEPTION_DURING_PARSE.get(
310                  e.getMessage());
311          System.err.println(wrapText(message, MAX_LINE_WIDTH));
312          return 1;
313        }
314    
315    
316        // If there were any warnings, then print them.
317        if (! warnings.isEmpty())
318        {
319          for (Message s : warnings)
320          {
321            System.err.println(wrapText(s, MAX_LINE_WIDTH));
322          }
323        }
324    
325    
326        // Create the LDIF writer that will be used to actually write the LDIF.
327        LDIFExportConfig exportConfig =
328             new LDIFExportConfig(ldifFile.getValue(),
329                                  ExistingFileBehavior.OVERWRITE);
330        try
331        {
332          ldifWriter = new LDIFWriter(exportConfig);
333        }
334        catch (IOException ioe)
335        {
336          Message message = ERR_MAKELDIF_UNABLE_TO_CREATE_LDIF.get(
337                  ldifFile.getValue(), String.valueOf(ioe));
338          System.err.println(wrapText(message, MAX_LINE_WIDTH));
339          return 1;
340        }
341    
342    
343        // Generate the LDIF content.
344        try
345        {
346          templateFile.generateLDIF(this);
347        }
348        catch (Exception e)
349        {
350          Message message = ERR_MAKELDIF_ERROR_WRITING_LDIF.get(
351                  ldifFile.getValue(), stackTraceToSingleLineString(e));
352          System.err.println(wrapText(message, MAX_LINE_WIDTH));
353          return 1;
354        }
355        finally
356        {
357          try
358          {
359            ldifWriter.close();
360          } catch (Exception e) {}
361        }
362    
363    
364        // If we've gotten here, then everything was successful.
365        return 0;
366      }
367    
368    
369    
370      /**
371       * Writes the provided entry to the appropriate target.
372       *
373       * @param  entry  The entry to be written.
374       *
375       * @return  <CODE>true</CODE> if the entry writer will accept more entries, or
376       *          <CODE>false</CODE> if not.
377       *
378       * @throws  IOException  If a problem occurs while writing the entry to its
379       *                       intended destination.
380       *
381       * @throws  MakeLDIFException  If some other problem occurs.
382       */
383      public boolean writeEntry(Entry entry)
384             throws IOException, MakeLDIFException
385      {
386        try
387        {
388          ldifWriter.writeEntry(entry);
389    
390          if ((++entriesWritten % 1000) == 0)
391          {
392            Message message = INFO_MAKELDIF_PROCESSED_N_ENTRIES.get(entriesWritten);
393            System.out.println(wrapText(message, MAX_LINE_WIDTH));
394          }
395    
396          return true;
397        }
398        catch (IOException ioe)
399        {
400          throw ioe;
401        }
402        catch (Exception e)
403        {
404          Message message = ERR_MAKELDIF_CANNOT_WRITE_ENTRY.get(
405              String.valueOf(entry.getDN()), stackTraceToSingleLineString(e));
406          throw new MakeLDIFException(message, e);
407        }
408      }
409    
410    
411    
412      /**
413       * Notifies the entry writer that no more entries will be provided and that
414       * any associated cleanup may be performed.
415       */
416      public void closeEntryWriter()
417      {
418        Message message = INFO_MAKELDIF_PROCESSING_COMPLETE.get(entriesWritten);
419        System.out.println(wrapText(message, MAX_LINE_WIDTH));
420      }
421    }
422