From 9a8d97c273430b8eb0ab9afc4209f555321da4e8 Mon Sep 17 00:00:00 2001
From: jarnou <jarnou@localhost>
Date: Mon, 09 Jul 2007 16:13:16 +0000
Subject: [PATCH] Bug: 1428 Synopsis: import-ldif could allow to write skipped entries to a specified file

---
 opends/src/server/org/opends/server/messages/ToolMessages.java                              |   29 +++
 opends/src/server/org/opends/server/messages/UtilityMessages.java                           |   32 +++
 opends/src/server/org/opends/server/util/LDIFReader.java                                    |   65 +++++++-
 opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java |   66 ++++++++
 opends/src/server/org/opends/server/types/LDIFImportConfig.java                             |  124 +++++++++++++++
 opends/src/server/org/opends/server/tasks/ImportTask.java                                   |   46 ++++
 opends/src/server/org/opends/server/config/ConfigConstants.java                             |   15 +
 opends/src/server/org/opends/server/tools/ImportLDIF.java                                   |   47 +++++
 8 files changed, 392 insertions(+), 32 deletions(-)

diff --git a/opends/src/server/org/opends/server/config/ConfigConstants.java b/opends/src/server/org/opends/server/config/ConfigConstants.java
index 09ad9cf..ba2e5c2 100644
--- a/opends/src/server/org/opends/server/config/ConfigConstants.java
+++ b/opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -3749,17 +3749,24 @@
        NAME_PREFIX_TASK + "import-reject-file";
 
 
+  /**
+   * The name of the attribute in an import task definition that specifies
+   * the path to a file into which skipped entries may be written if they
+   * do not match criteria during the import process.
+   */
+  public static final String ATTR_IMPORT_SKIP_FILE =
+       NAME_PREFIX_TASK + "import-skip-file";
+
 
   /**
    * The name of the attribute in an import task definition that specifies
-   * whether to overwrite an existing rejects file when performing an LDIF
-   * import rather than appending to it.
+   * whether to overwrite an existing rejects and/or skip file when performing
+   * an LDIF import rather than appending to it.
    */
-  public static final String ATTR_IMPORT_OVERWRITE_REJECTS =
+  public static final String ATTR_IMPORT_OVERWRITE =
        NAME_PREFIX_TASK + "import-overwrite-rejects";
 
 
-
   /**
    * The name of the attribute in an import task definition that specifies
    * whether to skip schema validation during the import.
diff --git a/opends/src/server/org/opends/server/messages/ToolMessages.java b/opends/src/server/org/opends/server/messages/ToolMessages.java
index 0e309be..9b3992a 100644
--- a/opends/src/server/org/opends/server/messages/ToolMessages.java
+++ b/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -687,7 +687,7 @@
    * The message ID for the message that will be used as the description of the
    * overwriteRejects argument.  This does not take any arguments.
    */
