From b0a81eda9a0b2717e90dee49af53adc71f7cc3dc Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 31 Jan 2013 18:01:23 +0000
Subject: [PATCH] Fix OPENDJ-690: Rest2LDAP - Implement basic search support
---
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java | 149 ++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 127 insertions(+), 22 deletions(-)
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
index 9d83322..9a66c9c 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
@@ -11,7 +11,7 @@
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions Copyright [year] [name of copyright owner]".
*
- * Copyright 2012 ForgeRock AS.
+ * Copyright 2012-2013 ForgeRock AS.
*/
package org.forgerock.opendj.rest2ldap;
@@ -21,13 +21,18 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.bind.DatatypeConverter;
+import org.forgerock.json.resource.ResourceException;
+import org.forgerock.json.resource.ResultHandler;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.Function;
import org.forgerock.opendj.ldap.Functions;
import org.forgerock.opendj.ldap.schema.Syntax;
@@ -36,37 +41,85 @@
* Internal utility methods.
*/
final class Utils {
+ /**
+ * Implementation class for {@link #accumulate}.
+ *
+ * @param <V>
+ * The type of result.
+ */
+ private static final class AccumulatingResultHandler<V> implements ResultHandler<V> {
+ private final ResultHandler<List<V>> handler;
+ private final AtomicInteger latch;
+ private final List<V> results;
+
+ private AccumulatingResultHandler(final int size, final ResultHandler<List<V>> handler) {
+ this.latch = new AtomicInteger(size);
+ this.results = new ArrayList<V>(size);
+ this.handler = handler;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void handleError(final ResourceException e) {
+ // Ensure that handler is only invoked once.
+ if (latch.getAndSet(0) > 0) {
+ handler.handleError(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void handleResult(final V result) {
+ synchronized (results) {
+ results.add(result);
+ }
+ if (latch.decrementAndGet() == 0) {
+ handler.handleResult(results);
+ }
+ }
+
+ }
// @Checkstyle:off
private static final Function<ByteString, Object, Attribute> BYTESTRING_TO_JSON =
new Function<ByteString, Object, Attribute>() {
- @Override
- public Object apply(final ByteString value, final Attribute a) {
- final Syntax syntax = a.getAttributeDescription().getAttributeType().getSyntax();
- if (syntax.equals(getBooleanSyntax())) {
- return Functions.byteStringToBoolean().apply(value, null);
- } else if (syntax.equals(getIntegerSyntax())) {
- return Functions.byteStringToLong().apply(value, null);
- } else if (syntax.equals(getGeneralizedTimeSyntax())) {
- return DatatypeConverter.printDateTime(Functions.byteStringToGeneralizedTime()
- .apply(value, null).toCalendar());
- } else if (syntax.isHumanReadable()) {
- return Functions.byteStringToString().apply(value, null);
- } else {
- // Base 64 encoded binary.
- return DatatypeConverter.printBase64Binary(value.toByteArray());
- }
- }
- };
- // @Checkstyle:on
+ @Override
+ public Object apply(final ByteString value, final Attribute a) {
+ final Syntax syntax =
+ a.getAttributeDescription().getAttributeType().getSyntax();
+ if (syntax.equals(getBooleanSyntax())) {
+ return Functions.byteStringToBoolean().apply(value, null);
+ } else if (syntax.equals(getIntegerSyntax())) {
+ return Functions.byteStringToLong().apply(value, null);
+ } else if (syntax.equals(getGeneralizedTimeSyntax())) {
+ return DatatypeConverter.printDateTime(Functions
+ .byteStringToGeneralizedTime().apply(value, null).toCalendar());
+ } else if (syntax.isHumanReadable()) {
+ return Functions.byteStringToString().apply(value, null);
+ } else {
+ // Base 64 encoded binary.
+ return DatatypeConverter.printBase64Binary(value.toByteArray());
+ }
+ }
+ };
+
+ static <V> ResultHandler<V> accumulate(final int size, final ResultHandler<List<V>> handler) {
+ return new AccumulatingResultHandler<V>(size, handler);
+ }
static Object attributeToJson(final Attribute a) {
final Function<ByteString, Object, Void> f = Functions.fixedFunction(BYTESTRING_TO_JSON, a);
- final boolean isSingleValued = a.getAttributeDescription().getAttributeType()
- .isSingleValue();
+ final boolean isSingleValued =
+ a.getAttributeDescription().getAttributeType().isSingleValue();
return isSingleValued ? a.parse().as(f) : asList(a.parse().asSetOf(f));
}
+ // @Checkstyle:on
+
static Function<ByteString, Object, Attribute> byteStringToJson() {
return BYTESTRING_TO_JSON;
}
@@ -89,10 +142,62 @@
return a.getAttributeDescription().withoutOption("binary").toString();
}
+ static Filter toFilter(final Context c, final FilterType type, final String ldapAttribute,
+ final Object valueAssertion) {
+ final String v = String.valueOf(valueAssertion);
+ final Filter filter;
+ switch (type) {
+ case CONTAINS:
+ filter = Filter.substrings(ldapAttribute, null, Collections.singleton(v), null);
+ break;
+ case STARTS_WITH:
+ filter = Filter.substrings(ldapAttribute, v, null, null);
+ break;
+ case EQUAL_TO:
+ filter = Filter.equality(ldapAttribute, v);
+ break;
+ case GREATER_THAN:
+ filter = Filter.greaterThan(ldapAttribute, v);
+ break;
+ case GREATER_THAN_OR_EQUAL_TO:
+ filter = Filter.greaterOrEqual(ldapAttribute, v);
+ break;
+ case LESS_THAN:
+ filter = Filter.lessThan(ldapAttribute, v);
+ break;
+ case LESS_THAN_OR_EQUAL_TO:
+ filter = Filter.lessOrEqual(ldapAttribute, v);
+ break;
+ case PRESENT:
+ filter = Filter.present(ldapAttribute);
+ break;
+ case EXTENDED:
+ default:
+ filter = c.getConfig().getFalseFilter(); // Not supported.
+ break;
+ }
+ return filter;
+ }
+
static String toLowerCase(final String s) {
return s != null ? s.toLowerCase(Locale.ENGLISH) : null;
}
+ static <M, N> ResultHandler<M> transform(final Function<M, N, Void> f,
+ final ResultHandler<N> handler) {
+ return new ResultHandler<M>() {
+ @Override
+ public void handleError(final ResourceException error) {
+ handler.handleError(error);
+ }
+
+ @Override
+ public void handleResult(final M result) {
+ handler.handleResult(f.apply(result, null));
+ }
+ };
+ }
+
private static <T> List<T> asList(final Collection<T> c) {
if (c instanceof List) {
return (List<T>) c;
--
Gitblit v1.10.0