opendj-sdk/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. opendj-sdk/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; } } opendj-sdk/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); opendj-sdk/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 =