-  public static final int MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE_REJECTS =
+  public static final int MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE =
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 79;
 
 
@@ -8999,6 +8999,22 @@
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1196;
 
 
+  /**
+   * The message ID for the message that will be used as the description of the
+   * skipFile argument.  This does not take any arguments.
+   */
+  public static final int MSGID_LDIFIMPORT_DESCRIPTION_SKIP_FILE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1197;
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs while
+   * trying to open the skip file.  This takes two arguments, which are the
+   * path to the skip file and a string representation of the exception that
+   * was caught.
+   */
+  public static final int MSGID_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1198;
 
   /**
    * Associates a set of generic messages with the message IDs defined in this
@@ -9245,9 +9261,14 @@
                     "import");
     registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_REJECT_FILE,
                     "Write rejected entries to the specified file");
-    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE_REJECTS,
-                    "Overwrite an existing rejects file rather than " +
-                    "appending to it");
+    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_SKIP_FILE,
+                    "Write skipped entries to the specified file");
+    registerMessage(MSGID_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE,
+                    "An error occurred while trying to open the skip " +
+                    "file %s for writing:  %s");
+    registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE,
+                    "Overwrite an existing rejects and/or skip file " +
+                    "rather than appending to it");
     registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_RANDOM_SEED,
                     "Seed for the MakeLDIF random number generator");
     registerMessage(MSGID_LDIFIMPORT_DESCRIPTION_SKIP_SCHEMA_VALIDATION,
diff --git a/opends/src/server/org/opends/server/messages/UtilityMessages.java b/opends/src/server/org/opends/server/messages/UtilityMessages.java
index 20f612e..81c0768 100644
--- a/opends/src/server/org/opends/server/messages/UtilityMessages.java
+++ b/opends/src/server/org/opends/server/messages/UtilityMessages.java
@@ -1667,8 +1667,6 @@
   public static final int MSGID_RENAMEFILE_CANNOT_DELETE_TARGET =
        CATEGORY_MASK_UTIL | SEVERITY_MASK_SEVERE_ERROR | 158;
 
-
-
   /**
    * The message ID for the message that will be used if a client certificate is
    * rejected because it is expired.  This takes two arguments, which are the
@@ -1727,6 +1725,28 @@
 
 
   /**
+   * The message ID for the message that will be used if an attempt is made to
+   * write a skip file but the specified file already exists.  This takes a
+   * single argument, which is the name of the file.
+   */
+  public static final int MSGID_SKIP_FILE_EXISTS =
+       CATEGORY_MASK_UTIL | SEVERITY_MASK_SEVERE_ERROR | 164;
+
+
+  /**
+   * The message ID for the message that will be used if an attempt is made to
+   * read an LDIF entry, but that entry does not match the criteria.
+   * This takes three arguments, which are the DN of the entry,
+   * the starting line number for the entry, and a message that explains why
+   * it does not match the criteria.
+   */
+  public static final int MSGID_LDIF_SKIP =
+       CATEGORY_MASK_UTIL | SEVERITY_MASK_MILD_ERROR | 165;
+
+
+
+
+  /**
    * Associates a set of generic messages with the message IDs defined in this
    * class.
    */
@@ -1812,6 +1832,10 @@
                     "Entry %s read from LDIF starting at line %d is not " +
                     "valid because it violates the server's schema " +
                     "configuration:  %s");
+    registerMessage(MSGID_LDIF_SKIP,
+                    "Skipping entry %s because the DN is not one that " +
+                    "should be included based on the include and " +
+                    "exclude branches");
     registerMessage(MSGID_LDIF_FILE_EXISTS,
                     "The specified LDIF file %s already exists and the " +
                     "export configuration indicates that no attempt should " +
@@ -1829,6 +1853,10 @@
                     "The specified reject file %s already exists and the " +
                     "import configuration indicates that no attempt should " +
                     "be made to append to or replace the file");
