From 975c043fb68244888e4f4b08583b4704dc3c9076 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 21 Jun 2011 20:52:08 +0000
Subject: [PATCH] Partial fix for OPENDJ-205: Add support for rejecting and skipping records to the LDIF readers

---
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java |  105 ++++++++++++++++++++++++++++++++--------------------
 1 files changed, 65 insertions(+), 40 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
index 6a891c1..5f13925 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
+ *      Portions copyright 2011 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldif;
@@ -34,6 +35,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.NoSuchElementException;
 
@@ -361,6 +363,25 @@
 
 
   /**
+   * Sets the rejected record listener which should be notified whenever a
+   * record is skipped, malformed, or fails schema validation.
+   * <p>
+   * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used.
+   *
+   * @param listener
+   *          The rejected record listener.
+   * @return A reference to this {@code LDIFEntryReader}.
+   */
+  public LDIFEntryReader setRejectedRecordListener(
+      final RejectedRecordListener listener)
+  {
+    this.rejectedRecordListener = listener;
+    return this;
+  }
+
+
+
+  /**
    * Sets the schema which should be used for decoding entries that are read
    * from LDIF. The default schema is used if no other is specified.
    *
@@ -372,7 +393,8 @@
   public LDIFEntryReader setSchema(final Schema schema)
   {
     Validator.ensureNotNull(schema);
-    this.schema = schema;
+    this.schema = validateSchema ? schema.asStrictSchema() : schema
+        .asNonStrictSchema();
     return this;
   }
 
@@ -380,7 +402,12 @@
 
   /**
    * Specifies whether or not schema validation should be performed for entries
-   * that are read from LDIF. The default is {@code true}.
+   * that are read from LDIF.
+   * <p>
+   * When enabled, this LDIF reader will implicitly use a strict schema so that
+   * unrecognized attribute types will be detected.
+   * <p>
+   * Schema validation is disabled by default.
    *
    * @param validateSchema
    *          {@code true} if schema validation should be performed, or
@@ -390,6 +417,8 @@
   public LDIFEntryReader setValidateSchema(final boolean validateSchema)
   {
     this.validateSchema = validateSchema;
+    this.schema = validateSchema ? schema.asStrictSchema() : schema
+        .asNonStrictSchema();
     return this;
   }
 
@@ -399,69 +428,65 @@
   {
     while (nextEntry == null)
     {
-      LDIFRecord record = null;
-
       // Read the set of lines that make up the next entry.
-      record = readLDIFRecord();
+      final LDIFRecord record = readLDIFRecord();
       if (record == null)
       {
         nextEntry = EOF;
         break;
       }
 
-      // Read the DN of the entry and see if it is one that should be
-      // included in the import.
-      DN entryDN;
       try
       {
-        entryDN = readLDIFRecordDN(record);
+        // Read the DN of the entry and see if it is one that should be
+        // included in the import.
+        final DN entryDN = readLDIFRecordDN(record);
         if (entryDN == null)
         {
           // Skip version record.
           continue;
         }
-      }
-      catch (final DecodeException e)
-      {
-        rejectLDIFRecord(record, e.getMessageObject());
-        continue;
-      }
 
-      // Skip if branch containing the entry DN is excluded.
-      if (isBranchExcluded(entryDN))
-      {
-        final LocalizableMessage message = LocalizableMessage
-            .raw("Skipping entry because it is in excluded branch");
-        skipLDIFRecord(record, message);
-        continue;
-      }
+        // Skip if branch containing the entry DN is excluded.
+        if (isBranchExcluded(entryDN))
+        {
+          final LocalizableMessage message = ERR_LDIF_ENTRY_EXCLUDED_BY_DN.get(
+              record.lineNumber, entryDN.toString());
+          handleSkippedRecord(record, message);
+          continue;
+        }
 
-      // Use an Entry for the AttributeSequence.
-      final Entry entry = new LinkedHashMapEntry(entryDN);
-      try
-      {
+        // Use an Entry for the AttributeSequence.
+        final Entry entry = new LinkedHashMapEntry(entryDN);
+        final List<LocalizableMessage> schemaErrors = new LinkedList<LocalizableMessage>();
         while (record.iterator.hasNext())
         {
           final String ldifLine = record.iterator.next();
-          readLDIFRecordAttributeValue(record, ldifLine, entry);
+          readLDIFRecordAttributeValue(record, ldifLine, entry, schemaErrors);
         }
+
+        // Skip if the entry is excluded by any filters.
+        if (isEntryExcluded(entry))
+        {
+          final LocalizableMessage message = ERR_LDIF_ENTRY_EXCLUDED_BY_FILTER
+              .get(record.lineNumber, entryDN.toString());
+          handleSkippedRecord(record, message);
+          continue;
+        }
+
+        if (!schemaErrors.isEmpty())
+        {
+          handleSchemaValidationFailure(record, schemaErrors);
+          continue;
+        }
+
+        nextEntry = entry;
       }
       catch (final DecodeException e)
       {
-        rejectLDIFRecord(record, e.getMessageObject());
+        handleMalformedRecord(record, e.getMessageObject());
         continue;
       }
-
-      // Skip if the entry is excluded by any filters.
-      if (isEntryExcluded(entry))
-      {
-        final LocalizableMessage message = LocalizableMessage
-            .raw("Skipping entry due to exclusing filters");
-        skipLDIFRecord(record, message);
-        continue;
-      }
-
-      nextEntry = entry;
     }
 
     return nextEntry;

--
Gitblit v1.10.0