From aa8dbe8ce1729e268d6bcf7503d172365e7c2705 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 02 Apr 2013 11:04:11 +0000
Subject: [PATCH] Additional change for OPENDJ-354: Implement a RequestHandler which provides an in-memory backend
---
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java | 12 ++++
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/Iterables.java | 72 ++++++++++++-----------
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java | 4
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java | 42 +++++++++++--
4 files changed, 85 insertions(+), 45 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/Iterables.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/Iterables.java
index c5102b9..1d4cf19 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/Iterables.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/Iterables.java
@@ -22,6 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
+ * Portions copyright 2013 ForgeRock AS.
*/
package com.forgerock.opendj.util;
@@ -34,8 +35,14 @@
* Utility methods for manipulating {@link Iterable}s.
*/
public final class Iterables {
- private static final class ArrayIterable<M> implements Iterable<M> {
+ private static abstract class AbstractIterable<M> implements Iterable<M> {
+ @Override
+ public String toString() {
+ return Iterables.toString(this);
+ }
+ }
+ private static final class ArrayIterable<M> extends AbstractIterable<M> {
private final M[] a;
// Constructed via factory methods.
@@ -43,28 +50,18 @@
this.a = a;
}
- /**
- * {@inheritDoc}
- */
public Iterator<M> iterator() {
return Iterators.arrayIterator(a);
}
-
}
- private static final class EmptyIterable<M> implements Iterable<M> {
-
- /**
- * {@inheritDoc}
- */
+ private static final class EmptyIterable<M> extends AbstractIterable<M> {
public Iterator<M> iterator() {
return Iterators.emptyIterator();
}
-
}
- private static final class FilteredIterable<M, P> implements Iterable<M> {
-
+ private static final class FilteredIterable<M, P> extends AbstractIterable<M> {
private final Iterable<M> iterable;
private final P parameter;
private final Predicate<? super M, P> predicate;
@@ -77,17 +74,12 @@
this.parameter = p;
}
- /**
- * {@inheritDoc}
- */
public Iterator<M> iterator() {
return Iterators.filteredIterator(iterable.iterator(), predicate, parameter);
}
-
}
- private static final class SingletonIterable<M> implements Iterable<M> {
-
+ private static final class SingletonIterable<M> extends AbstractIterable<M> {
private final M value;
// Constructed via factory methods.
@@ -95,17 +87,12 @@
this.value = value;
}
- /**
- * {@inheritDoc}
- */
public Iterator<M> iterator() {
return Iterators.singletonIterator(value);
}
-
}
- private static final class TransformedIterable<M, N, P> implements Iterable<N> {
-
+ private static final class TransformedIterable<M, N, P> extends AbstractIterable<N> {
private final Function<? super M, ? extends N, P> function;
private final Iterable<M> iterable;
private final P parameter;
@@ -118,17 +105,12 @@
this.parameter = p;
}
- /**
- * {@inheritDoc}
- */
public Iterator<N> iterator() {
return Iterators.transformedIterator(iterable.iterator(), function, parameter);
}
-
}
- private static final class UnmodifiableIterable<M> implements Iterable<M> {
-
+ private static final class UnmodifiableIterable<M> extends AbstractIterable<M> {
private final Iterable<M> iterable;
// Constructed via factory methods.
@@ -136,13 +118,9 @@
this.iterable = iterable;
}
- /**
- * {@inheritDoc}
- */
public Iterator<M> iterator() {
return Iterators.unmodifiableIterator(iterable.iterator());
}
-
}
private static final Iterable<Object> EMPTY_ITERABLE = new EmptyIterable<Object>();
@@ -302,6 +280,30 @@
return new UnmodifiableIterable<M>(iterable);
}
+ /**
+ * Returns a string representation of the provided iterable composed of an
+ * opening square bracket, followed by each element separated by commas, and
+ * then a closing square bracket.
+ *
+ * @param iterable
+ * The iterable whose string representation is to be returned.
+ * @return A string representation of the provided iterable.
+ */
+ public static String toString(Iterable<?> iterable) {
+ final StringBuilder builder = new StringBuilder();
+ boolean firstValue = true;
+ builder.append('[');
+ for (Object value : iterable) {
+ if (!firstValue) {
+ builder.append(',');
+ }
+ builder.append(String.valueOf(value));
+ firstValue = false;
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
// Prevent instantiation
private Iterables() {
// Do nothing.
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java
index f7ee890..cb66c19 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java
@@ -40,6 +40,8 @@
import org.forgerock.opendj.ldap.schema.ObjectClass;
import org.forgerock.opendj.ldap.schema.Schema;
+import com.forgerock.opendj.util.Iterables;
+
/**
* A configurable factory for filtering the attributes exposed by an entry. An
* {@code AttributeFilter} is useful for performing fine-grained access control,
@@ -57,9 +59,10 @@
* </ul>
*/
public final class AttributeFilter {
- // TODO: exclude specific attributes, matched values, types only, custom predicates, etc.
- private boolean includeAllOperationalAttributes;
- private boolean includeAllUserAttributes;
+ // TODO: exclude specific attributes, matched values, custom predicates, etc.
+ private boolean includeAllOperationalAttributes = false;
+ private boolean includeAllUserAttributes; // Depends on constructor.
+ private boolean typesOnly = false;
/**
* Use a map so that we can perform membership checks as well as recover the
@@ -74,7 +77,6 @@
*/
public AttributeFilter() {
includeAllUserAttributes = true;
- includeAllOperationalAttributes = false;
}
/**
@@ -106,7 +108,6 @@
if (attributeDescriptions == null || attributeDescriptions.isEmpty()) {
// Fast-path for common case.
includeAllUserAttributes = true;
- includeAllOperationalAttributes = false;
} else {
for (final String attribute : attributeDescriptions) {
includeAttribute(attribute, schema);
@@ -212,7 +213,7 @@
throw new NoSuchElementException();
}
hasNextMustIterate = true;
- return next;
+ return filterAttribute(next);
}
@Override
@@ -221,6 +222,11 @@
}
};
}
+
+ @Override
+ public String toString() {
+ return Iterables.toString(this);
+ }
};
}
@@ -237,10 +243,10 @@
final AttributeType at = ad.getAttributeType();
final AttributeDescription requestedAd = requestedAttributes.get(ad);
if (requestedAd != null) {
- return renameAttribute(attribute, requestedAd);
+ return filterAttribute(renameAttribute(attribute, requestedAd));
} else if ((at.isOperational() && includeAllOperationalAttributes)
|| (!at.isOperational() && includeAllUserAttributes)) {
- return attribute;
+ return filterAttribute(attribute);
}
}
return null;
@@ -397,9 +403,29 @@
}
}
+ /**
+ * Specifies whether or not filtered attributes are to contain both
+ * attribute descriptions and values, or just attribute descriptions.
+ *
+ * @param typesOnly
+ * {@code true} if only attribute descriptions (and not values)
+ * are to be included, or {@code false} (the default) if both
+ * attribute descriptions and values are to be included.
+ * @return A reference to this attribute filter.
+ */
+ public AttributeFilter typesOnly(final boolean typesOnly) {
+ this.typesOnly = typesOnly;
+ return this;
+ }
+
private void allocatedRequestedAttributes() {
if (requestedAttributes.isEmpty()) {
requestedAttributes = new HashMap<AttributeDescription, AttributeDescription>();
}
}
+
+ private Attribute filterAttribute(final Attribute attribute) {
+ return typesOnly ? Attributes.emptyAttribute(attribute.getAttributeDescription())
+ : attribute;
+ }
}
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
index 794ee02..f7ce541 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
@@ -324,8 +324,8 @@
final Filter filter = request.getFilter();
final Matcher matcher = filter.matcher(schema);
final AttributeFilter attributeFilter =
- new AttributeFilter(request.getAttributes(), schema);
-
+ new AttributeFilter(request.getAttributes(), schema).typesOnly(request
+ .isTypesOnly());
if (scope.equals(SearchScope.BASE_OBJECT)) {
if (matcher.matches(baseEntry).toBoolean()) {
sendEntry(attributeFilter, resultHandler, baseEntry);
diff --git a/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java b/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
index cdb7204..a682970 100644
--- a/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
+++ b/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
@@ -42,6 +42,7 @@
import org.forgerock.opendj.ldap.controls.PostReadResponseControl;
import org.forgerock.opendj.ldap.controls.PreReadRequestControl;
import org.forgerock.opendj.ldap.controls.PreReadResponseControl;
+import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.forgerock.opendj.ldif.LDIFEntryReader;
import org.testng.annotations.Test;
@@ -346,6 +347,17 @@
}
@Test
+ public void testSearchAttributesSelectedTypesOnly() throws Exception {
+ final Connection connection = getConnection();
+ assertThat(
+ connection.searchSingleEntry(Requests.newSearchRequest(
+ "uid=test1,ou=People,dc=example,dc=com", SearchScope.BASE_OBJECT,
+ "(objectClass=*)", "uid", "entryDN").setTypesOnly(true))).isEqualTo(
+ new LinkedHashMapEntry("uid=test1,ou=People,dc=example,dc=com").addAttribute("uid")
+ .addAttribute("entryDN"));
+ }
+
+ @Test
public void testSearchAttributesRenamed() throws Exception {
final Connection connection = getConnection();
final Entry entry =
--
Gitblit v1.10.0