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. 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; } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/AggregationClientTest.java
New file @@ -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); } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/CreateEntryMockLDAPConnection.java
New file @@ -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; } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/DeleteSubtreeMockLDAPConnection.java
New file @@ -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; } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/LDAPClientTest.java
New file @@ -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); } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockConstraint.java
New file @@ -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(); } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/MockLDAPConnection.java
New file @@ -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 } } opendj-admin/src/test/java/org/opends/server/admin/client/ldap/ModifyEntryMockLDAPConnection.java
New file @@ -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; } }