+    registerMessage(MSGID_SKIP_FILE_EXISTS,
+                    "The specified skip file %s already exists and the " +
+                    "import configuration indicates that no attempt should " +
+                    "be made to append to or replace the file");
     registerMessage(MSGID_LDIF_COULD_NOT_EVALUATE_FILTERS_FOR_IMPORT,
                     "An error occurred while attempting to determine whether " +
                     "LDIF entry \"%s\" starting at line %d should be " +
diff --git a/opends/src/server/org/opends/server/tasks/ImportTask.java b/opends/src/server/org/opends/server/tasks/ImportTask.java
index c1a0891..217677b 100644
--- a/opends/src/server/org/opends/server/tasks/ImportTask.java
+++ b/opends/src/server/org/opends/server/tasks/ImportTask.java
@@ -77,11 +77,12 @@
   boolean append                  = false;
   boolean isCompressed            = false;
   boolean isEncrypted             = false;
-  boolean overwriteRejects        = false;
+  boolean overwrite               = false;
   boolean replaceExisting         = false;
   boolean skipSchemaValidation    = false;
   String  backendID               = null;
   String  rejectFile              = null;
+  String  skipFile                = null;
   ArrayList<String>  excludeAttributeStrings = null;
   ArrayList<String>  excludeBranchStrings    = null;
   ArrayList<String>  excludeFilterStrings    = null;
@@ -126,7 +127,8 @@
     AttributeType typeIncludeFilter;
     AttributeType typeExcludeFilter;
     AttributeType typeRejectFile;
-    AttributeType typeOverwriteRejects;
+    AttributeType typeSkipFile;
+    AttributeType typeOverwrite;
     AttributeType typeSkipSchemaValidation;
     AttributeType typeIsCompressed;
     AttributeType typeIsEncrypted;
@@ -153,8 +155,10 @@
          getAttributeType(ATTR_IMPORT_EXCLUDE_FILTER, true);
     typeRejectFile =
          getAttributeType(ATTR_IMPORT_REJECT_FILE, true);
-    typeOverwriteRejects =
-         getAttributeType(ATTR_IMPORT_OVERWRITE_REJECTS, true);
+    typeSkipFile =
+      getAttributeType(ATTR_IMPORT_SKIP_FILE, true);
+    typeOverwrite =
+         getAttributeType(ATTR_IMPORT_OVERWRITE, true);
     typeSkipSchemaValidation =
          getAttributeType(ATTR_IMPORT_SKIP_SCHEMA_VALIDATION, true);
     typeIsCompressed =
@@ -197,8 +201,11 @@
     attrList = taskEntry.getAttribute(typeRejectFile);
     rejectFile = TaskUtils.getSingleValueString(attrList);
 
-    attrList = taskEntry.getAttribute(typeOverwriteRejects);
-    overwriteRejects = TaskUtils.getBoolean(attrList, false);
+    attrList = taskEntry.getAttribute(typeSkipFile);
+    skipFile = TaskUtils.getSingleValueString(attrList);
+
+    attrList = taskEntry.getAttribute(typeOverwrite);
+    overwrite = TaskUtils.getBoolean(attrList, false);
 
     attrList = taskEntry.getAttribute(typeSkipSchemaValidation);
     skipSchemaValidation = TaskUtils.getBoolean(attrList, false);
@@ -444,7 +451,7 @@
       try
       {
         ExistingFileBehavior existingBehavior;
-        if (overwriteRejects)
+        if (overwrite)
         {
           existingBehavior = ExistingFileBehavior.OVERWRITE;
         }
@@ -465,6 +472,31 @@
       }
     }
 
+    if (skipFile != null)
+    {
+      try
+      {
+        ExistingFileBehavior existingBehavior;
+        if (overwrite)
+        {
+          existingBehavior = ExistingFileBehavior.OVERWRITE;
+        }
+        else
+        {
+          existingBehavior = ExistingFileBehavior.APPEND;
+        }
+
+        importConfig.writeRejectedEntries(skipFile, existingBehavior);
+      }
+      catch (Exception e)
+      {
+        int    msgID   = MSGID_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE;
+        String message = getMessage(msgID, skipFile, getExceptionMessage(e));
+        logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
+                 message, msgID);
+        return TaskState.STOPPED_BY_ERROR;
+      }
+    }
 
     // Get the set of base DNs for the backend as an array.
     DN[] baseDNs = new DN[defaultIncludeBranches.size()];
diff --git a/opends/src/server/org/opends/server/tools/ImportLDIF.java b/opends/src/server/org/opends/server/tools/ImportLDIF.java
index 8611970..400dbf2 100644
--- a/opends/src/server/org/opends/server/tools/ImportLDIF.java
+++ b/opends/src/server/org/opends/server/tools/ImportLDIF.java
@@ -139,7 +139,7 @@
     BooleanArgument displayUsage            = null;
     BooleanArgument isCompressed            = null;
     BooleanArgument isEncrypted             = null;
