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