From c6f5f43745ec42f805b4ff0809dcb8d5cdbc1ba3 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 17 Dec 2013 14:07:42 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1235 : Migrate configuration framework
---
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java | 386 +++++++++++
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java | 314 ++++++++
opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java | 7
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java | 112 +++
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java | 70 ++
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java | 115 +++
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java | 131 +++
opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java | 36
opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java | 889 +++++++++++++++++++++++++
9 files changed, 2,042 insertions(+), 18 deletions(-)
diff --git a/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java b/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
index a6780f6..8d66bd2 100644
--- a/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
+++ b/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -37,7 +37,6 @@
import org.forgerock.opendj.ldap.LinkedAttribute;
import org.forgerock.opendj.ldap.LinkedHashMapEntry;
import org.forgerock.opendj.ldap.ModificationType;
-import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.requests.Requests;
@@ -175,8 +174,7 @@
addObjectClassesToEntry(objectClasses, entry);
// Create the branch's naming attribute.
- RDN rdn = dn.parent(dn.size() - 1).rdn();
- entry.addAttribute(rdn.getFirstAVA().toAttribute());
+ entry.addAttribute(dn.rdn().getFirstAVA().toAttribute());
// Create the entry.
try {
@@ -204,8 +202,7 @@
// Create the naming attribute if there is not naming property.
PropertyDefinition<?> namingPropertyDef = getNamingPropertyDefinition();
if (namingPropertyDef == null) {
- RDN rdn = dn.parent(dn.size() - 1).rdn();
- entry.addAttribute(rdn.getFirstAVA().toAttribute());
+ entry.addAttribute(dn.rdn().getFirstAVA().toAttribute());
}
// Create the remaining attributes.
diff --git a/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java b/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
index 9f5f372..f8fba78 100644
--- a/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
+++ b/opendj-sdk/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
@@ -26,8 +26,10 @@
package org.opends.server.admin.client.ldap;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
+import java.util.List;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.RDN;
@@ -104,10 +106,9 @@
return builder.getInstance();
}
- // The list of RDNs in big-endian order.
+ /** The list of RDNs in big-endian order. */
private final LinkedList<RDN> rdns;
- // The LDAP profile.
private final LDAPProfile profile;
/**
@@ -145,9 +146,24 @@
public void appendManagedObjectPathElement(RelationDefinition<?, ?> r) {
// Add the RDN sequence representing the relation.
DN dn = DN.valueOf(profile.getRelationRDNSequence(r));
+ List<RDN> rdnsOfDn = getRdnsInBigEndianOrder(dn);
+ rdns.addAll(rdnsOfDn);
+ }
+
+ /**
+ * Returns list of RDNs of provided DN in big-endian order.
+ *
+ * @param dn
+ * The DN to decompose in RDNs.
+ * @return rdns in big endian order
+ */
+ private List<RDN> getRdnsInBigEndianOrder(DN dn) {
+ List<RDN> rdnsOfDn = new ArrayList<RDN>();
for (RDN rdn : dn) {
- rdns.add(rdn);
+ rdnsOfDn.add(rdn);
}
+ Collections.reverse(rdnsOfDn);
+ return rdnsOfDn;
}
/**
@@ -188,16 +204,10 @@
* @return Returns the new DN instance.
*/
public DN getInstance() {
- if (rdns.isEmpty()) {
- return DN.rootDN();
+ DN dn = DN.rootDN();
+ for (RDN rdn : rdns) {
+ dn = dn.child(rdn);
}
- else {
- Collections.reverse(rdns);
- DN dn = DN.valueOf(rdns.removeFirst().toString());
- for (RDN rdn : rdns) {
- dn = dn.child(rdn);
- }
- return dn;
- }
+ return dn;
}
}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java
new file mode 100644
index 0000000..5fcfd2b
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java
@@ -0,0 +1,314 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.forgerock.opendj.admin.client.RootCfgClient;
+import org.opends.server.admin.AdminTestCase;
+import org.opends.server.admin.IllegalPropertyValueStringException;
+import org.opends.server.admin.PropertyException;
+import org.opends.server.admin.TestCfg;
+import org.opends.server.admin.TestChildCfgClient;
+import org.opends.server.admin.TestChildCfgDefn;
+import org.opends.server.admin.TestParentCfgClient;
+import org.opends.server.admin.client.ManagedObject;
+import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.ManagementContext;
+import org.opends.server.core.DirectoryServer;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+@Test(singleThreaded = true)
+public class AggregationClientTest extends AdminTestCase {
+
+ // Test LDIF.
+ private static final String[] TEST_LDIF = new String[] {
+ // Base entries.
+ "dn: cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: config",
+ "",
+ "dn: cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: test-parents",
+ "",
+ // Parent 1 - uses default values for
+ // optional-multi-valued-dn-property.
+ "dn: cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-parent-dummy",
+ "cn: test parent 1",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "",
+ // Child base entry.
+ "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: multiple children",
+ "",
+ // Child 1 has no references.
+ "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy",
+ "cn: test child 1",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "",
+ // Child 2 has a single valid reference.
+ "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy",
+ "cn: test child 2",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config",
+ "",
+ // Child 3 has a multiple valid references.
+ "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy",
+ "cn: test child 3",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config",
+ "ds-cfg-rotation-policy: cn=LDAPS Connection Handler, cn=connection handlers, cn=config",
+ "",
+ // Child 4 has a single bad reference.
+ "dn: cn=test child 4,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy", "cn: test child 4", "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=bad rdn, cn=config", "",
+ "dn: cn=Connection Handlers,cn=config", "objectClass: top", "objectClass: ds-cfg-branch",
+ "cn: Connection Handlers", "", "dn: cn=LDAP Connection Handler,cn=Connection Handlers,cn=config",
+ "objectClass: top", "objectClass: ds-cfg-connection-handler",
+ "objectClass: ds-cfg-ldap-connection-handler", "cn: LDAP Connection Handler",
+ "ds-cfg-java-class: org.opends.server.protocols.ldap.LDAPConnectionHandler", "ds-cfg-enabled: true",
+ "ds-cfg-listen-address: 0.0.0.0", "ds-cfg-listen-port: 389", "",
+ "dn: cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config", "objectClass: top",
+ "objectClass: ds-cfg-connection-handler", "objectClass: ds-cfg-ldap-connection-handler",
+ "cn: LDAPS Connection Handler",
+ "ds-cfg-java-class: org.opends.server.protocols.ldap.LDAPConnectionHandler", "ds-cfg-enabled: false",
+ "ds-cfg-listen-address: 0.0.0.0", "ds-cfg-listen-port: 636", "ds-cfg-use-ssl: true",
+ "ds-cfg-ssl-client-auth-policy: optional", "ds-cfg-ssl-cert-nickname: server-cert",
+ "ds-cfg-key-manager-provider: cn=JKS,cn=Key Manager Providers,cn=config",
+ "ds-cfg-trust-manager-provider: cn=JKS,cn=Trust Manager Providers,cn=config", "",
+ "dn: cn=JMX Connection Handler,cn=Connection Handlers,cn=config", "objectClass: top",
+ "objectClass: ds-cfg-connection-handler", "objectClass: ds-cfg-jmx-connection-handler",
+ "cn: JMX Connection Handler", "ds-cfg-java-class: org.opends.server.protocols.jmx.JmxConnectionHandler",
+ "ds-cfg-enabled: false", "ds-cfg-listen-port: 1689", "" };
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ disableClassValidationForProperties();
+ TestCfg.setUp();
+ }
+
+ /**
+ * Tears down test environment.
+ */
+ @AfterClass
+ public void tearDown() {
+ TestCfg.cleanup();
+ }
+
+ /**
+ * Tests that aggregation contains no values when it contains does not
+ * contain any DN attribute values.
+ *
+ * @throws Exception
+ * If the test unexpectedly fails.
+ */
+ @Test
+ public void testAggregationEmpty() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 1");
+ assertSetEquals(child.getAggregationProperty(), new String[0]);
+ }
+
+ /**
+ * Tests that aggregation contains single valid value when it contains a
+ * single valid DN attribute values.
+ *
+ * @throws Exception
+ * If the test unexpectedly fails.
+ */
+ @Test
+ public void testAggregationSingle() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 2");
+
+ // Test normalization.
+ assertSetEquals(child.getAggregationProperty(), "LDAP Connection Handler");
+ assertSetEquals(child.getAggregationProperty(), " LDAP Connection Handler ");
+ assertSetEquals(child.getAggregationProperty(), " ldap connection HANDLER ");
+ }
+
+ /**
+ * Tests that aggregation contains multiple valid values when it contains a
+ * multiple valid DN attribute values.
+ *
+ * @throws Exception
+ * If the test unexpectedly fails.
+ */
+ @Test
+ public void testAggregationMultiple() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 3");
+ assertSetEquals(child.getAggregationProperty(), "LDAPS Connection Handler", "LDAP Connection Handler");
+ }
+
+ /**
+ * Tests that aggregation is rejected when the LDAP DN contains a valid RDN
+ * but an invalid parent DN.
+ *
+ * @throws Exception
+ * If the test unexpectedly fails.
+ */
+ @Test
+ public void testAggregationBadBaseDN() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+
+ try {
+ parent.getTestChild("test child 4");
+ Assert.fail("Unexpectedly retrieved test child 4" + " when it had a bad aggregation value");
+ } catch (ManagedObjectDecodingException e) {
+ Collection<PropertyException> causes = e.getCauses();
+ Assert.assertEquals(causes.size(), 1);
+
+ Throwable cause = causes.iterator().next();
+ if (cause instanceof IllegalPropertyValueStringException) {
+ IllegalPropertyValueStringException pe = (IllegalPropertyValueStringException) cause;
+ Assert.assertEquals(pe.getPropertyDefinition(), TestChildCfgDefn.getInstance()
+ .getAggregationPropertyPropertyDefinition());
+ Assert.assertEquals(pe.getIllegalValueString(), "cn=LDAP Connection Handler, cn=bad rdn, cn=config");
+ } else {
+ // Got an unexpected cause.
+ throw e;
+ }
+ }
+ }
+
+ /**
+ * Tests creation of a child managed object with a single reference.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testCreateChildManagedObject() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child new");
+ c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
+ c.addExpectedAttribute("ds-cfg-enabled", "true");
+ c.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ c.addExpectedAttribute("ds-cfg-attribute-type", "description");
+ c.addExpectedAttribute("ds-cfg-rotation-policy",
+ "cn=LDAP Connection Handler,cn=connection handlers, cn=config");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
+ child.setMandatoryBooleanProperty(true);
+ child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ child.setAggregationProperty(Collections.singleton("LDAP Connection Handler"));
+ child.commit();
+
+ c.assertEntryIsCreated();
+ }
+
+ /**
+ * Tests modification of a child managed object so that it has a different
+ * reference.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testModifyChildManagedObject() throws Exception {
+ ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
+ "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedModification("ds-cfg-rotation-policy",
+ "cn=LDAPS Connection Handler,cn=connection handlers, cn=config",
+ "cn=JMX Connection Handler,cn=connection handlers, cn=config");
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 2");
+ child.setAggregationProperty(Arrays.asList("LDAPS Connection Handler", "JMX Connection Handler"));
+ child.commit();
+ Assert.assertTrue(c.isEntryModified());
+ }
+
+ // Retrieve the named test parent managed object.
+ private TestParentCfgClient getTestParent(ManagementContext context, String name) throws Exception {
+ ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
+ return root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name).getConfiguration();
+ }
+
+ // Asserts that the actual set of DNs contains the expected values.
+ private void assertSetEquals(SortedSet<String> actual, String... expected) {
+ SortedSet<String> values = new TreeSet<String>(TestChildCfgDefn.getInstance()
+ .getAggregationPropertyPropertyDefinition());
+ if (expected != null) {
+ for (String value : expected) {
+ values.add(value);
+ }
+ }
+ Assert.assertEquals((Object) actual, (Object) values);
+ }
+
+}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java
new file mode 100644
index 0000000..f26ea14
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java
@@ -0,0 +1,112 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.testng.Assert;
+
+import com.forgerock.opendj.util.Validator;
+
+/**
+ * A mock LDAP connection which is used to verify that an add operation was
+ * requested and that it has the correct parameters.
+ */
+public final class CreateEntryMockLDAPConnection extends MockLDAPConnection {
+
+ // Detect multiple calls.
+ private boolean alreadyAdded = false;
+
+ // The expected set of attributes (attribute name -> list of
+ // values).
+ private final Map<String, List<String>> attributes = new HashMap<String, List<String>>();
+
+ // The expected DN.
+ private final DN expectedDN;
+
+ /**
+ * Create a new mock ldap connection for detecting add operations.
+ *
+ * @param dn
+ * The expected DN of the entry to be added.
+ */
+ public CreateEntryMockLDAPConnection(String dn) {
+ this.expectedDN = DN.valueOf(dn);
+ }
+
+ /**
+ * Add an attribute which should be part of the add operation.
+ *
+ * @param expectedName
+ * The name of the expected attribute.
+ * @param expectedValues
+ * The attribute's expected values (never empty).
+ */
+ public void addExpectedAttribute(String expectedName, String... expectedValues) {
+ Validator.ensureNotNull(expectedName);
+ Validator.ensureNotNull(expectedValues);
+ Validator.ensureTrue(expectedValues.length > 0, "should have at least one expected value");
+ attributes.put(expectedName, Arrays.asList(expectedValues));
+ }
+
+ /**
+ * Asserts that the entry was created.
+ */
+ public void assertEntryIsCreated() {
+ Assert.assertTrue(alreadyAdded);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void createEntry(Entry entry) throws ErrorResultException {
+ Assert.assertFalse(alreadyAdded);
+ Assert.assertEquals(entry.getName(), expectedDN);
+
+ Map<String, List<String>> expected = new HashMap<String, List<String>>(this.attributes);
+ for (Attribute attribute : entry.getAllAttributes()) {
+ String attrName = attribute.getAttributeDescription().getAttributeType().getNameOrOID();
+ List<String> values = expected.remove(attrName);
+ if (values == null) {
+ Assert.fail("Unexpected attribute " + attrName);
+ }
+ assertAttributeEquals(attribute, values);
+ }
+ if (!expected.isEmpty()) {
+ Assert.fail("Missing expected attributes: " + expected.keySet());
+ }
+
+ alreadyAdded = true;
+ }
+}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java
new file mode 100644
index 0000000..aa980df
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java
@@ -0,0 +1,70 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.testng.Assert;
+
+/**
+ * A mock LDAP connection which is used to verify that a delete subtree takes
+ * place.
+ */
+public final class DeleteSubtreeMockLDAPConnection extends MockLDAPConnection {
+
+ // Detect multiple calls.
+ private boolean alreadyDeleted = false;
+
+ // The expected DN.
+ private final DN expectedDN;
+
+ /**
+ * Create a new mock ldap connection for detecting subtree deletes.
+ *
+ * @param dn
+ * The expected subtree DN.
+ */
+ public DeleteSubtreeMockLDAPConnection(String dn) {
+ this.expectedDN = DN.valueOf(dn);
+ }
+
+ /**
+ * Asserts that the subtree was deleted.
+ */
+ public void assertSubtreeIsDeleted() {
+ Assert.assertTrue(alreadyDeleted);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void deleteSubtree(DN dn) throws ErrorResultException {
+ Assert.assertFalse(alreadyDeleted);
+ Assert.assertEquals(dn, expectedDN);
+ alreadyDeleted = true;
+ }
+}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java
new file mode 100644
index 0000000..f2d93ab
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java
@@ -0,0 +1,889 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import static org.fest.assertions.Assertions.*;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+
+import org.forgerock.opendj.admin.client.RootCfgClient;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.opends.server.admin.AdminTestCase;
+import org.opends.server.admin.Constraint;
+import org.opends.server.admin.ManagedObjectAlreadyExistsException;
+import org.opends.server.admin.ManagedObjectNotFoundException;
+import org.opends.server.admin.TestCfg;
+import org.opends.server.admin.TestChildCfgClient;
+import org.opends.server.admin.TestChildCfgDefn;
+import org.opends.server.admin.TestParentCfgClient;
+import org.opends.server.admin.TestParentCfgDefn;
+import org.opends.server.admin.client.ManagedObject;
+import org.opends.server.admin.client.ManagementContext;
+import org.opends.server.admin.client.OperationRejectedException;
+import org.opends.server.core.DirectoryServer;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+@Test(singleThreaded = true)
+public final class LDAPClientTest extends AdminTestCase {
+
+ // Test LDIF.
+ private static final String[] TEST_LDIF = new String[] {
+ // Base entries.
+ "dn: cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: config",
+ "",
+ "dn: cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: test-parents",
+ "",
+ // Parent 1 - uses default values for
+ // optional-multi-valued-dn-property.
+ "dn: cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-parent-dummy",
+ "cn: test parent 1",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "",
+ // Parent 2 - overrides default values for
+ // optional-multi-valued-dn-property.
+ "dn: cn=test parent 2,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-parent-dummy",
+ "cn: test parent 2",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-base-dn: dc=default value p2v1,dc=com",
+ "ds-cfg-base-dn: dc=default value p2v2,dc=com",
+ "",
+ // Parent 3 - overrides default values for
+ // optional-multi-valued-dn-property.
+ "dn: cn=test parent 3,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-parent-dummy",
+ "cn: test parent 3",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-base-dn: dc=default value p3v1,dc=com",
+ "ds-cfg-base-dn: dc=default value p3v2,dc=com",
+ "",
+ // Child base entries.
+ "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: multiple children",
+ "",
+ "dn:cn=test children,cn=test parent 2,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-branch",
+ "cn: multiple children",
+ "",
+ // Child 1 inherits defaults for both
+ // optional-multi-valued-dn-property1 and
+ // optional-multi-valued-dn-property2.
+ "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy",
+ "cn: test child 1",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "",
+ // Child 2 inherits defaults for
+ // optional-multi-valued-dn-property2.
+ "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy",
+ "cn: test child 2",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-base-dn: dc=default value c2v1,dc=com",
+ "ds-cfg-base-dn: dc=default value c2v2,dc=com",
+ "",
+ // Child 3 overrides defaults for
+ // optional-multi-valued-dn-property1 and
+ // optional-multi-valued-dn-property2.
+ "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config",
+ "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy",
+ "cn: test child 3",
+ "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description",
+ "ds-cfg-base-dn: dc=default value c3v1,dc=com",
+ "ds-cfg-base-dn: dc=default value c3v2,dc=com",
+ "ds-cfg-group-dn: dc=default value c3v3,dc=com",
+ "ds-cfg-group-dn: dc=default value c3v4,dc=com",
+ "",
+ // Child 4 inherits overridden defaults for both
+ // optional-multi-valued-dn-property1 and
+ // optional-multi-valued-dn-property2.
+ "dn: cn=test child 1,cn=test children,cn=test parent 2,cn=test parents,cn=config", "objectclass: top",
+ "objectclass: ds-cfg-test-child-dummy", "cn: test child 1", "ds-cfg-enabled: true",
+ "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider",
+ "ds-cfg-attribute-type: description", "", };
+
+ /**
+ * Provide valid naming exception to client API exception mappings.
+ *
+ * @return Returns valid naming exception to client API exception mappings.
+ */
+ @DataProvider(name = "createManagedObjectExceptions")
+ public Object[][] createManagedObjectExceptions() {
+ return new Object[][] {
+ // result code corresponding to exception thrown, expected exception, expected code result
+ { ResultCode.PROTOCOL_ERROR, ErrorResultException.class, ResultCode.PROTOCOL_ERROR },
+ { ResultCode.UNAVAILABLE , ErrorResultException.class, ResultCode.UNAVAILABLE },
+ { ResultCode.ENTRY_ALREADY_EXISTS, ManagedObjectAlreadyExistsException.class, null },
+ { ResultCode.INSUFFICIENT_ACCESS_RIGHTS, ErrorResultException.class,
+ ResultCode.INSUFFICIENT_ACCESS_RIGHTS },
+ { ResultCode.UNWILLING_TO_PERFORM, OperationRejectedException.class, null }
+ };
+ }
+
+ /**
+ * Provide valid naming exception to client API exception mappings.
+ *
+ * @return Returns valid naming exception to client API exception mappings.
+ */
+ @DataProvider(name = "getManagedObjectExceptions")
+ public Object[][] getManagedObjectExceptions() {
+ return new Object[][] {
+ // result code corresponding to exception thrown, expected exception, expected code result
+ { ResultCode.PROTOCOL_ERROR, ErrorResultException.class, ResultCode.PROTOCOL_ERROR },
+ { ResultCode.UNAVAILABLE, ErrorResultException.class, ResultCode.UNAVAILABLE },
+ { ResultCode.NO_SUCH_OBJECT, ManagedObjectNotFoundException.class, null },
+ { ResultCode.INSUFFICIENT_ACCESS_RIGHTS, ErrorResultException.class,
+ ResultCode.INSUFFICIENT_ACCESS_RIGHTS },
+ { ResultCode.UNWILLING_TO_PERFORM, ErrorResultException.class,
+ ResultCode.UNWILLING_TO_PERFORM }
+ };
+ }
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ disableClassValidationForProperties();
+ TestCfg.setUp();
+ }
+
+
+ @AfterClass
+ public void tearDown() {
+ TestCfg.cleanup();
+ }
+
+ /**
+ * Tests creation of a child managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testCreateChildManagedObject() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child new");
+ c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
+ c.addExpectedAttribute("ds-cfg-enabled", "true");
+ c.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ c.addExpectedAttribute("ds-cfg-attribute-type", "description");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
+ child.setMandatoryBooleanProperty(true);
+ child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ child.commit();
+
+ c.assertEntryIsCreated();
+ }
+
+ /**
+ * Tests creation of a top-level managed object using fails when an
+ * underlying exception occurs.
+ */
+ @Test(dataProvider = "createManagedObjectExceptions")
+ public void testCreateManagedObjectException(final ResultCode resultCodeOfThrownException,
+ Class<? extends Exception> expectedExceptionClass, ResultCode expectedCode) {
+ MockLDAPConnection conn = new MockLDAPConnection() {
+
+ @Override
+ public void createEntry(Entry entry) throws ErrorResultException {
+ throw ErrorResultException.newErrorResult(resultCodeOfThrownException);
+ }
+
+ };
+ conn.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(conn);
+ try {
+ TestParentCfgClient parent = createTestParent(ctx, "test parent new");
+ parent.setMandatoryBooleanProperty(true);
+ parent.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ parent.commit();
+ } catch (Exception e) {
+ if (expectedExceptionClass.equals(ErrorResultException.class)) {
+ assertThat(e).isInstanceOf(ErrorResultException.class);
+ assertThat(((ErrorResultException) e).getResult().getResultCode()).isEqualTo(expectedCode);
+ }
+ else {
+ assertThat(e).isInstanceOf(expectedExceptionClass);
+ }
+ }
+ }
+
+ /**
+ * Tests creation of a top-level managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testCreateTopLevelManagedObject() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test parent new,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test parent new");
+ c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-parent-dummy");
+ c.addExpectedAttribute("ds-cfg-enabled", "true");
+ c.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.SomeVirtualAttributeProvider");
+ c.addExpectedAttribute("ds-cfg-attribute-type", "description");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = createTestParent(ctx, "test parent new");
+ parent.setMandatoryBooleanProperty(true);
+ parent.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ parent.commit();
+ c.assertEntryIsCreated();
+ }
+
+ /**
+ * Tests retrieval of a child managed object with non-default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testGetChildManagedObject() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 3");
+ Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
+ Assert.assertEquals(child.getMandatoryClassProperty(),
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(),
+ DirectoryServer.getAttributeType("description"));
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value c3v1,dc=com",
+ "dc=default value c3v2,dc=com");
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value c3v3,dc=com",
+ "dc=default value c3v4,dc=com");
+ }
+
+ /**
+ * Tests retrieval of a child managed object with default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testGetChildManagedObjectDefault() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 1");
+ Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
+ Assert.assertEquals(child.getMandatoryClassProperty(),
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(),
+ DirectoryServer.getAttributeType("description"));
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=domain1,dc=com", "dc=domain2,dc=com",
+ "dc=domain3,dc=com");
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=domain1,dc=com", "dc=domain2,dc=com",
+ "dc=domain3,dc=com");
+ Assert.assertEquals(child.isMandatoryBooleanProperty(), Boolean.TRUE);
+ }
+
+ /**
+ * Tests retrieval of a top-level managed object fails when an underlying
+ * ErrorResultException occurs.
+ *
+ * @param cause
+ * The ErrorResultException cause of the failure.
+ * @param expected
+ * The expected client API exception class.
+ */
+ @Test(dataProvider = "getManagedObjectExceptions")
+ public void testGetManagedObjectException(final ResultCode resultCodeOfThrownException,
+ final Class<? extends Exception> expectedExceptionClass, final ResultCode expectedCode) {
+ MockLDAPConnection c = new MockLDAPConnection() {
+
+ @Override
+ public SearchResultEntry readEntry(DN dn, Collection<String> attrIds) throws ErrorResultException {
+ throw ErrorResultException.newErrorResult(resultCodeOfThrownException);
+ }
+
+ };
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ try {
+ getTestParent(ctx, "test parent 2");
+ } catch (Exception e) {
+ if (expectedExceptionClass.equals(ErrorResultException.class)) {
+ assertThat(e).isInstanceOf(ErrorResultException.class);
+ assertThat(((ErrorResultException) e).getResult().getResultCode()).isEqualTo(expectedCode);
+ }
+ else {
+ assertThat(e).isInstanceOf(expectedExceptionClass);
+ }
+ }
+ }
+
+ /**
+ * Tests retrieval of a top-level managed object with non-default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testGetTopLevelManagedObject() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
+ Assert.assertEquals(parent.isMandatoryBooleanProperty(), Boolean.TRUE);
+ Assert.assertEquals(parent.getMandatoryClassProperty(),
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(),
+ DirectoryServer.getAttributeType("description"));
+ assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(), "dc=default value p2v1,dc=com",
+ "dc=default value p2v2,dc=com");
+ }
+
+ /**
+ * Tests retrieval of a top-level managed object with default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testGetTopLevelManagedObjectDefault() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ Assert.assertEquals(parent.isMandatoryBooleanProperty(), Boolean.TRUE);
+ Assert.assertEquals(parent.getMandatoryClassProperty(),
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(),
+ DirectoryServer.getAttributeType("description"));
+ assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(), "dc=domain1,dc=com", "dc=domain2,dc=com",
+ "dc=domain3,dc=com");
+ }
+
+ /**
+ * Tests retrieval of relative inherited default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testInheritedDefaultValues1() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child new");
+ c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
+ c.addExpectedAttribute("ds-cfg-enabled", "true");
+ c.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ c.addExpectedAttribute("ds-cfg-attribute-type", "description");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
+
+ // Check pre-commit values.
+ Assert.assertEquals(child.isMandatoryBooleanProperty(), null);
+ Assert.assertEquals(child.getMandatoryClassProperty(),
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), null);
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=domain1,dc=com", "dc=domain2,dc=com",
+ "dc=domain3,dc=com");
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=domain1,dc=com", "dc=domain2,dc=com",
+ "dc=domain3,dc=com");
+
+ // Check that the default values are not committed.
+ child.setMandatoryBooleanProperty(true);
+ child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ child.commit();
+
+ c.assertEntryIsCreated();
+ }
+
+ /**
+ * Tests retrieval of relative inherited default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testInheritedDefaultValues2() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child new,cn=test children,cn=test parent 2,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child new");
+ c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
+ c.addExpectedAttribute("ds-cfg-enabled", "true");
+ c.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ c.addExpectedAttribute("ds-cfg-attribute-type", "description");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
+
+ // Check pre-commit values.
+ Assert.assertEquals(child.isMandatoryBooleanProperty(), null);
+ Assert.assertEquals(child.getMandatoryClassProperty(),
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), null);
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value p2v1,dc=com",
+ "dc=default value p2v2,dc=com");
+ assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value p2v1,dc=com",
+ "dc=default value p2v2,dc=com");
+
+ // Check that the default values are not committed.
+ child.setMandatoryBooleanProperty(true);
+ child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ child.commit();
+
+ c.assertEntryIsCreated();
+ }
+
+ /**
+ * Tests listing of child managed objects.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testListChildManagedObjects() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ String[] actual = parent.listTestChildren();
+ String[] expected = new String[] { "test child 1", "test child 2", "test child 3" };
+ Assert.assertEqualsNoOrder(actual, expected);
+ }
+
+ /**
+ * Tests listing of child managed objects when their are not any.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testListChildManagedObjectsEmpty() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 3");
+ String[] actual = parent.listTestChildren();
+ String[] expected = new String[] {};
+ Assert.assertEqualsNoOrder(actual, expected);
+ }
+
+ /**
+ * Tests listing of top level managed objects.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testListTopLevelManagedObjects() throws Exception {
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ String[] actual = listTestParents(ctx);
+ String[] expected = new String[] { "test parent 1", "test parent 2", "test parent 3" };
+ Assert.assertEqualsNoOrder(actual, expected);
+ }
+
+ /**
+ * Tests listing of top level managed objects when their are not any.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testListTopLevelManagedObjectsEmpty() throws Exception {
+ String[] ldif = {};
+ MockLDAPConnection c = new MockLDAPConnection();
+ c.importLDIF(ldif);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ String[] actual = listTestParents(ctx);
+ String[] expected = new String[] {};
+ Assert.assertEqualsNoOrder(actual, expected);
+ }
+
+ /**
+ * Tests modification of a child managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testModifyChildManagedObjectResetToDefault() throws Exception {
+ ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
+ "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedModification("ds-cfg-base-dn");
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 2");
+ child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
+ child.commit();
+ Assert.assertTrue(c.isEntryModified());
+ }
+
+ /**
+ * Tests modification of a top-level managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testModifyTopLevelManagedObjectNoChanges() throws Exception {
+ ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
+ "cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ parent.commit();
+ Assert.assertFalse(c.isEntryModified());
+ }
+
+ /**
+ * Tests modification of a top-level managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testModifyTopLevelManagedObjectWithChanges() throws Exception {
+ ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
+ "cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedModification("ds-cfg-enabled", "false");
+ c.addExpectedModification("ds-cfg-base-dn", "dc=mod1,dc=com", "dc=mod2,dc=com");
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ parent.setMandatoryBooleanProperty(false);
+ parent.setOptionalMultiValuedDNProperty(Arrays.asList(DN.valueOf("dc=mod1,dc=com"),
+ DN.valueOf("dc=mod2,dc=com")));
+ parent.commit();
+ Assert.assertTrue(c.isEntryModified());
+ }
+
+ /**
+ * Tests removal of a child managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testRemoveChildManagedObject() throws Exception {
+ DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
+ "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ parent.removeTestChild("test child 1");
+ c.assertSubtreeIsDeleted();
+ }
+
+ /**
+ * Tests removal of a top-level managed object.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testRemoveTopLevelManagedObject() throws Exception {
+ DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
+ "cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ removeTestParent(ctx, "test parent 1");
+ c.assertSubtreeIsDeleted();
+ }
+
+ /**
+ * Tests creation of a child managed object succeeds when registered add
+ * constraints succeed.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testAddConstraintSuccess() throws Exception {
+ Constraint constraint = new MockConstraint(true, false, false);
+ TestCfg.addConstraint(constraint);
+
+ try {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child new");
+ c.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
+ c.addExpectedAttribute("ds-cfg-enabled", "true");
+ c.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ c.addExpectedAttribute("ds-cfg-attribute-type", "description");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
+ child.setMandatoryBooleanProperty(true);
+ child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ child.commit();
+
+ c.assertEntryIsCreated();
+ } finally {
+ // Clean up.
+ TestCfg.removeConstraint(constraint);
+ }
+ }
+
+ /**
+ * Tests creation of a child managed object fails when registered add
+ * constraints fail.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test(expectedExceptions = OperationRejectedException.class)
+ public void testAddConstraintFail() throws Exception {
+ Constraint constraint = new MockConstraint(false, true, true);
+ TestCfg.addConstraint(constraint);
+
+ try {
+ CreateEntryMockLDAPConnection conn = new CreateEntryMockLDAPConnection(
+ "cn=test child new,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ conn.importLDIF(TEST_LDIF);
+ conn.addExpectedAttribute("cn", "test child new");
+ conn.addExpectedAttribute("objectClass", "top", "ds-cfg-test-child-dummy");
+ conn.addExpectedAttribute("ds-cfg-enabled", "true");
+ conn.addExpectedAttribute("ds-cfg-java-class",
+ "org.opends.server.extensions.UserDefinedVirtualAttributeProvider");
+ conn.addExpectedAttribute("ds-cfg-attribute-type", "description");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(conn);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn.getInstance(), "test child new", null);
+ child.setMandatoryBooleanProperty(true);
+ child.setMandatoryReadOnlyAttributeTypeProperty(DirectoryServer.getAttributeType("description"));
+ child.commit();
+ Assert.fail("The add constraint failed to prevent creation of the managed object");
+ } finally {
+ // Clean up.
+ TestCfg.removeConstraint(constraint);
+ }
+ }
+
+ /**
+ * Tests removal of a child managed object succeeds when registered remove
+ * constraints succeed.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testRemoveConstraintSuccess() throws Exception {
+ Constraint constraint = new MockConstraint(false, false, true);
+ TestCfg.addConstraint(constraint);
+
+ try {
+ DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
+ "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ parent.removeTestChild("test child 1");
+ c.assertSubtreeIsDeleted();
+ } finally {
+ // Clean up.
+ TestCfg.removeConstraint(constraint);
+ }
+ }
+
+ /**
+ * Tests removal of a child managed object fails when registered remove
+ * constraints fails.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test(expectedExceptions = OperationRejectedException.class)
+ public void testRemoveConstraintFail() throws Exception {
+ Constraint constraint = new MockConstraint(true, true, false);
+ TestCfg.addConstraint(constraint);
+
+ try {
+ DeleteSubtreeMockLDAPConnection c = new DeleteSubtreeMockLDAPConnection(
+ "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ parent.removeTestChild("test child 1");
+ Assert.fail("The remove constraint failed to prevent removal of the managed object");
+ } finally {
+ // Clean up.
+ TestCfg.removeConstraint(constraint);
+ }
+ }
+
+ /**
+ * Tests modification of a child managed object succeeds when registered
+ * remove constraints succeed.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testModifyConstraintSuccess() throws Exception {
+ Constraint constraint = new MockConstraint(false, true, false);
+ TestCfg.addConstraint(constraint);
+
+ try {
+ ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
+ "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedModification("ds-cfg-base-dn");
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 2");
+ child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
+ child.commit();
+ Assert.assertTrue(c.isEntryModified());
+ } finally {
+ // Clean up.
+ TestCfg.removeConstraint(constraint);
+ }
+ }
+
+ /**
+ * Tests modification of a child managed object fails when registered remove
+ * constraints fails.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test(expectedExceptions = OperationRejectedException.class)
+ public void testModifyConstraintFail() throws Exception {
+ Constraint constraint = new MockConstraint(true, false, true);
+ TestCfg.addConstraint(constraint);
+
+ try {
+ ModifyEntryMockLDAPConnection c = new ModifyEntryMockLDAPConnection(
+ "cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedModification("ds-cfg-base-dn");
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c);
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.getTestChild("test child 2");
+ child.setOptionalMultiValuedDNProperty1(Collections.<DN> emptySet());
+ child.commit();
+ Assert.fail("The modify constraint failed to prevent modification of the managed object");
+ } finally {
+ // Clean up.
+ TestCfg.removeConstraint(constraint);
+ }
+ }
+
+ // Asserts that the actual set of DNs contains the expected values.
+ private void assertDNSetEquals(SortedSet<DN> actual, String... expected) {
+ String[] actualStrings = new String[actual.size()];
+ int i = 0;
+ for (DN dn : actual) {
+ actualStrings[i] = dn.toString();
+ i++;
+ }
+ Assert.assertEqualsNoOrder(actualStrings, expected);
+ }
+
+ // Create the named test parent managed object.
+ private TestParentCfgClient createTestParent(ManagementContext context, String name)
+ throws Exception {
+ ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
+ return root.createChild(TestCfg.getTestOneToManyParentRelationDefinition(), TestParentCfgDefn.getInstance(),
+ name, null).getConfiguration();
+ }
+
+ // Retrieve the named test parent managed object.
+ private TestParentCfgClient getTestParent(ManagementContext context, String name)
+ throws Exception {
+ ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
+ return root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name).getConfiguration();
+ }
+
+ // List test parent managed objects.
+ private String[] listTestParents(ManagementContext context) throws Exception {
+ ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
+ return root.listChildren(TestCfg.getTestOneToManyParentRelationDefinition());
+ }
+
+ // Remove the named test parent managed object.
+ private void removeTestParent(ManagementContext context, String name) throws Exception {
+ ManagedObject<RootCfgClient> root = context.getRootConfigurationManagedObject();
+ root.removeChild(TestCfg.getTestOneToManyParentRelationDefinition(), name);
+ }
+}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java
new file mode 100644
index 0000000..cf2b024
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.opends.server.admin.Constraint;
+import org.opends.server.admin.ManagedObjectPath;
+import org.opends.server.admin.client.ClientConstraintHandler;
+import org.opends.server.admin.client.ManagedObject;
+import org.opends.server.admin.client.ManagementContext;
+import org.opends.server.admin.server.ServerConstraintHandler;
+
+/**
+ * A mock constraint which can be configured to refuse various types of
+ * operation.
+ */
+public final class MockConstraint extends Constraint {
+
+ /**
+ * Mock client constraint handler.
+ */
+ private class Handler extends ClientConstraintHandler {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAddAcceptable(ManagementContext context, ManagedObject<?> managedObject,
+ Collection<LocalizableMessage> unacceptableReasons) throws ErrorResultException {
+ if (!allowAdds) {
+ unacceptableReasons.add(LocalizableMessage.raw("Adds not allowed"));
+ }
+
+ return allowAdds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isDeleteAcceptable(ManagementContext context, ManagedObjectPath<?, ?> path,
+ Collection<LocalizableMessage> unacceptableReasons) throws ErrorResultException {
+ if (!allowDeletes) {
+ unacceptableReasons.add(LocalizableMessage.raw("Deletes not allowed"));
+ }
+
+ return allowDeletes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isModifyAcceptable(ManagementContext context, ManagedObject<?> managedObject,
+ Collection<LocalizableMessage> unacceptableReasons) throws ErrorResultException {
+ if (!allowModifies) {
+ unacceptableReasons.add(LocalizableMessage.raw("Modifies not allowed"));
+ }
+
+ return allowModifies;
+ }
+
+ }
+
+ // Determines if add operations are allowed.
+ private final boolean allowAdds;
+
+ // Determines if modify operations are allowed.
+ private final boolean allowModifies;
+
+ // Determines if delete operations are allowed.
+ private final boolean allowDeletes;
+
+ /**
+ * Creates a new mock constraint.
+ *
+ * @param allowAdds
+ * Determines if add operations are allowed.
+ * @param allowModifies
+ * Determines if modify operations are allowed.
+ * @param allowDeletes
+ * Determines if delete operations are allowed.
+ */
+ public MockConstraint(boolean allowAdds, boolean allowModifies, boolean allowDeletes) {
+ this.allowAdds = allowAdds;
+ this.allowModifies = allowModifies;
+ this.allowDeletes = allowDeletes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
+ return Collections.<ClientConstraintHandler> singleton(new Handler());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
+ return Collections.emptySet();
+ }
+
+}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java
new file mode 100644
index 0000000..1de1f4a
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java
@@ -0,0 +1,386 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2007-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import static org.fest.assertions.Assertions.*;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.AttributeDescription;
+import org.forgerock.opendj.ldap.AttributeParser;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.LinkedHashMapEntry;
+import org.forgerock.opendj.ldap.RDN;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.TestCaseUtils;
+import org.forgerock.opendj.ldap.controls.Control;
+import org.forgerock.opendj.ldap.controls.ControlDecoder;
+import org.forgerock.opendj.ldap.requests.ModifyRequest;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+
+/**
+ * A mock LDAP connection which fakes up search results based on some LDIF
+ * content. Implementations should override the modify operations in order to
+ * get provide the correct fake behavior.
+ */
+public class MockLDAPConnection extends LDAPConnection {
+
+ /**
+ * A mock entry.
+ */
+ private static final class MockEntry {
+
+ private final Entry entry;
+
+ private final List<MockEntry> children;
+
+ private final DN dn;
+
+ public MockEntry(DN dn, Entry entry) {
+ this.dn = dn;
+ this.entry = entry;
+ this.children = new LinkedList<MockEntry>();
+ }
+
+ public Entry getEntry() {
+ return entry;
+ }
+
+ public List<MockEntry> getChildren() {
+ return children;
+ }
+
+ public DN getDN() {
+ return dn;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("dn:");
+ builder.append(dn);
+ builder.append(", attributes:");
+ builder.append(entry.getAllAttributes());
+ return builder.toString();
+ }
+ }
+
+ /** All the entries. */
+ private final Map<DN, MockEntry> entries;
+
+ /** The single root entry. */
+ private final MockEntry rootEntry;
+
+ /**
+ * Create a mock connection.
+ */
+ public MockLDAPConnection() {
+ this.rootEntry = new MockEntry(DN.rootDN(), new LinkedHashMapEntry(DN.rootDN()));
+ this.entries = new HashMap<DN, MockEntry>();
+ this.entries.put(DN.rootDN(), this.rootEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createEntry(Entry entry) throws ErrorResultException {
+ throw new UnsupportedOperationException("createEntry");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deleteSubtree(DN dn) throws ErrorResultException {
+ throw new UnsupportedOperationException("deleteSubtree");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean entryExists(DN dn) throws ErrorResultException {
+ return getEntry(dn) != null;
+ }
+
+ /**
+ * Imports the provided LDIF into this mock connection.
+ *
+ * @param lines
+ * The LDIF.
+ */
+ public final void importLDIF(String... lines) {
+ try {
+ for (Entry entry : TestCaseUtils.makeEntries(lines)) {
+ addEntry(entry);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<DN> listEntries(DN dn, String filter) throws ErrorResultException {
+ MockEntry entry = getEntry(dn);
+
+ if (entry == null) {
+ throw ErrorResultException.newErrorResult(ResultCode.NO_SUCH_OBJECT, "Could not find entry: " + dn);
+ } else {
+ List<DN> names = new LinkedList<DN>();
+ for (MockEntry child : entry.children) {
+ names.add(DN.valueOf(child.getDN().toString()));
+ }
+ return names;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void modifyEntry(ModifyRequest request) throws ErrorResultException {
+ throw new UnsupportedOperationException("modifyEntry");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SearchResultEntry readEntry(DN dn, Collection<String> attrIds) throws ErrorResultException {
+ final MockEntry entry = getEntry(dn);
+ return new SearchResultEntry() {
+
+ public AttributeParser parseAttribute(String attributeDescription) {
+ throw new RuntimeException("not implemented");
+ }
+
+ public AttributeParser parseAttribute(AttributeDescription attributeDescription) {
+ throw new RuntimeException("not implemented");
+ }
+
+ public boolean containsControl(String oid) {
+ return false;
+ }
+
+ public SearchResultEntry setName(String dn) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public SearchResultEntry setName(DN dn) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public SearchResultEntry replaceAttribute(String attributeDescription, Object... values) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public boolean replaceAttribute(Attribute attribute) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public SearchResultEntry removeAttribute(String attributeDescription, Object... values) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public boolean removeAttribute(AttributeDescription attributeDescription) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public boolean removeAttribute(Attribute attribute, Collection<? super ByteString> missingValues) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public DN getName() {
+ return entry.getDN();
+ }
+
+ @Override
+ public List<Control> getControls() {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public <C extends Control> C getControl(ControlDecoder<C> decoder, DecodeOptions options) throws DecodeException {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public int getAttributeCount() {
+ return entry.getEntry().getAttributeCount();
+ }
+
+ @Override
+ public Attribute getAttribute(String attributeDescription) {
+ return entry.getEntry().getAttribute(attributeDescription);
+ }
+
+ @Override
+ public Attribute getAttribute(AttributeDescription attributeDescription) {
+ return entry.getEntry().getAttribute(attributeDescription);
+ }
+
+ @Override
+ public Iterable<Attribute> getAllAttributes(String attributeDescription) {
+ return entry.getEntry().getAllAttributes(attributeDescription);
+ }
+
+ @Override
+ public Iterable<Attribute> getAllAttributes(AttributeDescription attributeDescription) {
+ return entry.getEntry().getAllAttributes(attributeDescription);
+ }
+
+ @Override
+ public Iterable<Attribute> getAllAttributes() {
+ return entry.getEntry().getAllAttributes();
+ }
+
+ @Override
+ public boolean containsAttribute(String attributeDescription, Object... values) {
+ return entry.getEntry().containsAttribute(attributeDescription, values);
+ }
+
+ @Override
+ public boolean containsAttribute(Attribute attribute, Collection<? super ByteString> missingValues) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public SearchResultEntry clearAttributes() {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public SearchResultEntry addControl(Control control) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public SearchResultEntry addAttribute(String attributeDescription, Object... values) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public boolean addAttribute(Attribute attribute, Collection<? super ByteString> duplicateValues) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public boolean addAttribute(Attribute attribute) {
+ throw new RuntimeException("not implemented");
+ }
+ };
+ }
+
+ /**
+ * Asserts whether the provided attribute contains exactly the set of values
+ * contained in the provided collection.
+ *
+ * @param attr
+ * The attribute.
+ * @param values
+ * The expected values.
+ * @throws ErrorResultException
+ * If an unexpected problem occurred.
+ */
+ protected final void assertAttributeEquals(Attribute attr, Collection<String> values) throws ErrorResultException {
+ List<String> actualValues = new LinkedList<String>();
+ for (ByteString actualValue : attr) {
+ actualValues.add(actualValue.toString());
+ }
+
+ assertThat(actualValues).hasSize(values.size());
+ assertThat(actualValues).containsOnly(values.toArray());
+ }
+
+ /**
+ * Create a new mock entry.
+ *
+ * @param entry
+ * The entry to be added.
+ */
+ private void addEntry(Entry entry) {
+ MockEntry parent = rootEntry;
+ DN entryDN = entry.getName();
+
+ // Create required glue entries.
+ for (int i = 0; i < entryDN.size() - 1; i++) {
+ RDN rdn = entryDN.parent(entryDN.size() - i - 1).rdn();
+ DN dn = parent.getDN().child(rdn);
+
+ if (!entries.containsKey(dn)) {
+ MockEntry glue = new MockEntry(dn, new LinkedHashMapEntry(dn));
+ parent.getChildren().add(glue);
+ entries.put(dn, glue);
+ }
+
+ parent = entries.get(dn);
+ }
+
+ // We now have the parent entry - so construct the new entry.
+ MockEntry child = new MockEntry(entryDN, LinkedHashMapEntry.deepCopyOfEntry(entry));
+ parent.getChildren().add(child);
+ entries.put(entryDN, child);
+ }
+
+ /**
+ * Gets the named entry.
+ *
+ * @param dn
+ * The name of the entry.
+ * @return Returns the mock entry or <code>null</code> if it does not exist.
+ */
+ private MockEntry getEntry(DN dn) {
+ DN name = DN.valueOf(dn.toString());
+ return entries.get(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void unbind() {
+ // nothing to do
+ }
+
+}
diff --git a/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java
new file mode 100644
index 0000000..45e8c81
--- /dev/null
+++ b/opendj-sdk/opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java
@@ -0,0 +1,115 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin.client.ldap;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.Modification;
+import org.forgerock.opendj.ldap.requests.ModifyRequest;
+import org.testng.Assert;
+
+import com.forgerock.opendj.util.Validator;
+
+/**
+ * A mock LDAP connection which is used to verify that a modify operation was
+ * requested and that it has the correct parameters.
+ */
+public final class ModifyEntryMockLDAPConnection extends MockLDAPConnection {
+
+ // Detect multiple calls.
+ private boolean alreadyModified = false;
+
+ private final DN expectedDN;
+
+ // The expected set of modifications (attribute name -> list of
+ // values).
+ private final Map<String, List<String>> modifications = new HashMap<String, List<String>>();
+
+ /**
+ * Create a new mock ldap connection for detecting modify operations.
+ *
+ * @param dn
+ * The expected DN of the entry to be added.
+ */
+ public ModifyEntryMockLDAPConnection(String dn) {
+ this.expectedDN = DN.valueOf(dn);
+ }
+
+ /**
+ * Add a modification which should be part of the modify operation.
+ *
+ * @param expectedName
+ * The name of the expected attribute.
+ * @param expectedValues
+ * The attribute's expected new values (possibly empty if
+ * deleted).
+ */
+ public void addExpectedModification(String expectedName, String... expectedValues) {
+ Validator.ensureNotNull(expectedName);
+ Validator.ensureNotNull(expectedValues);
+ modifications.put(expectedName, Arrays.asList(expectedValues));
+ }
+
+ /**
+ * Determines whether or not the entry was modified.
+ *
+ * @return Returns <code>true</code> if it was modified.
+ */
+ public boolean isEntryModified() {
+ return alreadyModified;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyEntry(ModifyRequest request) throws ErrorResultException {
+ Assert.assertFalse(alreadyModified);
+ Assert.assertEquals(request.getName(), expectedDN);
+
+ Map<String, List<String>> expected = new HashMap<String, List<String>>(modifications);
+ for (Modification modification : request.getModifications()) {
+ Attribute attribute = modification.getAttribute();
+ String attrName = attribute.getAttributeDescription().getAttributeType().getNameOrOID();
+ List<String> values = expected.remove(attrName);
+ if (values == null) {
+ Assert.fail("Unexpected modification to attribute " + attrName);
+ }
+ assertAttributeEquals(attribute, values);
+ }
+ if (!expected.isEmpty()) {
+ Assert.fail("Missing modifications to: " + expected.keySet());
+ }
+
+ alreadyModified = true;
+ }
+}
--
Gitblit v1.10.0