-    BooleanArgument overwriteRejects        = null;
+    BooleanArgument overwrite               = null;
     BooleanArgument quietMode               = null;
     BooleanArgument replaceExisting         = null;
     BooleanArgument skipSchemaValidation    = null;
@@ -155,6 +155,7 @@
     StringArgument  includeFilterStrings    = null;
     StringArgument  ldifFiles               = null;
     StringArgument  rejectFile              = null;
+    StringArgument  skipFile                = null;
     StringArgument  templateFile            = null;
 
 
@@ -270,10 +271,17 @@
       argParser.addArgument(rejectFile);
 
 
-      overwriteRejects =
-           new BooleanArgument("overwriterejects", 'O', "overwriteRejects",
-                               MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE_REJECTS);
-      argParser.addArgument(overwriteRejects);
+      skipFile =
+           new StringArgument("skipfile", 'K', "skipFile", false, false,
+                              true, "{skipFile}", null, null,
+                              MSGID_LDIFIMPORT_DESCRIPTION_SKIP_FILE);
+      argParser.addArgument(skipFile);
+
+
+      overwrite =
+           new BooleanArgument("overwrite", 'O', "overwrite",
+                               MSGID_LDIFIMPORT_DESCRIPTION_OVERWRITE);
+      argParser.addArgument(overwrite);
 
 
       randomSeed =
@@ -971,7 +979,7 @@
       try
       {
         ExistingFileBehavior existingBehavior;
-        if (overwriteRejects.isPresent())
+        if (overwrite.isPresent())
         {
           existingBehavior = ExistingFileBehavior.OVERWRITE;
         }
@@ -994,6 +1002,33 @@
       }
     }
 
+    if (skipFile != null)
+    {
+      try
+      {
+        ExistingFileBehavior existingBehavior;
+        if (overwrite.isPresent())
+        {
+          existingBehavior = ExistingFileBehavior.OVERWRITE;
+        }
+        else
+        {
+          existingBehavior = ExistingFileBehavior.APPEND;
+        }
+
+        importConfig.writeSkippedEntries(skipFile.getValue(),
+                                          existingBehavior);
+      }
+      catch (Exception e)
+      {
+        int    msgID   = MSGID_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE;
+        String message = getMessage(msgID, skipFile.getValue(),
+                                    getExceptionMessage(e));
+        logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
+                 message, msgID);
+        return 1;
+      }
+    }
 
     // Get the set of base DNs for the backend as an array.
     DN[] baseDNs = new DN[defaultIncludeBranches.size()];
diff --git a/opends/src/server/org/opends/server/types/LDIFImportConfig.java b/opends/src/server/org/opends/server/types/LDIFImportConfig.java
index 4741e56..a5976cd 100644
--- a/opends/src/server/org/opends/server/types/LDIFImportConfig.java
+++ b/opends/src/server/org/opends/server/types/LDIFImportConfig.java
@@ -109,6 +109,9 @@
   // The buffered writer to which rejected entries should be written.
   private BufferedWriter rejectWriter;
 
+  // The buffered writer to which rejected entries should be written.
+  private BufferedWriter skipWriter;
+
   // The input stream to use to read the data to import.
   private InputStream ldifInputStream;
 
@@ -184,6 +187,7 @@
     validateSchema         = true;
     reader                 = null;
     rejectWriter           = null;
+    skipWriter             = null;
     excludeAttributes      = new HashSet<AttributeType>();
     includeAttributes      = new HashSet<AttributeType>();
     includeAllUserAttrs    = false;
@@ -223,6 +227,7 @@
     validateSchema         = true;
     reader                 = null;
     rejectWriter           = null;
+    skipWriter             = null;
     excludeAttributes      = new HashSet<AttributeType>();
     includeAttributes      = new HashSet<AttributeType>();
     includeAllUserAttrs    = false;
@@ -260,6 +265,7 @@
     isEncrypted            = false;
     reader                 = null;
     rejectWriter           = null;
