From 9c1e151ca2da620abfb0ed4864665c48f53e1efd Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 12 Dec 2011 17:33:59 +0000
Subject: [PATCH] Additional fixes for OPENDJ-381: Implement LDIF diff, patch, and search API support in the SDK
---
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java | 8
/dev/null | 233 --------------
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java | 51 +-
opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java | 20
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java | 275 +++++++++++++++++
opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java | 44 +
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java | 247 ++++++++++++++
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java | 10
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java | 6
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java | 2
opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java | 53 +++
11 files changed, 646 insertions(+), 303 deletions(-)
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
index 1176c4e..2cfc0d6 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
@@ -374,12 +374,18 @@
/**
* Returns a DN which is an immediate child of this DN and having the
* specified RDN.
+ * <p>
+ * <b>Note:</b> the child DN whose RDN is {@link RDN#maxValue()} compares
+ * greater than all other possible child DNs, and may be used to construct
+ * range queries against DN keyed sorted collections such as {@code SortedSet}
+ * and {@code SortedMap}.
*
* @param rdn
* The RDN for the child DN.
* @return The child DN.
* @throws NullPointerException
* If {@code rdn} was {@code null}.
+ * @see RDN#maxValue()
*/
public DN child(final RDN rdn) throws NullPointerException
{
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java
index 957528f..9e52acc 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS.
*/
package org.forgerock.opendj.ldap;
@@ -75,6 +76,38 @@
*/
public final class RDN implements Iterable<AVA>, Comparable<RDN>
{
+
+ // A constant holding a special RDN having zero AVAs and which always compares
+ // greater than any other RDN other than itself.
+ private static final RDN MAX_VALUE = new RDN(new AVA[0], "");
+
+
+
+ /**
+ * Returns a constant containing a special RDN which is greater than any other
+ * RDN other than itself. This RDN may be used in order to perform range
+ * queries on DN keyed collections such as {@code SortedSet}s and
+ * {@code SortedMap}s. For example, the following code can be used to
+ * construct a range whose contents is a sub-tree of entries:
+ *
+ * <pre>
+ * SortedMap<DN, Entry> entries = ...;
+ * DN baseDN = ...;
+ *
+ * // Returns a map containing the baseDN and all of its subordinates.
+ * SortedMap<DN,Entry> subtree = entries.subMap(baseDN, baseDN.child(RDN.maxValue));
+ * </pre>
+ *
+ * @return A constant containing a special RDN which is greater than any other
+ * RDN other than itself.
+ */
+ public static RDN maxValue()
+ {
+ return MAX_VALUE;
+ }
+
+
+
/**
* Parses the provided LDAP string representation of an RDN using the default
* schema.
@@ -235,14 +268,32 @@
*/
public int compareTo(final RDN rdn)
{
+ // Identity.
+ if (this == rdn)
+ {
+ return 0;
+ }
+
+ // MAX_VALUE is always greater than any other RDN other than itself.
+ if (this == MAX_VALUE)
+ {
+ return 1;
+ }
+
+ if (rdn == MAX_VALUE)
+ {
+ return -1;
+ }
+
+ // Compare number of AVAs first as this is quick and easy.
final int sz1 = avas.length;
final int sz2 = rdn.avas.length;
-
if (sz1 != sz2)
{
return sz1 - sz2 > 0 ? 1 : -1;
}
+ // Fast path for common case.
if (sz1 == 1)
{
return avas[0].compareTo(rdn.avas[0]);
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
index 7b8b0e7..36e2270 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
@@ -230,7 +230,7 @@
- RejectedRecordListener rejectedRecordListener = RejectedRecordListener.FAIL_FAST;
+ RejectedLDIFListener rejectedRecordListener = RejectedLDIFListener.FAIL_FAST;
Schema schema = Schema.getDefaultSchema().asNonStrictSchema();
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
index d3061ec..17d8b4d 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
@@ -28,11 +28,18 @@
+import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_DELETE;
+import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFY;
+import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFYDN;
+
import java.io.IOException;
import java.util.*;
import org.forgerock.opendj.ldap.*;
+import org.forgerock.opendj.ldap.controls.SubtreeDeleteRequestControl;
import org.forgerock.opendj.ldap.requests.*;
+import org.forgerock.opendj.ldap.schema.AttributeUsage;
+import org.forgerock.opendj.ldap.schema.Schema;
@@ -66,7 +73,7 @@
* @throws IOException
* If an unexpected IO error occurred.
*/
- public static final ChangeRecordWriter copyTo(final ChangeRecordReader input,
+ public static ChangeRecordWriter copyTo(final ChangeRecordReader input,
final ChangeRecordWriter output) throws IOException
{
while (input.hasNext())
@@ -90,7 +97,7 @@
* @throws IOException
* If an unexpected IO error occurred.
*/
- public static final EntryWriter copyTo(final EntryReader input,
+ public static EntryWriter copyTo(final EntryReader input,
final EntryWriter output) throws IOException
{
while (input.hasNext())
@@ -278,7 +285,7 @@
public static EntryReader patch(final EntryReader input,
final ChangeRecordReader patch) throws IOException
{
- return patch(input, patch, RejectedChangeListener.OVERWRITE);
+ return patch(input, patch, RejectedChangeRecordListener.OVERWRITE);
}
@@ -305,8 +312,8 @@
* If an unexpected IO error occurred.
*/
public static EntryReader patch(final EntryReader input,
- final ChangeRecordReader patch, final RejectedChangeListener listener)
- throws IOException
+ final ChangeRecordReader patch,
+ final RejectedChangeRecordListener listener) throws IOException
{
final SortedMap<DN, Entry> entries = readEntries(input);
@@ -353,7 +360,9 @@
{
try
{
- listener.handleMissingEntry(change);
+ listener.handleRejectedChangeRecord(change,
+ REJECTED_CHANGE_FAIL_DELETE.get(change.getName()
+ .toString()));
}
catch (final DecodeException e)
{
@@ -362,7 +371,24 @@
}
else
{
- entries.remove(change.getName());
+ try
+ {
+ if (change.getControl(SubtreeDeleteRequestControl.DECODER,
+ new DecodeOptions()) != null)
+ {
+ entries.subMap(change.getName(),
+ change.getName().child(RDN.maxValue())).clear();
+ }
+ else
+ {
+ entries.remove(change.getName());
+ }
+ }
+ catch (final DecodeException e)
+ {
+ return e;
+ }
+
}
return null;
}
@@ -377,7 +403,9 @@
{
try
{
- listener.handleMissingEntry(change);
+ listener.handleRejectedChangeRecord(change,
+ REJECTED_CHANGE_FAIL_MODIFYDN.get(change.getName()
+ .toString()));
}
catch (final DecodeException e)
{
@@ -404,7 +432,9 @@
// avoid cases where the renamed subtree overlaps.
final SortedMap<DN, Entry> renamedEntries = new TreeMap<DN, Entry>();
final Iterator<Map.Entry<DN, Entry>> i = entries
- .tailMap(change.getName()).entrySet().iterator();
+ .subMap(change.getName(),
+ change.getName().child(RDN.maxValue())).entrySet()
+ .iterator();
while (i.hasNext())
{
final Map.Entry<DN, Entry> e = i.next();
@@ -466,7 +496,9 @@
{
try
{
- listener.handleMissingEntry(change);
+ listener.handleRejectedChangeRecord(change,
+ REJECTED_CHANGE_FAIL_MODIFY.get(change.getName()
+ .toString()));
}
catch (final DecodeException e)
{
@@ -551,6 +583,201 @@
+ /**
+ * Returns a filtered view of {@code input} containing only those entries
+ * which match the search base DN, scope, and filtered defined in
+ * {@code search}. In addition, returned entries will be filtered according to
+ * any attribute filtering criteria defined in the search request.
+ * <p>
+ * The filter and attribute descriptions will be decoded using the default
+ * schema.
+ *
+ * @param input
+ * The entry reader containing the set of entries to be filtered.
+ * @param search
+ * The search request defining the filtering criteria.
+ * @return A filtered view of {@code input} containing only those entries
+ * which match the provided search request.
+ */
+ public static EntryReader search(final EntryReader input,
+ final SearchRequest search)
+ {
+ return search(input, search, Schema.getDefaultSchema());
+ }
+
+
+
+ /**
+ * Returns a filtered view of {@code input} containing only those entries
+ * which match the search base DN, scope, and filtered defined in
+ * {@code search}. In addition, returned entries will be filtered according to
+ * any attribute filtering criteria defined in the search request.
+ * <p>
+ * The filter and attribute descriptions will be decoded using the provided
+ * schema.
+ *
+ * @param input
+ * The entry reader containing the set of entries to be filtered.
+ * @param search
+ * The search request defining the filtering criteria.
+ * @param schema
+ * The schema which should be used to decode the search filter and
+ * attribute descriptions.
+ * @return A filtered view of {@code input} containing only those entries
+ * which match the provided search request.
+ */
+ public static EntryReader search(final EntryReader input,
+ final SearchRequest search, final Schema schema)
+ {
+ final Matcher matcher = search.getFilter().matcher(schema);
+
+ return new EntryReader()
+ {
+ private Entry nextEntry = null;
+ private int entryCount = 0;
+
+
+
+ public void close() throws IOException
+ {
+ input.close();
+ }
+
+
+
+ public boolean hasNext() throws IOException
+ {
+ if (nextEntry == null)
+ {
+ final int sizeLimit = search.getSizeLimit();
+ if (sizeLimit == 0 || entryCount < sizeLimit)
+ {
+ final DN baseDN = search.getName();
+ final SearchScope scope = search.getScope();
+ while (input.hasNext())
+ {
+ final Entry entry = input.readEntry();
+ if (entry.getName().isInScopeOf(baseDN, scope)
+ && matcher.matches(entry).toBoolean())
+ {
+ nextEntry = filterEntry(entry);
+ break;
+ }
+ }
+ }
+ }
+ return nextEntry != null;
+ }
+
+
+
+ public Entry readEntry() throws IOException, NoSuchElementException
+ {
+ if (hasNext())
+ {
+ final Entry entry = nextEntry;
+ nextEntry = null;
+ entryCount++;
+ return entry;
+ }
+ else
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+
+
+ private Entry filterEntry(final Entry entry)
+ {
+ // TODO: rename attributes; move functionality to Entries.
+ if (search.getAttributes().isEmpty())
+ {
+ if (search.isTypesOnly())
+ {
+ final Entry filteredEntry = new LinkedHashMapEntry(entry.getName());
+ for (final Attribute attribute : entry.getAllAttributes())
+ {
+ filteredEntry.addAttribute(Attributes.emptyAttribute(attribute
+ .getAttributeDescription()));
+ }
+ return filteredEntry;
+ }
+ else
+ {
+ return entry;
+ }
+ }
+ else
+ {
+ final Entry filteredEntry = new LinkedHashMapEntry(entry.getName());
+ for (final String atd : search.getAttributes())
+ {
+ if (atd.equals("*"))
+ {
+ for (final Attribute attribute : entry.getAllAttributes())
+ {
+ if (attribute.getAttributeDescription().getAttributeType()
+ .getUsage() == AttributeUsage.USER_APPLICATIONS)
+ {
+ if (search.isTypesOnly())
+ {
+ filteredEntry.addAttribute(Attributes
+ .emptyAttribute(attribute.getAttributeDescription()));
+ }
+ else
+ {
+ filteredEntry.addAttribute(attribute);
+ }
+ }
+ }
+ }
+ else if (atd.equals("+"))
+ {
+ for (final Attribute attribute : entry.getAllAttributes())
+ {
+ if (attribute.getAttributeDescription().getAttributeType()
+ .getUsage() != AttributeUsage.USER_APPLICATIONS)
+ {
+ if (search.isTypesOnly())
+ {
+ filteredEntry.addAttribute(Attributes
+ .emptyAttribute(attribute.getAttributeDescription()));
+ }
+ else
+ {
+ filteredEntry.addAttribute(attribute);
+ }
+ }
+ }
+ }
+ else
+ {
+ final AttributeDescription ad = AttributeDescription.valueOf(atd,
+ schema);
+ for (final Attribute attribute : entry.getAllAttributes(ad))
+ {
+ if (search.isTypesOnly())
+ {
+ filteredEntry.addAttribute(Attributes
+ .emptyAttribute(attribute.getAttributeDescription()));
+ }
+ else
+ {
+ filteredEntry.addAttribute(attribute);
+ }
+ }
+ }
+ }
+ return filteredEntry;
+ }
+ }
+
+ };
+ }
+
+
+
private static SortedMap<DN, Entry> readEntries(final EntryReader reader)
throws IOException
{
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
index c8498ad..1807e90 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
@@ -336,17 +336,17 @@
/**
- * Sets the rejected record listener which should be notified whenever a
+ * Sets the rejected record listener which should be notified whenever an LDIF
* record is skipped, malformed, or fails schema validation.
* <p>
- * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used.
+ * By default the {@link RejectedLDIFListener#FAIL_FAST} listener is used.
*
* @param listener
* The rejected record listener.
* @return A reference to this {@code LDIFChangeRecordReader}.
*/
- public LDIFChangeRecordReader setRejectedRecordListener(
- final RejectedRecordListener listener)
+ public LDIFChangeRecordReader setRejectedLDIFListener(
+ final RejectedLDIFListener listener)
{
this.rejectedRecordListener = listener;
return this;
@@ -623,7 +623,7 @@
case WARN:
schemaErrors.add(message);
continue;
- default: //Ignore
+ default: // Ignore
// This should not happen: we should be using a non-strict schema for
// this policy.
throw new IllegalStateException(
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
index 5e15fb0..3772797 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
@@ -364,17 +364,17 @@
/**
- * Sets the rejected record listener which should be notified whenever a
+ * Sets the rejected record listener which should be notified whenever an LDIF
* record is skipped, malformed, or fails schema validation.
* <p>
- * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used.
+ * By default the {@link RejectedLDIFListener#FAIL_FAST} listener is used.
*
* @param listener
* The rejected record listener.
* @return A reference to this {@code LDIFEntryReader}.
*/
- public LDIFEntryReader setRejectedRecordListener(
- final RejectedRecordListener listener)
+ public LDIFEntryReader setRejectedLDIFListener(
+ final RejectedLDIFListener listener)
{
this.rejectedRecordListener = listener;
return this;
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeListener.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeListener.java
deleted file mode 100644
index 856230f..0000000
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeListener.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opendj3/legal-notices/CDDLv1_0.txt
- * or http://forgerock.org/license/CDDLv1.0.html.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opendj3/legal-notices/CDDLv1_0.txt. If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- * Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright 2011 ForgeRock AS
- */
-
-package org.forgerock.opendj.ldif;
-
-
-
-import static org.forgerock.opendj.ldap.CoreMessages.*;
-
-import org.forgerock.opendj.ldap.DecodeException;
-import org.forgerock.opendj.ldap.Entry;
-import org.forgerock.opendj.ldap.requests.AddRequest;
-import org.forgerock.opendj.ldap.requests.DeleteRequest;
-import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
-import org.forgerock.opendj.ldap.requests.ModifyRequest;
-
-
-
-/**
- * A listener interface which is notified whenever a change record cannot be
- * applied to an entry. This may occur when an attempt is made to update a
- * non-existent entry, or add an entry which already exists.
- * <p>
- * By default the {@link #FAIL_FAST} listener is used.
- */
-public interface RejectedChangeListener
-{
- /**
- * A handler which terminates processing by throwing a {@code DecodeException}
- * as soon as a change is rejected.
- */
- public final static RejectedChangeListener FAIL_FAST = new RejectedChangeListener()
- {
-
- @Override
- public Entry handleDuplicateEntry(final AddRequest change,
- final Entry existingEntry) throws DecodeException
- {
- throw DecodeException.error(REJECTED_CHANGE_FAIL_ADD_DUPE.get(change
- .getName().toString()));
- }
-
-
-
- @Override
- public Entry handleDuplicateEntry(final ModifyDNRequest change,
- final Entry existingEntry, final Entry renamedEntry)
- throws DecodeException
- {
- throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN_DUPE
- .get(renamedEntry.getName().toString()));
- }
-
-
-
- @Override
- public void handleMissingEntry(final DeleteRequest change)
- throws DecodeException
- {
- throw DecodeException.error(REJECTED_CHANGE_FAIL_DELETE.get(change
- .getName().toString()));
- }
-
-
-
- @Override
- public void handleMissingEntry(final ModifyDNRequest change)
- throws DecodeException
- {
- throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN.get(change
- .getName().toString()));
- }
-
-
-
- @Override
- public void handleMissingEntry(final ModifyRequest change)
- throws DecodeException
- {
- throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFY.get(change
- .getName().toString()));
- }
- };
-
- /**
- * The default handler which ignores changes applied to missing entries and
- * tolerates duplicate entries by overwriting the existing entry with the new
- * entry.
- */
- public final static RejectedChangeListener OVERWRITE = new RejectedChangeListener()
- {
-
- @Override
- public Entry handleDuplicateEntry(final AddRequest change,
- final Entry existingEntry) throws DecodeException
- {
- // Overwrite existing entries.
- return change;
- }
-
-
-
- @Override
- public Entry handleDuplicateEntry(final ModifyDNRequest change,
- final Entry existingEntry, final Entry renamedEntry)
- throws DecodeException
- {
- // Overwrite existing entries.
- return renamedEntry;
- }
-
-
-
- @Override
- public void handleMissingEntry(final DeleteRequest change)
- throws DecodeException
- {
- // Ignore changes applied to missing entries.
- }
-
-
-
- @Override
- public void handleMissingEntry(final ModifyDNRequest change)
- throws DecodeException
- {
- // Ignore changes applied to missing entries.
- }
-
-
-
- @Override
- public void handleMissingEntry(final ModifyRequest change)
- throws DecodeException
- {
- // Ignore changes applied to missing entries.
- }
- };
-
-
-
- /**
- * Invoked when an attempt was made to add an entry which already exists.
- *
- * @param change
- * The conflicting add request.
- * @param existingEntry
- * The pre-existing entry.
- * @return The entry which should be kept.
- * @throws DecodeException
- * If processing should terminate.
- */
- Entry handleDuplicateEntry(AddRequest change, Entry existingEntry)
- throws DecodeException;
-
-
-
- /**
- * Invoked when an attempt was made to rename an entry which already exists.
- *
- * @param change
- * The conflicting add request.
- * @param existingEntry
- * The pre-existing entry.
- * @param renamedEntry
- * The renamed entry.
- * @return The entry which should be kept.
- * @throws DecodeException
- * If processing should terminate.
- */
- Entry handleDuplicateEntry(ModifyDNRequest change, Entry existingEntry,
- Entry renamedEntry) throws DecodeException;
-
-
-
- /**
- * Invoked when an attempt was made to delete an entry which does not exist.
- *
- * @param change
- * The conflicting delete request.
- * @throws DecodeException
- * If processing should terminate.
- */
- void handleMissingEntry(DeleteRequest change) throws DecodeException;
-
-
-
- /**
- * Invoked when an attempt was made to rename an entry which does not exist.
- *
- * @param change
- * The conflicting rename request.
- * @throws DecodeException
- * If processing should terminate.
- */
- void handleMissingEntry(ModifyDNRequest change) throws DecodeException;
-
-
-
- /**
- * Invoked when an attempt was made to modify an entry which does not exist.
- *
- * @param change
- * The conflicting modify request.
- * @throws DecodeException
- * If processing should terminate.
- */
- void handleMissingEntry(ModifyRequest change) throws DecodeException;
-
-}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java
new file mode 100644
index 0000000..62d9b2a
--- /dev/null
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java
@@ -0,0 +1,275 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opendj3/legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opendj3/legal-notices/CDDLv1_0.txt. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2011 ForgeRock AS
+ */
+
+package org.forgerock.opendj.ldif;
+
+
+
+import static org.forgerock.opendj.ldap.CoreMessages.*;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.requests.AddRequest;
+import org.forgerock.opendj.ldap.requests.DeleteRequest;
+import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
+import org.forgerock.opendj.ldap.requests.ModifyRequest;
+
+
+
+/**
+ * A listener interface which is notified whenever a change record cannot be
+ * applied to an entry. This may occur when an attempt is made to update a
+ * non-existent entry, or add an entry which already exists.
+ * <p>
+ * By default the {@link #FAIL_FAST} listener is used.
+ */
+public interface RejectedChangeRecordListener
+{
+ /**
+ * A handler which terminates processing by throwing a {@code DecodeException}
+ * as soon as a change is rejected.
+ */
+ public final static RejectedChangeRecordListener FAIL_FAST = new RejectedChangeRecordListener()
+ {
+
+ public Entry handleDuplicateEntry(final AddRequest change,
+ final Entry existingEntry) throws DecodeException
+ {
+ throw DecodeException.error(REJECTED_CHANGE_FAIL_ADD_DUPE.get(change
+ .getName().toString()));
+ }
+
+
+
+ public Entry handleDuplicateEntry(final ModifyDNRequest change,
+ final Entry existingEntry, final Entry renamedEntry)
+ throws DecodeException
+ {
+ throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN_DUPE
+ .get(renamedEntry.getName().toString()));
+ }
+
+
+
+ public void handleRejectedChangeRecord(final AddRequest change,
+ final LocalizableMessage reason) throws DecodeException
+ {
+ throw DecodeException.error(reason);
+ }
+
+
+
+ public void handleRejectedChangeRecord(final DeleteRequest change,
+ final LocalizableMessage reason) throws DecodeException
+ {
+ throw DecodeException.error(reason);
+ }
+
+
+
+ public void handleRejectedChangeRecord(final ModifyRequest change,
+ final LocalizableMessage reason) throws DecodeException
+ {
+ throw DecodeException.error(reason);
+ }
+
+
+
+ public void handleRejectedChangeRecord(final ModifyDNRequest change,
+ final LocalizableMessage reason) throws DecodeException
+ {
+ throw DecodeException.error(reason);
+ }
+
+ };
+
+ /**
+ * The default handler which ignores changes applied to missing entries and
+ * tolerates duplicate entries by overwriting the existing entry with the new
+ * entry.
+ */
+ public final static RejectedChangeRecordListener OVERWRITE = new RejectedChangeRecordListener()
+ {
+
+ public Entry handleDuplicateEntry(final AddRequest change,
+ final Entry existingEntry) throws DecodeException
+ {
+ // Overwrite existing entries.
+ return change;
+ }
+
+
+
+ public Entry handleDuplicateEntry(final ModifyDNRequest change,
+ final Entry existingEntry, final Entry renamedEntry)
+ throws DecodeException
+ {
+ // Overwrite existing entries.
+ return renamedEntry;
+ }
+
+
+
+ public void handleRejectedChangeRecord(AddRequest change,
+ LocalizableMessage reason) throws DecodeException
+ {
+ // Ignore.
+ }
+
+
+
+ public void handleRejectedChangeRecord(DeleteRequest change,
+ LocalizableMessage reason) throws DecodeException
+ {
+ // Ignore.
+ }
+
+
+
+ public void handleRejectedChangeRecord(ModifyRequest change,
+ LocalizableMessage reason) throws DecodeException
+ {
+ // Ignore.
+ }
+
+
+
+ public void handleRejectedChangeRecord(ModifyDNRequest change,
+ LocalizableMessage reason) throws DecodeException
+ {
+ // Ignore.
+ }
+
+ };
+
+
+
+ /**
+ * Invoked when an attempt was made to add an entry which already exists.
+ *
+ * @param change
+ * The conflicting add request.
+ * @param existingEntry
+ * The pre-existing entry.
+ * @return The entry which should be kept.
+ * @throws DecodeException
+ * If processing should terminate.
+ */
+ Entry handleDuplicateEntry(AddRequest change, Entry existingEntry)
+ throws DecodeException;
+
+
+
+ /**
+ * Invoked when an attempt was made to rename an entry which already exists.
+ *
+ * @param change
+ * The conflicting add request.
+ * @param existingEntry
+ * The pre-existing entry.
+ * @param renamedEntry
+ * The renamed entry.
+ * @return The entry which should be kept.
+ * @throws DecodeException
+ * If processing should terminate.
+ */
+ Entry handleDuplicateEntry(ModifyDNRequest change, Entry existingEntry,
+ Entry renamedEntry) throws DecodeException;
+
+
+
+ /**
+ * Invoked when an attempt to add an entry was rejected. This may be because
+ * the target parent entry was not found, or controls provided with the
+ * request are not supported. This method will not be called when the entry to
+ * be added already exists, since this is handled by
+ * {@link #handleDuplicateEntry(AddRequest, Entry)}.
+ *
+ * @param change
+ * The rejected add request.
+ * @param reason
+ * The reason why the record was rejected.
+ * @throws DecodeException
+ * If processing should terminate.
+ */
+ void handleRejectedChangeRecord(AddRequest change, LocalizableMessage reason)
+ throws DecodeException;
+
+
+
+ /**
+ * Invoked when an attempt to delete an entry was rejected. This may be
+ * because the target entry was not found, or controls provided with the
+ * request are not supported.
+ *
+ * @param change
+ * The rejected delete request.
+ * @param reason
+ * The reason why the record was rejected.
+ * @throws DecodeException
+ * If processing should terminate.
+ */
+ void handleRejectedChangeRecord(DeleteRequest change,
+ LocalizableMessage reason) throws DecodeException;
+
+
+
+ /**
+ * Invoked when an attempt to modify an entry was rejected. This may be
+ * because the target entry was not found, or controls provided with the
+ * request are not supported.
+ *
+ * @param change
+ * The rejected modify request.
+ * @param reason
+ * The reason why the record was rejected.
+ * @throws DecodeException
+ * If processing should terminate.
+ */
+ void handleRejectedChangeRecord(ModifyRequest change,
+ LocalizableMessage reason) throws DecodeException;
+
+
+
+ /**
+ * Invoked when an attempt to rename an entry was rejected. This may be
+ * because the target entry was not found, or controls provided with the
+ * request are not supported. This method will not be called when a renamed
+ * entry already exists, since this is handled by
+ * {@link #handleDuplicateEntry(ModifyDNRequest, Entry, Entry)}.
+ *
+ * @param change
+ * The rejected modify DN request.
+ * @param reason
+ * The reason why the record was rejected.
+ * @throws DecodeException
+ * If processing should terminate.
+ */
+ void handleRejectedChangeRecord(ModifyDNRequest change,
+ LocalizableMessage reason) throws DecodeException;
+
+}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedRecordListener.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
similarity index 77%
rename from opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedRecordListener.java
rename to opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
index 157a4d1..0be1187 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedRecordListener.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
@@ -36,24 +36,24 @@
/**
- * A listener interface which is notified whenever records are skipped,
+ * A listener interface which is notified whenever LDIF records are skipped,
* malformed, or fail schema validation.
* <p>
* By default the {@link #FAIL_FAST} listener is used.
*/
-public interface RejectedRecordListener
+public interface RejectedLDIFListener
{
/**
* The default handler which ignores skipped records but which terminates
* processing by throwing a {@code DecodeException} as soon as a record is
* found to be malformed or rejected due to a schema validation failure.
*/
- public static final RejectedRecordListener FAIL_FAST = new RejectedRecordListener()
+ public static final RejectedLDIFListener FAIL_FAST = new RejectedLDIFListener()
{
@Override
public void handleMalformedRecord(final long lineNumber,
- final List<String> ldifRecord, final LocalizableMessage reason)
+ final List<String> lines, final LocalizableMessage reason)
throws DecodeException
{
// Fail fast.
@@ -64,7 +64,7 @@
@Override
public void handleSchemaValidationFailure(final long lineNumber,
- final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+ final List<String> lines, final List<LocalizableMessage> reasons)
throws DecodeException
{
// Fail fast - just use first message.
@@ -75,7 +75,7 @@
@Override
public void handleSchemaValidationWarning(final long lineNumber,
- final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+ final List<String> lines, final List<LocalizableMessage> reasons)
throws DecodeException
{
// Ignore schema validation warnings.
@@ -85,7 +85,7 @@
@Override
public void handleSkippedRecord(final long lineNumber,
- final List<String> ldifRecord, final LocalizableMessage reason)
+ final List<String> lines, final LocalizableMessage reason)
throws DecodeException
{
// Ignore skipped records.
@@ -95,12 +95,12 @@
/**
* A handler which ignores all rejected record notifications.
*/
- public static final RejectedRecordListener IGNORE_ALL = new RejectedRecordListener()
+ public static final RejectedLDIFListener IGNORE_ALL = new RejectedLDIFListener()
{
@Override
public void handleMalformedRecord(final long lineNumber,
- final List<String> ldifRecord, final LocalizableMessage reason)
+ final List<String> lines, final LocalizableMessage reason)
throws DecodeException
{
// Ignore malformed records.
@@ -110,7 +110,7 @@
@Override
public void handleSchemaValidationFailure(final long lineNumber,
- final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+ final List<String> lines, final List<LocalizableMessage> reasons)
throws DecodeException
{
// Ignore schema validation failures.
@@ -120,7 +120,7 @@
@Override
public void handleSchemaValidationWarning(final long lineNumber,
- final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+ final List<String> lines, final List<LocalizableMessage> reasons)
throws DecodeException
{
// Ignore schema validation warnings.
@@ -130,7 +130,7 @@
@Override
public void handleSkippedRecord(final long lineNumber,
- final List<String> ldifRecord, final LocalizableMessage reason)
+ final List<String> lines, final LocalizableMessage reason)
throws DecodeException
{
// Ignore skipped records.
@@ -146,14 +146,14 @@
* @param lineNumber
* The line number within the source location in which the malformed
* record is located, if known, otherwise {@code -1}.
- * @param ldifRecord
- * An LDIF representation of the malformed record.
+ * @param lines
+ * The content of the malformed record.
* @param reason
* The reason why the record is malformed.
* @throws DecodeException
* If processing should terminate.
*/
- void handleMalformedRecord(long lineNumber, List<String> ldifRecord,
+ void handleMalformedRecord(long lineNumber, List<String> lines,
LocalizableMessage reason) throws DecodeException;
@@ -165,15 +165,14 @@
* @param lineNumber
* The line number within the source location in which the rejected
* record is located, if known, otherwise {@code -1}.
- * @param ldifRecord
- * An LDIF representation of the record which failed schema
- * validation.
+ * @param lines
+ * The content of the record which failed schema validation.
* @param reasons
* The reasons why the record failed schema validation.
* @throws DecodeException
* If processing should terminate.
*/
- void handleSchemaValidationFailure(long lineNumber, List<String> ldifRecord,
+ void handleSchemaValidationFailure(long lineNumber, List<String> lines,
List<LocalizableMessage> reasons) throws DecodeException;
@@ -185,15 +184,15 @@
* @param lineNumber
* The line number within the source location in which the record is
* located, if known, otherwise {@code -1}.
- * @param ldifRecord
- * An LDIF representation of the record which contained schema
- * validation warnings.
+ * @param lines
+ * The content of the record which contained schema validation
+ * warnings.
* @param reasons
* The schema validation warnings.
* @throws DecodeException
* If processing should terminate.
*/
- void handleSchemaValidationWarning(long lineNumber, List<String> ldifRecord,
+ void handleSchemaValidationWarning(long lineNumber, List<String> lines,
List<LocalizableMessage> reasons) throws DecodeException;
@@ -205,14 +204,14 @@
* @param lineNumber
* The line number within the source location in which the skipped
* record is located, if known, otherwise {@code -1}.
- * @param ldifRecord
- * An LDIF representation of the skipped record.
+ * @param lines
+ * The content of the record which was skipped.
* @param reason
* The reason why the record was skipped.
* @throws DecodeException
* If processing should terminate.
*/
- void handleSkippedRecord(long lineNumber, List<String> ldifRecord,
+ void handleSkippedRecord(long lineNumber, List<String> lines,
LocalizableMessage reason) throws DecodeException;
}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
index f589f31..27a5e6d 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS.
*/
package org.forgerock.opendj.ldap;
@@ -149,6 +150,7 @@
@DataProvider(name = "createRDNEqualityData")
public Object[][] createRDNEqualityData()
{
+ // @formatter:off
return new Object[][] {
{ "cn=hello world", "cn=hello world", 0 },
{ "cn=hello world", "CN=hello world", 0 },
@@ -168,10 +170,19 @@
// { "x-test-integer-type=999", "x-test-integer-type=1000", -1 },
// { "x-test-integer-type=-1", "x-test-integer-type=0", -1 },
// { "x-test-integer-type=0", "x-test-integer-type=-1", 1 },
- { "cn=aaa", "cn=aaaa", -1 }, { "cn=AAA", "cn=aaaa", -1 },
- { "cn=aaa", "cn=AAAA", -1 }, { "cn=aaaa", "cn=aaa", 1 },
- { "cn=AAAA", "cn=aaa", 1 }, { "cn=aaaa", "cn=AAA", 1 },
- { "cn=aaab", "cn=aaaa", 1 }, { "cn=aaaa", "cn=aaab", -1 } };
+ { "cn=aaa", "cn=aaaa", -1 },
+ { "cn=AAA", "cn=aaaa", -1 },
+ { "cn=aaa", "cn=AAAA", -1 },
+ { "cn=aaaa", "cn=aaa", 1 },
+ { "cn=AAAA", "cn=aaa", 1 },
+ { "cn=aaaa", "cn=AAA", 1 },
+ { "cn=aaab", "cn=aaaa", 1 },
+ { "cn=aaaa", "cn=aaab", -1 },
+ { RDN.maxValue(), RDN.maxValue(), 0 },
+ { RDN.maxValue(), "cn=aaa", 1 },
+ { "cn=aaa", RDN.maxValue(), -1 },
+ };
+ // @formatter:on
}
@@ -206,11 +217,11 @@
* If the test failed unexpectedly.
*/
@Test(dataProvider = "createRDNEqualityData")
- public void testCompareTo(final String first, final String second,
+ public void testCompareTo(final Object first, final Object second,
final int result) throws Exception
{
- final RDN rdn1 = RDN.valueOf(first);
- final RDN rdn2 = RDN.valueOf(second);
+ final RDN rdn1 = parseRDN(first);
+ final RDN rdn2 = parseRDN(second);
int rc = rdn1.compareTo(rdn2);
@@ -230,6 +241,13 @@
+ private RDN parseRDN(final Object value)
+ {
+ return (value instanceof RDN) ? ((RDN) value) : RDN.valueOf(value.toString());
+ }
+
+
+
/**
* Test RDN construction with single AVA.
*
@@ -362,11 +380,11 @@
* If the test failed unexpectedly.
*/
@Test(dataProvider = "createRDNEqualityData")
- public void testEquality(final String first, final String second,
+ public void testEquality(final Object first, final Object second,
final int result) throws Exception
{
- final RDN rdn1 = RDN.valueOf(first);
- final RDN rdn2 = RDN.valueOf(second);
+ final RDN rdn1 = parseRDN(first);
+ final RDN rdn2 = parseRDN(second);
if (result == 0)
{
@@ -448,11 +466,11 @@
* If the test failed unexpectedly.
*/
@Test(dataProvider = "createRDNEqualityData")
- public void testHashCode(final String first, final String second,
+ public void testHashCode(final Object first, final Object second,
final int result) throws Exception
{
- final RDN rdn1 = RDN.valueOf(first);
- final RDN rdn2 = RDN.valueOf(second);
+ final RDN rdn1 = parseRDN(first);
+ final RDN rdn2 = parseRDN(second);
final int h1 = rdn1.hashCode();
final int h2 = rdn2.hashCode();
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
index 99a99c4..91fe962 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
@@ -342,7 +342,7 @@
@Test
public void testRejectedRecordListenerMalformedFirstRecord() throws Exception
{
- RejectedRecordListener listener = mock(RejectedRecordListener.class);
+ RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
// @formatter:off
LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -351,7 +351,7 @@
"objectClass: top",
"objectClass: domainComponent",
"dc: example"
- ).setRejectedRecordListener(listener);
+ ).setRejectedLDIFListener(listener);
// @formatter:on
assertThat(reader.hasNext()).isFalse();
@@ -375,7 +375,7 @@
public void testRejectedRecordListenerMalformedSecondRecord()
throws Exception
{
- RejectedRecordListener listener = mock(RejectedRecordListener.class);
+ RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
// @formatter:off
LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -390,7 +390,7 @@
"objectClass: top",
"objectClass: domainComponent",
"dc: example"
- ).setRejectedRecordListener(listener);
+ ).setRejectedLDIFListener(listener);
// @formatter:on
reader.readChangeRecord(); // Skip good record.
@@ -414,7 +414,7 @@
@Test
public void testRejectedRecordListenerSkipsRecord() throws Exception
{
- RejectedRecordListener listener = mock(RejectedRecordListener.class);
+ RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
// @formatter:off
LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -423,7 +423,7 @@
"objectClass: top",
"objectClass: domainComponent",
"dc: example"
- ).setRejectedRecordListener(listener).setExcludeBranch(DN.valueOf("dc=com"));
+ ).setRejectedLDIFListener(listener).setExcludeBranch(DN.valueOf("dc=com"));
// @formatter:on
assertThat(reader.hasNext()).isFalse();
@@ -449,7 +449,7 @@
public void testRejectedRecordListenerRejectsBadSchemaRecord()
throws Exception
{
- RejectedRecordListener listener = mock(RejectedRecordListener.class);
+ RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
// @formatter:off
LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -459,7 +459,7 @@
"objectClass: domainComponent",
"dc: example",
"xxx: unknown attribute"
- ).setRejectedRecordListener(listener)
+ ).setRejectedLDIFListener(listener)
.setSchemaValidationPolicy(
SchemaValidationPolicy.ignoreAll()
.checkAttributesAndObjectClasses(Policy.REJECT));
@@ -487,7 +487,7 @@
public void testRejectedRecordListenerWarnsBadSchemaRecord()
throws Exception
{
- RejectedRecordListener listener = mock(RejectedRecordListener.class);
+ RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
// @formatter:off
LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -497,7 +497,7 @@
"objectClass: domainComponent",
"dc: example",
"xxx: unknown attribute"
- ).setRejectedRecordListener(listener)
+ ).setRejectedLDIFListener(listener)
.setSchemaValidationPolicy(
SchemaValidationPolicy.ignoreAll()
.checkAttributesAndObjectClasses(Policy.WARN));
--
Gitblit v1.10.0