* {@inheritDoc}
*/
public ConfigChangeResult applyConfigurationChange(BackendCfg cfg)
{
DN backendDN = cfg.dn();
Backend backend = registeredBackends.get(backendDN);
ResultCode resultCode = ResultCode.SUCCESS;
boolean adminActionRequired = false;
ArrayList<Message> messages = new ArrayList<Message>();
// See if the entry contains an attribute that indicates whether the
// backend should be enabled.
boolean needToEnable = false;
try
{
if (cfg.isEnabled())
{
// The backend is marked as enabled. See if that is already true.
if (backend == null)
{
needToEnable = true;
}
else
{
// It's already enabled, so we don't need to do anything.
}
}
else
{
// The backend is marked as disabled. See if that is already true.
if (backend != null)
{
// It isn't disabled, so we will do so now and deregister it from the
// Directory Server.
registeredBackends.remove(backendDN);
DirectoryServer.deregisterBackend(backend);
for (BackendInitializationListener listener :
DirectoryServer.getBackendInitializationListeners())
{
listener.performBackendFinalizationProcessing(backend);
}
backend.finalizeBackend();
// Remove the shared lock for this backend.
try
{
String lockFile = LockFileManager.getBackendLockFileName(backend);
StringBuilder failureReason = new StringBuilder();
if (! LockFileManager.releaseLock(lockFile, failureReason))
{
Message message = WARN_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK.
get(backend.getBackendID(), String.valueOf(failureReason));
logError(message);
// FIXME -- Do we need to send an admin alert?
}
}
catch (Exception e2)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e2);
}
Message message = WARN_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK.
get(backend.getBackendID(), stackTraceToSingleLineString(e2));
logError(message);
// FIXME -- Do we need to send an admin alert?
}
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
else
{
// It's already disabled, so we don't need to do anything.
}
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
messages.add(ERR_CONFIG_BACKEND_UNABLE_TO_DETERMINE_ENABLED_STATE.get(
String.valueOf(backendDN), stackTraceToSingleLineString(e)));
resultCode = DirectoryServer.getServerErrorResultCode();
return new ConfigChangeResult(resultCode, adminActionRequired, messages);
}
// See if the entry contains an attribute that specifies the backend ID for
// the backend.
String backendID = cfg.getBackendId();
// See if the entry contains an attribute that specifies the writability
// mode.
WritabilityMode writabilityMode = WritabilityMode.ENABLED;
BackendCfgDefn.WritabilityMode bwm =
cfg.getWritabilityMode();
switch (bwm)
{
case DISABLED:
writabilityMode = WritabilityMode.DISABLED;
break;
case ENABLED:
writabilityMode = WritabilityMode.ENABLED;
break;
case INTERNAL_ONLY:
writabilityMode = WritabilityMode.INTERNAL_ONLY;
break;
}
// See if the entry contains an attribute that specifies the base DNs for
// the backend.
Set<DN> baseList = cfg.getBaseDN();
DN[] baseDNs = new DN[baseList.size()];
baseList.toArray(baseDNs);
// See if the entry contains an attribute that specifies the class name
// for the backend implementation. If it does, then load it and make sure
// that it's a valid backend implementation. There is no such attribute,
// the specified class cannot be loaded, or it does not contain a valid
// backend implementation, then log an error and skip it.
String className = cfg.getJavaClass();
// See if this backend is currently active and if so if the name of the
// class is the same.
if (backend != null)
{
if (! className.equals(backend.getClass().getName()))
{
// It is not the same. Try to load it and see if it is a valid backend
// implementation.
try
{
Class backendClass = DirectoryServer.loadClass(className);
if (Backend.class.isAssignableFrom(backendClass))
{
// It appears to be a valid backend class. We'll return that the
// change is successful, but indicate that some administrative
// action is required.
messages.add(
NOTE_CONFIG_BACKEND_ACTION_REQUIRED_TO_CHANGE_CLASS.get(
String.valueOf(backendDN),
backend.getClass().getName(), className));
adminActionRequired = true;
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
else
{
// It is not a valid backend class. This is an error.
messages.add(ERR_CONFIG_BACKEND_CLASS_NOT_BACKEND.get(
String.valueOf(className), String.valueOf(backendDN)));
resultCode = ResultCode.CONSTRAINT_VIOLATION;
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
messages.add(ERR_CONFIG_BACKEND_CANNOT_INSTANTIATE.get(
String.valueOf(className), String.valueOf(backendDN),
stackTraceToSingleLineString(e)));
resultCode = DirectoryServer.getServerErrorResultCode();
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
}
}
// If we've gotten here, then that should mean that we need to enable the
// backend. Try to do so.
if (needToEnable)
{
Class backendClass;
try
{
backendClass = DirectoryServer.loadClass(className);
backend = (Backend) backendClass.newInstance();
}
catch (Exception e)
{
// It is not a valid backend class. This is an error.
messages.add(ERR_CONFIG_BACKEND_CLASS_NOT_BACKEND.get(
String.valueOf(className), String.valueOf(backendDN)));
resultCode = ResultCode.CONSTRAINT_VIOLATION;
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
// Set the backend ID and writability mode for this backend.
backend.setBackendID(backendID);
backend.setWritabilityMode(writabilityMode);
// Acquire a shared lock on this backend. This will prevent operations
// like LDIF import or restore from occurring while the backend is active.
try
{
String lockFile = LockFileManager.getBackendLockFileName(backend);
StringBuilder failureReason = new StringBuilder();
if (! LockFileManager.acquireSharedLock(lockFile, failureReason))
{
Message message = ERR_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK.get(
backendID, String.valueOf(failureReason));
logError(message);
// FIXME -- Do we need to send an admin alert?
resultCode = ResultCode.CONSTRAINT_VIOLATION;
adminActionRequired = true;
messages.add(message);
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_CONFIG_BACKEND_CANNOT_ACQUIRE_SHARED_LOCK.get(
backendID, stackTraceToSingleLineString(e));
logError(message);
// FIXME -- Do we need to send an admin alert?
resultCode = ResultCode.CONSTRAINT_VIOLATION;
adminActionRequired = true;
messages.add(message);
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
try
{
initializeBackend(backend, cfg);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
messages.add(ERR_CONFIG_BACKEND_CANNOT_INITIALIZE.get(
String.valueOf(className), String.valueOf(backendDN),
stackTraceToSingleLineString(e)));
resultCode = DirectoryServer.getServerErrorResultCode();
try
{
String lockFile = LockFileManager.getBackendLockFileName(backend);
StringBuilder failureReason = new StringBuilder();
if (! LockFileManager.releaseLock(lockFile, failureReason))
{
Message message = WARN_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK.
get(backendID, String.valueOf(failureReason));
logError(message);
// FIXME -- Do we need to send an admin alert?
}
}
catch (Exception e2)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e2);
}
Message message = WARN_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK.get(
backendID, stackTraceToSingleLineString(e2));
logError(message);
// FIXME -- Do we need to send an admin alert?
}
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
// Notify any backend initialization listeners.
for (BackendInitializationListener listener :
DirectoryServer.getBackendInitializationListeners())
{
listener.performBackendInitializationProcessing(backend);
}
// Register the backend with the server.
try
{
DirectoryServer.registerBackend(backend);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(
backendID, getExceptionMessage(e));
resultCode = DirectoryServer.getServerErrorResultCode();
messages.add(message);
logError(message);
// FIXME -- Do we need to send an admin alert?
return new ConfigChangeResult(resultCode, adminActionRequired,
messages);
}
registeredBackends.put(backendDN, backend);
}
else if ((resultCode == ResultCode.SUCCESS) && (backend != null))
{
// The backend is already enabled, so we may need to apply a
// configuration change. Check to see if the writability mode has been
// changed.
if (writabilityMode != backend.getWritabilityMode())
{
backend.setWritabilityMode(writabilityMode);
}
}
return new ConfigChangeResult(resultCode, adminActionRequired, messages);