/*
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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.server;
import static org.testng.Assert.*;
import java.util.List;
import org.opends.messages.Message;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.AdminTestCase;
import org.opends.server.admin.TestCfg;
import org.opends.server.admin.TestParentCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.config.ConfigEntry;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.ResultCode;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Test cases for listener registration.
*/
public final class ListenerTest extends AdminTestCase {
// Add listener implementation.
private static final class TestParentAddListener implements
ConfigurationAddListener<TestParentCfg> {
/**
* {@inheritDoc}
*/
public ConfigChangeResult applyConfigurationAdd(TestParentCfg configuration) {
// No implementation required.
return null;
}
/**
* {@inheritDoc}
*/
public boolean isConfigurationAddAcceptable(TestParentCfg configuration,
List<Message> unacceptableReasons) {
// No implementation required.
return false;
}
}
// Delete listener implementation.
private static final class TestParentDeleteListener implements
ConfigurationDeleteListener<TestParentCfg> {
/**
* {@inheritDoc}
*/
public ConfigChangeResult applyConfigurationDelete(
TestParentCfg configuration) {
// No implementation required.
return null;
}
/**
* {@inheritDoc}
*/
public boolean isConfigurationDeleteAcceptable(TestParentCfg configuration,
List<Message> unacceptableReasons) {
// No implementation required.
return false;
}
}
/**
* Sets up tests
*
* @throws Exception
* If the server could not be initialized.
*/
@BeforeClass
public void setUp() throws Exception {
// This test suite depends on having the schema available, so
// we'll start the server.
TestCaseUtils.startServer();
TestCfg.setUp();
}
/**
* Tears down test environment.
*/
@AfterClass
public void tearDown() {
TestCfg.cleanup();
}
/**
* Checks that a ConfigAddListenerAdaptor is delayed when its
* associated instantiable relation entry does not exist.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test
public void testConfigAddListenerAdaptorInstantiableDelayed()
throws Exception {
ServerManagementContext ctx = ServerManagementContext.getInstance();
ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
ConfigurationAddListener<TestParentCfg> listener = new TestParentAddListener();
root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), listener);
// Make sure that the relation entry does not exist.
DN relationDN = DN.decode("cn=test parents,cn=config");
ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNull(configEntry, "Relation entry " + relationDN + " already exists");
// Make sure that the listener was delayed and registered against
// the parent.
DN parentDN = DN.decode("cn=config");
configEntry = DirectoryServer.getConfigEntry(parentDN);
assertNotNull(configEntry, "Relation parent entry " + parentDN
+ " does not exist");
boolean isFound = false;
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof DelayedConfigAddListener) {
DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
ConfigAddListener tmp = dl.getDelayedAddListener();
if (tmp instanceof ConfigAddListenerAdaptor) {
ConfigAddListenerAdaptor<?> al = (ConfigAddListenerAdaptor<?>) tmp;
if (extractListener(al) == listener) {
isFound = true;
}
}
}
}
if (!isFound) {
fail("Unable to locate delayed listener in entry " + parentDN);
}
// Now make sure that the delayed listener is removed from the
// parent and the add listener register against the relation entry
// when it is created.
String[] entry = new String[] {
"dn: cn=test parents,cn=config",
"objectclass: top",
"objectclass: ds-cfg-branch",
"cn: test-parents"
};
TestCaseUtils.addEntry(entry);
// Check the delayed listener is removed.
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof DelayedConfigAddListener) {
DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
ConfigAddListener tmp = dl.getDelayedAddListener();
if (tmp instanceof ConfigAddListenerAdaptor) {
ConfigAddListenerAdaptor<?> al = (ConfigAddListenerAdaptor<?>) tmp;
if (extractListener(al) == listener) {
fail("Delayed listener still exists in entry " + parentDN
+ " when it should have been removed");
// Clean up.
configEntry.deregisterAddListener(dl);
}
}
}
}
// Check the add listener is registered.
configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNotNull(configEntry, "Relation entry " + relationDN
+ " does not exist");
isFound = false;
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof ConfigAddListenerAdaptor) {
ConfigAddListenerAdaptor<?> al = (ConfigAddListenerAdaptor<?>) l;
if (extractListener(al) == listener) {
isFound = true;
// Clean up.
configEntry.deregisterAddListener(al);
}
}
}
if (!isFound) {
fail("Unable to locate listener adaptor in entry " + relationDN);
}
// Remove the test entry.
InternalClientConnection conn = InternalClientConnection
.getRootConnection();
DeleteOperation deleteOperation = conn.processDelete(relationDN);
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Checks that a ConfigAddListenerAdaptor is not delayed when its
* associated instantiable relation entry already exists.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test
public void testConfigAddListenerAdaptorInstantiableImmediate()
throws Exception {
ServerManagementContext ctx = ServerManagementContext.getInstance();
ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
ConfigurationAddListener<TestParentCfg> listener = new TestParentAddListener();
root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), listener);
// Add the relation entry.
String[] entry = new String[] {
"dn: cn=test parents,cn=config",
"objectclass: top",
"objectclass: ds-cfg-branch",
"cn: test-parents"
};
TestCaseUtils.addEntry(entry);
// Make sure that the relation entry exist.
DN relationDN = DN.decode("cn=test parents,cn=config");
ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNotNull(configEntry, "Relation entry " + relationDN
+ " does not exist");
// Check the add listener is registered.
boolean isFound = false;
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof ConfigAddListenerAdaptor) {
ConfigAddListenerAdaptor<?> al = (ConfigAddListenerAdaptor<?>) l;
if (extractListener(al) == listener) {
isFound = true;
// Clean up.
configEntry.deregisterAddListener(al);
}
}
}
if (!isFound) {
fail("Unable to locate listener adaptor in entry " + relationDN);
}
// Remove the test entry.
InternalClientConnection conn = InternalClientConnection
.getRootConnection();
DeleteOperation deleteOperation = conn.processDelete(relationDN);
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Checks that a ConfigAddListenerAdaptor is registered for optional
* relations.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test
public void testConfigAddListenerAdaptorOptional() throws Exception {
ServerManagementContext ctx = ServerManagementContext.getInstance();
ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
ConfigurationAddListener<TestParentCfg> listener = new TestParentAddListener();
root.registerAddListener(TestCfg.getTestOneToZeroOrOneParentRelationDefinition(),
listener);
// Make sure that the relation entry exists.
DN relationDN = DN.decode("cn=config");
ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNotNull(configEntry, "Relation entry " + relationDN
+ " does not exist");
// Check the add listener is registered.
boolean isFound = false;
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof ConfigAddListenerAdaptor) {
ConfigAddListenerAdaptor<?> al = (ConfigAddListenerAdaptor<?>) l;
if (extractListener(al) == listener) {
isFound = true;
// Clean up.
configEntry.deregisterAddListener(al);
}
}
}
if (!isFound) {
fail("Unable to locate listener adaptor in entry " + relationDN);
}
}
/**
* Checks that a ConfigDeleteListenerAdaptor is delayed when its
* associated instantiable relation entry does not exist.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test
public void testConfigDeleteListenerAdaptorInstantiableDelayed()
throws Exception {
ServerManagementContext ctx = ServerManagementContext.getInstance();
ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
ConfigurationDeleteListener<TestParentCfg> listener = new TestParentDeleteListener();
root.registerDeleteListener(TestCfg.getTestOneToManyParentRelationDefinition(), listener);
// Make sure that the relation entry does not exist.
DN relationDN = DN.decode("cn=test parents,cn=config");
ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNull(configEntry, "Relation entry " + relationDN + " already exists");
// Make sure that the listener was delayed and registered against
// the parent.
DN parentDN = DN.decode("cn=config");
configEntry = DirectoryServer.getConfigEntry(parentDN);
assertNotNull(configEntry, "Relation parent entry " + parentDN
+ " does not exist");
boolean isFound = false;
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof DelayedConfigAddListener) {
DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
ConfigDeleteListener tmp = dl.getDelayedDeleteListener();
if (tmp instanceof ConfigDeleteListenerAdaptor) {
ConfigDeleteListenerAdaptor<?> al = (ConfigDeleteListenerAdaptor<?>) tmp;
if (extractListener(al) == listener) {
isFound = true;
}
}
}
}
if (!isFound) {
fail("Unable to locate delayed listener in entry " + parentDN);
}
// Now make sure that the delayed listener is removed from the
// parent and the add listener register against the relation entry
// when it is created.
String[] entry = new String[] {
"dn: cn=test parents,cn=config",
"objectclass: top",
"objectclass: ds-cfg-branch",
"cn: test-parents"
};
TestCaseUtils.addEntry(entry);
// Check the delayed listener is removed.
for (ConfigAddListener l : configEntry.getAddListeners()) {
if (l instanceof DelayedConfigAddListener) {
DelayedConfigAddListener dl = (DelayedConfigAddListener) l;
ConfigDeleteListener tmp = dl.getDelayedDeleteListener();
if (tmp instanceof ConfigDeleteListenerAdaptor) {
ConfigDeleteListenerAdaptor<?> al = (ConfigDeleteListenerAdaptor<?>) tmp;
if (extractListener(al) == listener) {
fail("Delayed listener still exists in entry " + parentDN
+ " when it should have been removed");
// Clean up.
configEntry.deregisterAddListener(dl);
}
}
}
}
// Check the add listener is registered.
configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNotNull(configEntry, "Relation entry " + relationDN
+ " does not exist");
isFound = false;
for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
if (l instanceof ConfigDeleteListenerAdaptor) {
ConfigDeleteListenerAdaptor<?> al = (ConfigDeleteListenerAdaptor<?>) l;
if (extractListener(al) == listener) {
isFound = true;
// Clean up.
configEntry.deregisterDeleteListener(al);
}
}
}
if (!isFound) {
fail("Unable to locate listener adaptor in entry " + relationDN);
}
// Remove the test entry.
InternalClientConnection conn = InternalClientConnection
.getRootConnection();
DeleteOperation deleteOperation = conn.processDelete(relationDN);
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Checks that a ConfigDeleteListenerAdaptor is not delayed when its
* associated instantiable relation entry already exists.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test
public void testConfigDeleteListenerAdaptorInstantiableImmediate()
throws Exception {
ServerManagementContext ctx = ServerManagementContext.getInstance();
ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
ConfigurationDeleteListener<TestParentCfg> listener = new TestParentDeleteListener();
root.registerDeleteListener(TestCfg.getTestOneToManyParentRelationDefinition(), listener);
// Add the relation entry.
String[] entry = new String[] {
"dn: cn=test parents,cn=config",
"objectclass: top",
"objectclass: ds-cfg-branch",
"cn: test-parents"
};
TestCaseUtils.addEntry(entry);
// Make sure that the relation entry exist.
DN relationDN = DN.decode("cn=test parents,cn=config");
ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNotNull(configEntry, "Relation entry " + relationDN
+ " does not exist");
// Check the add listener is registered.
boolean isFound = false;
for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
if (l instanceof ConfigDeleteListenerAdaptor) {
ConfigDeleteListenerAdaptor<?> al = (ConfigDeleteListenerAdaptor<?>) l;
if (extractListener(al) == listener) {
isFound = true;
// Clean up.
configEntry.deregisterDeleteListener(al);
}
}
}
if (!isFound) {
fail("Unable to locate listener adaptor in entry " + relationDN);
}
// Remove the test entry.
InternalClientConnection conn = InternalClientConnection
.getRootConnection();
DeleteOperation deleteOperation = conn.processDelete(relationDN);
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
}
/**
* Checks that a ConfigDeleteListenerAdaptor is registered for
* optional relations.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test
public void testConfigDeleteListenerAdaptorOptional() throws Exception {
ServerManagementContext ctx = ServerManagementContext.getInstance();
ServerManagedObject<RootCfg> root = ctx.getRootConfigurationManagedObject();
ConfigurationDeleteListener<TestParentCfg> listener = new TestParentDeleteListener();
root.registerDeleteListener(TestCfg.getTestOneToZeroOrOneParentRelationDefinition(),
listener);
// Make sure that the relation entry exists.
DN relationDN = DN.decode("cn=config");
ConfigEntry configEntry = DirectoryServer.getConfigEntry(relationDN);
assertNotNull(configEntry, "Relation entry " + relationDN
+ " does not exist");
// Check the add listener is registered.
boolean isFound = false;
for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
if (l instanceof ConfigDeleteListenerAdaptor) {
ConfigDeleteListenerAdaptor<?> al = (ConfigDeleteListenerAdaptor<?>) l;
if (extractListener(al) == listener) {
isFound = true;
// Clean up.
configEntry.deregisterDeleteListener(al);
}
}
}
if (!isFound) {
fail("Unable to locate listener adaptor in entry " + relationDN);
}
}
// Attempt to extract an add listener from the provided adaptor.
private ConfigurationAddListener<?> extractListener(
ConfigAddListenerAdaptor<?> al) {
ServerManagedObjectAddListener<?> al2 = al
.getServerManagedObjectAddListener();
if (al2 instanceof ServerManagedObjectAddListenerAdaptor) {
ServerManagedObjectAddListenerAdaptor<?> al3 =
(ServerManagedObjectAddListenerAdaptor<?>) al2;
return al3.getConfigurationAddListener();
}
return null;
}
// Attempt to extract a delete listener from the provided adaptor.
private ConfigurationDeleteListener<?> extractListener(
ConfigDeleteListenerAdaptor<?> al) {
ServerManagedObjectDeleteListener<?> al2 = al
.getServerManagedObjectDeleteListener();
if (al2 instanceof ServerManagedObjectDeleteListenerAdaptor) {
ServerManagedObjectDeleteListenerAdaptor<?> al3 =
(ServerManagedObjectDeleteListenerAdaptor<?>) al2;
return al3.getConfigurationDeleteListener();
}
return null;
}
}