/* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.admin.server; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.Configuration; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.messages.AdminMessages; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; /** * A skeleton implementation of a configuration manager. This type of * manager can be used for managing "optional" configurations (i.e. * where there is a one to zero or one relationship). *
* Configuration managers are responsible for initializing and * finalizing instances as required. During initialization, the * manager takes responsibility for loading and instantiating the * implementation class. It then initializes the implementation * instance by invoking a method having the following signature: * *
* void initializeXXX(YYY config) throws ConfigException, * InitializationException; ** * Where
XXX is the simple name of the instance type
* T, and YYY is the expected
* configuration type for the implementation, which is either the
* configuration type C or a sub-type thereof.
*
* @param
* It is safe to initialize the manager more than once. This is
* useful during testing as an easy way to set the manager's
* configuration.
*
* @param config
* The configuration (can be
* Sub-classes should usually implement this method using a call to
* the configuration's
* Sub-classes should usually implement this method using a call to
* the configuration's null if there
* is no initial configuration.
* @throws ConfigException
* If there is a problem with the configuration.
* @throws InitializationException
* If a problem occurs during initialization.
*/
public final void initialize(C config) throws ConfigException,
InitializationException {
// Register to be notified when a configuration is added or
// removed (only do this once).
if (!listenersRegistered) {
registerAddListener(addListener);
registerDeleteListener(deleteListener);
listenersRegistered = true;
}
// Make sure that there is no current instance.
instance = null;
if (config != null) {
// Always register as a listener.
setConfiguration(config);
if (isEnabled(config)) {
// We have a configuration and it is enabled.
doRegisterInstance(getImplementation(config));
} else {
// There is a configuration present but it is disabled. Don't
// process the configuration in case it is invalid. We don't
// want to issue warnings for components which are disabled.
notifyDisableInstance(config);
}
}
}
/**
* Deregisters an add listener.
*
* @param listener
* The configuration add listener.
*/
protected abstract void deregisterAddListener(
ConfigurationAddListenergetJavaImplementationClass()
* method.
*
* @param config
* The active configuration.
* @return Returns the name of the Java implementation class.
*/
protected abstract String getJavaImplementationClass(C config);
/**
* Indicates whether the active instance can be disabled or deleted.
*
* @param config
* The configuration that will be disabled or deleted.
* @param unacceptableReasons
* A list that can be used to hold messages about why the
* active instance cannot be disabled or deleted..
* @return Returns true if the active instance can be
* disabled or deleted.
*/
protected abstract boolean isDisableInstanceAcceptable(C config,
ListisEnabled() method.
*
* @param config
* The active configuration.
* @return Returns true if the configuration is
* enabled.
*/
protected abstract boolean isEnabled(C config);
/**
* Notify that the configuration has been deleted. This may involve
* logging a message. Implementations do not need to worry about
* finalizing the instance, since that is performed by the
* {@link #finalizeInstance(Object)} method.
*
* @param config
* The deleted configuration.
*/
protected abstract void notifyDeleteInstance(C config);
/**
* Notify that the configuration has been disabled. This may involve
* logging a message. Implementations do not need to worry about
* finalizing the instance, since that is performed by the
* {@link #finalizeInstance(Object)} method.
*
* @param config
* The disabled configuration.
*/
protected abstract void notifyDisableInstance(C config);
/**
* Register to be notified when the configuration is added.
*
* @param listener
* The configuration add listener.
* @throws ConfigException
* If the add listener could not be registered.
*/
protected abstract void registerAddListener(
ConfigurationAddListenerinitialize(C config)
* against the instance.
*
* @param instance
* The new instance.
* @throws InitializationException
* If a problem occurs during initialization.
*/
protected abstract void registerInstance(T instance)
throws InitializationException;
// Notify listeners that a new instance has been added and/or
// enabled.
private void doRegisterInstance(T instance)
throws InitializationException {
this.instance = instance;
// Let sub-class implementation decide what to do with the new
// instance.
registerInstance(instance);
}
// Load, instantiate, and initialize the class named in the Java
// implementation class property of the provided configuration.
private T getImplementation(C config) throws ConfigException {
String className = getJavaImplementationClass(config);
// Load the class and cast it to a T.
Class extends T> implClass;
T instance;
try {
implClass = propertyDefinition.loadClass(className, theClass);
instance = implClass.newInstance();
} catch (Exception e) {
int msgID = AdminMessages.MSGID_ADMIN_CANNOT_INSTANTIATE_CLASS;
String message = getMessage(msgID, String.valueOf(className),
String.valueOf(config.dn()),
stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
}
// Perform the necessary initialization for the instance.
try {
// Determine the initialization method to use: it must take a
// single parameter which is the exact type of the configuration
// object.
String name = getInitializationMethodName();
Method method = implClass.getMethod(name, config.definition()
.getServerConfigurationClass());
method.invoke(instance, config);
} catch (Exception e) {
int msgID = AdminMessages.MSGID_ADMIN_CANNOT_INITIALIZE_COMPONENT;
String message = getMessage(msgID, String.valueOf(className),
String.valueOf(config.dn()),
stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
}
// The instance has been successfully initialized.
return instance;
}
// Get the name of the method which should be used
// to initialize instances.
private String getInitializationMethodName() {
return "initialize" + theClass.getSimpleName();
}
// Determines whether or not the new configuration's implementation
// class is acceptable.
private boolean isJavaClassAcceptable(C config,
List