From 1df4f51adf614210ca4a9b9728327090ec5ea264 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Fri, 11 Sep 2015 20:33:53 +0000
Subject: [PATCH] OPENDJ-1666 PR-19 CREST-3.0.0 Migration
---
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java | 269 ++++++++++++++++++++++-------------------------------
1 files changed, 114 insertions(+), 155 deletions(-)
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
index 3e7803e..dcf269f 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
@@ -21,7 +21,6 @@
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
import static org.forgerock.opendj.rest2ldap.Utils.i18n;
import static org.forgerock.opendj.rest2ldap.Utils.isNullOrEmpty;
-import static org.forgerock.opendj.rest2ldap.Utils.transform;
import static org.forgerock.opendj.rest2ldap.WritabilityPolicy.READ_WRITE;
import java.util.ArrayList;
@@ -29,13 +28,12 @@
import java.util.List;
import java.util.Set;
-import org.forgerock.json.fluent.JsonPointer;
-import org.forgerock.json.fluent.JsonValue;
+import org.forgerock.json.JsonPointer;
+import org.forgerock.json.JsonValue;
import org.forgerock.json.resource.BadRequestException;
import org.forgerock.json.resource.NotSupportedException;
import org.forgerock.json.resource.PatchOperation;
import org.forgerock.json.resource.ResourceException;
-import org.forgerock.json.resource.ResultHandler;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.AttributeDescription;
import org.forgerock.opendj.ldap.Entry;
@@ -43,14 +41,14 @@
import org.forgerock.opendj.ldap.Modification;
import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.util.Function;
-import org.forgerock.util.promise.NeverThrowsException;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.Promises;
/**
* An abstract LDAP attribute mapper which provides a simple mapping from a JSON
* value to a single LDAP attribute.
*/
-abstract class AbstractLDAPAttributeMapper<T extends AbstractLDAPAttributeMapper<T>> extends
- AttributeMapper {
+abstract class AbstractLDAPAttributeMapper<T extends AbstractLDAPAttributeMapper<T>> extends AttributeMapper {
List<Object> defaultJSONValues = emptyList();
final AttributeDescription ldapAttributeName;
private boolean isRequired;
@@ -101,25 +99,45 @@
}
@Override
- void create(final Context c, final JsonPointer path, final JsonValue v,
- final ResultHandler<List<Attribute>> h) {
- getNewLDAPAttributes(c, path, v, createAttributeHandler(path, h));
+ Promise<List<Attribute>, ResourceException> create(
+ final RequestState requestState, final JsonPointer path, final JsonValue v) {
+ return getNewLDAPAttributes(requestState, path, v).then(
+ new Function<Attribute, List<Attribute>, ResourceException>() {
+ @Override
+ public List<Attribute> apply(Attribute newLDAPAttribute) throws ResourceException {
+ if (!writabilityPolicy.canCreate(ldapAttributeName)) {
+ if (!newLDAPAttribute.isEmpty() && !writabilityPolicy.discardWrites()) {
+ throw new BadRequestException(i18n("The request cannot be processed because it attempts "
+ + "to create the read-only field '%s'", path));
+ }
+ return Collections.emptyList();
+ } else if (newLDAPAttribute.isEmpty()) {
+ if (isRequired) {
+ throw new BadRequestException(i18n("The request cannot be processed because it attempts "
+ + "to remove the required field '%s'", path));
+ }
+ return Collections.emptyList();
+ }
+
+ return singletonList(newLDAPAttribute);
+ }
+ });
}
@Override
- void getLDAPAttributes(final Context c, final JsonPointer path, final JsonPointer subPath,
- final Set<String> ldapAttributes) {
+ void getLDAPAttributes(final RequestState requestState, final JsonPointer path,
+ final JsonPointer subPath, final Set<String> ldapAttributes) {
ldapAttributes.add(ldapAttributeName.toString());
}
- abstract void getNewLDAPAttributes(Context c, JsonPointer path, List<Object> newValues,
- ResultHandler<Attribute> h);
+ abstract Promise<Attribute, ResourceException> getNewLDAPAttributes(
+ RequestState requestState, JsonPointer path, List<Object> newValues);
abstract T getThis();
@Override
- void patch(final Context c, final JsonPointer path, final PatchOperation operation,
- final ResultHandler<List<Modification>> h) {
+ Promise<List<Modification>, ResourceException> patch(
+ final RequestState requestState, final JsonPointer path, final PatchOperation operation) {
try {
final JsonPointer field = operation.getField();
final JsonValue v = operation.getValue();
@@ -235,33 +253,95 @@
if (newValues.isEmpty()) {
// Deleting the attribute.
if (isRequired) {
- h.handleError(new BadRequestException(i18n(
- "The request cannot be processed because it attempts to remove "
- + "the required field '%s'", path)));
+ return Promises.<List<Modification>, ResourceException> newExceptionPromise(
+ new BadRequestException(i18n(
+ "The request cannot be processed because it attempts to remove the required field '%s'",
+ path)));
} else {
- h.handleResult(singletonList(new Modification(modType,
- emptyAttribute(ldapAttributeName))));
+ return Promises.newResultPromise(
+ singletonList(new Modification(modType, emptyAttribute(ldapAttributeName))));
}
} else {
- getNewLDAPAttributes(c, path, newValues, transform(
- new Function<Attribute, List<Modification>, NeverThrowsException>() {
+ return getNewLDAPAttributes(requestState, path, newValues)
+ .then(new Function<Attribute, List<Modification>, ResourceException>() {
@Override
public List<Modification> apply(final Attribute value) {
return singletonList(new Modification(modType, value));
}
- }, h));
+ });
}
} catch (final RuntimeException e) {
- h.handleError(asResourceException(e));
+ return Promises.newExceptionPromise(asResourceException(e));
} catch (final ResourceException e) {
- h.handleError(e);
+ return Promises.newExceptionPromise(e);
}
}
@Override
- void update(final Context c, final JsonPointer path, final Entry e, final JsonValue v,
- final ResultHandler<List<Modification>> h) {
- getNewLDAPAttributes(c, path, v, updateAttributeHandler(path, e, h));
+ Promise<List<Modification>, ResourceException> update(
+ final RequestState requestState, final JsonPointer path, final Entry e, final JsonValue v) {
+ return getNewLDAPAttributes(requestState, path, v).then(
+ new Function<Attribute, List<Modification>, ResourceException>() {
+ @Override
+ public List<Modification> apply(final Attribute newLDAPAttribute) throws ResourceException {
+ // Get the existing LDAP attribute.
+ final Attribute tmp = e.getAttribute(ldapAttributeName);
+ final Attribute oldLDAPAttribute = tmp != null ? tmp : emptyAttribute(ldapAttributeName);
+ /*
+ * If the attribute is read-only then handle the following cases:
+ * 1) new values are provided and they are the same as the existing values
+ * 2) no new values are provided.
+ */
+ if (!writabilityPolicy.canWrite(ldapAttributeName)) {
+ if (newLDAPAttribute.isEmpty()
+ || newLDAPAttribute.equals(oldLDAPAttribute)
+ || writabilityPolicy.discardWrites()) {
+ // No change.
+ return Collections.emptyList();
+ }
+ throw new BadRequestException(i18n(
+ "The request cannot be processed because it attempts to modify the read-only field '%s'",
+ path));
+ }
+
+ if (oldLDAPAttribute.isEmpty() && newLDAPAttribute.isEmpty()) {
+ // No change.
+ return Collections.emptyList();
+ } else if (oldLDAPAttribute.isEmpty()) {
+ // The attribute is being added.
+ return singletonList(new Modification(ModificationType.REPLACE, newLDAPAttribute));
+ } else if (newLDAPAttribute.isEmpty()) {
+ // The attribute is being deleted - this is not allowed if the attribute is required.
+ if (isRequired) {
+ throw new BadRequestException(i18n(
+ "The request cannot be processed because it attempts to remove the required field '%s'",
+ path));
+ }
+ return singletonList(new Modification(ModificationType.REPLACE, newLDAPAttribute));
+ } else {
+ /*
+ * We could do a replace, but try to save bandwidth and send diffs instead.
+ * Perform deletes first in case we don't have an appropriate normalizer:
+ * permissive add(x) followed by delete(x) is destructive, whereas
+ * delete(x) followed by add(x) is idempotent when adding/removing the same value.
+ */
+ final List<Modification> modifications = new ArrayList<>(2);
+
+ final Attribute deletedValues = new LinkedAttribute(oldLDAPAttribute);
+ deletedValues.removeAll(newLDAPAttribute);
+ if (!deletedValues.isEmpty()) {
+ modifications.add(new Modification(ModificationType.DELETE, deletedValues));
+ }
+
+ final Attribute addedValues = new LinkedAttribute(newLDAPAttribute);
+ addedValues.removeAll(oldLDAPAttribute);
+ if (!addedValues.isEmpty()) {
+ modifications.add(new Modification(ModificationType.ADD, addedValues));
+ }
+ return modifications;
+ }
+ }
+ });
}
private List<Object> asList(final JsonValue v, final List<Object> defaultValues) {
@@ -290,142 +370,21 @@
}
}
- private ResultHandler<Attribute> createAttributeHandler(final JsonPointer path,
- final ResultHandler<List<Attribute>> h) {
- return new ResultHandler<Attribute>() {
- @Override
- public void handleError(final ResourceException error) {
- h.handleError(error);
- }
-
- @Override
- public void handleResult(final Attribute newLDAPAttribute) {
- if (!writabilityPolicy.canCreate(ldapAttributeName)) {
- if (newLDAPAttribute.isEmpty() || writabilityPolicy.discardWrites()) {
- h.handleResult(Collections.<Attribute> emptyList());
- } else {
- h.handleError(new BadRequestException(i18n(
- "The request cannot be processed because it attempts to create "
- + "the read-only field '%s'", path)));
- }
- } else if (newLDAPAttribute.isEmpty()) {
- if (isRequired) {
- h.handleError(new BadRequestException(i18n(
- "The request cannot be processed because it attempts to remove "
- + "the required field '%s'", path)));
- return;
- } else {
- h.handleResult(Collections.<Attribute> emptyList());
- }
- } else {
- h.handleResult(singletonList(newLDAPAttribute));
- }
- }
- };
- }
-
- private void getNewLDAPAttributes(final Context c, final JsonPointer path, final JsonValue v,
- final ResultHandler<Attribute> attributeHandler) {
+ private Promise<Attribute, ResourceException> getNewLDAPAttributes(
+ final RequestState requestState, final JsonPointer path, final JsonValue v) {
try {
// Ensure that the value is of the correct type.
checkSchema(path, v);
final List<Object> newValues = asList(v, defaultJSONValues);
if (newValues.isEmpty()) {
// Skip sub-class implementation if there are no values.
- attributeHandler.handleResult(emptyAttribute(ldapAttributeName));
+ return Promises.newResultPromise(emptyAttribute(ldapAttributeName));
} else {
- getNewLDAPAttributes(c, path, newValues, attributeHandler);
+ return getNewLDAPAttributes(requestState, path, newValues);
}
} catch (final Exception ex) {
- attributeHandler.handleError(asResourceException(ex));
+ return Promises.newExceptionPromise(asResourceException(ex));
}
}
- private ResultHandler<Attribute> updateAttributeHandler(final JsonPointer path, final Entry e,
- final ResultHandler<List<Modification>> h) {
- // Get the existing LDAP attribute.
- final Attribute tmp = e.getAttribute(ldapAttributeName);
- final Attribute oldLDAPAttribute = tmp != null ? tmp : emptyAttribute(ldapAttributeName);
- return new ResultHandler<Attribute>() {
- @Override
- public void handleError(final ResourceException error) {
- h.handleError(error);
- }
-
- @Override
- public void handleResult(final Attribute newLDAPAttribute) {
- /*
- * If the attribute is read-only then handle the following
- * cases:
- *
- * 1) new values are provided and they are the same as the
- * existing values
- *
- * 2) no new values are provided.
- */
- if (!writabilityPolicy.canWrite(ldapAttributeName)) {
- if (newLDAPAttribute.isEmpty() || newLDAPAttribute.equals(oldLDAPAttribute)
- || writabilityPolicy.discardWrites()) {
- // No change.
- h.handleResult(Collections.<Modification> emptyList());
- } else {
- h.handleError(new BadRequestException(i18n(
- "The request cannot be processed because it attempts to modify "
- + "the read-only field '%s'", path)));
- }
- } else {
- // Compute the changes to the attribute.
- final List<Modification> modifications;
- if (oldLDAPAttribute.isEmpty() && newLDAPAttribute.isEmpty()) {
- // No change.
- modifications = Collections.<Modification> emptyList();
- } else if (oldLDAPAttribute.isEmpty()) {
- // The attribute is being added.
- modifications =
- singletonList(new Modification(ModificationType.REPLACE,
- newLDAPAttribute));
- } else if (newLDAPAttribute.isEmpty()) {
- /*
- * The attribute is being deleted - this is not allowed
- * if the attribute is required.
- */
- if (isRequired) {
- h.handleError(new BadRequestException(i18n(
- "The request cannot be processed because it attempts to remove "
- + "the required field '%s'", path)));
- return;
- } else {
- modifications =
- singletonList(new Modification(ModificationType.REPLACE,
- newLDAPAttribute));
- }
- } else {
- /*
- * We could do a replace, but try to save bandwidth and
- * send diffs instead. Perform deletes first in case we
- * don't have an appropriate normalizer: permissive
- * add(x) followed by delete(x) is destructive, whereas
- * delete(x) followed by add(x) is idempotent when
- * adding/removing the same value.
- */
- modifications = new ArrayList<>(2);
-
- final Attribute deletedValues = new LinkedAttribute(oldLDAPAttribute);
- deletedValues.removeAll(newLDAPAttribute);
- if (!deletedValues.isEmpty()) {
- modifications.add(new Modification(ModificationType.DELETE,
- deletedValues));
- }
-
- final Attribute addedValues = new LinkedAttribute(newLDAPAttribute);
- addedValues.removeAll(oldLDAPAttribute);
- if (!addedValues.isEmpty()) {
- modifications.add(new Modification(ModificationType.ADD, addedValues));
- }
- }
- h.handleResult(modifications);
- }
- }
- };
- }
}
--
Gitblit v1.10.0