+    skipWriter             = null;
     excludeAttributes      = new HashSet<AttributeType>();
     includeAttributes      = new HashSet<AttributeType>();
     includeAllUserAttrs    = false;
@@ -295,6 +301,7 @@
     isEncrypted            = false;
     reader                 = getBufferedReader(ldifInputReader);
     rejectWriter           = null;
+    skipWriter             = null;
     excludeAttributes      = new HashSet<AttributeType>();
     includeAttributes      = new HashSet<AttributeType>();
     includeAllUserAttrs    = false;
@@ -437,7 +444,17 @@
     return rejectWriter;
   }
 
-
+  /**
+   * Retrieves the writer that should be used to write entries that
+   * are skipped because they don't match the criteri.
+   *
+   * @return  The skip writer, or <CODE>null</CODE> if none is to be
+   *          used.
+   */
+  public BufferedWriter getSkipWriter()
+  {
+    return skipWriter;
+  }
 
   /**
    * Indicates that rejected entries should be written to the
@@ -533,7 +550,97 @@
          new BufferedWriter(new OutputStreamWriter(outputStream));
   }
 
+  /**
+   * Indicates that skipped entries should be written to the
+   * specified file.  Note that this applies only to entries that are
+   * skipped because they matched exclude criteria.
+   *
+   * @param  skipFile              The path to the file to which
+   *                               skipped information should be
+   *                               written.
+   * @param  existingFileBehavior  Indicates how to treat an existing
+   *                               file.
+   *
+   * @throws  IOException  If a problem occurs while opening the
+   *                       skip file for writing.
+   */
+  public void writeSkippedEntries(String skipFile,
+                   ExistingFileBehavior existingFileBehavior)
+         throws IOException
+  {
+    if (skipFile == null)
+    {
+      if (skipWriter != null)
+      {
+        try
+        {
+          skipWriter.close();
+        } catch (Exception e) {}
 
+        skipWriter = null;
+      }
+
+      return;
+    }
+
+    switch (existingFileBehavior)
+    {
+      case APPEND:
+        skipWriter =
+             new BufferedWriter(new FileWriter(skipFile, true));
+        break;
+      case OVERWRITE:
+        skipWriter =
+             new BufferedWriter(new FileWriter(skipFile, false));
+        break;
+      case FAIL:
+        File f = new File(skipFile);
+        if (f.exists())
+        {
+          throw new IOException(getMessage(MSGID_SKIP_FILE_EXISTS,
+                                           skipFile));
+        }
+        else
+        {
+          skipWriter =
+               new BufferedWriter(new FileWriter(skipFile));
+        }
+        break;
+    }
+  }
+
+
+
+  /**
+   * Indicates that skipped entries should be written to the provided
+   * output stream.  Note that this does not apply to entries that are
+   * rejected because they are invalid (e.g., are malformed or don't
+   * conform to schema requirements), but only apply to entries that
+   * are skipped because they matched exclude criteria.
+   *
+   * @param  outputStream  The output stream to which skipped entries
+   *                       should be written.
+   */
+  public void writeSkippedEntries(OutputStream outputStream)
+  {
+    if (outputStream == null)
+    {
+      if (skipWriter != null)
+      {
+        try
+        {
+          skipWriter.close();
+        } catch (Exception e) {}
+
+        skipWriter = null;
+      }
+
+      return;
+    }
+
+    skipWriter =
+         new BufferedWriter(new OutputStreamWriter(outputStream));
+  }
 
   /**
    * Indicates whether to append to an existing data set or completely
@@ -1221,6 +1328,21 @@
         }
       }
     }
+
+    if (skipWriter != null)
+    {
+      try
+      {
+        skipWriter.close();
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          TRACER.debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+    }
   }
 }
 
diff --git a/opends/src/server/org/opends/server/util/LDIFReader.java b/opends/src/server/org/opends/server/util/LDIFReader.java
index 75c5b72..91268dc 100644
--- a/opends/src/server/org/opends/server/util/LDIFReader.java
+++ b/opends/src/server/org/opends/server/util/LDIFReader.java
@@ -224,6 +224,10 @@
                     entryDN);
         }
         entriesRead++;
+        int    msgID   = MSGID_LDIF_SKIP;
+        String message = getMessage(msgID, String.valueOf(entryDN),
+            lastEntryLineNumber);
+        logToSkipWriter(lines, message);
         entriesIgnored++;
         continue;
       }
@@ -269,6 +273,10 @@
                 "that should be included based on the include and exclude " +
                 "filters.", entryDN);
           }
+          int    msgID   = MSGID_LDIF_SKIP;
+          String message = getMessage(msgID, String.valueOf(entryDN),
+              lastEntryLineNumber);
+          logToSkipWriter(lines, message);
           entriesIgnored++;
           continue;
         }
@@ -294,6 +302,10 @@
              pluginConfigManager.invokeLDIFImportPlugins(importConfig, entry);
         if (! pluginResult.continueEntryProcessing())
         {
+          int    msgID   = MSGID_LDIF_SKIP;
+          String message = getMessage(msgID, String.valueOf(entryDN),
+              lastEntryLineNumber);
+          logToSkipWriter(lines, message);
           entriesIgnored++;
           continue;
         }
@@ -1738,8 +1750,6 @@
     return value;
   }
 
-
-
   /**
    * Log a message to the reject writer if one is configured.
    *
@@ -1754,18 +1764,56 @@
     BufferedWriter rejectWriter = importConfig.getRejectWriter();
     if (rejectWriter != null)
     {
+      logToWriter(rejectWriter, lines, message);
+    }
+  }
+
+  /**
+   * Log a message to the reject writer if one is configured.
+   *
+   * @param lines
+   *          The set of rejected lines.
+   * @param message
+   *          The associated error message.
+   */
+  private void logToSkipWriter(LinkedList<StringBuilder> lines,
+      String message) {
+
+    BufferedWriter skipWriter = importConfig.getSkipWriter();
+    if (skipWriter != null)
+    {
+      logToWriter(skipWriter, lines, message);
+    }
+  }
+
+  /**
+   * Log a message to the given writer.
+   *
+   * @param writer
+   *          The writer to write to.
+   * @param lines
+   *          The set of rejected lines.
+   * @param message
+   *          The associated error message.
+   */
+  private void logToWriter(BufferedWriter writer,
+      LinkedList<StringBuilder> lines,
+      String message)
+  {
+    if (writer != null)
+    {
       try
       {
-        rejectWriter.write("# ");
-        rejectWriter.write(message);
-        rejectWriter.newLine();
+        writer.write("# ");
+        writer.write(message);
+        writer.newLine();
         for (StringBuilder sb : lines)
         {
-          rejectWriter.write(sb.toString());
-          rejectWriter.newLine();
+          writer.write(sb.toString());
+          writer.newLine();
         }
 
-        rejectWriter.newLine();
+        writer.newLine();
       }
       catch (Exception e)
       {
@@ -1776,5 +1824,6 @@
       }
     }
   }
