From 0930abd89f504f1b374467af2311676bfc82c0d6 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Wed, 06 Mar 2013 10:01:06 +0000
Subject: [PATCH] Minor improvements:
---
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java | 111 +++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 82 insertions(+), 29 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 ce51dcc..a39c966 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
@@ -68,6 +68,7 @@
private final ResultHandler<List<V>> handler;
private final AtomicInteger latch;
private final List<V> results;
+ private ResourceException exception; // Guarded by latch.
private AccumulatingResultHandler(final int size, final ResultHandler<List<V>> handler) {
this.latch = new AtomicInteger(size);
@@ -75,20 +76,12 @@
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);
- }
+ exception = e;
+ latch(); // Volatile write publishes exception.
}
- /**
- * {@inheritDoc}
- */
@Override
public void handleResult(final V result) {
if (result != null) {
@@ -96,11 +89,21 @@
results.add(result);
}
}
- if (latch.decrementAndGet() == 0) {
- handler.handleResult(results);
- }
+ latch();
}
+ private void latch() {
+ // Invoke the handler once all results have been received. Avoid failing-fast
+ // when an error occurs because some in-flight tasks may depend on resources
+ // (e.g. connections) which are automatically closed on completion.
+ if (latch.decrementAndGet() == 0) {
+ if (exception != null) {
+ handler.handleError(exception);
+ } else {
+ handler.handleResult(results);
+ }
+ }
+ }
}
private static final Function<Object, ByteString, Void> BASE64_TO_BYTESTRING =
@@ -156,21 +159,45 @@
}
};
+ /**
+ * Returns a result handler which can be used to collect the results of
+ * {@code size} asynchronous operations. Once all results have been received
+ * {@code handler} will be invoked with a list containing the results.
+ * Accumulation ignores {@code null} results, so the result list may be
+ * smaller than {@code size}. The returned result handler does not
+ * fail-fast: it will wait until all results have been received even if an
+ * error has been detected. This ensures that asynchronous operations can
+ * use resources such as connections which are automatically released
+ * (closed) upon completion of the final operation.
+ *
+ * @param <V>
+ * The type of result to be collected.
+ * @param size
+ * The number of expected results.
+ * @param handler
+ * The result handler to be invoked when all results have been
+ * received.
+ * @return A result handler which can be used to collect the results of
+ * {@code size} asynchronous operations.
+ */
static <V> ResultHandler<V> accumulate(final int size, final ResultHandler<List<V>> handler) {
return new AccumulatingResultHandler<V>(size, handler);
}
/**
- * Adapts an LDAP result code to a resource exception.
+ * Adapts a {@code Throwable} to a {@code ResourceException}. If the
+ * {@code Throwable} is an LDAP {@code ErrorResultException} then an
+ * appropriate {@code ResourceException} is returned, otherwise an
+ * {@code InternalServerErrorException} is returned.
*
- * @param error
- * The LDAP error that should be adapted.
+ * @param t
+ * The {@code Throwable} to be converted.
* @return The equivalent resource exception.
*/
- static ResourceException adapt(final ErrorResultException error) {
+ static ResourceException adapt(final Throwable t) {
int resourceResultCode;
try {
- throw error;
+ throw t;
} catch (final AssertionFailureException e) {
resourceResultCode = ResourceException.VERSION_MISMATCH;
} catch (final AuthenticationException e) {
@@ -194,8 +221,10 @@
} else {
resourceResultCode = ResourceException.INTERNAL_ERROR;
}
+ } catch (final Throwable tmp) {
+ resourceResultCode = ResourceException.INTERNAL_ERROR;
}
- return ResourceException.getException(resourceResultCode, error.getMessage(), error);
+ return ResourceException.getException(resourceResultCode, t.getMessage(), t);
}
static Object attributeToJson(final Attribute a) {
@@ -269,30 +298,31 @@
}
static Filter toFilter(final Context c, final FilterType type, final String ldapAttribute,
- final Object valueAssertion) {
- final String v = String.valueOf(valueAssertion);
+ final ByteString valueAssertion) {
final Filter filter;
switch (type) {
case CONTAINS:
- filter = Filter.substrings(ldapAttribute, null, Collections.singleton(v), null);
+ filter =
+ Filter.substrings(ldapAttribute, null, Collections.singleton(valueAssertion),
+ null);
break;
case STARTS_WITH:
- filter = Filter.substrings(ldapAttribute, v, null, null);
+ filter = Filter.substrings(ldapAttribute, valueAssertion, null, null);
break;
case EQUAL_TO:
- filter = Filter.equality(ldapAttribute, v);
+ filter = Filter.equality(ldapAttribute, valueAssertion);
break;
case GREATER_THAN:
- filter = Filter.greaterThan(ldapAttribute, v);
+ filter = Filter.greaterThan(ldapAttribute, valueAssertion);
break;
case GREATER_THAN_OR_EQUAL_TO:
- filter = Filter.greaterOrEqual(ldapAttribute, v);
+ filter = Filter.greaterOrEqual(ldapAttribute, valueAssertion);
break;
case LESS_THAN:
- filter = Filter.lessThan(ldapAttribute, v);
+ filter = Filter.lessThan(ldapAttribute, valueAssertion);
break;
case LESS_THAN_OR_EQUAL_TO:
- filter = Filter.lessOrEqual(ldapAttribute, v);
+ filter = Filter.lessOrEqual(ldapAttribute, valueAssertion);
break;
case PRESENT:
filter = Filter.present(ldapAttribute);
@@ -309,6 +339,25 @@
return s != null ? s.toLowerCase(Locale.ENGLISH) : null;
}
+ /**
+ * Returns a result handler which accepts results of type {@code M}, applies
+ * the function {@code f} in order to convert the result to an object of
+ * type {@code N}, and subsequently invokes {@code handler}. If an
+ * unexpected error occurs while performing the transformation, the
+ * exception is converted to a {@code ResourceException} before invoking
+ * {@code handler.handleError()}.
+ *
+ * @param <M>
+ * The type of result expected by the returned handler.
+ * @param <N>
+ * The type of result expected by {@code handler}.
+ * @param f
+ * A function which converts the result of type {@code M} to type
+ * {@code N}.
+ * @param handler
+ * A result handler which accepts results of type {@code N}.
+ * @return A result handler which accepts results of type {@code M}.
+ */
static <M, N> ResultHandler<M> transform(final Function<M, N, Void> f,
final ResultHandler<N> handler) {
return new ResultHandler<M>() {
@@ -319,7 +368,11 @@
@Override
public void handleResult(final M result) {
- handler.handleResult(f.apply(result, null));
+ try {
+ handler.handleResult(f.apply(result, null));
+ } catch (Throwable t) {
+ handler.handleError(adapt(t));
+ }
}
};
}
--
Gitblit v1.10.0