From 93ff600530bef0b1acb70290b0d6cc38653e5fb9 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 09 Jul 2007 17:09:43 +0000
Subject: [PATCH] Update the access control API to get rid of the AccessControlProvider interface and move all of its methods into the abstract AccessControlHandler class. This makes the access control API more future-proof because the use of an interface would not allow the introduction of new methods into the API (such as will be required for issue #1861) without breaking backward compatibility, and potentially interfering with third-party implementations.
---
opends/src/server/org/opends/server/core/AccessControlConfigManager.java | 493 +++++++++++++++++++-----------------------------------
1 files changed, 178 insertions(+), 315 deletions(-)
diff --git a/opends/src/server/org/opends/server/core/AccessControlConfigManager.java b/opends/src/server/org/opends/server/core/AccessControlConfigManager.java
index d7923b2..6f68139 100644
--- a/opends/src/server/org/opends/server/core/AccessControlConfigManager.java
+++ b/opends/src/server/org/opends/server/core/AccessControlConfigManager.java
@@ -26,10 +26,10 @@
*/
package org.opends.server.core;
-import org.opends.server.types.DebugLogLevel;
+
+
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.ServerConstants.*;
@@ -48,25 +48,29 @@
import org.opends.server.admin.std.server.AccessControlHandlerCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.AccessControlHandler;
-import org.opends.server.api.AccessControlProvider;
import org.opends.server.api.AlertGenerator;
import org.opends.server.config.ConfigException;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
+
+
/**
* This class manages the application-wide access-control configuration.
* <p>
* When access control is disabled a default "permissive" access control
- * implementation is used, which permits all operations regardless of
- * the identity of the user.
+ * implementation is used, which permits all operations regardless of the
+ * identity of the user.
*/
public final class AccessControlConfigManager
- implements AlertGenerator
+ implements AlertGenerator ,
+ ConfigurationChangeListener<AccessControlHandlerCfg>
{
/**
* The tracer object for the debug logger.
@@ -81,48 +85,72 @@
private static AccessControlConfigManager instance = null;
// The active access control implementation.
- private AtomicReference<AccessControlProvider> accessControlProvider;
+ private AtomicReference<AccessControlHandler> accessControlHandler;
// The current configuration.
- private PrivateACLConfiguration currentConfiguration;
+ private AccessControlHandlerCfg currentConfiguration;
+
+
+
+ /**
+ * Creates a new instance of this access control configuration
+ * manager.
+ */
+ private AccessControlConfigManager()
+ {
+ this.accessControlHandler = new AtomicReference<AccessControlHandler>(
+ new DefaultAccessControlHandler());
+ this.currentConfiguration = null;
+ }
+
+
/**
* Get the single application-wide access control manager instance.
*
* @return The access control manager.
*/
- public static AccessControlConfigManager getInstance() {
-
- if (instance == null) {
+ public static AccessControlConfigManager getInstance()
+ {
+ if (instance == null)
+ {
instance = new AccessControlConfigManager();
}
+
return instance;
}
+
+
/**
* Determine if access control is enabled according to the current
* configuration.
*
- * @return Returns <code>true</code> if access control is enabled,
- * <code>false</code> otherwise.
+ * @return {@code true} if access control is enabled, {@code false}
+ * otherwise.
*/
- public boolean isAccessControlEnabled() {
+ public boolean isAccessControlEnabled()
+ {
return currentConfiguration.isEnabled();
}
+
+
/**
* Get the active access control handler.
* <p>
- * When access control is disabled, this method returns a default
- * access control implementation which permits all operations.
+ * When access control is disabled, this method returns a default access
+ * control implementation which permits all operations.
*
- * @return Returns the active access control handler (never
- * <code>null</code>).
+ * @return The active access control handler (never {@code null}).
*/
- public AccessControlHandler getAccessControlHandler() {
- return accessControlProvider.get().getInstance();
+ public AccessControlHandler getAccessControlHandler()
+ {
+ return accessControlHandler.get();
}
+
+
/**
* Initializes the access control sub-system. This should only be
* called at Directory Server startup. If an error occurs then an
@@ -137,9 +165,9 @@
* handler that is not related to the Directory Server
* configuration.
*/
- void initializeAccessControl() throws ConfigException,
- InitializationException {
-
+ public void initializeAccessControl()
+ throws ConfigException, InitializationException
+ {
// Get the root configuration object.
ServerManagementContext managementContext =
ServerManagementContext.getInstance();
@@ -153,371 +181,212 @@
AccessControlHandlerCfg accessControlConfiguration =
rootConfiguration.getAccessControlHandler();
- // Parse the configuration entry.
- PrivateACLConfiguration configuration = PrivateACLConfiguration
- .readConfiguration(accessControlConfiguration);
-
// We have a valid usable entry, so register a change listener in
// order to handle configuration changes.
- accessControlConfiguration.addChangeListener(new ChangeListener());
+ accessControlConfiguration.addChangeListener(this);
// The configuration looks valid, so install it.
- updateConfiguration(configuration);
+ updateConfiguration(accessControlConfiguration);
}
- /**
- * Creates a new instance of this access control configuration
- * manager.
- */
- private AccessControlConfigManager() {
- this.accessControlProvider = new AtomicReference<AccessControlProvider>(
- new DefaultAccessControlProvider());
- this.currentConfiguration = null;
- }
/**
* Updates the access control configuration based on the contents of a
* valid configuration entry.
*
- * @param newConfiguration
- * The new configuration object.
- * @throws ConfigException
- * If the access control configuration is invalid.
- * @throws InitializationException
- * If the access control handler provider could not be
- * instantiated.
+ * @param newConfiguration The new configuration object.
+ *
+ * @throws ConfigException If the access control configuration is invalid.
+ *
+ * @throws InitializationException If the access control handler provider
+ * could not be instantiated.
*/
- private void updateConfiguration(PrivateACLConfiguration newConfiguration)
- throws ConfigException, InitializationException {
+ private void updateConfiguration(AccessControlHandlerCfg newConfiguration)
+ throws ConfigException, InitializationException
+ {
+ DN configEntryDN = newConfiguration.dn();
+ String newHandlerClass = null;
- DN configEntryDN = newConfiguration.getConfiguration().dn();
- Class<? extends AccessControlProvider> newHandlerClass = null;
-
- if (currentConfiguration == null) {
+ if (currentConfiguration == null)
+ {
// Initialization phase.
- if (newConfiguration.isEnabled()) {
- newHandlerClass = newConfiguration.getProviderClass();
- } else {
- newHandlerClass = DefaultAccessControlProvider.class;
+ if (newConfiguration.isEnabled())
+ {
+ newHandlerClass = newConfiguration.getAclHandlerClass();
}
- } else {
+ else
+ {
+ newHandlerClass = DefaultAccessControlHandler.class.getName();
+ }
+ }
+ else
+ {
boolean enabledOld = currentConfiguration.isEnabled();
boolean enabledNew = newConfiguration.isEnabled();
- if (enabledOld == false && enabledNew == true) {
- // Access control has been enabled - load new class.
- newHandlerClass = newConfiguration.getProviderClass();
- } else if (enabledOld == true && enabledNew == false) {
- // Access control has been disabled - load null handler.
- newHandlerClass = DefaultAccessControlProvider.class;
- } else if (enabledNew == true) {
- // Access control is enabled - load new class if it has changed.
- if (currentConfiguration.getProviderClass().equals(
- newConfiguration.getProviderClass()) == false) {
- newHandlerClass = newConfiguration.getProviderClass();
- }
+ if ((! enabledOld) && enabledNew)
+ {
+ // Access control has been enabled - get the new class name.
+ newHandlerClass = newConfiguration.getAclHandlerClass();
+ }
+ else if (enabledOld && (! enabledNew))
+ {
+ // Access control has been disabled - get the default handler class
+ // name.
+ newHandlerClass = DefaultAccessControlHandler.class.getName();
+ }
+ else if (enabledNew)
+ {
+ // Access control is already enabled, but still get the handler class
+ // name to see if it has changed.
+ newHandlerClass = newConfiguration.getAclHandlerClass();
}
}
- // If the access control handler provider class has changed,
- // finalize the old
- // one and instantiate the new.
- if (newHandlerClass != null) {
- AccessControlProvider<? extends AccessControlHandlerCfg> newHandler ;
- try {
+ // If the access control handler provider class has changed, finalize the
+ // old one and instantiate the new one.
+ if (newHandlerClass != null)
+ {
+ AccessControlHandler<? extends AccessControlHandlerCfg> newHandler;
+ try
+ {
if (newConfiguration.isEnabled())
{
- newHandler = loadProvider(newHandlerClass.getName(), newConfiguration
- .getConfiguration());
+ newHandler = loadHandler(newHandlerClass, newConfiguration);
}
else
{
- newHandler = new DefaultAccessControlProvider();
+ newHandler = new DefaultAccessControlHandler();
newHandler.initializeAccessControlHandler(null);
}
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER;
- String message = getMessage(msgID, newHandlerClass.getName(),
- String.valueOf(configEntryDN.toString()),
- stackTraceToSingleLineString(e));
+ String message = getMessage(msgID, newHandlerClass,
+ String.valueOf(configEntryDN.toString()),
+ stackTraceToSingleLineString(e));
throw new InitializationException(msgID, message, e);
}
// Switch the handlers without interfering with other threads.
- AccessControlProvider oldHandler = accessControlProvider
- .getAndSet(newHandler);
+ AccessControlHandler oldHandler =
+ accessControlHandler.getAndSet(newHandler);
- if (oldHandler != null) {
+ if (oldHandler != null)
+ {
oldHandler.finalizeAccessControlHandler();
}
// If access control has been disabled put a warning in the log.
- if (newHandlerClass.equals(DefaultAccessControlProvider.class)) {
+ if (newHandlerClass.equals(DefaultAccessControlHandler.class))
+ {
int msgID = MSGID_CONFIG_AUTHZ_DISABLED;
String message = getMessage(msgID);
logError(ErrorLogCategory.CONFIGURATION,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+ ErrorLogSeverity.SEVERE_WARNING, message, msgID);
if (currentConfiguration != null)
{
DirectoryServer.sendAlertNotification(this,
- ALERT_TYPE_ACCESS_CONTROL_DISABLED, msgID, message);
+ ALERT_TYPE_ACCESS_CONTROL_DISABLED, msgID, message);
}
- } else {
+ }
+ else
+ {
int msgID = MSGID_CONFIG_AUTHZ_ENABLED;
- String message = getMessage(msgID, newHandlerClass.getName());
- logError(ErrorLogCategory.CONFIGURATION,
- ErrorLogSeverity.NOTICE, message, msgID);
+ String message = getMessage(msgID, newHandlerClass);
+ logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.NOTICE,
+ message, msgID);
if (currentConfiguration != null)
{
DirectoryServer.sendAlertNotification(this,
- ALERT_TYPE_ACCESS_CONTROL_ENABLED, msgID, message);
+ ALERT_TYPE_ACCESS_CONTROL_ENABLED, msgID, message);
}
}
}
// Switch in the local configuration.
- //
- // TODO: possible race condition here - should be an atomic
- // reference and sync'ed with the handler reference. We can assume
- // that config changes won't happen that much though.
currentConfiguration = newConfiguration;
}
+
+
/**
- * Internal class implementing the change listener interface.
+ * {@inheritDoc}
*/
- private class ChangeListener implements
- ConfigurationChangeListener<AccessControlHandlerCfg>
+ public boolean isConfigurationChangeAcceptable(
+ AccessControlHandlerCfg configuration,
+ List<String> unacceptableReasons)
{
-
- /**
- * {@inheritDoc}
- */
- public boolean isConfigurationChangeAcceptable(
- AccessControlHandlerCfg configuration,
- List<String> unacceptableReasons)
+ try
{
- try {
- // Parse the configuration entry.
- PrivateACLConfiguration.readConfiguration(configuration);
- } catch (ConfigException e) {
- unacceptableReasons.add(e.getMessage());
- return false;
+ // If the access control handler is disabled, we don't care about the
+ // configuration. If it is enabled, then all we care about is whether we
+ // can load the access control handler class.
+ if (configuration.isEnabled())
+ {
+ loadHandler(configuration.getAclHandlerClass(), null);
}
-
- return true;
+ }
+ catch (InitializationException e)
+ {
+ unacceptableReasons.add(e.getMessage());
+ return false;
}
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationChange(
- AccessControlHandlerCfg configuration)
- {
-
- ResultCode resultCode = ResultCode.SUCCESS;
- ArrayList<String> messages = new ArrayList<String>();
-
- try {
- // Parse the configuration entry.
- PrivateACLConfiguration newConfiguration = PrivateACLConfiguration
- .readConfiguration(configuration);
-
- // The configuration looks valid, so install it.
- updateConfiguration(newConfiguration);
- } catch (ConfigException e) {
- messages.add(e.getMessage());
- resultCode = ResultCode.CONSTRAINT_VIOLATION;
- } catch (InitializationException e) {
- messages.add(e.getMessage());
- resultCode = DirectoryServer.getServerErrorResultCode();
- }
-
- return new ConfigChangeResult(resultCode, false, messages);
- }
+ return true;
}
+
+
/**
- * Internal class used to represent the parsed configuration entry.
+ * {@inheritDoc}
*/
- private static class PrivateACLConfiguration {
+ public ConfigChangeResult applyConfigurationChange(
+ AccessControlHandlerCfg configuration)
+ {
+ ResultCode resultCode = ResultCode.SUCCESS;
+ ArrayList<String> messages = new ArrayList<String>();
- // Flag indicating whether or not access control is enabled.
- private boolean enabled;
-
- // The current access control provider class specified in
- // the configuration.
- private Class<? extends AccessControlProvider> providerClass;
-
- // The entry that this object is mapped to.
- private AccessControlHandlerCfg configuration;
-
- /**
- * Parses a configuration entry and, if it is valid, returns an
- * object representation of it.
- *
- * @param configuration
- * The access control configuration entry.
- * @return An object representation of the parsed configuration.
- * @throws ConfigException
- * If a the access control configuration is invalid.
- */
- public static PrivateACLConfiguration readConfiguration(
- AccessControlHandlerCfg configuration) throws ConfigException {
-
- // The access control configuration entry must have the correct
- // object class.
- if (configuration.getAclHandlerClass() == null) {
- int msgID = MSGID_CONFIG_AUTHZ_ENTRY_DOES_NOT_HAVE_OBJECT_CLASS;
- String message = getMessage(msgID, configuration.toString());
- throw new ConfigException(msgID, message);
- }
-
- // Parse the attributes.
- boolean enabled = configuration.isEnabled() ;
-
- Class<? extends AccessControlProvider> providerClass =
- getClassAttribute(configuration);
-
- return new PrivateACLConfiguration(configuration, enabled, providerClass);
+ try
+ {
+ // Attempt to install the new configuration.
+ updateConfiguration(configuration);
+ }
+ catch (ConfigException e)
+ {
+ messages.add(e.getMessage());
+ resultCode = ResultCode.CONSTRAINT_VIOLATION;
+ }
+ catch (InitializationException e)
+ {
+ messages.add(e.getMessage());
+ resultCode = DirectoryServer.getServerErrorResultCode();
}
- /**
- * Determine if access control is enabled according to the
- * configuration.
- *
- * @return Returns <code>true</code> if access control is enabled,
- * <code>false</code> otherwise.
- */
- public boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Get the access control provider class specified in the
- * configuration.
- *
- * @return Returns the {@link AccessControlProvider} class.
- */
- public Class<? extends AccessControlProvider> getProviderClass() {
- return providerClass;
- }
-
- /**
- * Get the configuration entry associated with this configuration
- * object.
- *
- * @return Returns the configuration entry.
- */
- public AccessControlHandlerCfg getConfiguration() {
- return configuration;
- }
-
- /**
- * Construct a new configuration object with the specified parsed
- * attribute values.
- *
- * @param configuration
- * The associated access control configuration entry.
- * @param enabled
- * The value of the enabled attribute.
- * @param providerClass
- * The access control provider class.
- */
- private PrivateACLConfiguration(
- AccessControlHandlerCfg configuration, boolean enabled,
- Class<? extends AccessControlProvider> providerClass) {
-
- this.configuration = configuration;
- this.enabled = enabled;
- this.providerClass = providerClass;
- }
-
-
- /**
- * Read the value of the attribute which indicates which access
- * control implementation class to use. This method checks the
- * validity of the class name.
- *
- * @param configuration
- * The access control configuration.
- * @return The access control provider class.
- * @throws ConfigException
- * If the class attribute could not be read or if it
- * contains an invalid class name.
- */
- private static Class<? extends AccessControlProvider> getClassAttribute(
- AccessControlHandlerCfg configuration) throws ConfigException {
-
- // If access control is enabled then make sure that the class
- // attribute is present.
- try {
- // Load the access control implementation class.
- String className = configuration.getAclHandlerClass();
- try {
- return DirectoryServer.loadClass(className).asSubclass(
- AccessControlProvider.class);
- } catch (ClassNotFoundException e) {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_LOAD_CLASS;
- String message = getMessage(msgID, className, String
- .valueOf(configuration.dn().toString()),
- getExceptionMessage(e));
- throw new ConfigException(msgID, message, e);
- } catch (ClassCastException e) {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_CONFIG_AUTHZ_BAD_CLASS;
- String message = getMessage(msgID, className, String
- .valueOf(configuration.dn().toString()),
- AccessControlProvider.class.getName(),
- getExceptionMessage(e));
- throw new ConfigException(msgID, message, e);
- }
- } catch (ConfigException e) {
- int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_DETERMINE_CLASS;
- String message = getMessage(msgID, configuration.dn()
- .toString(), getExceptionMessage(e));
- throw new ConfigException(msgID, message, e);
- }
- }
+ return new ConfigChangeResult(resultCode, false, messages);
}
/**
- * Retrieves the DN of the configuration entry with which this alert
- * generator is associated.
- *
- * @return The DN of the configuration entry with which this alert
- * generator is associated.
+ * {@inheritDoc}
*/
public DN getComponentEntryDN()
{
- return currentConfiguration.getConfiguration().dn();
+ return currentConfiguration.dn();
}
/**
- * Retrieves the fully-qualified name of the Java class for this
- * alert generator implementation.
- *
- * @return The fully-qualified name of the Java class for this
- * alert generator implementation.
+ * {@inheritDoc}
*/
public String getClassName()
{
@@ -527,15 +396,7 @@
/**
- * Retrieves information about the set of alerts that this generator
- * may produce. The map returned should be between the notification
- * type for a particular notification and the human-readable
- * description for that notification. This alert generator must not
- * generate any alerts with types that are not contained in this
- * list.
- *
- * @return Information about the set of alerts that this generator
- * may produce.
+ * {@inheritDoc}
*/
public LinkedHashMap<String,String> getAlerts()
{
@@ -549,6 +410,8 @@
return alerts;
}
+
+
/**
* Loads the specified class, instantiates it as a AccessControlProvider, and
* optionally initializes that instance.
@@ -564,21 +427,21 @@
* @throws InitializationException If a problem occurred while attempting to
* initialize the Access Control Provider.
*/
- private AccessControlProvider<? extends AccessControlHandlerCfg>
- loadProvider(String className,
- AccessControlHandlerCfg configuration)
+ private AccessControlHandler<? extends AccessControlHandlerCfg>
+ loadHandler(String className,
+ AccessControlHandlerCfg configuration)
throws InitializationException
{
try
{
AccessControlHandlerCfgDefn definition =
- AccessControlHandlerCfgDefn.getInstance();
+ AccessControlHandlerCfgDefn.getInstance();
ClassPropertyDefinition propertyDefinition =
definition.getAclHandlerClassPropertyDefinition();
- Class<? extends AccessControlProvider> providerClass =
- propertyDefinition.loadClass(className, AccessControlProvider.class);
- AccessControlProvider<? extends AccessControlHandlerCfg> provider =
- (AccessControlProvider<? extends AccessControlHandlerCfg>)
+ Class<? extends AccessControlHandler> providerClass =
+ propertyDefinition.loadClass(className, AccessControlHandler.class);
+ AccessControlHandler<? extends AccessControlHandlerCfg> provider =
+ (AccessControlHandler<? extends AccessControlHandlerCfg>)
providerClass.newInstance();
if (configuration != null)
--
Gitblit v1.10.0