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;
028
029 import java.io.OutputStream;
030 import java.io.PrintStream;
031 import java.util.ArrayList;
032 import java.util.HashSet;
033 import java.util.List;
034
035 import org.opends.server.api.Backend;
036 import org.opends.server.api.ErrorLogPublisher;
037 import org.opends.server.api.DebugLogPublisher;
038 import org.opends.server.api.plugin.PluginType;
039 import org.opends.server.config.ConfigException;
040 import static org.opends.server.config.ConfigConstants.*;
041 import org.opends.server.core.CoreConfigManager;
042 import org.opends.server.core.DirectoryServer;
043 import org.opends.server.core.LockFileManager;
044 import org.opends.server.extensions.ConfigFileHandler;
045 import org.opends.server.loggers.TextWriter;
046 import org.opends.server.loggers.TextErrorLogPublisher;
047 import org.opends.server.loggers.ErrorLogger;
048 import org.opends.server.loggers.debug.TextDebugLogPublisher;
049 import org.opends.server.loggers.debug.DebugLogger;
050 import org.opends.server.types.AttributeType;
051 import org.opends.server.types.DirectoryException;
052 import org.opends.server.types.DN;
053 import org.opends.server.types.ExistingFileBehavior;
054 import org.opends.server.types.InitializationException;
055 import org.opends.server.types.LDIFExportConfig;
056 import org.opends.server.types.NullOutputStream;
057 import org.opends.server.types.SearchFilter;
058 import org.opends.server.types.RawAttribute;
059 import org.opends.server.util.args.ArgumentException;
060 import org.opends.server.util.args.BooleanArgument;
061 import org.opends.server.util.args.IntegerArgument;
062 import org.opends.server.util.args.StringArgument;
063 import org.opends.server.util.args.LDAPConnectionArgumentParser;
064
065 import org.opends.messages.Message;
066 import static org.opends.messages.ToolMessages.*;
067 import static org.opends.server.loggers.ErrorLogger.*;
068 import static org.opends.server.util.ServerConstants.*;
069 import static org.opends.server.util.StaticUtils.*;
070 import static org.opends.server.tools.ToolConstants.*;
071 import org.opends.server.tools.tasks.TaskTool;
072 import org.opends.server.admin.std.server.BackendCfg;
073 import org.opends.server.protocols.ldap.LDAPAttribute;
074 import org.opends.server.protocols.asn1.ASN1OctetString;
075 import org.opends.server.tasks.ExportTask;
076
077
078 /**
079 * This program provides a utility that may be used to export the contents of a
080 * Directory Server backend to an LDIF file. Depending on the arguments given,
081 * this program will either perform the export directly as a process that
082 * runs separate from Directory Server; or by scheduling a task to perform the
083 * action within the Directory Server via the tasks interface.
084 */
085 public class ExportLDIF extends TaskTool {
086
087 /**
088 * The main method for ExportLDIF tool.
089 *
090 * @param args The command-line arguments provided to this program.
091 */
092 public static void main(String[] args)
093 {
094 int retCode = mainExportLDIF(args, true, System.out, System.err);
095
096 if(retCode != 0)
097 {
098 System.exit(filterExitCode(retCode));
099 }
100 }
101
102 /**
103 * Processes the command-line arguments and invokes the export process.
104 *
105 * @param args The command-line arguments provided to this program.
106 *
107 * @return The error code.
108 */
109 public static int mainExportLDIF(String[] args)
110 {
111 return mainExportLDIF(args, true, System.out, System.err);
112 }
113
114 /**
115 * Processes the command-line arguments and invokes the export process.
116 *
117 * @param args The command-line arguments provided to this
118 * program.
119 * @param initializeServer Indicates whether to initialize the server.
120 * @param outStream The output stream to use for standard output, or
121 * {@code null} if standard output is not needed.
122 * @param errStream The output stream to use for standard error, or
123 * {@code null} if standard error is not needed.
124 *
125 * @return The error code.
126 */
127 public static int mainExportLDIF(String[] args, boolean initializeServer,
128 OutputStream outStream,
129 OutputStream errStream)
130 {
131 ExportLDIF tool = new ExportLDIF();
132 return tool.process(args, initializeServer, outStream, errStream);
133 }
134
135 // Define the command-line arguments that may be used with this program.
136 private BooleanArgument appendToLDIF = null;
137 private BooleanArgument compressLDIF = null;
138 private BooleanArgument displayUsage = null;
139 private BooleanArgument encryptLDIF = null;
140 private BooleanArgument excludeOperationalAttrs = null;
141 private BooleanArgument signHash = null;
142 private IntegerArgument wrapColumn = null;
143 private StringArgument backendID = null;
144 private StringArgument configClass = null;
145 private StringArgument configFile = null;
146 private StringArgument excludeAttributeStrings = null;
147 private StringArgument excludeBranchStrings = null;
148 private StringArgument excludeFilterStrings = null;
149 private StringArgument includeAttributeStrings = null;
150 private StringArgument includeBranchStrings = null;
151 private StringArgument includeFilterStrings = null;
152 private StringArgument ldifFile = null;
153
154 private int process(String[] args, boolean initializeServer,
155 OutputStream outStream, OutputStream errStream) {
156
157 PrintStream out;
158 if (outStream == null)
159 {
160 out = NullOutputStream.printStream();
161 }
162 else
163 {
164 out = new PrintStream(outStream);
165 }
166
167 PrintStream err;
168 if (errStream == null)
169 {
170 err = NullOutputStream.printStream();
171 }
172 else
173 {
174 err = new PrintStream(errStream);
175 }
176
177 // Create the command-line argument parser for use with this program.
178 LDAPConnectionArgumentParser argParser =
179 createArgParser("org.opends.server.tools.ExportLDIF",
180 INFO_LDIFEXPORT_TOOL_DESCRIPTION.get());
181
182
183 // Initialize all the command-line argument types and register them with the
184 // parser.
185 try
186 {
187 configClass =
188 new StringArgument("configclass", OPTION_SHORT_CONFIG_CLASS,
189 OPTION_LONG_CONFIG_CLASS, true, false,
190 true, INFO_CONFIGCLASS_PLACEHOLDER.get(),
191 ConfigFileHandler.class.getName(), null,
192 INFO_DESCRIPTION_CONFIG_CLASS.get());
193 configClass.setHidden(true);
194 argParser.addArgument(configClass);
195
196
197 configFile =
198 new StringArgument("configfile", 'f', "configFile", true, false,
199 true, INFO_CONFIGFILE_PLACEHOLDER.get(), null,
200 null,
201 INFO_DESCRIPTION_CONFIG_FILE.get());
202 configFile.setHidden(true);
203 argParser.addArgument(configFile);
204
205
206 ldifFile =
207 new StringArgument("ldiffile", OPTION_SHORT_LDIF_FILE,
208 OPTION_LONG_LDIF_FILE,true, false, true,
209 INFO_LDIFFILE_PLACEHOLDER.get(), null, null,
210 INFO_LDIFEXPORT_DESCRIPTION_LDIF_FILE.get());
211 argParser.addArgument(ldifFile);
212
213
214 appendToLDIF = new BooleanArgument(
215 "appendldif", 'a', "appendToLDIF",
216 INFO_LDIFEXPORT_DESCRIPTION_APPEND_TO_LDIF.get());
217 argParser.addArgument(appendToLDIF);
218
219
220 backendID =
221 new StringArgument("backendid", 'n', "backendID", true, false, true,
222 INFO_BACKENDNAME_PLACEHOLDER.get(), null, null,
223 INFO_LDIFEXPORT_DESCRIPTION_BACKEND_ID.get());
224 argParser.addArgument(backendID);
225
226
227 includeBranchStrings =
228 new StringArgument("includebranch", 'b', "includeBranch", false,
229 true, true, INFO_BRANCH_DN_PLACEHOLDER.get(),
230 null, null,
231 INFO_LDIFEXPORT_DESCRIPTION_INCLUDE_BRANCH.get());
232 argParser.addArgument(includeBranchStrings);
233
234
235 excludeBranchStrings =
236 new StringArgument("excludebranch", 'B', "excludeBranch", false,
237 true, true, INFO_BRANCH_DN_PLACEHOLDER.get(),
238 null, null,
239 INFO_LDIFEXPORT_DESCRIPTION_EXCLUDE_BRANCH.get());
240 argParser.addArgument(excludeBranchStrings);
241
242
243 includeAttributeStrings =
244 new StringArgument(
245 "includeattribute", 'i', "includeAttribute",
246 false, true, true, INFO_ATTRIBUTE_PLACEHOLDER.get(), null,
247 null,
248 INFO_LDIFEXPORT_DESCRIPTION_INCLUDE_ATTRIBUTE.get());
249 argParser.addArgument(includeAttributeStrings);
250
251
252 excludeAttributeStrings =
253 new StringArgument(
254 "excludeattribute", 'e', "excludeAttribute",
255 false, true, true, INFO_ATTRIBUTE_PLACEHOLDER.get(), null,
256 null,
257 INFO_LDIFEXPORT_DESCRIPTION_EXCLUDE_ATTRIBUTE.get());
258 argParser.addArgument(excludeAttributeStrings);
259
260
261 includeFilterStrings =
262 new StringArgument("includefilter", 'I', "includeFilter",
263 false, true, true, INFO_FILTER_PLACEHOLDER.get(),
264 null, null,
265 INFO_LDIFEXPORT_DESCRIPTION_INCLUDE_FILTER.get());
266 argParser.addArgument(includeFilterStrings);
267
268
269 excludeFilterStrings =
270 new StringArgument("excludefilter", 'E', "excludeFilter",
271 false, true, true, INFO_FILTER_PLACEHOLDER.get(),
272 null, null,
273 INFO_LDIFEXPORT_DESCRIPTION_EXCLUDE_FILTER.get());
274 argParser.addArgument(excludeFilterStrings);
275
276
277 excludeOperationalAttrs =
278 new BooleanArgument("excludeoperational", 'O', "excludeOperational",
279 INFO_LDIFEXPORT_DESCRIPTION_EXCLUDE_OPERATIONAL.get());
280 argParser.addArgument(excludeOperationalAttrs);
281
282
283 wrapColumn =
284 new IntegerArgument("wrapcolumn", null, "wrapColumn", false, false,
285 true, INFO_WRAP_COLUMN_PLACEHOLDER.get(), 0,
286 null, true, 0, false, 0,
287 INFO_LDIFEXPORT_DESCRIPTION_WRAP_COLUMN.get());
288 argParser.addArgument(wrapColumn);
289
290
291 compressLDIF =
292 new BooleanArgument("compressldif", OPTION_SHORT_COMPRESS,
293 OPTION_LONG_COMPRESS,
294 INFO_LDIFEXPORT_DESCRIPTION_COMPRESS_LDIF.get());
295 argParser.addArgument(compressLDIF);
296
297
298 encryptLDIF =
299 new BooleanArgument("encryptldif", 'y', "encryptLDIF",
300 INFO_LDIFEXPORT_DESCRIPTION_ENCRYPT_LDIF.get());
301 encryptLDIF.setHidden(true); // See issue #27
302 argParser.addArgument(encryptLDIF);
303
304
305 signHash =
306 new BooleanArgument("signhash", 's', "signHash",
307 INFO_LDIFEXPORT_DESCRIPTION_SIGN_HASH.get());
308 signHash.setHidden(true); // See issue #28
309 argParser.addArgument(signHash);
310
311
312 displayUsage =
313 new BooleanArgument("help", OPTION_SHORT_HELP,
314 OPTION_LONG_HELP,
315 INFO_DESCRIPTION_USAGE.get());
316 argParser.addArgument(displayUsage);
317 argParser.setUsageArgument(displayUsage);
318 }
319 catch (ArgumentException ae)
320 {
321 Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
322
323 err.println(wrapText(message, MAX_LINE_WIDTH));
324 return 1;
325 }
326
327
328 // Parse the command-line arguments provided to this program.
329 try
330 {
331 argParser.parseArguments(args);
332 validateTaskArgs();
333 }
334 catch (ArgumentException ae)
335 {
336 Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
337
338 err.println(wrapText(message, MAX_LINE_WIDTH));
339 err.println(argParser.getUsage());
340 return 1;
341 }
342
343
344 // If we should just display usage or version information,
345 // then print it and exit.
346 if (argParser.usageOrVersionDisplayed())
347 {
348 return 0;
349 }
350
351 return process(argParser, initializeServer, out, err);
352 }
353
354 /**
355 * {@inheritDoc}
356 */
357 public void addTaskAttributes(List<RawAttribute> attributes)
358 {
359 //
360 // Required attributes
361 //
362 ArrayList<ASN1OctetString> values = new ArrayList<ASN1OctetString>(1);
363 values.add(new ASN1OctetString(ldifFile.getValue()));
364 attributes.add(new LDAPAttribute(ATTR_TASK_EXPORT_LDIF_FILE, values));
365
366 values = new ArrayList<ASN1OctetString>(1);
367 values.add(new ASN1OctetString(backendID.getValue()));
368 attributes.add(new LDAPAttribute(ATTR_TASK_EXPORT_BACKEND_ID, values));
369
370 //
371 // Optional attributes
372 //
373 if (appendToLDIF.getValue() != null &&
374 !appendToLDIF.getValue().equals(appendToLDIF.getDefaultValue())) {
375 values = new ArrayList<ASN1OctetString>(1);
376 values.add(new ASN1OctetString(appendToLDIF.getValue()));
377 attributes.add(
378 new LDAPAttribute(ATTR_TASK_EXPORT_APPEND_TO_LDIF, values));
379 }
380
381 if (compressLDIF.getValue() != null &&
382 !compressLDIF.getValue().equals(compressLDIF.getDefaultValue())) {
383 values = new ArrayList<ASN1OctetString>(1);
384 values.add(new ASN1OctetString(compressLDIF.getValue()));
385 attributes.add(new LDAPAttribute(ATTR_TASK_EXPORT_COMPRESS_LDIF, values));
386 }
387
388 if (encryptLDIF.getValue() != null &&
389 !encryptLDIF.getValue().equals(encryptLDIF.getDefaultValue())) {
390 values = new ArrayList<ASN1OctetString>(1);
391 values.add(new ASN1OctetString(encryptLDIF.getValue()));
392 attributes.add(new LDAPAttribute(ATTR_TASK_EXPORT_ENCRYPT_LDIF, values));
393 }
394
395 if (signHash.getValue() != null &&
396 !signHash.getValue().equals(signHash.getDefaultValue())) {
397 values = new ArrayList<ASN1OctetString>(1);
398 values.add(new ASN1OctetString(signHash.getValue()));
399 attributes.add(
400 new LDAPAttribute(ATTR_TASK_EXPORT_SIGN_HASH, values));
401 }
402
403 List<String> includeAttributes = includeAttributeStrings.getValues();
404 if (includeAttributes != null && includeAttributes.size() > 0) {
405 values = new ArrayList<ASN1OctetString>(includeAttributes.size());
406 for (String includeAttribute : includeAttributes) {
407 values.add(new ASN1OctetString(includeAttribute));
408 }
409 attributes.add(
410 new LDAPAttribute(ATTR_TASK_EXPORT_INCLUDE_ATTRIBUTE, values));
411 }
412
413 List<String> excludeAttributes = excludeAttributeStrings.getValues();
414 if (excludeAttributes != null && excludeAttributes.size() > 0) {
415 values = new ArrayList<ASN1OctetString>(excludeAttributes.size());
416 for (String excludeAttribute : excludeAttributes) {
417 values.add(new ASN1OctetString(excludeAttribute));
418 }
419 attributes.add(
420 new LDAPAttribute(ATTR_TASK_EXPORT_EXCLUDE_ATTRIBUTE, values));
421 }
422
423 List<String> includeFilters = includeFilterStrings.getValues();
424 if (includeFilters != null && includeFilters.size() > 0) {
425 values = new ArrayList<ASN1OctetString>(includeFilters.size());
426 for (String includeFilter : includeFilters) {
427 values.add(new ASN1OctetString(includeFilter));
428 }
429 attributes.add(
430 new LDAPAttribute(ATTR_TASK_EXPORT_INCLUDE_FILTER, values));
431 }
432
433 List<String> excludeFilters = excludeFilterStrings.getValues();
434 if (excludeFilters != null && excludeFilters.size() > 0) {
435 values = new ArrayList<ASN1OctetString>(excludeFilters.size());
436 for (String excludeFilter : excludeFilters) {
437 values.add(new ASN1OctetString(excludeFilter));
438 }
439 attributes.add(
440 new LDAPAttribute(ATTR_TASK_EXPORT_EXCLUDE_FILTER, values));
441 }
442
443 List<String> includeBranches = includeBranchStrings.getValues();
444 if (includeBranches != null && includeBranches.size() > 0) {
445 values = new ArrayList<ASN1OctetString>(includeBranches.size());
446 for (String includeBranche : includeBranches) {
447 values.add(new ASN1OctetString(includeBranche));
448 }
449 attributes.add(
450 new LDAPAttribute(ATTR_TASK_EXPORT_INCLUDE_BRANCH, values));
451 }
452
453 List<String> excludeBranches = excludeBranchStrings.getValues();
454 if (excludeBranches != null && excludeBranches.size() > 0) {
455 values = new ArrayList<ASN1OctetString>(excludeBranches.size());
456 for (String excludeBranche : excludeBranches) {
457 values.add(new ASN1OctetString(excludeBranche));
458 }
459 attributes.add(
460 new LDAPAttribute(ATTR_TASK_EXPORT_EXCLUDE_BRANCH, values));
461 }
462
463 if (wrapColumn.getValue() != null &&
464 !wrapColumn.getValue().equals(wrapColumn.getDefaultValue())) {
465 values = new ArrayList<ASN1OctetString>(1);
466 values.add(new ASN1OctetString(wrapColumn.getValue()));
467 attributes.add(
468 new LDAPAttribute(ATTR_TASK_EXPORT_WRAP_COLUMN, values));
469 }
470
471 if (excludeOperationalAttrs.isPresent())
472 {
473 values = new ArrayList<ASN1OctetString>(1);
474 values.add(new ASN1OctetString("false"));
475 attributes.add(
476 new LDAPAttribute(ATTR_TASK_EXPORT_INCLUDE_OPERATIONAL_ATTRIBUTES,
477 values));
478 }
479 }
480
481 /**
482 * {@inheritDoc}
483 */
484 public String getTaskObjectclass() {
485 return "ds-task-export";
486 }
487
488 /**
489 * {@inheritDoc}
490 */
491 public Class getTaskClass() {
492 return ExportTask.class;
493 }
494
495 /**
496 * {@inheritDoc}
497 */
498 protected int processLocal(boolean initializeServer,
499 PrintStream out,
500 PrintStream err) {
501
502 // Perform the initial bootstrap of the Directory Server and process the
503 // configuration.
504 DirectoryServer directoryServer = DirectoryServer.getInstance();
505 if (initializeServer)
506 {
507 try
508 {
509 DirectoryServer.bootstrapClient();
510 DirectoryServer.initializeJMX();
511 }
512 catch (Exception e)
513 {
514 Message message =
515 ERR_SERVER_BOOTSTRAP_ERROR.get(getExceptionMessage(e));
516 err.println(wrapText(message, MAX_LINE_WIDTH));
517 return 1;
518 }
519
520 try
521 {
522 directoryServer.initializeConfiguration(configClass.getValue(),
523 configFile.getValue());
524 }
525 catch (InitializationException ie)
526 {
527 Message message = ERR_CANNOT_LOAD_CONFIG.get(ie.getMessage());
528 err.println(wrapText(message, MAX_LINE_WIDTH));
529 return 1;
530 }
531 catch (Exception e)
532 {
533 Message message = ERR_CANNOT_LOAD_CONFIG.get(getExceptionMessage(e));
534 err.println(wrapText(message, MAX_LINE_WIDTH));
535 return 1;
536 }
537
538
539
540 // Initialize the Directory Server schema elements.
541 try
542 {
543 directoryServer.initializeSchema();
544 }
545 catch (ConfigException ce)
546 {
547 Message message = ERR_CANNOT_LOAD_SCHEMA.get(ce.getMessage());
548 err.println(wrapText(message, MAX_LINE_WIDTH));
549 return 1;
550 }
551 catch (InitializationException ie)
552 {
553 Message message = ERR_CANNOT_LOAD_SCHEMA.get(ie.getMessage());
554 err.println(wrapText(message, MAX_LINE_WIDTH));
555 return 1;
556 }
557 catch (Exception e)
558 {
559 Message message = ERR_CANNOT_LOAD_SCHEMA.get(getExceptionMessage(e));
560 err.println(wrapText(message, MAX_LINE_WIDTH));
561 return 1;
562 }
563
564
565 // Initialize the Directory Server core configuration.
566 try
567 {
568 CoreConfigManager coreConfigManager = new CoreConfigManager();
569 coreConfigManager.initializeCoreConfig();
570 }
571 catch (ConfigException ce)
572 {
573 Message message =
574 ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(ce.getMessage());
575 err.println(wrapText(message, MAX_LINE_WIDTH));
576 return 1;
577 }
578 catch (InitializationException ie)
579 {
580 Message message =
581 ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(ie.getMessage());
582 err.println(wrapText(message, MAX_LINE_WIDTH));
583 return 1;
584 }
585 catch (Exception e)
586 {
587 Message message =
588 ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(getExceptionMessage(e));
589 err.println(wrapText(message, MAX_LINE_WIDTH));
590 return 1;
591 }
592
593
594 // Initialize the Directory Server crypto manager.
595 try
596 {
597 directoryServer.initializeCryptoManager();
598 }
599 catch (ConfigException ce)
600 {
601 Message message =
602 ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(ce.getMessage());
603 err.println(wrapText(message, MAX_LINE_WIDTH));
604 return 1;
605 }
606 catch (InitializationException ie)
607 {
608 Message message =
609 ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(ie.getMessage());
610 err.println(wrapText(message, MAX_LINE_WIDTH));
611 return 1;
612 }
613 catch (Exception e)
614 {
615 Message message =
616 ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(
617 getExceptionMessage(e));
618 err.println(wrapText(message, MAX_LINE_WIDTH));
619 return 1;
620 }
621
622
623 try
624 {
625 ErrorLogPublisher errorLogPublisher =
626 TextErrorLogPublisher.getStartupTextErrorPublisher(
627 new TextWriter.STREAM(out));
628 DebugLogPublisher debugLogPublisher =
629 TextDebugLogPublisher.getStartupTextDebugPublisher(
630 new TextWriter.STREAM(out));
631 ErrorLogger.addErrorLogPublisher(errorLogPublisher);
632 DebugLogger.addDebugLogPublisher(debugLogPublisher);
633 }
634 catch(Exception e)
635 {
636 err.println("Error installing the custom error logger: " +
637 stackTraceToSingleLineString(e));
638 }
639
640
641
642 // Make sure that the Directory Server plugin initialization is performed.
643 try
644 {
645 HashSet<PluginType> pluginTypes = new HashSet<PluginType>(1);
646 pluginTypes.add(PluginType.LDIF_EXPORT);
647 directoryServer.initializePlugins(pluginTypes);
648 }
649 catch (ConfigException ce)
650 {
651 Message message =
652 ERR_LDIFEXPORT_CANNOT_INITIALIZE_PLUGINS.get(ce.getMessage());
653 err.println(wrapText(message, MAX_LINE_WIDTH));
654 return 1;
655 }
656 catch (InitializationException ie)
657 {
658 Message message =
659 ERR_LDIFEXPORT_CANNOT_INITIALIZE_PLUGINS.get(ie.getMessage());
660 err.println(wrapText(message, MAX_LINE_WIDTH));
661 return 1;
662 }
663 catch (Exception e)
664 {
665 Message message =
666 ERR_LDIFEXPORT_CANNOT_INITIALIZE_PLUGINS.get(
667 getExceptionMessage(e));
668 err.println(wrapText(message, MAX_LINE_WIDTH));
669 return 1;
670 }
671 }
672
673
674 // See if there were any user-defined sets of include/exclude attributes or
675 // filters. If so, then process them.
676 HashSet<AttributeType> excludeAttributes;
677 if (excludeAttributeStrings == null)
678 {
679 excludeAttributes = null;
680 }
681 else
682 {
683 excludeAttributes = new HashSet<AttributeType>();
684 for (String attrName : excludeAttributeStrings.getValues())
685 {
686 String lowerName = attrName.toLowerCase();
687 AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
688 if (attrType == null)
689 {
690 attrType = DirectoryServer.getDefaultAttributeType(attrName);
691 }
692
693 excludeAttributes.add(attrType);
694 }
695 }
696
697 HashSet<AttributeType> includeAttributes;
698 if (includeAttributeStrings == null)
699 {
700 includeAttributes = null;
701 }
702 else
703 {
704 includeAttributes =new HashSet<AttributeType>();
705 for (String attrName : includeAttributeStrings.getValues())
706 {
707 String lowerName = attrName.toLowerCase();
708 AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
709 if (attrType == null)
710 {
711 attrType = DirectoryServer.getDefaultAttributeType(attrName);
712 }
713
714 includeAttributes.add(attrType);
715 }
716 }
717
718 ArrayList<SearchFilter> excludeFilters;
719 if (excludeFilterStrings == null)
720 {
721 excludeFilters = null;
722 }
723 else
724 {
725 excludeFilters = new ArrayList<SearchFilter>();
726 for (String filterString : excludeFilterStrings.getValues())
727 {
728 try
729 {
730 excludeFilters.add(SearchFilter.createFilterFromString(filterString));
731 }
732 catch (DirectoryException de)
733 {
734 Message message = ERR_LDIFEXPORT_CANNOT_PARSE_EXCLUDE_FILTER.get(
735 filterString, de.getMessageObject());
736 logError(message);
737 return 1;
738 }
739 catch (Exception e)
740 {
741 Message message = ERR_LDIFEXPORT_CANNOT_PARSE_EXCLUDE_FILTER.get(
742 filterString, getExceptionMessage(e));
743 logError(message);
744 return 1;
745 }
746 }
747 }
748
749 ArrayList<SearchFilter> includeFilters;
750 if (includeFilterStrings == null)
751 {
752 includeFilters = null;
753 }
754 else
755 {
756 includeFilters = new ArrayList<SearchFilter>();
757 for (String filterString : includeFilterStrings.getValues())
758 {
759 try
760 {
761 includeFilters.add(SearchFilter.createFilterFromString(filterString));
762 }
763 catch (DirectoryException de)
764 {
765 Message message = ERR_LDIFEXPORT_CANNOT_PARSE_INCLUDE_FILTER.get(
766 filterString, de.getMessageObject());
767 logError(message);
768 return 1;
769 }
770 catch (Exception e)
771 {
772 Message message = ERR_LDIFEXPORT_CANNOT_PARSE_INCLUDE_FILTER.get(
773 filterString, getExceptionMessage(e));
774 logError(message);
775 return 1;
776 }
777 }
778 }
779
780
781 // Get information about the backends defined in the server. Iterate
782 // through them, finding the one backend that should be used for the export,
783 // and also finding backends with subordinate base DNs that should be
784 // excluded from the export.
785 Backend backend = null;
786 List<DN> baseDNList = null;
787 List<DN> defaultIncludeBranches = null;
788 ArrayList<DN> excludeBranches = null;
789
790 ArrayList<Backend> backendList = new ArrayList<Backend>();
791 ArrayList<BackendCfg> entryList = new ArrayList<BackendCfg>();
792 ArrayList<List<DN>> dnList = new ArrayList<List<DN>>();
793 BackendToolUtils.getBackends(backendList, entryList, dnList);
794
795 int numBackends = backendList.size();
796 for (int i=0; i < numBackends; i++)
797 {
798 Backend b = backendList.get(i);
799 if (! backendID.getValue().equals(b.getBackendID()))
800 {
801 continue;
802 }
803
804 if (backend == null)
805 {
806 backend = b;
807 baseDNList = dnList.get(i);
808 defaultIncludeBranches = dnList.get(i);
809 }
810 else
811 {
812 Message message =
813 ERR_LDIFEXPORT_MULTIPLE_BACKENDS_FOR_ID.get(backendID.getValue());
814 logError(message);
815 return 1;
816 }
817 }
818
819 if (backend == null)
820 {
821 Message message =
822 ERR_LDIFEXPORT_NO_BACKENDS_FOR_ID.get(backendID.getValue());
823 logError(message);
824 return 1;
825 }
826 else if (! backend.supportsLDIFExport())
827 {
828 Message message =
829 ERR_LDIFEXPORT_CANNOT_EXPORT_BACKEND.get(backendID.getValue());
830 logError(message);
831 return 1;
832 }
833
834 if (excludeBranchStrings.isPresent())
835 {
836 excludeBranches = new ArrayList<DN>();
837 for (String s : excludeBranchStrings.getValues())
838 {
839 DN excludeBranch;
840 try
841 {
842 excludeBranch = DN.decode(s);
843 }
844 catch (DirectoryException de)
845 {
846 Message message = ERR_LDIFEXPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
847 s, de.getMessageObject());
848 logError(message);
849 return 1;
850 }
851 catch (Exception e)
852 {
853 Message message = ERR_LDIFEXPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
854 s, getExceptionMessage(e));
855 logError(message);
856 return 1;
857 }
858
859 if (! excludeBranches.contains(excludeBranch))
860 {
861 excludeBranches.add(excludeBranch);
862 }
863 }
864 }
865
866
867 List<DN> includeBranches;
868 if (includeBranchStrings.isPresent())
869 {
870 includeBranches = new ArrayList<DN>();
871 for (String s : includeBranchStrings.getValues())
872 {
873 DN includeBranch;
874 try
875 {
876 includeBranch = DN.decode(s);
877 }
878 catch (DirectoryException de)
879 {
880 Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
881 s, de.getMessageObject());
882 logError(message);
883 return 1;
884 }
885 catch (Exception e)
886 {
887 Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
888 s, getExceptionMessage(e));
889 logError(message);
890 return 1;
891 }
892
893 if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches,
894 excludeBranches))
895 {
896 Message message =
897 ERR_LDIFEXPORT_INVALID_INCLUDE_BASE.get(s, backendID.getValue());
898 logError(message);
899 return 1;
900 }
901
902 includeBranches.add(includeBranch);
903 }
904 }
905 else
906 {
907 includeBranches = defaultIncludeBranches;
908 }
909
910
911 // Create the LDIF export configuration to use when reading the LDIF.
912 ExistingFileBehavior existingBehavior;
913 if (appendToLDIF.isPresent())
914 {
915 existingBehavior = ExistingFileBehavior.APPEND;
916 }
917 else
918 {
919 existingBehavior = ExistingFileBehavior.OVERWRITE;
920 }
921
922 LDIFExportConfig exportConfig = new LDIFExportConfig(ldifFile.getValue(),
923 existingBehavior);
924 exportConfig.setCompressData(compressLDIF.isPresent());
925 exportConfig.setEncryptData(encryptLDIF.isPresent());
926 exportConfig.setExcludeAttributes(excludeAttributes);
927 exportConfig.setExcludeBranches(excludeBranches);
928 exportConfig.setExcludeFilters(excludeFilters);
929 exportConfig.setIncludeAttributes(includeAttributes);
930 exportConfig.setIncludeBranches(includeBranches);
931 exportConfig.setIncludeFilters(includeFilters);
932 exportConfig.setSignHash(signHash.isPresent());
933 exportConfig.setIncludeOperationalAttributes(
934 (! excludeOperationalAttrs.isPresent()));
935
936 // FIXME -- Should this be conditional?
937 exportConfig.setInvokeExportPlugins(true);
938
939 try
940 {
941 exportConfig.setWrapColumn(wrapColumn.getIntValue());
942 }
943 catch (ArgumentException ae)
944 {
945 Message message = ERR_LDIFEXPORT_CANNOT_DECODE_WRAP_COLUMN_AS_INTEGER.get(
946 wrapColumn.getValue());
947 logError(message);
948 return 1;
949 }
950
951
952 // Get the set of base DNs for the backend as an array.
953 DN[] baseDNs = new DN[baseDNList.size()];
954 baseDNList.toArray(baseDNs);
955
956
957 // Acquire a shared lock for the backend.
958 try
959 {
960 String lockFile = LockFileManager.getBackendLockFileName(backend);
961 StringBuilder failureReason = new StringBuilder();
962 if (! LockFileManager.acquireSharedLock(lockFile, failureReason))
963 {
964 Message message = ERR_LDIFEXPORT_CANNOT_LOCK_BACKEND.get(
965 backend.getBackendID(), String.valueOf(failureReason));
966 logError(message);
967 return 1;
968 }
969 }
970 catch (Exception e)
971 {
972 Message message = ERR_LDIFEXPORT_CANNOT_LOCK_BACKEND.get(
973 backend.getBackendID(), getExceptionMessage(e));
974 logError(message);
975 return 1;
976 }
977
978 boolean errorOccurred = false;
979
980 // Launch the export.
981 try
982 {
983 backend.exportLDIF(exportConfig);
984 }
985 catch (DirectoryException de)
986 {
987 Message message =
988 ERR_LDIFEXPORT_ERROR_DURING_EXPORT.get(de.getMessageObject());
989 logError(message);
990 errorOccurred = true;
991 }
992 catch (Exception e)
993 {
994 Message message =
995 ERR_LDIFEXPORT_ERROR_DURING_EXPORT.get(getExceptionMessage(e));
996 logError(message);
997 errorOccurred = true;
998 }
999
1000
1001 // Release the shared lock on the backend.
1002 try
1003 {
1004 String lockFile = LockFileManager.getBackendLockFileName(backend);
1005 StringBuilder failureReason = new StringBuilder();
1006 if (! LockFileManager.releaseLock(lockFile, failureReason))
1007 {
1008 Message message = WARN_LDIFEXPORT_CANNOT_UNLOCK_BACKEND.get(
1009 backend.getBackendID(), String.valueOf(failureReason));
1010 logError(message);
1011 }
1012 }
1013 catch (Exception e)
1014 {
1015 Message message = WARN_LDIFEXPORT_CANNOT_UNLOCK_BACKEND.get(
1016 backend.getBackendID(), getExceptionMessage(e));
1017 logError(message);
1018 }
1019
1020
1021 // Clean up after the export by closing the export config.
1022 exportConfig.close();
1023 if (!errorOccurred)
1024 {
1025 return 0;
1026 }
1027 else
1028 {
1029 return 1;
1030 }
1031 }
1032 }
1033