+
 }
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java
index cda9633..ba2e511 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java
@@ -197,6 +197,36 @@
       "postalAddress: Annalee Avard$43221 Hill Street$Charleston, CO  60918\n" +
       "description: This is the description for Annalee Bogard.\n";
 
+  private String skippedEntries =
+    "dn: dc=skipped,dc=importtest1,dc=com\n" +
+    "objectclass: top\n" +
+    "objectclass: domain\n" +
+    "dc: skipped\n" +
+    "\n" +
+    "dn: uid=user.446,dc=skipped,dc=importtest1,dc=com\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "objectClass: organizationalPerson\n" +
+    "objectClass: inetOrgPerson\n" +
+    "givenName: Annalee\n" +
+    "sn: Bogard\n" +
+    "cn: Annalee Bogard\n" +
+    "initials: ANG\n" +
+    "employeeNumber: 446\n" +
+    "uid: user.446\n" +
+    "mail: user.446@example.com\n" +
+    "userPassword: password\n" +
+    "telephoneNumber: 875-335-8882\n" +
+    "homePhone: 181-995-6635\n" +
+    "pager: 586-905-4185\n" +
+    "mobile: 826-857-7592\n" +
+    "street: 43221 Hill Street\n" +
+    "l: Charleston\n" +
+    "st: CO\n" +
+    "postalCode: 60918\n" +
+    "postalAddress: Annalee Avard$43221 Hill Street$Charleston, CO  60918\n" +
+    "description: This is the description for Annalee Bogard.\n";
+  
 
   @BeforeClass
   public void setUp() throws Exception
