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    
030    
031    import java.io.File;
032    import java.io.OutputStream;
033    import java.io.PrintStream;
034    import java.util.ArrayList;
035    import java.util.HashSet;
036    import java.util.List;
037    import java.util.Random;
038    
039    import org.opends.server.admin.std.server.BackendCfg;
040    import org.opends.server.api.Backend;
041    import org.opends.server.api.ErrorLogPublisher;
042    import org.opends.server.api.DebugLogPublisher;
043    import org.opends.server.api.plugin.PluginType;
044    import org.opends.server.config.ConfigException;
045    import static org.opends.server.config.ConfigConstants.*;
046    import org.opends.server.core.CoreConfigManager;
047    import org.opends.server.core.DirectoryServer;
048    import org.opends.server.core.LockFileManager;
049    import org.opends.server.extensions.ConfigFileHandler;
050    import org.opends.server.loggers.TextWriter;
051    import org.opends.server.loggers.TextErrorLogPublisher;
052    import org.opends.server.loggers.ErrorLogger;
053    import org.opends.server.loggers.debug.TextDebugLogPublisher;
054    import org.opends.server.loggers.debug.DebugLogger;
055    
056    import org.opends.server.tools.makeldif.TemplateFile;
057    import org.opends.server.types.AttributeType;
058    import org.opends.server.types.DirectoryException;
059    import org.opends.server.types.DN;
060    import org.opends.server.types.ExistingFileBehavior;
061    import org.opends.server.types.InitializationException;
062    import org.opends.server.types.LDIFImportConfig;
063    import org.opends.server.types.LDIFImportResult;
064    import org.opends.server.types.NullOutputStream;
065    import org.opends.server.types.SearchFilter;
066    import org.opends.server.types.RawAttribute;
067    import org.opends.server.util.args.ArgumentException;
068    import org.opends.server.util.args.BooleanArgument;
069    import org.opends.server.util.args.IntegerArgument;
070    import org.opends.server.util.args.StringArgument;
071    import org.opends.server.util.args.LDAPConnectionArgumentParser;
072    
073    import static org.opends.server.loggers.ErrorLogger.*;
074    import static org.opends.messages.ToolMessages.*;
075    import org.opends.messages.Message;
076    import static org.opends.server.util.ServerConstants.*;
077    import static org.opends.server.util.StaticUtils.*;
078    import static org.opends.server.tools.ToolConstants.*;
079    import org.opends.server.tools.tasks.TaskTool;
080    import org.opends.server.tasks.ImportTask;
081    import org.opends.server.protocols.asn1.ASN1OctetString;
082    import org.opends.server.protocols.ldap.LDAPAttribute;
083    
084    
085    /**
086     * This program provides a utility that may be used to import the contents of an
087     * LDIF file into a Directory Server backend.  This will be a process that is
088     * intended to run separate from Directory Server and not internally within the
089     * server process (e.g., via the tasks interface).
090     */
091    public class ImportLDIF extends TaskTool {
092      /**
093       * The buffer size that should be used when reading data from LDIF.
094       */
095      public static final int LDIF_BUFFER_SIZE = 1048576;
096    
097    
098      /**
099       * The main method for ImportLDIF tool.
100       *
101       * @param  args  The command-line arguments provided to this program.
102       */
103      public static void main(String[] args)
104      {
105        int retCode = mainImportLDIF(args, true, System.out, System.err);
106    
107        if(retCode != 0)
108        {
109          System.exit(filterExitCode(retCode));
110        }
111      }
112    
113      /**
114       * Processes the command-line arguments and invokes the import process.
115       *
116       * @param  args  The command-line arguments provided to thisprogram.
117       *
118       * @return The error code.
119       */
120      public static int mainImportLDIF(String[] args)
121      {
122        return mainImportLDIF(args, true, System.out, System.err);
123      }
124    
125      /**
126       * Processes the command-line arguments and invokes the import process.
127       *
128       * @param  args              The command-line arguments provided to this
129       *                           program.
130       * @param  initializeServer  Indicates whether to initialize the server.
131       * @param  outStream         The output stream to use for standard output, or
132       *                           {@code null} if standard output is not needed.
133       * @param  errStream         The output stream to use for standard error, or
134       *                           {@code null} if standard error is not needed.
135       *
136       * @return The error code.
137       */
138      public static int mainImportLDIF(String[] args, boolean initializeServer,
139                                       OutputStream outStream,
140                                       OutputStream errStream)
141      {
142        ImportLDIF tool = new ImportLDIF();
143        return tool.process(args, initializeServer, outStream, errStream);
144      }
145    
146      // Define the command-line arguments that may be used with this program.
147      private BooleanArgument append                  = null;
148      private BooleanArgument countRejects            = null;
149      private BooleanArgument displayUsage            = null;
150      private BooleanArgument isCompressed            = null;
151      private BooleanArgument isEncrypted             = null;
152      private BooleanArgument overwrite               = null;
153      private BooleanArgument quietMode               = null;
154      private BooleanArgument replaceExisting         = null;
155      private BooleanArgument skipSchemaValidation    = null;
156      private BooleanArgument clearBackend            = null;
157      private IntegerArgument randomSeed              = null;
158      private StringArgument  backendID               = null;
159      private StringArgument  configClass             = null;
160      private StringArgument  configFile              = null;
161      private StringArgument  excludeAttributeStrings = null;
162      private StringArgument  excludeBranchStrings    = null;
163      private StringArgument  excludeFilterStrings    = null;
164      private StringArgument  includeAttributeStrings = null;
165      private StringArgument  includeBranchStrings    = null;
166      private StringArgument  includeFilterStrings    = null;
167      private StringArgument  ldifFiles               = null;
168      private StringArgument  rejectFile              = null;
169      private StringArgument  skipFile                = null;
170      private StringArgument  templateFile            = null;
171    
172      private int process(String[] args, boolean initializeServer,
173                          OutputStream outStream, OutputStream errStream) {
174    
175        PrintStream out;
176        if (outStream == null)
177        {
178          out = NullOutputStream.printStream();
179        }
180        else
181        {
182          out = new PrintStream(outStream);
183        }
184    
185        PrintStream err;
186        if (errStream == null)
187        {
188          err = NullOutputStream.printStream();
189        }
190        else
191        {
192          err = new PrintStream(errStream);
193        }
194    
195        // FIXME -- Need to add a mechanism for verifying the file signature.
196    
197    
198        // Create the command-line argument parser for use with this program.
199        LDAPConnectionArgumentParser argParser =
200                createArgParser("org.opends.server.tools.ImportLDIF",
201                                INFO_LDIFIMPORT_TOOL_DESCRIPTION.get());
202    
203        // Initialize all the command-line argument types and register them with the
204        // parser.
205        try
206        {
207          configClass =
208               new StringArgument("configclass", OPTION_SHORT_CONFIG_CLASS,
209                                  OPTION_LONG_CONFIG_CLASS, true, false,
210                                  true, INFO_CONFIGCLASS_PLACEHOLDER.get(),
211                                  ConfigFileHandler.class.getName(), null,
212                                  INFO_DESCRIPTION_CONFIG_CLASS.get());
213          configClass.setHidden(true);
214          argParser.addArgument(configClass);
215    
216    
217          configFile =
218               new StringArgument("configfile", 'f', "configFile", true, false,
219                                  true, INFO_CONFIGFILE_PLACEHOLDER.get(), null,
220                                  null,
221                                  INFO_DESCRIPTION_CONFIG_FILE.get());
222          configFile.setHidden(true);
223          argParser.addArgument(configFile);
224    
225    
226          ldifFiles =
227               new StringArgument("ldiffile", OPTION_SHORT_LDIF_FILE,
228                                  OPTION_LONG_LDIF_FILE, false, true, true,
229                                  INFO_LDIFFILE_PLACEHOLDER.get(), null, null,
230                                  INFO_LDIFIMPORT_DESCRIPTION_LDIF_FILE.get());
231          argParser.addArgument(ldifFiles);
232    
233    
234          templateFile =
235               new StringArgument("templatefile", 'A', "templateFile", false, false,
236                                  true, INFO_TEMPLATE_FILE_PLACEHOLDER.get(), null,
237                                  null,
238                                  INFO_LDIFIMPORT_DESCRIPTION_TEMPLATE_FILE.get());
239          argParser.addArgument(templateFile);
240    
241    
242          append =
243               new BooleanArgument("append", 'a', "append",
244                                   INFO_LDIFIMPORT_DESCRIPTION_APPEND.get());
245          argParser.addArgument(append);
246    
247    
248          replaceExisting =
249               new BooleanArgument(
250                       "replaceexisting", 'r', "replaceExisting",
251                       INFO_LDIFIMPORT_DESCRIPTION_REPLACE_EXISTING.get());
252          argParser.addArgument(replaceExisting);
253    
254    
255          backendID =
256               new StringArgument("backendid", 'n', "backendID", false, false, true,
257                                  INFO_BACKENDNAME_PLACEHOLDER.get(), null, null,
258                                  INFO_LDIFIMPORT_DESCRIPTION_BACKEND_ID.get());
259          argParser.addArgument(backendID);
260    
261          clearBackend =
262              new BooleanArgument("clearbackend", 'F', "clearBackend",
263                                  INFO_LDIFIMPORT_DESCRIPTION_CLEAR_BACKEND.get());
264          argParser.addArgument(clearBackend);
265    
266    
267          includeBranchStrings =
268               new StringArgument("includebranch", 'b', "includeBranch", false,
269                                  true, true, INFO_BRANCH_DN_PLACEHOLDER.get(),
270                                  null, null,
271                                  INFO_LDIFIMPORT_DESCRIPTION_INCLUDE_BRANCH.get());
272          argParser.addArgument(includeBranchStrings);
273    
274    
275          excludeBranchStrings =
276               new StringArgument("excludebranch", 'B', "excludeBranch", false,
277                                  true, true, INFO_BRANCH_DN_PLACEHOLDER.get(),
278                                  null, null,
279                                  INFO_LDIFIMPORT_DESCRIPTION_EXCLUDE_BRANCH.get());
280          argParser.addArgument(excludeBranchStrings);
281    
282    
283          includeAttributeStrings =
284               new StringArgument(
285                       "includeattribute", 'i', "includeAttribute",
286                       false, true, true, INFO_ATTRIBUTE_PLACEHOLDER.get(), null,
287                       null,
288                       INFO_LDIFIMPORT_DESCRIPTION_INCLUDE_ATTRIBUTE.get());
289          argParser.addArgument(includeAttributeStrings);
290    
291    
292          excludeAttributeStrings =
293               new StringArgument(
294                       "excludeattribute", 'e', "excludeAttribute",
295                       false, true, true, INFO_ATTRIBUTE_PLACEHOLDER.get(), null,
296                       null,
297                       INFO_LDIFIMPORT_DESCRIPTION_EXCLUDE_ATTRIBUTE.get());
298          argParser.addArgument(excludeAttributeStrings);
299    
300    
301          includeFilterStrings =
302               new StringArgument(
303                       "includefilter", 'I', "includeFilter",
304                       false, true, true, INFO_FILTER_PLACEHOLDER.get(), null, null,
305                       INFO_LDIFIMPORT_DESCRIPTION_INCLUDE_FILTER.get());
306          argParser.addArgument(includeFilterStrings);
307    
308    
309          excludeFilterStrings =
310               new StringArgument("excludefilter", 'E', "excludeFilter",
311                                  false, true, true, INFO_FILTER_PLACEHOLDER.get(),
312                                  null, null,
313                                  INFO_LDIFIMPORT_DESCRIPTION_EXCLUDE_FILTER.get());
314          argParser.addArgument(excludeFilterStrings);
315    
316    
317          rejectFile =
318               new StringArgument("rejectfile", 'R', "rejectFile", false, false,
319                                  true, INFO_REJECT_FILE_PLACEHOLDER.get(), null,
320                                  null,
321                                  INFO_LDIFIMPORT_DESCRIPTION_REJECT_FILE.get());
322          argParser.addArgument(rejectFile);
323    
324    
325          skipFile =
326               new StringArgument("skipfile", null, "skipFile", false, false,
327                                  true, INFO_SKIP_FILE_PLACEHOLDER.get(), null,
328                                  null,
329                                  INFO_LDIFIMPORT_DESCRIPTION_SKIP_FILE.get());
330          argParser.addArgument(skipFile);
331    
332    
333          overwrite =
334               new BooleanArgument("overwrite", 'O', "overwrite",
335                                   INFO_LDIFIMPORT_DESCRIPTION_OVERWRITE.get());
336          argParser.addArgument(overwrite);
337    
338    
339          randomSeed =
340               new IntegerArgument("randomseed", OPTION_SHORT_RANDOM_SEED,
341                                   OPTION_LONG_RANDOM_SEED, false, false,
342                                   true, INFO_SEED_PLACEHOLDER.get(),
343                                   0, null, false, 0, false, 0,
344                                   INFO_LDIFIMPORT_DESCRIPTION_RANDOM_SEED.get());
345          argParser.addArgument(randomSeed);
346    
347    
348          skipSchemaValidation =
349               new BooleanArgument("skipschema", 'S', "skipSchemaValidation",
350                        INFO_LDIFIMPORT_DESCRIPTION_SKIP_SCHEMA_VALIDATION.get());
351          argParser.addArgument(skipSchemaValidation);
352    
353    
354          countRejects =
355               new BooleanArgument("countrejects", null, "countRejects",
356                                   INFO_LDIFIMPORT_DESCRIPTION_COUNT_REJECTS.get());
357          argParser.addArgument(countRejects);
358    
359    
360          isCompressed =
361               new BooleanArgument("iscompressed", 'c', "isCompressed",
362                                   INFO_LDIFIMPORT_DESCRIPTION_IS_COMPRESSED.get());
363          argParser.addArgument(isCompressed);
364    
365    
366          isEncrypted =
367               new BooleanArgument("isencrypted", 'y', "isEncrypted",
368                                   INFO_LDIFIMPORT_DESCRIPTION_IS_ENCRYPTED.get());
369          isEncrypted.setHidden(true); //See issue #27
370          argParser.addArgument(isEncrypted);
371    
372    
373          quietMode = new BooleanArgument("quietmode", OPTION_SHORT_QUIET,
374                                          OPTION_LONG_QUIET,
375                                          INFO_LDIFIMPORT_DESCRIPTION_QUIET.get());
376          argParser.addArgument(quietMode);
377    
378    
379          displayUsage =
380               new BooleanArgument("help", OPTION_SHORT_HELP, OPTION_LONG_HELP,
381                                   INFO_DESCRIPTION_USAGE.get());
382          argParser.addArgument(displayUsage);
383          argParser.setUsageArgument(displayUsage);
384        }
385        catch (ArgumentException ae)
386        {
387          Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
388    
389          err.println(wrapText(message, MAX_LINE_WIDTH));
390          return 1;
391        }
392    
393    
394        // Parse the command-line arguments provided to this program.
395        try
396        {
397          argParser.parseArguments(args);
398          validateTaskArgs();
399        }
400        catch (ArgumentException ae)
401        {
402          Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
403    
404          err.println(wrapText(message, MAX_LINE_WIDTH));
405          err.println(argParser.getUsage());
406          return 1;
407        }
408    
409    
410        // If we should just display usage or version information,
411        // then print it and exit.
412        if (argParser.usageOrVersionDisplayed())
413        {
414          return 0;
415        }
416    
417    
418        // Make sure that either the "ldifFile" argument or the "templateFile"
419        // argument was provided, but not both.
420        if (ldifFiles.isPresent())
421        {
422          if (templateFile.isPresent())
423          {
424            Message message = ERR_LDIFIMPORT_CONFLICTING_OPTIONS.get(
425                    ldifFiles.getLongIdentifier(),
426                    templateFile.getLongIdentifier());
427            err.println(wrapText(message, MAX_LINE_WIDTH));
428            return 1;
429          }
430        }
431        else if (! templateFile.isPresent())
432        {
433          Message message = ERR_LDIFIMPORT_MISSING_REQUIRED_ARGUMENT.get(
434                  ldifFiles.getLongIdentifier(),
435                  templateFile.getLongIdentifier());
436          err.println(wrapText(message, MAX_LINE_WIDTH));
437          return 1;
438        }
439    
440        // Make sure that either the "includeBranchStrings" argument or the
441        // "backendID" argument was provided.
442        if(!includeBranchStrings.isPresent() && !backendID.isPresent())
443        {
444          Message message = ERR_LDIFIMPORT_MISSING_BACKEND_ARGUMENT.get(
445                  includeBranchStrings.getLongIdentifier(),
446                  backendID.getLongIdentifier());
447          err.println(wrapText(message, MAX_LINE_WIDTH));
448          return 1;
449        }
450    
451        // Don't write non-error messages to console if quite
452        if (quietMode.isPresent()) {
453          out = new PrintStream(NullOutputStream.instance());
454        }
455    
456        return process(argParser, initializeServer, out, err);
457      }
458    
459      /**
460       * {@inheritDoc}
461       */
462      public void addTaskAttributes(List<RawAttribute> attributes)
463      {
464        //
465        // Required attributes
466        //
467        ArrayList<ASN1OctetString> values;
468        List<String> fileList = ldifFiles.getValues();
469        if (fileList != null && fileList.size() > 0) {
470          values = new ArrayList<ASN1OctetString>(fileList.size());
471          for (String file : fileList) {
472            values.add(new ASN1OctetString(file));
473          }
474          attributes.add(new LDAPAttribute(ATTR_IMPORT_LDIF_FILE, values));
475        }
476    
477        //
478        // Optional attributes
479        //
480        if (append.getValue() != null &&
481                !append.getValue().equals(append.getDefaultValue())) {
482          values = new ArrayList<ASN1OctetString>(1);
483          values.add(new ASN1OctetString(append.getValue()));
484          attributes.add(new LDAPAttribute(ATTR_IMPORT_APPEND, values));
485        }
486    
487        if (replaceExisting.getValue() != null &&
488                !replaceExisting.getValue().equals(
489                        replaceExisting.getDefaultValue())) {
490          values = new ArrayList<ASN1OctetString>(1);
491          values.add(new ASN1OctetString(replaceExisting.getValue()));
492          attributes.add(new LDAPAttribute(ATTR_IMPORT_REPLACE_EXISTING, values));
493        }
494    
495        if (backendID.getValue() != null &&
496                !backendID.getValue().equals(
497                        backendID.getDefaultValue())) {
498          values = new ArrayList<ASN1OctetString>(1);
499          values.add(new ASN1OctetString(backendID.getValue()));
500          attributes.add(new LDAPAttribute(ATTR_IMPORT_BACKEND_ID, values));
501        }
502    
503        List<String> includeAttributes = includeAttributeStrings.getValues();
504        if (includeAttributes != null && includeAttributes.size() > 0) {
505          values = new ArrayList<ASN1OctetString>(includeAttributes.size());
506          for (String includeAttribute : includeAttributes) {
507            values.add(new ASN1OctetString(includeAttribute));
508          }
509          attributes.add(new LDAPAttribute(ATTR_IMPORT_INCLUDE_ATTRIBUTE, values));
510        }
511    
512        List<String> excludeAttributes = excludeAttributeStrings.getValues();
513        if (excludeAttributes != null && excludeAttributes.size() > 0) {
514          values = new ArrayList<ASN1OctetString>(excludeAttributes.size());
515          for (String excludeAttribute : excludeAttributes) {
516            values.add(new ASN1OctetString(excludeAttribute));
517          }
518          attributes.add(new LDAPAttribute(ATTR_IMPORT_EXCLUDE_ATTRIBUTE, values));
519        }
520    
521        List<String> includeFilters = includeFilterStrings.getValues();
522        if (includeFilters != null && includeFilters.size() > 0) {
523          values = new ArrayList<ASN1OctetString>(includeFilters.size());
524          for (String includeFilter : includeFilters) {
525            values.add(new ASN1OctetString(includeFilter));
526          }
527          attributes.add(new LDAPAttribute(ATTR_IMPORT_INCLUDE_FILTER, values));
528        }
529    
530        List<String> excludeFilters = excludeFilterStrings.getValues();
531        if (excludeFilters != null && excludeFilters.size() > 0) {
532          values = new ArrayList<ASN1OctetString>(excludeFilters.size());
533          for (String excludeFilter : excludeFilters) {
534            values.add(new ASN1OctetString(excludeFilter));
535          }
536          attributes.add(new LDAPAttribute(ATTR_IMPORT_EXCLUDE_FILTER, values));
537        }
538    
539        List<String> includeBranches = includeBranchStrings.getValues();
540        if (includeBranches != null && includeBranches.size() > 0) {
541          values = new ArrayList<ASN1OctetString>(includeBranches.size());
542          for (String includeBranche : includeBranches) {
543            values.add(new ASN1OctetString(includeBranche));
544          }
545          attributes.add(new LDAPAttribute(ATTR_IMPORT_INCLUDE_BRANCH, values));
546        }
547    
548        List<String> excludeBranches = excludeBranchStrings.getValues();
549        if (excludeBranches != null && excludeBranches.size() > 0) {
550          values = new ArrayList<ASN1OctetString>(excludeBranches.size());
551          for (String excludeBranch : excludeBranches) {
552            values.add(new ASN1OctetString(excludeBranch));
553          }
554          attributes.add(new LDAPAttribute(ATTR_IMPORT_EXCLUDE_BRANCH, values));
555        }
556    
557        if (rejectFile.getValue() != null &&
558                !rejectFile.getValue().equals(
559                        rejectFile.getDefaultValue())) {
560          values = new ArrayList<ASN1OctetString>(1);
561          values.add(new ASN1OctetString(rejectFile.getValue()));
562          attributes.add(new LDAPAttribute(ATTR_IMPORT_REJECT_FILE, values));
563        }
564    
565        if (skipFile.getValue() != null &&
566                !skipFile.getValue().equals(
567                        skipFile.getDefaultValue())) {
568          values = new ArrayList<ASN1OctetString>(1);
569          values.add(new ASN1OctetString(skipFile.getValue()));
570          attributes.add(new LDAPAttribute(ATTR_IMPORT_SKIP_FILE, values));
571        }
572    
573        if (overwrite.getValue() != null &&
574                !overwrite.getValue().equals(
575                        overwrite.getDefaultValue())) {
576          values = new ArrayList<ASN1OctetString>(1);
577          values.add(new ASN1OctetString(overwrite.getValue()));
578          attributes.add(new LDAPAttribute(ATTR_IMPORT_OVERWRITE, values));
579        }
580    
581        if (skipSchemaValidation.getValue() != null &&
582                !skipSchemaValidation.getValue().equals(
583                        skipSchemaValidation.getDefaultValue())) {
584          values = new ArrayList<ASN1OctetString>(1);
585          values.add(new ASN1OctetString(skipSchemaValidation.getValue()));
586          attributes.add(
587                  new LDAPAttribute(ATTR_IMPORT_SKIP_SCHEMA_VALIDATION, values));
588        }
589    
590        if (isCompressed.getValue() != null &&
591                !isCompressed.getValue().equals(
592                        isCompressed.getDefaultValue())) {
593          values = new ArrayList<ASN1OctetString>(1);
594          values.add(new ASN1OctetString(isCompressed.getValue()));
595          attributes.add(
596                  new LDAPAttribute(ATTR_IMPORT_IS_COMPRESSED, values));
597        }
598    
599        if (isEncrypted.getValue() != null &&
600                !isEncrypted.getValue().equals(
601                        isEncrypted.getDefaultValue())) {
602          values = new ArrayList<ASN1OctetString>(1);
603          values.add(new ASN1OctetString(isEncrypted.getValue()));
604          attributes.add(
605                  new LDAPAttribute(ATTR_IMPORT_IS_ENCRYPTED, values));
606        }
607    
608        if (clearBackend.getValue() != null &&
609                !clearBackend.getValue().equals(
610                        clearBackend.getDefaultValue())) {
611          values = new ArrayList<ASN1OctetString>(1);
612          values.add(new ASN1OctetString(clearBackend.getValue()));
613          attributes.add(
614                  new LDAPAttribute(ATTR_IMPORT_CLEAR_BACKEND, values));
615        }
616    
617      }
618    
619      /**
620       * {@inheritDoc}
621       */
622      public String getTaskObjectclass() {
623        return "ds-task-import";
624      }
625    
626      /**
627       * {@inheritDoc}
628       */
629      public Class getTaskClass() {
630        return ImportTask.class;
631      }
632    
633      /**
634       * {@inheritDoc}
635       */
636      protected int processLocal(boolean initializeServer,
637                               PrintStream out,
638                               PrintStream err) {
639    
640    
641        // Perform the initial bootstrap of the Directory Server and process the
642        // configuration.
643        DirectoryServer directoryServer = DirectoryServer.getInstance();
644        if (initializeServer)
645        {
646          try
647          {
648            DirectoryServer.bootstrapClient();
649            DirectoryServer.initializeJMX();
650          }
651          catch (Exception e)
652          {
653            Message message = ERR_SERVER_BOOTSTRAP_ERROR.get(
654                    getExceptionMessage(e));
655            err.println(wrapText(message, MAX_LINE_WIDTH));
656            return 1;
657          }
658    
659          try
660          {
661            directoryServer.initializeConfiguration(configClass.getValue(),
662                                                    configFile.getValue());
663          }
664          catch (InitializationException ie)
665          {
666            Message message = ERR_CANNOT_LOAD_CONFIG.get(ie.getMessage());
667            err.println(wrapText(message, MAX_LINE_WIDTH));
668            return 1;
669          }
670          catch (Exception e)
671          {
672            Message message = ERR_CANNOT_LOAD_CONFIG.get(getExceptionMessage(e));
673            err.println(wrapText(message, MAX_LINE_WIDTH));
674            return 1;
675          }
676    
677    
678    
679          // Initialize the Directory Server schema elements.
680          try
681          {
682            directoryServer.initializeSchema();
683          }
684          catch (ConfigException ce)
685          {
686            Message message = ERR_CANNOT_LOAD_SCHEMA.get(ce.getMessage());
687            err.println(wrapText(message, MAX_LINE_WIDTH));
688            return 1;
689          }
690          catch (InitializationException ie)
691          {
692            Message message = ERR_CANNOT_LOAD_SCHEMA.get(ie.getMessage());
693            err.println(wrapText(message, MAX_LINE_WIDTH));
694            return 1;
695          }
696          catch (Exception e)
697          {
698            Message message = ERR_CANNOT_LOAD_SCHEMA.get(getExceptionMessage(e));
699            err.println(wrapText(message, MAX_LINE_WIDTH));
700            return 1;
701          }
702    
703    
704          // Initialize the Directory Server core configuration.
705          try
706          {
707            CoreConfigManager coreConfigManager = new CoreConfigManager();
708            coreConfigManager.initializeCoreConfig();
709          }
710          catch (ConfigException ce)
711          {
712            Message message = ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(
713                    ce.getMessage());
714            err.println(wrapText(message, MAX_LINE_WIDTH));
715            return 1;
716          }
717          catch (InitializationException ie)
718          {
719            Message message = ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(
720                    ie.getMessage());
721            err.println(wrapText(message, MAX_LINE_WIDTH));
722            return 1;
723          }
724          catch (Exception e)
725          {
726            Message message = ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(
727                    getExceptionMessage(e));
728            err.println(wrapText(message, MAX_LINE_WIDTH));
729            return 1;
730          }
731    
732    
733          // Initialize the Directory Server crypto manager.
734          try
735          {
736            directoryServer.initializeCryptoManager();
737          }
738          catch (ConfigException ce)
739          {
740            Message message = ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(
741                    ce.getMessage());
742            err.println(wrapText(message, MAX_LINE_WIDTH));
743            return 1;
744          }
745          catch (InitializationException ie)
746          {
747            Message message = ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(
748                    ie.getMessage());
749            err.println(wrapText(message, MAX_LINE_WIDTH));
750            return 1;
751          }
752          catch (Exception e)
753          {
754            Message message = ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(
755                    getExceptionMessage(e));
756            err.println(wrapText(message, MAX_LINE_WIDTH));
757            return 1;
758          }
759    
760    
761          if (! quietMode.isPresent())
762          {
763            try
764            {
765              ErrorLogPublisher errorLogPublisher =
766                  TextErrorLogPublisher.getStartupTextErrorPublisher(
767                      new TextWriter.STREAM(out));
768              DebugLogPublisher debugLogPublisher =
769                  TextDebugLogPublisher.getStartupTextDebugPublisher(
770                      new TextWriter.STREAM(out));
771              ErrorLogger.addErrorLogPublisher(errorLogPublisher);
772              DebugLogger.addDebugLogPublisher(debugLogPublisher);
773            }
774            catch(Exception e)
775            {
776              err.println("Error installing the custom error logger: " +
777                  stackTraceToSingleLineString(e));
778            }
779          }
780    
781    
782          // Initialize all the password policy information.
783          try
784          {
785            directoryServer.initializePasswordPolicyComponents();
786          }
787          catch (ConfigException ce)
788          {
789            Message message = ERR_LDIFIMPORT_CANNOT_INITIALIZE_PWPOLICY.get(
790                    ce.getMessage());
791            err.println(wrapText(message, MAX_LINE_WIDTH));
792            return 1;
793          }
794          catch (InitializationException ie)
795          {
796            Message message = ERR_LDIFIMPORT_CANNOT_INITIALIZE_PWPOLICY.get(
797                    ie.getMessage());
798            err.println(wrapText(message, MAX_LINE_WIDTH));
799            return 1;
800          }
801          catch (Exception e)
802          {
803            Message message = ERR_LDIFIMPORT_CANNOT_INITIALIZE_PWPOLICY.get(
804                    getExceptionMessage(e));
805            err.println(wrapText(message, MAX_LINE_WIDTH));
806            return 1;
807          }
808    
809    
810          // Make sure that the Directory Server plugin initialization is performed.
811          try
812          {
813            HashSet<PluginType> pluginTypes = new HashSet<PluginType>(1);
814            pluginTypes.add(PluginType.LDIF_IMPORT);
815            directoryServer.initializePlugins(pluginTypes);
816          }
817          catch (ConfigException ce)
818          {
819            Message message = ERR_LDIFIMPORT_CANNOT_INITIALIZE_PLUGINS.get(
820                    ce.getMessage());
821            err.println(wrapText(message, MAX_LINE_WIDTH));
822            return 1;
823          }
824          catch (InitializationException ie)
825          {
826            Message message = ERR_LDIFIMPORT_CANNOT_INITIALIZE_PLUGINS.get(
827                    ie.getMessage());
828            err.println(wrapText(message, MAX_LINE_WIDTH));
829            return 1;
830          }
831          catch (Exception e)
832          {
833            Message message = ERR_LDIFIMPORT_CANNOT_INITIALIZE_PLUGINS.get(
834                    getExceptionMessage(e));
835            err.println(wrapText(message, MAX_LINE_WIDTH));
836            return 1;
837          }
838        }
839    
840    
841        // See if there were any user-defined sets of include/exclude attributes or
842        // filters.  If so, then process them.
843        HashSet<AttributeType> excludeAttributes;
844        boolean excludeAllUserAttributes = false;
845        boolean excludeAllOperationalAttributes = false;
846        if (excludeAttributeStrings == null)
847        {
848          excludeAttributes = null;
849        }
850        else
851        {
852          excludeAttributes = new HashSet<AttributeType>();
853          for (String attrName : excludeAttributeStrings.getValues())
854          {
855            String        lowerName = attrName.toLowerCase();
856            if(lowerName.equals("*"))
857            {
858              excludeAllUserAttributes = true;
859            }
860            else if(lowerName.equals("+"))
861            {
862              excludeAllOperationalAttributes = true;
863            }
864            else
865            {
866              AttributeType attrType  = DirectoryServer.getAttributeType(lowerName);
867              if (attrType == null)
868              {
869                attrType = DirectoryServer.getDefaultAttributeType(attrName);
870              }
871    
872              excludeAttributes.add(attrType);
873            }
874          }
875        }
876    
877        HashSet<AttributeType> includeAttributes;
878        boolean includeAllUserAttributes = false;
879        boolean includeAllOperationalAttributes = false;
880        if (includeAttributeStrings == null)
881        {
882          includeAttributes = null;
883        }
884        else
885        {
886          includeAttributes = new HashSet<AttributeType>();
887          for (String attrName : includeAttributeStrings.getValues())
888          {
889            String        lowerName = attrName.toLowerCase();
890             if(lowerName.equals("*"))
891            {
892              includeAllUserAttributes = true;
893            }
894            else if(lowerName.equals("+"))
895            {
896              includeAllOperationalAttributes = true;
897            }
898            else
899            {
900              AttributeType attrType  = DirectoryServer.getAttributeType(lowerName);
901              if (attrType == null)
902              {
903                attrType = DirectoryServer.getDefaultAttributeType(attrName);
904              }
905    
906              includeAttributes.add(attrType);
907            }
908          }
909        }
910    
911        ArrayList<SearchFilter> excludeFilters;
912        if (excludeFilterStrings == null)
913        {
914          excludeFilters = null;
915        }
916        else
917        {
918          excludeFilters = new ArrayList<SearchFilter>();
919          for (String filterString : excludeFilterStrings.getValues())
920          {
921            try
922            {
923              excludeFilters.add(SearchFilter.createFilterFromString(filterString));
924            }
925            catch (DirectoryException de)
926            {
927              Message message = ERR_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER.get(
928                  filterString, de.getMessageObject());
929              logError(message);
930              return 1;
931            }
932            catch (Exception e)
933            {
934              Message message = ERR_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER.get(
935                  filterString, getExceptionMessage(e));
936              logError(message);
937              return 1;
938            }
939          }
940        }
941    
942        ArrayList<SearchFilter> includeFilters;
943        if (includeFilterStrings == null)
944        {
945          includeFilters = null;
946        }
947        else
948        {
949          includeFilters = new ArrayList<SearchFilter>();
950          for (String filterString : includeFilterStrings.getValues())
951          {
952            try
953            {
954              includeFilters.add(SearchFilter.createFilterFromString(filterString));
955            }
956            catch (DirectoryException de)
957            {
958              Message message = ERR_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER.get(
959                  filterString, de.getMessageObject());
960              logError(message);
961              return 1;
962            }
963            catch (Exception e)
964            {
965              Message message = ERR_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER.get(
966                  filterString, getExceptionMessage(e));
967              logError(message);
968              return 1;
969            }
970          }
971        }
972    
973    
974        // Get information about the backends defined in the server.  Iterate
975        // through them, finding the one backend into which the LDIF should be
976        // imported and finding backends with subordinate base DNs that should be
977        // excluded from the import.
978        Backend       backend           = null;
979        List<DN> defaultIncludeBranches = null;
980        List<DN> excludeBranches        = new ArrayList<DN>();
981        List<DN> includeBranches        = new ArrayList<DN>();
982    
983        if (includeBranchStrings.isPresent())
984        {
985          includeBranches = new ArrayList<DN>();
986          for (String s : includeBranchStrings.getValues())
987          {
988            DN includeBranch;
989            try
990            {
991              includeBranch = DN.decode(s);
992            }
993            catch (DirectoryException de)
994            {
995              Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
996                  s, de.getMessageObject());
997              logError(message);
998              return 1;
999            }
1000            catch (Exception e)
1001            {
1002              Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
1003                  s, getExceptionMessage(e));
1004              logError(message);
1005              return 1;
1006            }
1007    
1008            includeBranches.add(includeBranch);
1009          }
1010        }
1011    
1012        ArrayList<Backend>     backendList = new ArrayList<Backend>();
1013        ArrayList<BackendCfg>  entryList   = new ArrayList<BackendCfg>();
1014        ArrayList<List<DN>> dnList = new ArrayList<List<DN>>();
1015        int code = BackendToolUtils.getBackends(backendList, entryList, dnList);
1016        if (code != 0)
1017        {
1018          return code;
1019        }
1020    
1021        int numBackends = backendList.size();
1022        for (int i=0; i < numBackends; i++)
1023        {
1024          Backend b = backendList.get(i);
1025    
1026          if(backendID.isPresent())
1027          {
1028            if (! backendID.getValue().equals(b.getBackendID()))
1029            {
1030              continue;
1031            }
1032          }
1033          else
1034          {
1035            boolean useBackend = false;
1036            for(DN baseDN : dnList.get(i))
1037            {
1038              for(DN includeDN : includeBranches)
1039              {
1040                if(baseDN.isAncestorOf(includeDN))
1041                {
1042                  useBackend = true;
1043                  break;
1044                }
1045              }
1046              if(useBackend)
1047              {
1048                break;
1049              }
1050            }
1051            if(!useBackend)
1052            {
1053              continue;
1054            }
1055          }
1056    
1057          if (backend == null)
1058          {
1059            backend                = b;
1060            defaultIncludeBranches = dnList.get(i);
1061          }
1062          else
1063          {
1064            Message message = ERR_LDIFIMPORT_MULTIPLE_BACKENDS_FOR_ID.get();
1065            logError(message);
1066            return 1;
1067          }
1068        }
1069    
1070        if (backend == null)
1071        {
1072          Message message =
1073              ERR_LDIFIMPORT_NO_BACKENDS_FOR_ID.get();
1074          logError(message);
1075          return 1;
1076        }
1077        else if (! backend.supportsLDIFImport())
1078        {
1079          Message message = ERR_LDIFIMPORT_CANNOT_IMPORT.get(backendID.getValue());
1080          logError(message);
1081          return 1;
1082        }
1083    
1084        for (List<DN> baseList : dnList)
1085        {
1086          for (DN baseDN : baseList)
1087          {
1088            for (DN importBase : defaultIncludeBranches)
1089            {
1090              if (baseDN.isDescendantOf(importBase) &&
1091                  (! baseDN.equals(importBase)))
1092              {
1093                if (! excludeBranches.contains(baseDN))
1094                {
1095                  excludeBranches.add(baseDN);
1096                }
1097    
1098                break;
1099              }
1100            }
1101          }
1102        }
1103    
1104        // Make sure that if the "backendID" argument was provided, no include base
1105        // was included, and the "append" option was not provided, the
1106        // "clearBackend" argument was also provided if there are more then one
1107        // baseDNs for the backend being imported.
1108        if(backendID.isPresent() && !includeBranchStrings.isPresent() &&
1109            !append.isPresent() && defaultIncludeBranches.size() > 1 &&
1110            !clearBackend.isPresent())
1111        {
1112          StringBuilder builder = new StringBuilder();
1113          builder.append(backend.getBaseDNs()[0].toNormalizedString());
1114          for(int i = 1; i < backend.getBaseDNs().length; i++)
1115          {
1116            builder.append(" / ");
1117            builder.append(backend.getBaseDNs()[i].toNormalizedString());
1118          }
1119          Message message = ERR_LDIFIMPORT_MISSING_CLEAR_BACKEND.get(
1120                  builder.toString(), clearBackend.getLongIdentifier());
1121          err.println(wrapText(message, MAX_LINE_WIDTH));
1122          return 1;
1123        }
1124    
1125        for (String s : excludeBranchStrings.getValues())
1126        {
1127          DN excludeBranch;
1128          try
1129          {
1130            excludeBranch = DN.decode(s);
1131          }
1132          catch (DirectoryException de)
1133          {
1134            Message message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
1135                s, de.getMessageObject());
1136            logError(message);
1137            return 1;
1138          }
1139          catch (Exception e)
1140          {
1141            Message message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
1142                s, getExceptionMessage(e));
1143            logError(message);
1144            return 1;
1145          }
1146    
1147          if (! excludeBranches.contains(excludeBranch))
1148          {
1149            excludeBranches.add(excludeBranch);
1150          }
1151        }
1152    
1153        if (! includeBranchStrings.isPresent())
1154        {
1155          includeBranches = defaultIncludeBranches;
1156        }
1157        else
1158        {
1159          // Make sure the selected backend will handle all the include branches
1160          for(DN includeBranch : includeBranches)
1161          {
1162            if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches,
1163                                       excludeBranches))
1164            {
1165              Message message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
1166                  includeBranch.toNormalizedString(), backendID.getValue());
1167              logError(message);
1168              return 1;
1169            }
1170          }
1171        }
1172    
1173    
1174        // See if the data should be read from LDIF files or generated via MakeLDIF.
1175        LDIFImportConfig importConfig;
1176        if (ldifFiles.isPresent())
1177        {
1178          ArrayList<String> fileList = new ArrayList<String>(ldifFiles.getValues());
1179          int badFileCount = 0;
1180          for (String pathname : fileList)
1181          {
1182            File f = new File(pathname);
1183            if (!f.canRead())
1184            {
1185              Message message = ERR_LDIFIMPORT_CANNOT_READ_FILE.get(pathname);
1186              logError(message);
1187              badFileCount++;
1188            }
1189          }
1190          if (badFileCount > 0) return 1;
1191          importConfig = new LDIFImportConfig(fileList);
1192        }
1193        else
1194        {
1195          Random random;
1196          if (randomSeed.isPresent())
1197          {
1198            try
1199            {
1200              random = new Random(randomSeed.getIntValue());
1201            }
1202            catch (Exception e)
1203            {
1204              random = new Random();
1205            }
1206          }
1207          else
1208          {
1209            random = new Random();
1210          }
1211    
1212          String resourcePath = DirectoryServer.getServerRoot() + File.separator +
1213                                PATH_MAKELDIF_RESOURCE_DIR;
1214          TemplateFile tf = new TemplateFile(resourcePath, random);
1215    
1216          ArrayList<Message> warnings = new ArrayList<Message>();
1217          try
1218          {
1219            tf.parse(templateFile.getValue(), warnings);
1220          }
1221          catch (Exception e)
1222          {
1223            Message message = ERR_LDIFIMPORT_CANNOT_PARSE_TEMPLATE_FILE.get(
1224                templateFile.getValue(), e.getMessage());
1225            logError(message);
1226            return 1;
1227          }
1228    
1229          importConfig = new LDIFImportConfig(tf);
1230        }
1231    
1232    
1233    
1234        // Create the LDIF import configuration to use when reading the LDIF.
1235        importConfig.setAppendToExistingData(append.isPresent());
1236        importConfig.setReplaceExistingEntries(replaceExisting.isPresent());
1237        importConfig.setCompressed(isCompressed.isPresent());
1238        importConfig.setClearBackend(clearBackend.isPresent());
1239        importConfig.setEncrypted(isEncrypted.isPresent());
1240        importConfig.setExcludeAttributes(excludeAttributes);
1241        importConfig.setExcludeBranches(excludeBranches);
1242        importConfig.setExcludeFilters(excludeFilters);
1243        importConfig.setIncludeAttributes(includeAttributes);
1244        importConfig.setIncludeBranches(includeBranches);
1245        importConfig.setIncludeFilters(includeFilters);
1246        importConfig.setValidateSchema(!skipSchemaValidation.isPresent());
1247        importConfig.setBufferSize(LDIF_BUFFER_SIZE);
1248        importConfig.setExcludeAllUserAttributes(
1249                                         excludeAllUserAttributes);
1250        importConfig.setExcludeAllOperationalAttributes(
1251                                         excludeAllOperationalAttributes);
1252        importConfig.setIncludeAllOpAttributes(
1253                                          includeAllOperationalAttributes);
1254        importConfig.setIncludeAllUserAttributes(includeAllUserAttributes);
1255    
1256        // FIXME -- Should this be conditional?
1257        importConfig.setInvokeImportPlugins(true);
1258    
1259        if (rejectFile != null)
1260        {
1261          try
1262          {
1263            ExistingFileBehavior existingBehavior;
1264            if (overwrite.isPresent())
1265            {
1266              existingBehavior = ExistingFileBehavior.OVERWRITE;
1267            }
1268            else
1269            {
1270              existingBehavior = ExistingFileBehavior.APPEND;
1271            }
1272    
1273            importConfig.writeRejectedEntries(rejectFile.getValue(),
1274                                              existingBehavior);
1275          }
1276          catch (Exception e)
1277          {
1278            Message message = ERR_LDIFIMPORT_CANNOT_OPEN_REJECTS_FILE.get(
1279                rejectFile.getValue(), getExceptionMessage(e));
1280            logError(message);
1281            return 1;
1282          }
1283        }
1284    
1285        if (skipFile != null)
1286        {
1287          try
1288          {
1289            ExistingFileBehavior existingBehavior;
1290            if (overwrite.isPresent())
1291            {
1292              existingBehavior = ExistingFileBehavior.OVERWRITE;
1293            }
1294            else
1295            {
1296              existingBehavior = ExistingFileBehavior.APPEND;
1297            }
1298    
1299            importConfig.writeSkippedEntries(skipFile.getValue(),
1300                                              existingBehavior);
1301          }
1302          catch (Exception e)
1303          {
1304            Message message = ERR_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE.get(
1305                skipFile.getValue(), getExceptionMessage(e));
1306            logError(message);
1307            return 1;
1308          }
1309        }
1310    
1311        // Get the set of base DNs for the backend as an array.
1312        DN[] baseDNs = new DN[defaultIncludeBranches.size()];
1313        defaultIncludeBranches.toArray(baseDNs);
1314    
1315    
1316        // Acquire an exclusive lock for the backend.
1317        try
1318        {
1319          String lockFile = LockFileManager.getBackendLockFileName(backend);
1320          StringBuilder failureReason = new StringBuilder();
1321          if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
1322          {
1323            Message message = ERR_LDIFIMPORT_CANNOT_LOCK_BACKEND.get(
1324                backend.getBackendID(), String.valueOf(failureReason));
1325            logError(message);
1326            return 1;
1327          }
1328        }
1329        catch (Exception e)
1330        {
1331          Message message = ERR_LDIFIMPORT_CANNOT_LOCK_BACKEND.get(
1332              backend.getBackendID(), getExceptionMessage(e));
1333          logError(message);
1334          return 1;
1335        }
1336    
1337    
1338        // Launch the import.
1339        int retCode = 0;
1340        try
1341        {
1342          LDIFImportResult importResult = backend.importLDIF(importConfig);
1343          if (countRejects.isPresent())
1344          {
1345            if (importResult.getEntriesRejected() > Integer.MAX_VALUE)
1346            {
1347              retCode = Integer.MAX_VALUE;
1348            }
1349            else
1350            {
1351              retCode = (int) importResult.getEntriesRejected();
1352            }
1353          }
1354        }
1355        catch (DirectoryException de)
1356        {
1357          Message message =
1358              ERR_LDIFIMPORT_ERROR_DURING_IMPORT.get(de.getMessageObject());
1359          logError(message);
1360          retCode = 1;
1361        }
1362        catch (Exception e)
1363        {
1364          Message message =
1365              ERR_LDIFIMPORT_ERROR_DURING_IMPORT.get(getExceptionMessage(e));
1366          logError(message);
1367          retCode = 1;
1368        }
1369    
1370    
1371        // Release the exclusive lock on the backend.
1372        try
1373        {
1374          String lockFile = LockFileManager.getBackendLockFileName(backend);
1375          StringBuilder failureReason = new StringBuilder();
1376          if (! LockFileManager.releaseLock(lockFile, failureReason))
1377          {
1378            Message message = WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND.get(
1379                backend.getBackendID(), String.valueOf(failureReason));
1380            logError(message);
1381            retCode = 1;
1382          }
1383        }
1384        catch (Exception e)
1385        {
1386          Message message = WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND.get(
1387              backend.getBackendID(), getExceptionMessage(e));
1388          logError(message);
1389          retCode = 1;
1390        }
1391    
1392    
1393        // Clean up after the import by closing the import config.
1394        importConfig.close();
1395        return retCode;
1396      }
1397    }
1398