From 702b6351ed3207102d0bf4a152f45cf74452eeb3 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
---
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java | 247 +++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 237 insertions(+), 10 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
index d3061ec..17d8b4d 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
+++ b/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
{
--
Gitblit v1.10.0