@@ -231,6 +261,12 @@
     writer.close();
     ldifFile.close();
 
+    ldifFile = new FileOutputStream(homeDirName + File.separator + "skipped.ldif");
+    writer = new PrintStream(ldifFile);
+
+    writer.println(skippedEntries);
+    writer.close();
+    ldifFile.close();
 
     baseDNs = new DN[]
     {
@@ -255,11 +291,13 @@
     fileList.add(homeDirName + File.separator + "entries1.ldif");
 
     ByteArrayOutputStream rejectedEntries = new ByteArrayOutputStream();
+    ByteArrayOutputStream skippedEntries = new ByteArrayOutputStream();
     LDIFImportConfig importConfig = new LDIFImportConfig(fileList);
     importConfig.setAppendToExistingData(false);
     importConfig.setReplaceExistingEntries(false);
     importConfig.setValidateSchema(true);
     importConfig.writeRejectedEntries(rejectedEntries);
+    importConfig.writeSkippedEntries(skippedEntries);
 
     be=(BackendImpl) DirectoryServer.getBackend(beID);
     TaskUtils.disableBackend(beID);
@@ -277,6 +315,7 @@
     EntryContainer entryContainer;
 
     assertTrue(rejectedEntries.size() <= 0);
+    assertTrue(skippedEntries.size() <= 0);
     for(DN baseDN : baseDNs)
     {
       entryContainer = rootContainer.getEntryContainer(baseDN);
@@ -495,6 +534,33 @@
     assertTrue(rejectedEntries.toString().contains("uid=user.446,dc=importtest1,dc=com"));
   }
 
+  @Test(dependsOnMethods = "testImportAll")
+  public void testImportSkip() throws Exception
+  {
+    ArrayList<DN> excludeBranches = new ArrayList<DN>();
+    excludeBranches.add(DN.decode("dc=skipped,dc=importtest1,dc=com"));
+    ByteArrayOutputStream skippedEntries = new ByteArrayOutputStream();
+    LDIFImportConfig importConfig = new LDIFImportConfig(homeDirName + File.separator + "skipped.ldif");
+    importConfig.setAppendToExistingData(false);
+    importConfig.setReplaceExistingEntries(true);
+    importConfig.setValidateSchema(true);
+    importConfig.setExcludeBranches(excludeBranches);
+    importConfig.writeSkippedEntries(skippedEntries);
+
+    be=(BackendImpl) DirectoryServer.getBackend(beID);
+    TaskUtils.disableBackend(beID);
+    try
+    {
+      be.importLDIF(importConfig);
+    }
+    finally
+    {
+      TaskUtils.enableBackend(beID);
+    }
+    assertTrue(skippedEntries.toString().contains("dc=skipped,dc=importtest1,dc=com"));
+    assertTrue(skippedEntries.toString().contains("uid=user.446,dc=skipped,dc=importtest1,dc=com"));
+  }
+  
       /**
      * Builds an entry suitable for using in the verify job to gather statistics about
      * the verify.

--
Gitblit v1.10.0