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