From c2d0d212b510d8e82b9b123b4d06a80b835c8cd4 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 06 Dec 2013 16:52:01 +0000
Subject: [PATCH] OpenDJ 3 : config framework
---
opendj-admin/src/main/resources/com/forgerock/opendj/ldap/extension.properties | 1016 ++++++++++
opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java | 2375 ++++++++++-------------
opendj-admin/src/main/java/org/opends/server/admin/ACIPropertyDefinition.java | 1
opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/AciException.java | 78
opendj-admin/src/main/resources/stylesheets/catalog.xml | 5
opendj-admin/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java | 3
opendj-admin/pom.xml | 29
opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java | 37
opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/Aci.java | 12
opendj-admin/src/main/java/org/opends/server/admin/Reference.java | 342 +-
opendj-admin/src/main/java/org/opends/server/config/ConfigurationRepository.java | 47
opendj-admin/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java | 4
opendj-admin/src/main/java/org/opends/server/config/ConfigEntry.java | 15
opendj-admin/src/main/java/org/opends/server/admin/DefaultBehaviorException.java | 2
opendj-admin/src/main/resources/com/forgerock/opendj/ldap/admin.properties | 7
opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagedObject.java | 29
opendj-admin/src/main/java/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java | 485 ++--
opendj-admin/src/main/java/org/opends/server/admin/ClassLoaderProvider.java | 1336 ++++++-------
opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagementContext.java | 229 -
opendj-admin/src/main/resources/stylesheets/admin.xsd | 2
20 files changed, 3,369 insertions(+), 2,685 deletions(-)
diff --git a/opendj-admin/pom.xml b/opendj-admin/pom.xml
index 7ac4e87..af9dd40 100644
--- a/opendj-admin/pom.xml
+++ b/opendj-admin/pom.xml
@@ -56,12 +56,12 @@
com.sun.security.auth*;resolution:=optional,
*
</opendj.osgi.import>
- <xmlDefinitionsBaseDir>src/main/resources/definitions</xmlDefinitionsBaseDir>
+ <xmlDefinitionsBaseDir>${basedir}/src/main/resources/definitions</xmlDefinitionsBaseDir>
<xmlDefinitionsDir>${xmlDefinitionsBaseDir}/org/forgerock/opendj/admin</xmlDefinitionsDir>
<adminPackage>org/forgerock/opendj/admin</adminPackage>
<generatedSourcesDir>${project.build.directory}/generated-sources/admin/${adminPackage}</generatedSourcesDir>
- <xslDir>src/main/resources/stylesheets</xslDir>
-
+ <xslDir>${basedir}/src/main/resources/stylesheets</xslDir>
+
<!-- properties used to generate DynamicConstant class -->
<serverProductName>OpenDJ</serverProductName>
<serverShortProductName>OpenDJ</serverShortProductName>
@@ -87,6 +87,7 @@
<messageFiles>
<messageFile>com/forgerock/opendj/ldap/admin.properties</messageFile>
<messageFile>com/forgerock/opendj/ldap/config.properties</messageFile>
+ <messageFile>com/forgerock/opendj/ldap/extension.properties</messageFile>
<messageFile>com/forgerock/opendj/ldap/protocol.properties</messageFile>
</messageFiles>
</configuration>
@@ -99,8 +100,28 @@
<artifactId>xml-maven-plugin</artifactId>
<version>1.0</version>
<executions>
+ <!-- Validate core components XML definition files -->
+ <execution>
+ <id>validate-core-components</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ <configuration>
+ <validationSets>
+ <validationSet>
+ <dir>${xmlDefinitionsDir}</dir>
+ <systemId>${xslDir}/admin.xsd</systemId>
+ </validationSet>
+ </validationSets>
+ <catalogs>
+ <catalog>${xslDir}/catalog.xml</catalog>
+ </catalogs>
+ </configuration>
+ </execution>
<execution>
<id>generate-core-components</id>
+ <phase>generate-sources</phase>
<goals>
<goal>transform</goal>
</goals>
@@ -427,8 +448,6 @@
</executions>
</plugin>
</plugins>
- <pluginManagement>
- </pluginManagement>
</build>
<reporting>
<plugins>
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/ACIPropertyDefinition.java b/opendj-admin/src/main/java/org/opends/server/admin/ACIPropertyDefinition.java
index 75b597c..c9d3d05 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/ACIPropertyDefinition.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/ACIPropertyDefinition.java
@@ -30,6 +30,7 @@
import static com.forgerock.opendj.util.Validator.*;
import org.opends.server.authorization.dseecompat.Aci;
+import org.opends.server.authorization.dseecompat.AciException;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java b/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java
index 33d3c7b..651b95e 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java
@@ -26,6 +26,10 @@
*/
package org.opends.server.admin;
+import static com.forgerock.opendj.ldap.AdminMessages.*;
+import static com.forgerock.opendj.util.StaticUtils.*;
+import static com.forgerock.opendj.util.Validator.*;
+
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
@@ -53,7 +57,11 @@
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.config.ConfigException;
import org.opends.server.types.ConfigChangeResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.admin.meta.RootCfgDefn;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ResultCode;
@@ -260,13 +268,13 @@
}
} catch (ConfigException e) {
// The condition could not be evaluated.
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- LocalizableMessage message = ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION.get(mo.getManagedObjectDefinition()
- .getUserFriendlyName(), String.valueOf(mo.getDN()), StaticUtils.getExceptionLocalizableMessage(e));
- ErrorLogger.logError(message);
+ debugLogger.trace("Unable to perform post add", e);
+ LocalizableMessage message = ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION.get(mo
+ .getManagedObjectDefinition().getUserFriendlyName(), String.valueOf(mo.getDN()),
+ getExceptionMessage(e));
+ LocalizedLogger logger = LocalizedLogger
+ .getLocalizedLogger(ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION.resourceName());
+ logger.error(message);
unacceptableReasons.add(message);
return false;
}
@@ -504,12 +512,14 @@
try {
ref = context.getManagedObject(path);
} catch (DefinitionDecodingException e) {
- LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name, getName(), e.getLocalizableMessageObject());
+ LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name, getName(),
+ e.getMessageObject());
unacceptableReasons.add(msg);
isAcceptable = false;
continue;
} catch (ManagedObjectDecodingException e) {
- LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name, getName(), e.getLocalizableMessageObject());
+ LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name, getName(),
+ e.getMessageObject());
unacceptableReasons.add(msg);
isAcceptable = false;
continue;
@@ -688,11 +698,6 @@
}
/**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- /**
* Creates an aggregation property definition builder.
*
* @param <C>
@@ -713,6 +718,8 @@
return new Builder<C, S>(d, propertyName);
}
+ private static final Logger debugLogger = LoggerFactory.getLogger(AggregationPropertyDefinition.class);
+
// The active server-side referential integrity change listeners
// associated with this property.
private final Map<DN, List<ReferentialIntegrityChangeListener>> changeListeners = new HashMap<DN, List<ReferentialIntegrityChangeListener>>();
@@ -902,7 +909,7 @@
ManagedObjectDefinitionI18NResource resource = ManagedObjectDefinitionI18NResource.getInstance();
String property = "property." + getName() + ".syntax.aggregation.constraint-synopsis";
try {
- return resource.getLocalizableMessage(getManagedObjectDefinition(), property, locale);
+ return resource.getMessage(getManagedObjectDefinition(), property, locale);
} catch (MissingResourceException e) {
return null;
}
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/ClassLoaderProvider.java b/opendj-admin/src/main/java/org/opends/server/admin/ClassLoaderProvider.java
index ca8e856..ec8166e 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/ClassLoaderProvider.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/ClassLoaderProvider.java
@@ -27,8 +27,9 @@
*/
package org.opends.server.admin;
-
-
+import static com.forgerock.opendj.ldap.AdminMessages.*;
+import static com.forgerock.opendj.ldap.ExtensionMessages.*;
+import static com.forgerock.opendj.util.StaticUtils.*;
import static com.forgerock.opendj.util.Validator.*;
import java.io.ByteArrayOutputStream;
@@ -54,767 +55,664 @@
import java.util.jar.Manifest;
import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.admin.meta.RootCfgDefn;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.InitializationException;
+import org.opends.server.util.DynamicConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.forgerock.opendj.ldap.AdminMessages;
/**
- * Manages the class loader which should be used for loading
- * configuration definition classes and associated extensions.
+ * Manages the class loader which should be used for loading configuration
+ * definition classes and associated extensions.
* <p>
- * For extensions which define their own extended configuration
- * definitions, the class loader will make sure that the configuration
- * definition classes are loaded and initialized.
+ * For extensions which define their own extended configuration definitions, the
+ * class loader will make sure that the configuration definition classes are
+ * loaded and initialized.
* <p>
* Initially the class loader provider is disabled, and calls to the
- * {@link #getClassLoader()} will return the system default class
- * loader.
+ * {@link #getClassLoader()} will return the system default class loader.
* <p>
- * Applications <b>MUST NOT</b> maintain persistent references to the
- * class loader as it can change at run-time.
+ * Applications <b>MUST NOT</b> maintain persistent references to the class
+ * loader as it can change at run-time.
*/
public final class ClassLoaderProvider {
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- /**
- * Private URLClassLoader implementation. This is only required so
- * that we can provide access to the addURL method.
- */
- private static final class MyURLClassLoader extends URLClassLoader {
+ private static final LocalizedLogger adminLogger = LocalizedLogger.getLocalizedLogger(AdminMessages.resourceName());
+ private static final Logger debugLogger = LoggerFactory.getLogger(ClassLoaderProvider.class);
/**
- * Create a class loader with the default parent class loader.
+ * Private URLClassLoader implementation. This is only required so that we
+ * can provide access to the addURL method.
*/
- public MyURLClassLoader() {
- super(new URL[0]);
- }
-
-
-
- /**
- * Create a class loader with the provided parent class loader.
- *
- * @param parent
- * The parent class loader.
- */
- public MyURLClassLoader(ClassLoader parent) {
- super(new URL[0], parent);
- }
-
-
-
- /**
- * Add a Jar file to this class loader.
- *
- * @param jarFile
- * The name of the Jar file.
- * @throws MalformedURLException
- * If a protocol handler for the URL could not be found,
- * or if some other error occurred while constructing
- * the URL.
- * @throws SecurityException
- * If a required system property value cannot be
- * accessed.
- */
- public void addJarFile(File jarFile) throws SecurityException,
- MalformedURLException {
- addURL(jarFile.toURI().toURL());
- }
-
- }
-
- // The name of the manifest file listing the core configuration
- // definition classes.
- private static final String CORE_MANIFEST = "core.manifest";
-
- // The name of the manifest file listing a extension's configuration
- // definition classes.
- private static final String EXTENSION_MANIFEST = "extension.manifest";
-
- // The name of the lib directory.
- private static final String LIB_DIR = "lib";
-
- // The name of the extensions directory.
- private static final String EXTENSIONS_DIR = "extensions";
-
- // The singleton instance.
- private static final ClassLoaderProvider INSTANCE = new ClassLoaderProvider();
-
- // Attribute name in jar's MANIFEST corresponding to the revision number.
- private static final String REVISION_NUMBER = "Revision-Number";
-
- // The attribute names for build information is name, version and revision
- // number
- private static final String[] BUILD_INFORMATION_ATTRIBUTE_NAMES =
- new String[]{Attributes.Name.EXTENSION_NAME.toString(),
- Attributes.Name.IMPLEMENTATION_VERSION.toString(),
- REVISION_NUMBER};
-
-
- /**
- * Get the single application wide class loader provider instance.
- *
- * @return Returns the single application wide class loader provider
- * instance.
- */
- public static ClassLoaderProvider getInstance() {
- return INSTANCE;
- }
-
- // Set of registered Jar files.
- private Set<File> jarFiles = new HashSet<File>();
-
- // Underlying class loader used to load classes and resources (null
- // if disabled).
- //
- // We contain a reference to the URLClassLoader rather than
- // sub-class it so that it is possible to replace the loader at
- // run-time. For example, when removing or replacing extension Jar
- // files (the URLClassLoader only supports adding new
- // URLs, not removal).
- private MyURLClassLoader loader = null;
-
-
-
- // Private constructor.
- private ClassLoaderProvider() {
- // No implementation required.
- }
-
-
-
- /**
- * Add the named extensions to this class loader provider.
- *
- * @param extensions
- * The names of the extensions to be loaded. The names
- * should not contain any path elements and must be located
- * within the extensions folder.
- * @throws InitializationException
- * If one of the extensions could not be loaded and
- * initialized.
- * @throws IllegalStateException
- * If this class loader provider is disabled.
- * @throws IllegalArgumentException
- * If one of the extension names was not a single relative
- * path name element or was an absolute path.
- */
- public synchronized void addExtension(String... extensions)
- throws InitializationException, IllegalStateException,
- IllegalArgumentException {
- ensureNotNull(extensions);
-
- if (loader == null) {
- throw new IllegalStateException(
- "Class loader provider is disabled.");
- }
-
- File libPath = new File(DirectoryServer.getInstanceRoot(), LIB_DIR);
- File extensionsPath = new File(libPath, EXTENSIONS_DIR);
-
- ArrayList<File> files = new ArrayList<File>(extensions.length);
- for (String extension : extensions) {
- File file = new File(extensionsPath, extension);
-
- // For security reasons we need to make sure that the file name
- // passed in did not contain any path elements and names a file
- // in the extensions folder.
-
- // Can handle potential null parent.
- if (!extensionsPath.equals(file.getParentFile())) {
- throw new IllegalArgumentException("Illegal file name: "
- + extension);
- }
-
- // The file is valid.
- files.add(file);
- }
-
- // Add the extensions.
- addExtension(files.toArray(new File[files.size()]));
- }
-
-
-
- /**
- * Disable this class loader provider and removed any registered
- * extensions.
- *
- * @throws IllegalStateException
- * If this class loader provider is already disabled.
- */
- public synchronized void disable() throws IllegalStateException {
- if (loader == null) {
- throw new IllegalStateException(
- "Class loader provider already disabled.");
- }
- loader = null;
- jarFiles = new HashSet<File>();
- }
-
-
-
- /**
- * Enable this class loader provider using the application's
- * class loader as the parent class loader.
- *
- * @throws InitializationException
- * If the class loader provider could not initialize
- * successfully.
- * @throws IllegalStateException
- * If this class loader provider is already enabled.
- */
- public synchronized void enable() throws InitializationException,
- IllegalStateException {
- enable(RootCfgDefn.class.getClassLoader());
- }
-
-
-
- /**
- * Enable this class loader provider using the provided parent class
- * loader.
- *
- * @param parent
- * The parent class loader.
- * @throws InitializationException
- * If the class loader provider could not initialize
- * successfully.
- * @throws IllegalStateException
- * If this class loader provider is already enabled.
- */
- public synchronized void enable(ClassLoader parent)
- throws InitializationException, IllegalStateException {
- if (loader != null) {
- throw new IllegalStateException(
- "Class loader provider already enabled.");
- }
-
- if (parent != null) {
- loader = new MyURLClassLoader(parent);
- } else {
- loader = new MyURLClassLoader();
- }
-
- // Forcefully load all configuration definition classes in
- // OpenDS.jar.
- initializeCoreComponents();
-
- // Put extensions jars into the class loader and load all
- // configuration definition classes in that they contain.
- // First load the extension from the install directory, then
- // from the instance directory.
- File libDir ;
- File installExtensionsPath ;
- File instanceExtensionsPath ;
-
-
- // load install dir extension
- libDir = new File(DirectoryServer.getServerRoot(), LIB_DIR);
- try
- {
- installExtensionsPath =
- new File(libDir, EXTENSIONS_DIR).getCanonicalFile();
- }
- catch (Exception e)
- {
- installExtensionsPath = new File(libDir, EXTENSIONS_DIR);
- }
- initializeAllExtensions(installExtensionsPath);
-
- // load instance dir extension
- libDir = new File(DirectoryServer.getInstanceRoot(),LIB_DIR);
- try
- {
- instanceExtensionsPath =
- new File(libDir, EXTENSIONS_DIR).getCanonicalFile();
- }
- catch (Exception e)
- {
- instanceExtensionsPath = new File(libDir, EXTENSIONS_DIR);
- }
- if (! installExtensionsPath.getAbsolutePath().equals(
- instanceExtensionsPath.getAbsolutePath()))
- {
- initializeAllExtensions(instanceExtensionsPath);
- }
- }
-
-
-
- /**
- * Gets the class loader which should be used for loading classes
- * and resources. When this class loader provider is disabled, the
- * system default class loader will be returned by default.
- * <p>
- * Applications <b>MUST NOT</b> maintain persistent references to
- * the class loader as it can change at run-time.
- *
- * @return Returns the class loader which should be used for loading
- * classes and resources.
- */
- public synchronized ClassLoader getClassLoader() {
- if (loader != null) {
- return loader;
- } else {
- return ClassLoader.getSystemClassLoader();
- }
- }
-
-
-
- /**
- * Indicates whether this class loader provider is enabled.
- *
- * @return Returns <code>true</code> if this class loader provider
- * is enabled.
- */
- public synchronized boolean isEnabled() {
- return loader != null;
- }
-
-
-
- /**
- * Add the named extensions to this class loader.
- *
- * @param extensions
- * The names of the extensions to be loaded.
- * @throws InitializationException
- * If one of the extensions could not be loaded and
- * initialized.
- */
- private synchronized void addExtension(File... extensions)
- throws InitializationException {
- // First add the Jar files to the class loader.
- List<JarFile> jars = new LinkedList<JarFile>();
- for (File extension : extensions) {
- if (jarFiles.contains(extension)) {
- // Skip this file as it is already loaded.
- continue;
- }
-
- // Attempt to load it.
- jars.add(loadJarFile(extension));
-
- // Register the Jar file with the class loader.
- try {
- loader.addJarFile(extension);
- } catch (Exception e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- LocalizableMessage message = ERR_ADMIN_CANNOT_OPEN_JAR_FILE.
- get(extension.getName(), extension.getParent(),
- stackTraceToSingleLineString(e));
- throw new InitializationException(message);
- }
- jarFiles.add(extension);
- }
-
- // Now forcefully load the configuration definition classes.
- for (JarFile jar : jars) {
- initializeExtension(jar);
- }
- }
-
-
-
- /**
- * Prints out all information about extensions.
- *
- * @return a String instance representing all information about extensions;
- * <code>null</code> if there is no information available.
- */
- public String printExtensionInformation() {
- File extensionsPath =
- new File(new StringBuilder(DirectoryServer.getServerRoot()).
- append(File.separator).
- append(LIB_DIR).
- append(File.separator).
- append(EXTENSIONS_DIR).
- toString());
-
- if (!extensionsPath.exists() || !extensionsPath.isDirectory()) {
- // no extensions' directory
- return null;
- }
-
- File[] extensions = extensionsPath.listFiles(new FileFilter(){
- public boolean accept(File pathname) {
- // only files with names ending with ".jar"
- return pathname.isFile() && pathname.getName().endsWith(".jar");
- }
- });
-
- if ( extensions.length == 0 ) {
- return null;
- }
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(baos);
- // prints:
- // --
- // Name Build number Revision number
- ps.printf("--%s %-20s %-20s %-20s%s",
- EOL,
- "Name",
- "Build number",
- "Revision number",
- EOL);
-
- for(File extension : extensions) {
- // retrieve MANIFEST entry and display name, build number and revision
- // number
- try {
- JarFile jarFile = new JarFile(extension);
- JarEntry entry = jarFile.getJarEntry("admin/" + EXTENSION_MANIFEST);
- if (entry == null)
- {
- continue;
- }
-
- String[] information = getBuildInformation(jarFile);
-
- ps.append("Extension: ");
- boolean addBlank = false;
- for(String name : information) {
- if ( addBlank ) {
- ps.append(addBlank ? " " : ""); // add blank if not first append
- } else {
- addBlank = true;
- }
-
- ps.printf("%-20s", name);
- }
- ps.append(EOL);
- } catch(Exception e) {
- // ignore extra information for this extension
- }
- }
-
- return baos.toString();
- }
-
-
-
- /**
- * Returns a String array with the following information :
- * <br>index 0: the name of the extension.
- * <br>index 1: the build number of the extension.
- * <br>index 2: the revision number of the extension.
- *
- * @param extension the jar file of the extension
- * @return a String array containing the name, the build number and the
- * revision number of the extension given in argument
- * @throws java.io.IOException thrown if the jar file has been closed.
- */
- private String[] getBuildInformation(JarFile extension) throws IOException {
- String[] result = new String[3];
-
- // retrieve MANIFEST entry and display name, version and revision
- Manifest manifest = extension.getManifest();
-
- if ( manifest != null ) {
- Attributes attributes = manifest.getMainAttributes();
-
- int index = 0;
- for(String name : BUILD_INFORMATION_ATTRIBUTE_NAMES) {
- String value = attributes.getValue(name);
- if ( value == null ) {
- value = "<unknown>";
- }
- result[index++] = value;
- }
- }
-
- return result;
- }
-
-
-
- /**
- * Put extensions jars into the class loader and load all
- * configuration definition classes in that they contain.
- * @param extensionsPath Indicates where extensions are located.
- *
- * @throws InitializationException
- * If the extensions folder could not be accessed or if a
- * extension jar file could not be accessed or if one of
- * the configuration definition classes could not be
- * initialized.
- */
- private void initializeAllExtensions(File extensionsPath)
- throws InitializationException {
-
- try {
- if (!extensionsPath.exists()) {
- // The extensions directory does not exist. This is not a
- // critical problem.
- LocalizableMessage message = ERR_ADMIN_NO_EXTENSIONS_DIR.get(
- String.valueOf(extensionsPath));
- logError(message);
- return;
- }
-
- if (!extensionsPath.isDirectory()) {
- // The extensions directory is not a directory. This is more
- // critical.
- LocalizableMessage message =
- ERR_ADMIN_EXTENSIONS_DIR_NOT_DIRECTORY.get(
- String.valueOf(extensionsPath));
- throw new InitializationException(message);
- }
-
- // Get each extension file name.
- FileFilter filter = new FileFilter() {
+ private static final class MyURLClassLoader extends URLClassLoader {
/**
- * Must be a Jar file.
+ * Create a class loader with the default parent class loader.
*/
- public boolean accept(File pathname) {
- if (!pathname.isFile()) {
- return false;
- }
-
- String name = pathname.getName();
- return name.endsWith(".jar");
+ public MyURLClassLoader() {
+ super(new URL[0]);
}
- };
-
- // Add and initialize the extensions.
- addExtension(extensionsPath.listFiles(filter));
- } catch (InitializationException e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- throw e;
- } catch (Exception e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- LocalizableMessage message = ERR_ADMIN_EXTENSIONS_CANNOT_LIST_FILES.get(
- String.valueOf(extensionsPath), stackTraceToSingleLineString(e));
- throw new InitializationException(message, e);
- }
- }
-
-
-
- /**
- * Make sure all core configuration definitions are loaded.
- *
- * @throws InitializationException
- * If the core manifest file could not be read or if one
- * of the configuration definition classes could not be
- * initialized.
- */
- private void initializeCoreComponents()
- throws InitializationException {
- InputStream is = RootCfgDefn.class.getResourceAsStream("/admin/"
- + CORE_MANIFEST);
-
- if (is == null) {
- LocalizableMessage message = ERR_ADMIN_CANNOT_FIND_CORE_MANIFEST.get(CORE_MANIFEST);
- throw new InitializationException(message);
- }
-
- try {
- loadDefinitionClasses(is);
- } catch (InitializationException e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- LocalizableMessage message = ERR_CLASS_LOADER_CANNOT_LOAD_CORE.get(CORE_MANIFEST,
- stackTraceToSingleLineString(e));
- throw new InitializationException(message);
- }
- }
-
-
-
- /**
- * Make sure all the configuration definition classes in a extension
- * are loaded.
- *
- * @param jarFile
- * The extension's Jar file.
- * @throws InitializationException
- * If the extension jar file could not be accessed or if
- * one of the configuration definition classes could not
- * be initialized.
- */
- private void initializeExtension(JarFile jarFile)
- throws InitializationException {
- JarEntry entry = jarFile.getJarEntry("admin/"
- + EXTENSION_MANIFEST);
- if (entry != null) {
- InputStream is;
- try {
- is = jarFile.getInputStream(entry);
- } catch (Exception e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ /**
+ * Create a class loader with the provided parent class loader.
+ *
+ * @param parent
+ * The parent class loader.
+ */
+ public MyURLClassLoader(ClassLoader parent) {
+ super(new URL[0], parent);
}
- LocalizableMessage message = ERR_ADMIN_CANNOT_READ_EXTENSION_MANIFEST.get(
- EXTENSION_MANIFEST, jarFile.getName(),
- stackTraceToSingleLineString(e));
- throw new InitializationException(message);
- }
-
- try {
- loadDefinitionClasses(is);
- } catch (InitializationException e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ /**
+ * Add a Jar file to this class loader.
+ *
+ * @param jarFile
+ * The name of the Jar file.
+ * @throws MalformedURLException
+ * If a protocol handler for the URL could not be found, or
+ * if some other error occurred while constructing the URL.
+ * @throws SecurityException
+ * If a required system property value cannot be accessed.
+ */
+ public void addJarFile(File jarFile) throws SecurityException, MalformedURLException {
+ addURL(jarFile.toURI().toURL());
}
- LocalizableMessage message = ERR_CLASS_LOADER_CANNOT_LOAD_EXTENSION.get(jarFile
- .getName(), EXTENSION_MANIFEST, stackTraceToSingleLineString(e));
- throw new InitializationException(message);
- }
- try {
- // Log build information of extensions in the error log
- String[] information = getBuildInformation(jarFile);
- logError(
- NOTE_LOG_EXTENSION_INFORMATION.
- get(jarFile.getName(),
- information[1],
- information[2]));
- } catch(Exception e) {
- // Do not log information for that extension
- }
}
- }
+ // The name of the manifest file listing the core configuration
+ // definition classes.
+ private static final String CORE_MANIFEST = "core.manifest";
+ // The name of the manifest file listing a extension's configuration
+ // definition classes.
+ private static final String EXTENSION_MANIFEST = "extension.manifest";
- /**
- * Forcefully load configuration definition classes named in a
- * manifest file.
- *
- * @param is
- * The manifest file input stream.
- * @throws InitializationException
- * If the definition classes could not be loaded and
- * initialized.
- */
- private void loadDefinitionClasses(InputStream is)
- throws InitializationException {
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- is));
- List<AbstractManagedObjectDefinition<?, ?>> definitions =
- new LinkedList<AbstractManagedObjectDefinition<?,?>>();
- while (true) {
- String className;
- try {
- className = reader.readLine();
- } catch (IOException e) {
- LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_READ_MANIFEST_FILE.get(String
- .valueOf(e.getLocalizableMessage()));
- throw new InitializationException(msg, e);
- }
+ // The name of the lib directory.
+ private static final String LIB_DIR = "lib";
- // Break out when the end of the manifest is reached.
- if (className == null) {
- break;
- }
+ // The name of the extensions directory.
+ private static final String EXTENSIONS_DIR = "extensions";
- // Skip blank lines.
- className = className.trim();
- if (className.length() == 0) {
- continue;
- }
+ // The singleton instance.
+ private static final ClassLoaderProvider INSTANCE = new ClassLoaderProvider();
- // Skip lines beginning with #.
- if (className.startsWith("#")) {
- continue;
- }
+ // Attribute name in jar's MANIFEST corresponding to the revision number.
+ private static final String REVISION_NUMBER = "Revision-Number";
- TRACER.debugLocalizableMessage(DebugLogLevel.INFO, "Loading class " + className);
+ // The attribute names for build information is name, version and revision
+ // number
+ private static final String[] BUILD_INFORMATION_ATTRIBUTE_NAMES = new String[] {
+ Attributes.Name.EXTENSION_NAME.toString(), Attributes.Name.IMPLEMENTATION_VERSION.toString(),
+ REVISION_NUMBER };
- // Load the class and get an instance of it if it is a definition.
- Class<?> theClass;
- try {
- theClass = Class.forName(className, true, loader);
- } catch (Exception e) {
- LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_LOAD_CLASS.get(className, String
- .valueOf(e.getLocalizableMessage()));
- throw new InitializationException(msg, e);
- }
- if (AbstractManagedObjectDefinition.class.isAssignableFrom(theClass)) {
- // We need to instantiate it using its getInstance() static method.
- Method method;
+ /**
+ * Get the single application wide class loader provider instance.
+ *
+ * @return Returns the single application wide class loader provider
+ * instance.
+ */
+ public static ClassLoaderProvider getInstance() {
+ return INSTANCE;
+ }
+
+ // Set of registered Jar files.
+ private Set<File> jarFiles = new HashSet<File>();
+
+ // Underlying class loader used to load classes and resources (null
+ // if disabled).
+ //
+ // We contain a reference to the URLClassLoader rather than
+ // sub-class it so that it is possible to replace the loader at
+ // run-time. For example, when removing or replacing extension Jar
+ // files (the URLClassLoader only supports adding new
+ // URLs, not removal).
+ private MyURLClassLoader loader = null;
+
+ // Private constructor.
+ private ClassLoaderProvider() {
+ // No implementation required.
+ }
+
+ /**
+ * Add the named extensions to this class loader provider.
+ *
+ * @param extensions
+ * The names of the extensions to be loaded. The names should not
+ * contain any path elements and must be located within the
+ * extensions folder.
+ * @throws InitializationException
+ * If one of the extensions could not be loaded and initialized.
+ * @throws IllegalStateException
+ * If this class loader provider is disabled.
+ * @throws IllegalArgumentException
+ * If one of the extension names was not a single relative path
+ * name element or was an absolute path.
+ */
+ public synchronized void addExtension(String... extensions) throws InitializationException, IllegalStateException,
+ IllegalArgumentException {
+ ensureNotNull(extensions);
+
+ if (loader == null) {
+ throw new IllegalStateException("Class loader provider is disabled.");
+ }
+
+ File libPath = new File(DirectoryServer.getInstanceRoot(), LIB_DIR);
+ File extensionsPath = new File(libPath, EXTENSIONS_DIR);
+
+ ArrayList<File> files = new ArrayList<File>(extensions.length);
+ for (String extension : extensions) {
+ File file = new File(extensionsPath, extension);
+
+ // For security reasons we need to make sure that the file name
+ // passed in did not contain any path elements and names a file
+ // in the extensions folder.
+
+ // Can handle potential null parent.
+ if (!extensionsPath.equals(file.getParentFile())) {
+ throw new IllegalArgumentException("Illegal file name: " + extension);
+ }
+
+ // The file is valid.
+ files.add(file);
+ }
+
+ // Add the extensions.
+ addExtension(files.toArray(new File[files.size()]));
+ }
+
+ /**
+ * Disable this class loader provider and removed any registered extensions.
+ *
+ * @throws IllegalStateException
+ * If this class loader provider is already disabled.
+ */
+ public synchronized void disable() throws IllegalStateException {
+ if (loader == null) {
+ throw new IllegalStateException("Class loader provider already disabled.");
+ }
+ loader = null;
+ jarFiles = new HashSet<File>();
+ }
+
+ /**
+ * Enable this class loader provider using the application's class loader as
+ * the parent class loader.
+ *
+ * @throws InitializationException
+ * If the class loader provider could not initialize
+ * successfully.
+ * @throws IllegalStateException
+ * If this class loader provider is already enabled.
+ */
+ public synchronized void enable() throws InitializationException, IllegalStateException {
+ enable(RootCfgDefn.class.getClassLoader());
+ }
+
+ /**
+ * Enable this class loader provider using the provided parent class loader.
+ *
+ * @param parent
+ * The parent class loader.
+ * @throws InitializationException
+ * If the class loader provider could not initialize
+ * successfully.
+ * @throws IllegalStateException
+ * If this class loader provider is already enabled.
+ */
+ public synchronized void enable(ClassLoader parent) throws InitializationException, IllegalStateException {
+ if (loader != null) {
+ throw new IllegalStateException("Class loader provider already enabled.");
+ }
+
+ if (parent != null) {
+ loader = new MyURLClassLoader(parent);
+ } else {
+ loader = new MyURLClassLoader();
+ }
+
+ // Forcefully load all configuration definition classes in
+ // OpenDS.jar.
+ initializeCoreComponents();
+
+ // Put extensions jars into the class loader and load all
+ // configuration definition classes in that they contain.
+ // First load the extension from the install directory, then
+ // from the instance directory.
+ File libDir;
+ File installExtensionsPath;
+ File instanceExtensionsPath;
+
+ // load install dir extension
+ libDir = new File(DirectoryServer.getServerRoot(), LIB_DIR);
try {
- method = theClass.getMethod("getInstance");
+ installExtensionsPath = new File(libDir, EXTENSIONS_DIR).getCanonicalFile();
} catch (Exception e) {
- LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_FIND_GET_INSTANCE_METHOD.get(
- className, String.valueOf(e.getLocalizableMessage()));
- throw new InitializationException(msg, e);
+ installExtensionsPath = new File(libDir, EXTENSIONS_DIR);
}
+ initializeAllExtensions(installExtensionsPath);
- // Get the definition instance.
- AbstractManagedObjectDefinition<?, ?> d;
+ // load instance dir extension
+ libDir = new File(DirectoryServer.getInstanceRoot(), LIB_DIR);
try {
- d = (AbstractManagedObjectDefinition<?, ?>) method.invoke(null);
+ instanceExtensionsPath = new File(libDir, EXTENSIONS_DIR).getCanonicalFile();
} catch (Exception e) {
- LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_INVOKE_GET_INSTANCE_METHOD.get(
- className, String.valueOf(e.getLocalizableMessage()));
- throw new InitializationException(msg, e);
+ instanceExtensionsPath = new File(libDir, EXTENSIONS_DIR);
}
- definitions.add(d);
- }
+ if (!installExtensionsPath.getAbsolutePath().equals(instanceExtensionsPath.getAbsolutePath())) {
+ initializeAllExtensions(instanceExtensionsPath);
+ }
}
- // Initialize any definitions that were loaded.
- for (AbstractManagedObjectDefinition<?, ?> d : definitions) {
- try {
- d.initialize();
- } catch (Exception e) {
- LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_INITIALIZE_DEFN.get(d.getName(),
- d.getClass().getName(), String.valueOf(e.getLocalizableMessage()));
- throw new InitializationException(msg, e);
- }
+ /**
+ * Gets the class loader which should be used for loading classes and
+ * resources. When this class loader provider is disabled, the system
+ * default class loader will be returned by default.
+ * <p>
+ * Applications <b>MUST NOT</b> maintain persistent references to the class
+ * loader as it can change at run-time.
+ *
+ * @return Returns the class loader which should be used for loading classes
+ * and resources.
+ */
+ public synchronized ClassLoader getClassLoader() {
+ if (loader != null) {
+ return loader;
+ } else {
+ return ClassLoader.getSystemClassLoader();
+ }
}
- }
-
-
- /**
- * Load the named Jar file.
- *
- * @param jar
- * The name of the Jar file to load.
- * @return Returns the loaded Jar file.
- * @throws InitializationException
- * If the Jar file could not be loaded.
- */
- private JarFile loadJarFile(File jar)
- throws InitializationException {
- JarFile jarFile;
-
- try {
- // Load the extension jar file.
- jarFile = new JarFile(jar);
- } catch (Exception e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- LocalizableMessage message = ERR_ADMIN_CANNOT_OPEN_JAR_FILE.get(
- jar.getName(), jar.getParent(), stackTraceToSingleLineString(e));
- throw new InitializationException(message);
+ /**
+ * Indicates whether this class loader provider is enabled.
+ *
+ * @return Returns <code>true</code> if this class loader provider is
+ * enabled.
+ */
+ public synchronized boolean isEnabled() {
+ return loader != null;
}
- return jarFile;
- }
+
+ /**
+ * Add the named extensions to this class loader.
+ *
+ * @param extensions
+ * The names of the extensions to be loaded.
+ * @throws InitializationException
+ * If one of the extensions could not be loaded and initialized.
+ */
+ private synchronized void addExtension(File... extensions) throws InitializationException {
+ // First add the Jar files to the class loader.
+ List<JarFile> jars = new LinkedList<JarFile>();
+ for (File extension : extensions) {
+ if (jarFiles.contains(extension)) {
+ // Skip this file as it is already loaded.
+ continue;
+ }
+
+ // Attempt to load it.
+ jars.add(loadJarFile(extension));
+
+ // Register the Jar file with the class loader.
+ try {
+ loader.addJarFile(extension);
+ } catch (Exception e) {
+ debugLogger.trace("Unable to register the jar file with the class loader", e);
+ LocalizableMessage message = ERR_ADMIN_CANNOT_OPEN_JAR_FILE.get(extension.getName(),
+ extension.getParent(), stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
+ throw new InitializationException(message);
+ }
+ jarFiles.add(extension);
+ }
+
+ // Now forcefully load the configuration definition classes.
+ for (JarFile jar : jars) {
+ initializeExtension(jar);
+ }
+ }
+
+ /**
+ * Prints out all information about extensions.
+ *
+ * @return a String instance representing all information about extensions;
+ * <code>null</code> if there is no information available.
+ */
+ public String printExtensionInformation() {
+ File extensionsPath = new File(new StringBuilder(DirectoryServer.getServerRoot()).append(File.separator)
+ .append(LIB_DIR).append(File.separator).append(EXTENSIONS_DIR).toString());
+
+ if (!extensionsPath.exists() || !extensionsPath.isDirectory()) {
+ // no extensions' directory
+ return null;
+ }
+
+ File[] extensions = extensionsPath.listFiles(new FileFilter() {
+ public boolean accept(File pathname) {
+ // only files with names ending with ".jar"
+ return pathname.isFile() && pathname.getName().endsWith(".jar");
+ }
+ });
+
+ if (extensions.length == 0) {
+ return null;
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ // prints:
+ // --
+ // Name Build number Revision number
+ ps.printf("--%s %-20s %-20s %-20s%s", EOL, "Name", "Build number", "Revision number", EOL);
+
+ for (File extension : extensions) {
+ // retrieve MANIFEST entry and display name, build number and
+ // revision
+ // number
+ try {
+ JarFile jarFile = new JarFile(extension);
+ JarEntry entry = jarFile.getJarEntry("admin/" + EXTENSION_MANIFEST);
+ if (entry == null) {
+ continue;
+ }
+
+ String[] information = getBuildInformation(jarFile);
+
+ ps.append("Extension: ");
+ boolean addBlank = false;
+ for (String name : information) {
+ if (addBlank) {
+ ps.append(addBlank ? " " : ""); // add blank if not
+ // first append
+ } else {
+ addBlank = true;
+ }
+
+ ps.printf("%-20s", name);
+ }
+ ps.append(EOL);
+ } catch (Exception e) {
+ // ignore extra information for this extension
+ }
+ }
+
+ return baos.toString();
+ }
+
+ /**
+ * Returns a String array with the following information : <br>
+ * index 0: the name of the extension. <br>
+ * index 1: the build number of the extension. <br>
+ * index 2: the revision number of the extension.
+ *
+ * @param extension
+ * the jar file of the extension
+ * @return a String array containing the name, the build number and the
+ * revision number of the extension given in argument
+ * @throws java.io.IOException
+ * thrown if the jar file has been closed.
+ */
+ private String[] getBuildInformation(JarFile extension) throws IOException {
+ String[] result = new String[3];
+
+ // retrieve MANIFEST entry and display name, version and revision
+ Manifest manifest = extension.getManifest();
+
+ if (manifest != null) {
+ Attributes attributes = manifest.getMainAttributes();
+
+ int index = 0;
+ for (String name : BUILD_INFORMATION_ATTRIBUTE_NAMES) {
+ String value = attributes.getValue(name);
+ if (value == null) {
+ value = "<unknown>";
+ }
+ result[index++] = value;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Put extensions jars into the class loader and load all configuration
+ * definition classes in that they contain.
+ *
+ * @param extensionsPath
+ * Indicates where extensions are located.
+ * @throws InitializationException
+ * If the extensions folder could not be accessed or if a
+ * extension jar file could not be accessed or if one of the
+ * configuration definition classes could not be initialized.
+ */
+ private void initializeAllExtensions(File extensionsPath) throws InitializationException {
+
+ try {
+ if (!extensionsPath.exists()) {
+ // The extensions directory does not exist. This is not a
+ // critical problem.
+ adminLogger.error(ERR_ADMIN_NO_EXTENSIONS_DIR, String.valueOf(extensionsPath));
+ return;
+ }
+
+ if (!extensionsPath.isDirectory()) {
+ // The extensions directory is not a directory. This is more
+ // critical.
+ LocalizableMessage message = ERR_ADMIN_EXTENSIONS_DIR_NOT_DIRECTORY.get(String.valueOf(extensionsPath));
+ throw new InitializationException(message);
+ }
+
+ // Get each extension file name.
+ FileFilter filter = new FileFilter() {
+
+ /**
+ * Must be a Jar file.
+ */
+ public boolean accept(File pathname) {
+ if (!pathname.isFile()) {
+ return false;
+ }
+
+ String name = pathname.getName();
+ return name.endsWith(".jar");
+ }
+
+ };
+
+ // Add and initialize the extensions.
+ addExtension(extensionsPath.listFiles(filter));
+ } catch (InitializationException e) {
+ debugLogger.trace("Unable to initialize all extensions", e);
+ throw e;
+ } catch (Exception e) {
+ debugLogger.trace("Unable to initialize all extensions", e);
+ LocalizableMessage message = ERR_ADMIN_EXTENSIONS_CANNOT_LIST_FILES.get(String.valueOf(extensionsPath),
+ stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
+ throw new InitializationException(message, e);
+ }
+ }
+
+ /**
+ * Make sure all core configuration definitions are loaded.
+ *
+ * @throws InitializationException
+ * If the core manifest file could not be read or if one of the
+ * configuration definition classes could not be initialized.
+ */
+ private void initializeCoreComponents() throws InitializationException {
+ InputStream is = RootCfgDefn.class.getResourceAsStream("/admin/" + CORE_MANIFEST);
+
+ if (is == null) {
+ LocalizableMessage message = ERR_ADMIN_CANNOT_FIND_CORE_MANIFEST.get(CORE_MANIFEST);
+ throw new InitializationException(message);
+ }
+
+ try {
+ loadDefinitionClasses(is);
+ } catch (InitializationException e) {
+ debugLogger.trace("Unable to initialize core components", e);
+ LocalizableMessage message = ERR_CLASS_LOADER_CANNOT_LOAD_CORE.get(CORE_MANIFEST,
+ stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
+ throw new InitializationException(message);
+ }
+ }
+
+ /**
+ * Make sure all the configuration definition classes in a extension are
+ * loaded.
+ *
+ * @param jarFile
+ * The extension's Jar file.
+ * @throws InitializationException
+ * If the extension jar file could not be accessed or if one of
+ * the configuration definition classes could not be
+ * initialized.
+ */
+ private void initializeExtension(JarFile jarFile) throws InitializationException {
+ JarEntry entry = jarFile.getJarEntry("admin/" + EXTENSION_MANIFEST);
+ if (entry != null) {
+ InputStream is;
+ try {
+ is = jarFile.getInputStream(entry);
+ } catch (Exception e) {
+ debugLogger.trace("Unable to get input stream from jar", e);
+ LocalizableMessage message = ERR_ADMIN_CANNOT_READ_EXTENSION_MANIFEST.get(EXTENSION_MANIFEST,
+ jarFile.getName(), stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
+ throw new InitializationException(message);
+ }
+
+ try {
+ loadDefinitionClasses(is);
+ } catch (InitializationException e) {
+ debugLogger.trace("Unable to load classes from input stream", e);
+ LocalizableMessage message = ERR_CLASS_LOADER_CANNOT_LOAD_EXTENSION.get(jarFile.getName(),
+ EXTENSION_MANIFEST, stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
+ throw new InitializationException(message);
+ }
+ try {
+ // Log build information of extensions in the error log
+ String[] information = getBuildInformation(jarFile);
+ LocalizableMessage message = NOTE_LOG_EXTENSION_INFORMATION.get(jarFile.getName(), information[1],
+ information[2]);
+ LocalizedLogger.getLocalizedLogger(message.resourceName()).error(message);
+ } catch (Exception e) {
+ // Do not log information for that extension
+ }
+ }
+ }
+
+ /**
+ * Forcefully load configuration definition classes named in a manifest
+ * file.
+ *
+ * @param is
+ * The manifest file input stream.
+ * @throws InitializationException
+ * If the definition classes could not be loaded and
+ * initialized.
+ */
+ private void loadDefinitionClasses(InputStream is) throws InitializationException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ List<AbstractManagedObjectDefinition<?, ?>> definitions = new LinkedList<AbstractManagedObjectDefinition<?, ?>>();
+ while (true) {
+ String className;
+ try {
+ className = reader.readLine();
+ } catch (IOException e) {
+ LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_READ_MANIFEST_FILE.get(String.valueOf(e.getMessage()));
+ throw new InitializationException(msg, e);
+ }
+
+ // Break out when the end of the manifest is reached.
+ if (className == null) {
+ break;
+ }
+
+ // Skip blank lines.
+ className = className.trim();
+ if (className.length() == 0) {
+ continue;
+ }
+
+ // Skip lines beginning with #.
+ if (className.startsWith("#")) {
+ continue;
+ }
+
+ debugLogger.trace("Loading class " + className);
+
+ // Load the class and get an instance of it if it is a definition.
+ Class<?> theClass;
+ try {
+ theClass = Class.forName(className, true, loader);
+ } catch (Exception e) {
+ LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_LOAD_CLASS.get(className,
+ String.valueOf(e.getMessage()));
+ throw new InitializationException(msg, e);
+ }
+ if (AbstractManagedObjectDefinition.class.isAssignableFrom(theClass)) {
+ // We need to instantiate it using its getInstance() static
+ // method.
+ Method method;
+ try {
+ method = theClass.getMethod("getInstance");
+ } catch (Exception e) {
+ LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_FIND_GET_INSTANCE_METHOD.get(className,
+ String.valueOf(e.getMessage()));
+ throw new InitializationException(msg, e);
+ }
+
+ // Get the definition instance.
+ AbstractManagedObjectDefinition<?, ?> d;
+ try {
+ d = (AbstractManagedObjectDefinition<?, ?>) method.invoke(null);
+ } catch (Exception e) {
+ LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_INVOKE_GET_INSTANCE_METHOD.get(className,
+ String.valueOf(e.getMessage()));
+ throw new InitializationException(msg, e);
+ }
+ definitions.add(d);
+ }
+ }
+
+ // Initialize any definitions that were loaded.
+ for (AbstractManagedObjectDefinition<?, ?> d : definitions) {
+ try {
+ d.initialize();
+ } catch (Exception e) {
+ LocalizableMessage msg = ERR_CLASS_LOADER_CANNOT_INITIALIZE_DEFN.get(d.getName(), d.getClass()
+ .getName(), String.valueOf(e.getMessage()));
+ throw new InitializationException(msg, e);
+ }
+ }
+ }
+
+ /**
+ * Load the named Jar file.
+ *
+ * @param jar
+ * The name of the Jar file to load.
+ * @return Returns the loaded Jar file.
+ * @throws InitializationException
+ * If the Jar file could not be loaded.
+ */
+ private JarFile loadJarFile(File jar) throws InitializationException {
+ JarFile jarFile;
+
+ try {
+ // Load the extension jar file.
+ jarFile = new JarFile(jar);
+ } catch (Exception e) {
+ debugLogger.trace("Unable to load jar file: " + jar, e);
+
+ LocalizableMessage message = ERR_ADMIN_CANNOT_OPEN_JAR_FILE.get(jar.getName(), jar.getParent(),
+ stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
+ throw new InitializationException(message);
+ }
+ return jarFile;
+ }
}
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/DefaultBehaviorException.java b/opendj-admin/src/main/java/org/opends/server/admin/DefaultBehaviorException.java
index 6e26c89..707c965 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/DefaultBehaviorException.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/DefaultBehaviorException.java
@@ -27,6 +27,8 @@
package org.opends.server.admin;
+import static com.forgerock.opendj.ldap.AdminMessages.*;
+
/**
* This exception is thrown when a property's default values cannot be
* determined. This can occur in the following situations:
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java b/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java
index a38d04a..c6c7144 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java
@@ -28,8 +28,6 @@
package org.opends.server.admin;
-
-
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -43,67 +41,58 @@
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.DirectoryException;
-
/**
- * A path which can be used to determine the location of a managed
- * object instance.
+ * A path which can be used to determine the location of a managed object
+ * instance.
* <p>
- * A path is made up of zero or more elements each of which represents
- * a managed object. Managed objects are arranged hierarchically with
- * the root configuration being the top-most managed object. Elements
- * are ordered such that the root configuration managed object is the
- * first element and subsequent elements representing managed objects
- * further down the hierarchy.
+ * A path is made up of zero or more elements each of which represents a managed
+ * object. Managed objects are arranged hierarchically with the root
+ * configuration being the top-most managed object. Elements are ordered such
+ * that the root configuration managed object is the first element and
+ * subsequent elements representing managed objects further down the hierarchy.
* <p>
* A path can be encoded into a string representation using the
- * {@link #toString()} and {@link #toString(StringBuilder)} methods.
- * Conversely, this string representation can be parsed using the
- * {@link #valueOf(String)} method.
+ * {@link #toString()} and {@link #toString(StringBuilder)} methods. Conversely,
+ * this string representation can be parsed using the {@link #valueOf(String)}
+ * method.
* <p>
- * The string representation of a managed object path is similar in
- * principle to a UNIX file-system path and is defined as follows:
+ * The string representation of a managed object path is similar in principle to
+ * a UNIX file-system path and is defined as follows:
* <ul>
* <li>the root element is represented by the string <code>/</code>
- * <li>subordinate elements are arranged in big-endian order
- * separated by a forward slash <code>/</code> character
- * <li>an element representing a managed object associated with a
- * one-to-one (singleton) or one-to-zero-or-one (optional) relation
- * has the form <code>relation=</code><i>relation</i>
- * <code>[+type=</code><i>definition</i><code>]</code>, where
- * <i>relation</i> is the name of the relation and <i>definition</i>
- * is the name of the referenced managed object's definition if
- * required (usually this is implied by the relation itself)
- * <li>an element representing a managed object associated with a
- * one-to-many (instantiable) relation has the form
- * <code>relation=</code><i>relation</i><code>[+type=</code>
- * <i>definition</i><code>]</code><code>+name=</code><i>name</i>,
- * where <i>relation</i> is the name of the relation and
- * <i>definition</i> is the name of the referenced managed object's
- * definition if required (usually this is implied by the relation
- * itself), and <i>name</i> is the name of the managed object
- * instance
- * <li>an element representing a managed object associated with a
- * one-to-many (set) relation has the form
- * <code>relation=</code><i>relation</i><code>[+type=</code>
- * <i>definition</i><code>]</code>,
- * where <i>relation</i> is the name of the relation and
- * <i>definition</i> is the name of the referenced managed object's
- * definition.
+ * <li>subordinate elements are arranged in big-endian order separated by a
+ * forward slash <code>/</code> character
+ * <li>an element representing a managed object associated with a one-to-one
+ * (singleton) or one-to-zero-or-one (optional) relation has the form
+ * <code>relation=</code><i>relation</i> <code>[+type=</code><i>definition</i>
+ * <code>]</code>, where <i>relation</i> is the name of the relation and
+ * <i>definition</i> is the name of the referenced managed object's definition
+ * if required (usually this is implied by the relation itself)
+ * <li>an element representing a managed object associated with a one-to-many
+ * (instantiable) relation has the form <code>relation=</code><i>relation</i>
+ * <code>[+type=</code> <i>definition</i><code>]</code><code>+name=</code>
+ * <i>name</i>, where <i>relation</i> is the name of the relation and
+ * <i>definition</i> is the name of the referenced managed object's definition
+ * if required (usually this is implied by the relation itself), and <i>name</i>
+ * is the name of the managed object instance
+ * <li>an element representing a managed object associated with a one-to-many
+ * (set) relation has the form <code>relation=</code><i>relation</i>
+ * <code>[+type=</code> <i>definition</i><code>]</code>, where <i>relation</i>
+ * is the name of the relation and <i>definition</i> is the name of the
+ * referenced managed object's definition.
* </ul>
- * The following path string representation identifies a connection
- * handler instance (note that the <code>type</code> is not
- * specified indicating that the path identifies a connection handler
- * called <i>my handler</i> which can be any type of connection
- * handler):
+ * The following path string representation identifies a connection handler
+ * instance (note that the <code>type</code> is not specified indicating that
+ * the path identifies a connection handler called <i>my handler</i> which can
+ * be any type of connection handler):
*
* <pre>
* /relation=connection-handler+name=my handler
* </pre>
*
- * If the identified connection handler must be an LDAP connection
- * handler then the above path should include the <code>type</code>:
+ * If the identified connection handler must be an LDAP connection handler then
+ * the above path should include the <code>type</code>:
*
* <pre>
* /relation=connection-handler+type=ldap-connection-handler+name=my handler
@@ -116,1333 +105,1079 @@
* </pre>
*
* @param <C>
- * The type of client managed object configuration that this
- * path references.
+ * The type of client managed object configuration that this path
+ * references.
* @param <S>
- * The type of server managed object configuration that this
- * path references.
+ * The type of server managed object configuration that this path
+ * references.
*/
-public final class ManagedObjectPath<C extends ConfigurationClient,
- S extends Configuration> {
-
- /**
- * A serialize which is used to generate the toDN representation.
- */
- private static final class DNSerializer implements
- ManagedObjectPathSerializer {
-
- // The current DN.
- private DN dn;
-
- // The LDAP profile.
- private final LDAPProfile profile;
-
-
-
- // Create a new DN builder.
- private DNSerializer() {
- this.dn = DN.rootDN();
- this.profile = LDAPProfile.getInstance();
- }
-
-
+public final class ManagedObjectPath<C extends ConfigurationClient, S extends Configuration> {
/**
- * {@inheritDoc}
+ * A serialize which is used to generate the toDN representation.
*/
- public <C extends ConfigurationClient, S extends Configuration>
- void appendManagedObjectPathElement(
- InstantiableRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d, String name) {
- // Add the RDN sequence representing the relation.
- appendManagedObjectPathElement(r);
+ private static final class DNSerializer implements ManagedObjectPathSerializer {
- // Now add the single RDN representing the named instance.
- String type = profile.getRelationChildRDNType(r);
- AttributeType atype = DirectoryServer.getAttributeType(
- type.toLowerCase(), true);
- AttributeValue avalue = AttributeValues.create(atype, name);
- dn = dn.concat(RDN.create(atype, avalue));
+ // The current DN.
+ private DN dn;
+
+ // The LDAP profile.
+ private final LDAPProfile profile;
+
+ // Create a new DN builder.
+ private DNSerializer() {
+ this.dn = DN.rootDN();
+ this.profile = LDAPProfile.getInstance();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+ InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d,
+ String name) {
+ // Add the RDN sequence representing the relation.
+ appendManagedObjectPathElement(r);
+
+ // Now add the single RDN representing the named instance.
+ String type = profile.getRelationChildRDNType(r);
+ AttributeType attrType = DirectoryServer.getAttributeType(type.toLowerCase(), true);
+ dn = dn.child(new RDN(attrType, name));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+ SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ // Add the RDN sequence representing the relation.
+ appendManagedObjectPathElement(r);
+
+ // Now add the single RDN representing the instance.
+ String type = profile.getRelationChildRDNType(r);
+ AttributeType attrType = DirectoryServer.getAttributeType(type.toLowerCase(), true);
+ dn = dn.child(new RDN(attrType, d.getName()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+ OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ // Add the RDN sequence representing the relation.
+ appendManagedObjectPathElement(r);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+ SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ // Add the RDN sequence representing the relation.
+ appendManagedObjectPathElement(r);
+ }
+
+ // Appends the RDN sequence representing the provided relation.
+ private void appendManagedObjectPathElement(RelationDefinition<?, ?> r) {
+ DN localName = DN.valueOf(profile.getRelationRDNSequence(r));
+ dn = dn.child(localName);
+ }
+
+ // Gets the serialized DN value.
+ private DN toDN() {
+ return dn;
+ }
}
-
-
/**
- * {@inheritDoc}
+ * Abstract path element.
*/
- public <C extends ConfigurationClient, S extends Configuration>
- void appendManagedObjectPathElement(
- SetRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- // Add the RDN sequence representing the relation.
- appendManagedObjectPathElement(r);
+ private static abstract class Element<C extends ConfigurationClient, S extends Configuration> {
- // Now add the single RDN representing the instance.
- String type = profile.getRelationChildRDNType(r);
- AttributeType atype = DirectoryServer.getAttributeType(
- type.toLowerCase(), true);
- AttributeValue avalue = AttributeValues.create(atype, d.getName());
- dn = dn.concat(RDN.create(atype, avalue));
+ // The type of managed object referenced by this element.
+ private final AbstractManagedObjectDefinition<C, S> definition;
+
+ /**
+ * Protected constructor.
+ *
+ * @param definition
+ * The type of managed object referenced by this element.
+ */
+ protected Element(AbstractManagedObjectDefinition<C, S> definition) {
+ this.definition = definition;
+ }
+
+ /**
+ * Get the managed object definition associated with this element.
+ *
+ * @return Returns the managed object definition associated with this
+ * element.
+ */
+ public final AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
+ return definition;
+ }
+
+ /**
+ * Get the name associated with this element if applicable.
+ *
+ * @return Returns the name associated with this element if applicable.
+ */
+ public String getName() {
+ return null;
+ }
+
+ /**
+ * Get the relation definition associated with this element.
+ *
+ * @return Returns the relation definition associated with this element.
+ */
+ public abstract RelationDefinition<? super C, ? super S> getRelationDefinition();
+
+ /**
+ * Serialize this path element using the provided serialization
+ * strategy.
+ *
+ * @param serializer
+ * The managed object path serialization strategy.
+ */
+ public abstract void serialize(ManagedObjectPathSerializer serializer);
}
-
-
/**
- * {@inheritDoc}
+ * A path element representing an instantiable managed object.
*/
- public <C extends ConfigurationClient, S extends Configuration>
- void appendManagedObjectPathElement(
- OptionalRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- // Add the RDN sequence representing the relation.
- appendManagedObjectPathElement(r);
+ private static final class InstantiableElement<C extends ConfigurationClient, S extends Configuration> extends
+ Element<C, S> {
+
+ // Factory method.
+ private static final <C extends ConfigurationClient, S extends Configuration> InstantiableElement<C, S> create(
+ InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d,
+ String name) {
+ return new InstantiableElement<C, S>(r, d, name);
+ }
+
+ // The name of the managed object.
+ private final String name;
+
+ // The instantiable relation.
+ private final InstantiableRelationDefinition<? super C, ? super S> r;
+
+ // Private constructor.
+ private InstantiableElement(InstantiableRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d, String name) {
+ super(d);
+ this.r = r;
+ this.name = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public InstantiableRelationDefinition<? super C, ? super S> getRelationDefinition() {
+ return r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void serialize(ManagedObjectPathSerializer serializer) {
+ serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition(), name);
+ }
}
-
-
/**
- * {@inheritDoc}
+ * A path element representing an optional managed object.
*/
- public <C extends ConfigurationClient, S extends Configuration>
- void appendManagedObjectPathElement(
- SingletonRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- // Add the RDN sequence representing the relation.
- appendManagedObjectPathElement(r);
+ private static final class OptionalElement<C extends ConfigurationClient, S extends Configuration> extends
+ Element<C, S> {
+
+ // Factory method.
+ private static final <C extends ConfigurationClient, S extends Configuration> OptionalElement<C, S> create(
+ OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ return new OptionalElement<C, S>(r, d);
+ }
+
+ // The optional relation.
+ private final OptionalRelationDefinition<? super C, ? super S> r;
+
+ // Private constructor.
+ private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ super(d);
+ this.r = r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public OptionalRelationDefinition<? super C, ? super S> getRelationDefinition() {
+ return r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void serialize(ManagedObjectPathSerializer serializer) {
+ serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition());
+ }
}
-
-
- // Appends the RDN sequence representing the provided relation.
- private void appendManagedObjectPathElement(RelationDefinition<?, ?> r) {
- // Add the RDN sequence representing the relation.
- try {
- DN localName = DN.decode(profile.getRelationRDNSequence(r));
- dn = dn.concat(localName);
- } catch (DirectoryException e) {
- throw new RuntimeException(e);
- }
- }
-
-
-
- // Gets the serialized DN value.
- private DN toDN() {
- return dn;
- }
- }
-
-
-
- /**
- * Abstract path element.
- */
- private static abstract class Element<C extends ConfigurationClient,
- S extends Configuration> {
-
- // The type of managed object referenced by this element.
- private final AbstractManagedObjectDefinition<C, S> definition;
-
-
-
/**
- * Protected constructor.
+ * A path element representing an set managed object.
+ */
+ private static final class SetElement<C extends ConfigurationClient, S extends Configuration> extends Element<C, S> {
+
+ // Factory method.
+ private static final <C extends ConfigurationClient, S extends Configuration> SetElement<C, S> create(
+ SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ return new SetElement<C, S>(r, d);
+ }
+
+ // The set relation.
+ private final SetRelationDefinition<? super C, ? super S> r;
+
+ // Private constructor.
+ private SetElement(SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ super(d);
+ this.r = r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SetRelationDefinition<? super C, ? super S> getRelationDefinition() {
+ return r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void serialize(ManagedObjectPathSerializer serializer) {
+ serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition());
+ }
+ }
+
+ /**
+ * A path element representing a singleton managed object.
+ */
+ private static final class SingletonElement<C extends ConfigurationClient, S extends Configuration> extends
+ Element<C, S> {
+
+ // Factory method.
+ private static final <C extends ConfigurationClient, S extends Configuration> SingletonElement<C, S> create(
+ SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+ return new SingletonElement<C, S>(r, d);
+ }
+
+ // The singleton relation.
+ private final SingletonRelationDefinition<? super C, ? super S> r;
+
+ // Private constructor.
+ private SingletonElement(SingletonRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ super(d);
+ this.r = r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SingletonRelationDefinition<? super C, ? super S> getRelationDefinition() {
+ return r;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void serialize(ManagedObjectPathSerializer serializer) {
+ serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition());
+ }
+ }
+
+ /**
+ * A serialize which is used to generate the toString representation.
+ */
+ private static final class StringSerializer implements ManagedObjectPathSerializer {
+
+ // Serialize to this string builder.
+ private final StringBuilder builder;
+
+ // Private constructor.
+ private StringSerializer(StringBuilder builder) {
+ this.builder = builder;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+ InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d,
+ String name) {
+ serializeElement(r, d);
+
+ // Be careful to escape any forward slashes in the name.
+ builder.append("+name=");
+ builder.append(name.replace("/", "//"));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+ OptionalRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+ serializeElement(r, d);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+ SingletonRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+ serializeElement(r, d);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+ SetRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+ serializeElement(r, d);
+ }
+
+ // Common element serialization.
+ private <M, N> void serializeElement(RelationDefinition<?, ?> r, AbstractManagedObjectDefinition<?, ?> d) {
+ // Always specify the relation name.
+ builder.append("/relation=");
+ builder.append(r.getName());
+
+ // Only specify the type if it is a sub-type of the relation's
+ // type.
+ if (r.getChildDefinition() != d) {
+ builder.append("+type=");
+ builder.append(d.getName());
+ }
+ }
+ }
+
+ // Single instance of a root path.
+ private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH = new ManagedObjectPath<RootCfgClient, RootCfg>(
+ new LinkedList<Element<?, ?>>(), null, RootCfgDefn.getInstance());
+
+ // A regular expression used to parse path elements.
+ private static final Pattern PE_REGEXP = Pattern.compile("^\\s*relation=\\s*([^+]+)\\s*"
+ + "(\\+\\s*type=\\s*([^+]+)\\s*)?" + "(\\+\\s*name=\\s*([^+]+)\\s*)?$");
+
+ /**
+ * Creates a new managed object path representing the configuration root.
*
- * @param definition
- * The type of managed object referenced by this element.
+ * @return Returns a new managed object path representing the configuration
+ * root.
*/
- protected Element(AbstractManagedObjectDefinition<C, S> definition) {
- this.definition = definition;
+ public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() {
+ return EMPTY_PATH;
}
-
-
/**
- * Get the managed object definition associated with this element.
+ * Returns a managed object path holding the value of the specified string.
*
- * @return Returns the managed object definition associated with
- * this element.
+ * @param s
+ * The string to be parsed.
+ * @return Returns a managed object path holding the value of the specified
+ * string.
+ * @throws IllegalArgumentException
+ * If the string could not be parsed.
*/
- public final AbstractManagedObjectDefinition<C, S>
- getManagedObjectDefinition() {
- return definition;
+ public static ManagedObjectPath<?, ?> valueOf(String s) throws IllegalArgumentException {
+ String ns = s.trim();
+
+ // Check for root special case.
+ if (ns.equals("/")) {
+ return EMPTY_PATH;
+ }
+
+ // Parse the elements.
+ LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
+ Element<?, ?> lastElement = null;
+ AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn.getInstance();
+
+ if (!ns.startsWith("/")) {
+ throw new IllegalArgumentException("Invalid path \"" + ns + "\": must begin with a \"/\"");
+ }
+
+ int start = 1;
+ while (true) {
+ // Get the next path element.
+ int end;
+ for (end = start; end < ns.length(); end++) {
+ char c = ns.charAt(end);
+ if (c == '/') {
+ if (end == (ns.length() - 1)) {
+ throw new IllegalArgumentException("Invalid path \"" + ns
+ + "\": must not end with a trailing \"/\"");
+ }
+
+ if (ns.charAt(end + 1) == '/') {
+ // Found an escaped forward slash.
+ end++;
+ } else {
+ // Found the end of this path element.
+ break;
+ }
+ }
+ }
+
+ // Get the next element.
+ String es = ns.substring(start, end);
+
+ Matcher m = PE_REGEXP.matcher(es);
+ if (!m.matches()) {
+ throw new IllegalArgumentException("Invalid path element \"" + es + "\" in path \"" + ns + "\"");
+ }
+
+ // Mandatory.
+ String relation = m.group(1);
+
+ // Optional.
+ String type = m.group(3);
+
+ // Mandatory if relation is instantiable.
+ String name = m.group(5);
+
+ // Get the relation definition.
+ RelationDefinition<?, ?> r;
+ try {
+ r = definition.getRelationDefinition(relation);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Invalid path element \"" + es + "\" in path \"" + ns
+ + "\": unknown relation \"" + relation + "\"");
+ }
+
+ // Append the next element.
+ lastElement = createElement(r, ns, es, type, name);
+ elements.add(lastElement);
+ definition = lastElement.getManagedObjectDefinition();
+
+ // Update start to point to the beginning of the next element.
+ if (end < ns.length()) {
+ // Skip to the beginning of the next element
+ start = end + 1;
+ } else {
+ // We reached the end of the string.
+ break;
+ }
+ }
+
+ // Construct the new path.
+ return create(elements, lastElement);
}
+ // Factory method required in order to allow generic wild-card
+ // construction of new paths.
+ private static <C extends ConfigurationClient, S extends Configuration> ManagedObjectPath<C, S> create(
+ LinkedList<Element<?, ?>> elements, Element<C, S> lastElement) {
+ return new ManagedObjectPath<C, S>(elements, lastElement.getRelationDefinition(),
+ lastElement.getManagedObjectDefinition());
+ }
+ // Decode an element.
+ private static <C extends ConfigurationClient, S extends Configuration> Element<? extends C, ? extends S> createElement(
+ RelationDefinition<C, S> r, String path, String element, String type, String name) {
+ // First determine the managed object definition.
+ AbstractManagedObjectDefinition<? extends C, ? extends S> d = null;
+
+ if (type != null) {
+ for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : r.getChildDefinition()
+ .getAllChildren()) {
+ if (child.getName().equals(type)) {
+ d = child;
+ break;
+ }
+ }
+
+ if (d == null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+ + "\": unknown sub-type \"" + type + "\"");
+ }
+ } else {
+ d = r.getChildDefinition();
+ }
+
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<C, S> ir = (InstantiableRelationDefinition<C, S>) r;
+
+ if (name == null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+ + "\": no instance name for instantiable relation");
+ }
+
+ return InstantiableElement.create(ir, d, name);
+ } else if (r instanceof SetRelationDefinition) {
+ SetRelationDefinition<C, S> ir = (SetRelationDefinition<C, S>) r;
+
+ if (name != null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+ + "\": instance name specified for set relation");
+ }
+
+ return SetElement.create(ir, d);
+ } else if (r instanceof OptionalRelationDefinition) {
+ OptionalRelationDefinition<C, S> or = (OptionalRelationDefinition<C, S>) r;
+
+ if (name != null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+ + "\": instance name specified for optional relation");
+ }
+
+ return OptionalElement.create(or, d);
+ } else if (r instanceof SingletonRelationDefinition) {
+ SingletonRelationDefinition<C, S> sr = (SingletonRelationDefinition<C, S>) r;
+
+ if (name != null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+ + "\": instance name specified for singleton relation");
+ }
+
+ return SingletonElement.create(sr, d);
+ } else {
+ throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+ + "\": unsupported relation type");
+ }
+ }
+
+ // The managed object definition in this path.
+ private final AbstractManagedObjectDefinition<C, S> d;
+
+ // The list of path elements in this path.
+ private final List<Element<?, ?>> elements;
+
+ // The last relation definition in this path.
+ private final RelationDefinition<? super C, ? super S> r;
+
+ // Private constructor.
+ private ManagedObjectPath(LinkedList<Element<?, ?>> elements, RelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ this.elements = Collections.unmodifiableList(elements);
+ this.r = r;
+ this.d = d;
+ }
/**
- * Get the name associated with this element if applicable.
+ * Creates a new managed object path which has the same structure as this
+ * path except that the final path element is associated with the specified
+ * managed object definition.
*
- * @return Returns the name associated with this element if
- * applicable.
+ * @param <CC>
+ * The type of client managed object configuration that this path
+ * will reference.
+ * @param <SS>
+ * The type of server managed object configuration that this path
+ * will reference.
+ * @param nd
+ * The new managed object definition.
+ * @return Returns a new managed object path which has the same structure as
+ * this path except that the final path element is associated with
+ * the specified managed object definition.
+ */
+ @SuppressWarnings("unchecked")
+ public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType(AbstractManagedObjectDefinition<CC, SS> nd) {
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<? super C, ? super S> ir = (InstantiableRelationDefinition<? super C, ? super S>) r;
+ if (elements.size() == 0) {
+ return parent().child(ir, nd, "null");
+ } else {
+ return parent().child(ir, nd, elements.get(elements.size() - 1).getName());
+ }
+ } else if (r instanceof SetRelationDefinition) {
+ SetRelationDefinition<? super C, ? super S> sr = (SetRelationDefinition<? super C, ? super S>) r;
+ return parent().child(sr, nd);
+ } else if (r instanceof OptionalRelationDefinition) {
+ OptionalRelationDefinition<? super C, ? super S> or = (OptionalRelationDefinition<? super C, ? super S>) r;
+ return parent().child(or, nd);
+ } else {
+ SingletonRelationDefinition<? super C, ? super S> sr = (SingletonRelationDefinition<? super C, ? super S>) r;
+ return parent().child(sr, nd);
+ }
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * having the specified managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The instantiable relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child (must
+ * be a sub-type of the relation).
+ * @param name
+ * The relative name of the child managed object.
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ * @throws IllegalArgumentException
+ * If the provided name is empty or blank.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d, String name)
+ throws IllegalArgumentException {
+ if (name.trim().length() == 0) {
+ throw new IllegalArgumentException("Empty or blank managed object names are not allowed");
+ }
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+ celements.add(new InstantiableElement<M, N>(r, d, name));
+ return new ManagedObjectPath<M, N>(celements, r, d);
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The instantiable relation referencing the child.
+ * @param name
+ * The relative name of the child managed object.
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ * @throws IllegalArgumentException
+ * If the provided name is empty or blank.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ InstantiableRelationDefinition<M, N> r, String name) throws IllegalArgumentException {
+ return child(r, r.getChildDefinition(), name);
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * having the specified managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The optional relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child (must
+ * be a sub-type of the relation).
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ OptionalRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+ celements.add(new OptionalElement<M, N>(r, d));
+ return new ManagedObjectPath<M, N>(celements, r, d);
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The optional relation referencing the child.
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ OptionalRelationDefinition<M, N> r) {
+ return child(r, r.getChildDefinition());
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * having the specified managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The singleton relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child (must
+ * be a sub-type of the relation).
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ SingletonRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+ celements.add(new SingletonElement<M, N>(r, d));
+ return new ManagedObjectPath<M, N>(celements, r, d);
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The singleton relation referencing the child.
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ SingletonRelationDefinition<M, N> r) {
+ return child(r, r.getChildDefinition());
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * having the specified managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The set relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child (must
+ * be a sub-type of the relation).
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ * @throws IllegalArgumentException
+ * If the provided name is empty or blank.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ SetRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d)
+ throws IllegalArgumentException {
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+ celements.add(new SetElement<M, N>(r, d));
+ return new ManagedObjectPath<M, N>(celements, r, d);
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * having the managed object definition indicated by <code>name</code>.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the path
+ * references.
+ * @param <N>
+ * The type of server managed object configuration that the path
+ * references.
+ * @param r
+ * The set relation referencing the child.
+ * @param name
+ * The name of the managed object definition associated with the
+ * child (must be a sub-type of the relation).
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ * @throws IllegalArgumentException
+ * If the provided name is empty or blank or specifies a managed
+ * object definition which is not a sub-type of the relation's
+ * child definition.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<? extends M, ? extends N> child(
+ SetRelationDefinition<M, N> r, String name) throws IllegalArgumentException {
+ AbstractManagedObjectDefinition<M, N> d = r.getChildDefinition();
+ return child(r, d.getChild(name));
+ }
+
+ /**
+ * Creates a new child managed object path beneath the provided parent path
+ * using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the child
+ * path references.
+ * @param <N>
+ * The type of server managed object configuration that the child
+ * path references.
+ * @param r
+ * The set relation referencing the child.
+ * @return Returns a new child managed object path beneath the provided
+ * parent path.
+ * @throws IllegalArgumentException
+ * If the provided name is empty or blank.
+ */
+ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+ SetRelationDefinition<M, N> r) throws IllegalArgumentException {
+ return child(r, r.getChildDefinition());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj instanceof ManagedObjectPath) {
+ ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj;
+ return toString().equals(other.toString());
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Get the definition of the managed object referred to by this path.
+ * <p>
+ * When the path is empty, the {@link RootCfgDefn} is returned.
+ *
+ * @return Returns the definition of the managed object referred to by this
+ * path, or the {@link RootCfgDefn} if the path is empty.
+ */
+ public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
+ return d;
+ }
+
+ /**
+ * Get the name of the managed object referred to by this path if
+ * applicable.
+ * <p>
+ * If there path does not refer to an instantiable managed object
+ * <code>null</code> is returned.
+ *
+ * @return Returns the name of the managed object referred to by this path,
+ * or <code>null</code> if the managed object does not have a name.
*/
public String getName() {
- return null;
+ if (elements.isEmpty()) {
+ return null;
+ } else {
+ return elements.get(elements.size() - 1).getName();
+ }
}
-
-
/**
- * Get the relation definition associated with this element.
+ * Get the relation definition of the managed object referred to by this
+ * path.
+ * <p>
+ * When the path is empty, the <code>null</code> is returned.
*
- * @return Returns the relation definition associated with this
- * element.
+ * @return Returns the relation definition of the managed object referred to
+ * by this path, or the <code>null</code> if the path is empty.
*/
- public abstract RelationDefinition<? super C, ? super S>
- getRelationDefinition();
-
-
+ public RelationDefinition<? super C, ? super S> getRelationDefinition() {
+ return r;
+ }
/**
- * Serialize this path element using the provided serialization
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ /**
+ * Determine whether or not this path contains any path elements.
+ *
+ * @return Returns <code>true</code> if this path does not contain any path
+ * elements.
+ */
+ public boolean isEmpty() {
+ return elements.isEmpty();
+ }
+
+ /**
+ * Determines whether this managed object path references the same location
+ * as the provided managed object path.
+ * <p>
+ * This method differs from <code>equals</code> in that it ignores sub-type
+ * definitions.
+ *
+ * @param other
+ * The managed object path to be compared.
+ * @return Returns <code>true</code> if this managed object path references
+ * the same location as the provided managed object path.
+ */
+ public boolean matches(ManagedObjectPath<?, ?> other) {
+ DN thisDN = toDN();
+ DN otherDN = other.toDN();
+ return thisDN.equals(otherDN);
+ }
+
+ /**
+ * Creates a new parent managed object path representing the immediate
+ * parent of this path. This method is a short-hand for
+ * <code>parent(1)</code>.
+ *
+ * @return Returns a new parent managed object path representing the
+ * immediate parent of this path.
+ * @throws IllegalArgumentException
+ * If this path does not have a parent (i.e. it is the empty
+ * path).
+ */
+ public ManagedObjectPath<?, ?> parent() throws IllegalArgumentException {
+ return parent(1);
+ }
+
+ /**
+ * Creates a new parent managed object path the specified number of path
+ * elements above this path.
+ *
+ * @param offset
+ * The number of path elements (0 - means no offset, 1 means the
+ * parent, and 2 means the grand-parent).
+ * @return Returns a new parent managed object path the specified number of
+ * path elements above this path.
+ * @throws IllegalArgumentException
+ * If the offset is less than 0, or greater than the number of
+ * path elements in this path.
+ */
+ public ManagedObjectPath<?, ?> parent(int offset) throws IllegalArgumentException {
+ if (offset < 0) {
+ throw new IllegalArgumentException("Negative offset");
+ }
+
+ if (offset > elements.size()) {
+ throw new IllegalArgumentException("Offset is greater than the number of path elements");
+ }
+
+ // An offset of 0 leaves the path unchanged.
+ if (offset == 0) {
+ return this;
+ }
+
+ // Return the empty path if the parent has zero elements.
+ if (elements.size() == offset) {
+ return emptyPath();
+ }
+
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements.subList(0, elements.size()
+ - offset));
+ return create(celements, celements.getLast());
+ }
+
+ /**
+ * Creates a new managed object path which has the same structure as this
+ * path except that the final path element is renamed. The final path
+ * element must comprise of an instantiable relation.
+ *
+ * @param newName
+ * The new name of the final path element.
+ * @return Returns a new managed object path which has the same structure as
+ * this path except that the final path element is renamed.
+ * @throws IllegalStateException
+ * If this managed object path is empty or if its final path
+ * element does not comprise of an instantiable relation.
+ */
+ @SuppressWarnings("unchecked")
+ public ManagedObjectPath<C, S> rename(String newName) throws IllegalStateException {
+ if (elements.size() == 0) {
+ throw new IllegalStateException("Cannot rename an empty path");
+ }
+
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<? super C, ? super S> ir = (InstantiableRelationDefinition<? super C, ? super S>) r;
+ return parent().child(ir, d, newName);
+ } else {
+ throw new IllegalStateException("Not an instantiable relation");
+ }
+ }
+
+ /**
+ * Serialize this managed object path using the provided serialization
* strategy.
+ * <p>
+ * The path elements will be passed to the serializer in big-endian order:
+ * starting from the root element and proceeding down to the leaf.
*
* @param serializer
- * The managed object path serialization strategy.
+ * The managed object path serialization strategy.
*/
- public abstract void serialize(ManagedObjectPathSerializer serializer);
- }
-
-
-
- /**
- * A path element representing an instantiable managed object.
- */
- private static final class InstantiableElement
- <C extends ConfigurationClient, S extends Configuration>
- extends Element<C, S> {
-
- // Factory method.
- private static final <C extends ConfigurationClient,
- S extends Configuration>
- InstantiableElement<C, S> create(
- InstantiableRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d, String name) {
- return new InstantiableElement<C, S>(r, d, name);
- }
-
- // The name of the managed object.
- private final String name;
-
- // The instantiable relation.
- private final InstantiableRelationDefinition<? super C, ? super S> r;
-
-
-
- // Private constructor.
- private InstantiableElement(
- InstantiableRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d, String name) {
- super(d);
- this.r = r;
- this.name = name;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getName() {
- return name;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public InstantiableRelationDefinition<? super C, ? super S>
- getRelationDefinition() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
public void serialize(ManagedObjectPathSerializer serializer) {
- serializer.appendManagedObjectPathElement(r,
- getManagedObjectDefinition(), name);
- }
- }
-
-
-
- /**
- * A path element representing an optional managed object.
- */
- private static final class OptionalElement
- <C extends ConfigurationClient, S extends Configuration>
- extends Element<C, S> {
-
- // Factory method.
- private static final <C extends ConfigurationClient,
- S extends Configuration> OptionalElement<C, S> create(
- OptionalRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- return new OptionalElement<C, S>(r, d);
- }
-
- // The optional relation.
- private final OptionalRelationDefinition<? super C, ? super S> r;
-
-
-
- // Private constructor.
- private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- super(d);
- this.r = r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public OptionalRelationDefinition<? super C, ? super S>
- getRelationDefinition() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(ManagedObjectPathSerializer serializer) {
- serializer
- .appendManagedObjectPathElement(r, getManagedObjectDefinition());
- }
- }
-
-
-
- /**
- * A path element representing an set managed object.
- */
- private static final class SetElement
- <C extends ConfigurationClient, S extends Configuration>
- extends Element<C, S> {
-
- // Factory method.
- private static final <C extends ConfigurationClient,
- S extends Configuration>
- SetElement<C, S> create(
- SetRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- return new SetElement<C, S>(r, d);
- }
-
- // The set relation.
- private final SetRelationDefinition<? super C, ? super S> r;
-
-
-
- // Private constructor.
- private SetElement(
- SetRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- super(d);
- this.r = r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public SetRelationDefinition<? super C, ? super S>
- getRelationDefinition() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(ManagedObjectPathSerializer serializer) {
- serializer.appendManagedObjectPathElement(r,
- getManagedObjectDefinition());
- }
- }
-
-
-
- /**
- * A path element representing a singleton managed object.
- */
- private static final class SingletonElement
- <C extends ConfigurationClient, S extends Configuration>
- extends Element<C, S> {
-
- // Factory method.
- private static final <C extends ConfigurationClient,
- S extends Configuration> SingletonElement<C, S> create(
- SingletonRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- return new SingletonElement<C, S>(r, d);
- }
-
- // The singleton relation.
- private final SingletonRelationDefinition<? super C, ? super S> r;
-
-
-
- // Private constructor.
- private SingletonElement(
- SingletonRelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- super(d);
- this.r = r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public SingletonRelationDefinition<? super C, ? super S>
- getRelationDefinition() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void serialize(ManagedObjectPathSerializer serializer) {
- serializer
- .appendManagedObjectPathElement(r, getManagedObjectDefinition());
- }
- }
-
-
-
- /**
- * A serialize which is used to generate the toString
- * representation.
- */
- private static final class StringSerializer implements
- ManagedObjectPathSerializer {
-
- // Serialize to this string builder.
- private final StringBuilder builder;
-
-
-
- // Private constructor.
- private StringSerializer(StringBuilder builder) {
- this.builder = builder;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <M extends ConfigurationClient, N extends Configuration>
- void appendManagedObjectPathElement(
- InstantiableRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d, String name) {
- serializeElement(r, d);
-
- // Be careful to escape any forward slashes in the name.
- builder.append("+name=");
- builder.append(name.replace("/", "//"));
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <M extends ConfigurationClient, N extends Configuration>
- void appendManagedObjectPathElement(
- OptionalRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d) {
- serializeElement(r, d);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <M extends ConfigurationClient, N extends Configuration>
- void appendManagedObjectPathElement(
- SingletonRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d) {
- serializeElement(r, d);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <M extends ConfigurationClient, N extends Configuration>
- void appendManagedObjectPathElement(
- SetRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d) {
- serializeElement(r, d);
- }
-
-
-
- // Common element serialization.
- private <M, N> void serializeElement(RelationDefinition<?, ?> r,
- AbstractManagedObjectDefinition<?, ?> d) {
- // Always specify the relation name.
- builder.append("/relation=");
- builder.append(r.getName());
-
- // Only specify the type if it is a sub-type of the relation's
- // type.
- if (r.getChildDefinition() != d) {
- builder.append("+type=");
- builder.append(d.getName());
- }
- }
- }
-
- // Single instance of a root path.
- private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH =
- new ManagedObjectPath<RootCfgClient, RootCfg>(
- new LinkedList<Element<?, ?>>(), null, RootCfgDefn.getInstance());
-
- // A regular expression used to parse path elements.
- private static final Pattern PE_REGEXP = Pattern
- .compile("^\\s*relation=\\s*([^+]+)\\s*"
- + "(\\+\\s*type=\\s*([^+]+)\\s*)?"
- + "(\\+\\s*name=\\s*([^+]+)\\s*)?$");
-
-
-
- /**
- * Creates a new managed object path representing the configuration
- * root.
- *
- * @return Returns a new managed object path representing the
- * configuration root.
- */
- public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() {
- return EMPTY_PATH;
- }
-
-
-
- /**
- * Returns a managed object path holding the value of the specified
- * string.
- *
- * @param s
- * The string to be parsed.
- * @return Returns a managed object path holding the value of the
- * specified string.
- * @throws IllegalArgumentException
- * If the string could not be parsed.
- */
- public static ManagedObjectPath<?, ?> valueOf(String s)
- throws IllegalArgumentException {
- String ns = s.trim();
-
- // Check for root special case.
- if (ns.equals("/")) {
- return EMPTY_PATH;
- }
-
- // Parse the elements.
- LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
- Element<?, ?> lastElement = null;
- AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn
- .getInstance();
-
- if (!ns.startsWith("/")) {
- throw new IllegalArgumentException("Invalid path \"" + ns
- + "\": must begin with a \"/\"");
- }
-
- int start = 1;
- while (true) {
- // Get the next path element.
- int end;
- for (end = start; end < ns.length(); end++) {
- char c = ns.charAt(end);
- if (c == '/') {
- if (end == (ns.length() - 1)) {
- throw new IllegalArgumentException("Invalid path \"" + ns
- + "\": must not end with a trailing \"/\"");
- }
-
- if (ns.charAt(end + 1) == '/') {
- // Found an escaped forward slash.
- end++;
- } else {
- // Found the end of this path element.
- break;
- }
+ for (Element<?, ?> element : elements) {
+ element.serialize(serializer);
}
- }
-
- // Get the next element.
- String es = ns.substring(start, end);
-
- Matcher m = PE_REGEXP.matcher(es);
- if (!m.matches()) {
- throw new IllegalArgumentException("Invalid path element \"" + es
- + "\" in path \"" + ns + "\"");
- }
-
- // Mandatory.
- String relation = m.group(1);
-
- // Optional.
- String type = m.group(3);
-
- // Mandatory if relation is instantiable.
- String name = m.group(5);
-
- // Get the relation definition.
- RelationDefinition<?, ?> r;
- try {
- r = definition.getRelationDefinition(relation);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Invalid path element \"" + es
- + "\" in path \"" + ns + "\": unknown relation \"" + relation
- + "\"");
- }
-
- // Append the next element.
- lastElement = createElement(r, ns, es, type, name);
- elements.add(lastElement);
- definition = lastElement.getManagedObjectDefinition();
-
- // Update start to point to the beginning of the next element.
- if (end < ns.length()) {
- // Skip to the beginning of the next element
- start = end + 1;
- } else {
- // We reached the end of the string.
- break;
- }
}
- // Construct the new path.
- return create(elements, lastElement);
- }
+ /**
+ * Get the number of path elements in this managed object path.
+ *
+ * @return Returns the number of path elements (0 - means no offset, 1 means
+ * the parent, and 2 means the grand-parent).
+ */
+ public int size() {
+ return elements.size();
+ }
+ /**
+ * Creates a DN representation of this managed object path.
+ *
+ * @return Returns a DN representation of this managed object path.
+ */
+ public DN toDN() {
+ // Use a simple serializer to create the contents.
+ DNSerializer serializer = new DNSerializer();
+ serialize(serializer);
+ return serializer.toDN();
+ }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ toString(builder);
+ return builder.toString();
+ }
- // Factory method required in order to allow generic wild-card
- // construction of new paths.
- private static <C extends ConfigurationClient, S extends Configuration>
- ManagedObjectPath<C, S> create(
- LinkedList<Element<?, ?>> elements, Element<C, S> lastElement) {
- return new ManagedObjectPath<C, S>(elements, lastElement
- .getRelationDefinition(), lastElement.getManagedObjectDefinition());
- }
-
-
-
- // Decode an element.
- private static <C extends ConfigurationClient, S extends Configuration>
- Element<? extends C, ? extends S> createElement(
- RelationDefinition<C, S> r, String path, String element, String type,
- String name) {
- // First determine the managed object definition.
- AbstractManagedObjectDefinition<? extends C, ? extends S> d = null;
-
- if (type != null) {
- for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : r
- .getChildDefinition().getAllChildren()) {
- if (child.getName().equals(type)) {
- d = child;
- break;
+ /**
+ * Appends a string representation of this managed object path to the
+ * provided string builder.
+ *
+ * @param builder
+ * Append the string representation to this builder.
+ * @see #toString()
+ */
+ public void toString(final StringBuilder builder) {
+ if (isEmpty()) {
+ // Special treatment of root configuration paths.
+ builder.append('/');
+ } else {
+ // Use a simple serializer to create the contents.
+ ManagedObjectPathSerializer serializer = new StringSerializer(builder);
+ serialize(serializer);
}
- }
-
- if (d == null) {
- throw new IllegalArgumentException("Invalid path element \"" + element
- + "\" in path \"" + path + "\": unknown sub-type \"" + type + "\"");
- }
- } else {
- d = r.getChildDefinition();
}
- if (r instanceof InstantiableRelationDefinition) {
- InstantiableRelationDefinition<C, S> ir =
- (InstantiableRelationDefinition<C, S>) r;
-
- if (name == null) {
- throw new IllegalArgumentException("Invalid path element \"" + element
- + "\" in path \"" + path
- + "\": no instance name for instantiable relation");
- }
-
- return InstantiableElement.create(ir, d, name);
- } else if (r instanceof SetRelationDefinition) {
- SetRelationDefinition<C, S> ir = (SetRelationDefinition<C, S>) r;
-
- if (name != null) {
- throw new IllegalArgumentException("Invalid path element \"" + element
- + "\" in path \"" + path
- + "\": instance name specified for set relation");
- }
-
- return SetElement.create(ir, d);
- } else if (r instanceof OptionalRelationDefinition) {
- OptionalRelationDefinition<C, S> or =
- (OptionalRelationDefinition<C, S>) r;
-
- if (name != null) {
- throw new IllegalArgumentException("Invalid path element \"" + element
- + "\" in path \"" + path
- + "\": instance name specified for optional relation");
- }
-
- return OptionalElement.create(or, d);
- } else if (r instanceof SingletonRelationDefinition) {
- SingletonRelationDefinition<C, S> sr =
- (SingletonRelationDefinition<C, S>) r;
-
- if (name != null) {
- throw new IllegalArgumentException("Invalid path element \"" + element
- + "\" in path \"" + path
- + "\": instance name specified for singleton relation");
- }
-
- return SingletonElement.create(sr, d);
- } else {
- throw new IllegalArgumentException("Invalid path element \"" + element
- + "\" in path \"" + path + "\": unsupported relation type");
- }
- }
-
- // The managed object definition in this path.
- private final AbstractManagedObjectDefinition<C, S> d;
-
- // The list of path elements in this path.
- private final List<Element<?, ?>> elements;
-
- // The last relation definition in this path.
- private final RelationDefinition<? super C, ? super S> r;
-
-
-
- // Private constructor.
- private ManagedObjectPath(LinkedList<Element<?, ?>> elements,
- RelationDefinition<? super C, ? super S> r,
- AbstractManagedObjectDefinition<C, S> d) {
- this.elements = Collections.unmodifiableList(elements);
- this.r = r;
- this.d = d;
- }
-
-
-
- /**
- * Creates a new managed object path which has the same structure as
- * this path except that the final path element is associated with
- * the specified managed object definition.
- *
- * @param <CC>
- * The type of client managed object configuration that
- * this path will reference.
- * @param <SS>
- * The type of server managed object configuration that
- * this path will reference.
- * @param nd
- * The new managed object definition.
- * @return Returns a new managed object path which has the same
- * structure as this path except that the final path element
- * is associated with the specified managed object
- * definition.
- */
- @SuppressWarnings("unchecked")
- public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType(
- AbstractManagedObjectDefinition<CC, SS> nd) {
- if (r instanceof InstantiableRelationDefinition) {
- InstantiableRelationDefinition<? super C, ? super S> ir =
- (InstantiableRelationDefinition<? super C, ? super S>) r;
- if (elements.size() == 0) {
- return parent().child(ir, nd, "null");
- } else {
- return parent().child(ir, nd,
- elements.get(elements.size() - 1).getName());
- }
- } else if (r instanceof SetRelationDefinition) {
- SetRelationDefinition<? super C, ? super S> sr =
- (SetRelationDefinition<? super C, ? super S>) r;
- return parent().child(sr, nd);
- } else if (r instanceof OptionalRelationDefinition) {
- OptionalRelationDefinition<? super C, ? super S> or =
- (OptionalRelationDefinition<? super C, ? super S>) r;
- return parent().child(or, nd);
- } else {
- SingletonRelationDefinition<? super C, ? super S> sr =
- (SingletonRelationDefinition<? super C, ? super S>) r;
- return parent().child(sr, nd);
- }
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path having the specified managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The instantiable relation referencing the child.
- * @param d
- * The managed object definition associated with the child
- * (must be a sub-type of the relation).
- * @param name
- * The relative name of the child managed object.
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- * @throws IllegalArgumentException
- * If the provided name is empty or blank.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- InstantiableRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d, String name)
- throws IllegalArgumentException {
- if (name.trim().length() == 0) {
- throw new IllegalArgumentException(
- "Empty or blank managed object names are not allowed");
- }
- LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
- elements);
- celements.add(new InstantiableElement<M, N>(r, d, name));
- return new ManagedObjectPath<M, N>(celements, r, d);
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path using the relation's child managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The instantiable relation referencing the child.
- * @param name
- * The relative name of the child managed object.
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- * @throws IllegalArgumentException
- * If the provided name is empty or blank.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- InstantiableRelationDefinition<M, N> r, String name)
- throws IllegalArgumentException {
- return child(r, r.getChildDefinition(), name);
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path having the specified managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The optional relation referencing the child.
- * @param d
- * The managed object definition associated with the child
- * (must be a sub-type of the relation).
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- OptionalRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d) {
- LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
- elements);
- celements.add(new OptionalElement<M, N>(r, d));
- return new ManagedObjectPath<M, N>(celements, r, d);
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path using the relation's child managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The optional relation referencing the child.
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(OptionalRelationDefinition<M, N> r) {
- return child(r, r.getChildDefinition());
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path having the specified managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The singleton relation referencing the child.
- * @param d
- * The managed object definition associated with the child
- * (must be a sub-type of the relation).
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- SingletonRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d) {
- LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
- elements);
- celements.add(new SingletonElement<M, N>(r, d));
- return new ManagedObjectPath<M, N>(celements, r, d);
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path using the relation's child managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The singleton relation referencing the child.
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(SingletonRelationDefinition<M, N> r) {
- return child(r, r.getChildDefinition());
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path having the specified managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The set relation referencing the child.
- * @param d
- * The managed object definition associated with the child
- * (must be a sub-type of the relation).
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- * @throws IllegalArgumentException
- * If the provided name is empty or blank.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- SetRelationDefinition<? super M, ? super N> r,
- AbstractManagedObjectDefinition<M, N> d)
- throws IllegalArgumentException {
- LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
- elements);
- celements.add(new SetElement<M, N>(r, d));
- return new ManagedObjectPath<M, N>(celements, r, d);
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided parent
- * path having the managed object definition indicated by
- * <code>name</code>.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * path references.
- * @param <N>
- * The type of server managed object configuration that the
- * path references.
- * @param r
- * The set relation referencing the child.
- * @param name
- * The name of the managed object definition associated with
- * the child (must be a sub-type of the relation).
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- * @throws IllegalArgumentException
- * If the provided name is empty or blank or specifies a
- * managed object definition which is not a sub-type of the
- * relation's child definition.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<? extends M, ? extends N> child(
- SetRelationDefinition<M, N> r,
- String name)
- throws IllegalArgumentException {
- AbstractManagedObjectDefinition<M, N> d = r.getChildDefinition();
- return child(r, d.getChild(name));
- }
-
-
-
- /**
- * Creates a new child managed object path beneath the provided
- * parent path using the relation's child managed object definition.
- *
- * @param <M>
- * The type of client managed object configuration that the
- * child path references.
- * @param <N>
- * The type of server managed object configuration that the
- * child path references.
- * @param r
- * The set relation referencing the child.
- * @return Returns a new child managed object path beneath the
- * provided parent path.
- * @throws IllegalArgumentException
- * If the provided name is empty or blank.
- */
- public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- SetRelationDefinition<M, N> r)
- throws IllegalArgumentException {
- return child(r, r.getChildDefinition());
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- } else if (obj instanceof ManagedObjectPath) {
- ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj;
- return toString().equals(other.toString());
- } else {
- return false;
- }
- }
-
-
-
- /**
- * Get the definition of the managed object referred to by this
- * path.
- * <p>
- * When the path is empty, the {@link RootCfgDefn} is returned.
- *
- * @return Returns the definition of the managed object referred to
- * by this path, or the {@link RootCfgDefn} if the path is
- * empty.
- */
- public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
- return d;
- }
-
-
-
- /**
- * Get the name of the managed object referred to by this path if
- * applicable.
- * <p>
- * If there path does not refer to an instantiable managed object
- * <code>null</code> is returned.
- *
- * @return Returns the name of the managed object referred to by
- * this path, or <code>null</code> if the managed object
- * does not have a name.
- */
- public String getName() {
- if (elements.isEmpty()) {
- return null;
- } else {
- return elements.get(elements.size() - 1).getName();
- }
- }
-
-
-
- /**
- * Get the relation definition of the managed object referred to by
- * this path.
- * <p>
- * When the path is empty, the <code>null</code> is returned.
- *
- * @return Returns the relation definition of the managed object
- * referred to by this path, or the <code>null</code> if
- * the path is empty.
- */
- public RelationDefinition<? super C, ? super S> getRelationDefinition() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return toString().hashCode();
- }
-
-
-
- /**
- * Determine whether or not this path contains any path elements.
- *
- * @return Returns <code>true</code> if this path does not contain
- * any path elements.
- */
- public boolean isEmpty() {
- return elements.isEmpty();
- }
-
-
-
- /**
- * Determines whether this managed object path references the same
- * location as the provided managed object path.
- * <p>
- * This method differs from <code>equals</code> in that it ignores
- * sub-type definitions.
- *
- * @param other
- * The managed object path to be compared.
- * @return Returns <code>true</code> if this managed object path
- * references the same location as the provided managed
- * object path.
- */
- public boolean matches(ManagedObjectPath<?, ?> other) {
- DN thisDN = toDN();
- DN otherDN = other.toDN();
- return thisDN.equals(otherDN);
- }
-
-
-
- /**
- * Creates a new parent managed object path representing the
- * immediate parent of this path. This method is a short-hand for
- * <code>parent(1)</code>.
- *
- * @return Returns a new parent managed object path representing the
- * immediate parent of this path.
- * @throws IllegalArgumentException
- * If this path does not have a parent (i.e. it is the
- * empty path).
- */
- public ManagedObjectPath<?, ?> parent() throws IllegalArgumentException {
- return parent(1);
- }
-
-
-
- /**
- * Creates a new parent managed object path the specified number of
- * path elements above this path.
- *
- * @param offset
- * The number of path elements (0 - means no offset, 1
- * means the parent, and 2 means the grand-parent).
- * @return Returns a new parent managed object path the specified
- * number of path elements above this path.
- * @throws IllegalArgumentException
- * If the offset is less than 0, or greater than the
- * number of path elements in this path.
- */
- public ManagedObjectPath<?, ?> parent(int offset)
- throws IllegalArgumentException {
- if (offset < 0) {
- throw new IllegalArgumentException("Negative offset");
- }
-
- if (offset > elements.size()) {
- throw new IllegalArgumentException(
- "Offset is greater than the number of path elements");
- }
-
- // An offset of 0 leaves the path unchanged.
- if (offset == 0) {
- return this;
- }
-
- // Return the empty path if the parent has zero elements.
- if (elements.size() == offset) {
- return emptyPath();
- }
-
- LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
- elements.subList(0, elements.size() - offset));
- return create(celements, celements.getLast());
- }
-
-
-
- /**
- * Creates a new managed object path which has the same structure as
- * this path except that the final path element is renamed. The
- * final path element must comprise of an instantiable relation.
- *
- * @param newName
- * The new name of the final path element.
- * @return Returns a new managed object path which has the same
- * structure as this path except that the final path element
- * is renamed.
- * @throws IllegalStateException
- * If this managed object path is empty or if its final
- * path element does not comprise of an instantiable
- * relation.
- */
- @SuppressWarnings("unchecked")
- public ManagedObjectPath<C, S> rename(String newName)
- throws IllegalStateException {
- if (elements.size() == 0) {
- throw new IllegalStateException("Cannot rename an empty path");
- }
-
- if (r instanceof InstantiableRelationDefinition) {
- InstantiableRelationDefinition<? super C, ? super S> ir =
- (InstantiableRelationDefinition<? super C, ? super S>) r;
- return parent().child(ir, d, newName);
- } else {
- throw new IllegalStateException("Not an instantiable relation");
- }
- }
-
-
-
- /**
- * Serialize this managed object path using the provided
- * serialization strategy.
- * <p>
- * The path elements will be passed to the serializer in big-endian
- * order: starting from the root element and proceeding down to the
- * leaf.
- *
- * @param serializer
- * The managed object path serialization strategy.
- */
- public void serialize(ManagedObjectPathSerializer serializer) {
- for (Element<?, ?> element : elements) {
- element.serialize(serializer);
- }
- }
-
-
-
- /**
- * Get the number of path elements in this managed object path.
- *
- * @return Returns the number of path elements (0 - means no offset,
- * 1 means the parent, and 2 means the grand-parent).
- */
- public int size() {
- return elements.size();
- }
-
-
-
- /**
- * Creates a DN representation of this managed object path.
- *
- * @return Returns a DN representation of this managed object path.
- */
- public DN toDN() {
- // Use a simple serializer to create the contents.
- DNSerializer serializer = new DNSerializer();
- serialize(serializer);
- return serializer.toDN();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- toString(builder);
- return builder.toString();
- }
-
-
-
- /**
- * Appends a string representation of this managed object path to
- * the provided string builder.
- *
- * @param builder
- * Append the string representation to this builder.
- * @see #toString()
- */
- public void toString(final StringBuilder builder) {
- if (isEmpty()) {
- // Special treatment of root configuration paths.
- builder.append('/');
- } else {
- // Use a simple serializer to create the contents.
- ManagedObjectPathSerializer serializer = new StringSerializer(builder);
- serialize(serializer);
- }
- }
-
}
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/Reference.java b/opendj-admin/src/main/java/org/opends/server/admin/Reference.java
index cf1cfbd..78a3ad9 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/Reference.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/Reference.java
@@ -26,220 +26,182 @@
*/
package org.opends.server.admin;
+import static com.forgerock.opendj.util.StaticUtils.*;
-
-import org.opends.server.types.AttributeValue;
import org.forgerock.opendj.ldap.DN;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.RDN;
-import org.opends.server.util.StaticUtils;
-
-
+import org.forgerock.opendj.ldap.RDN;
/**
* A reference to another managed object.
*
* @param <C>
- * The type of client managed object configuration that this
- * reference refers to.
+ * The type of client managed object configuration that this
+ * reference refers to.
* @param <S>
- * The type of server managed object configuration that this
- * reference refers to.
+ * The type of server managed object configuration that this
+ * reference refers to.
*/
-public final class Reference<C extends ConfigurationClient,
- S extends Configuration> {
+public final class Reference<C extends ConfigurationClient, S extends Configuration> {
- /**
- * Parses a DN string value as a reference using the provided
- * managed object path and relation definition.
- *
- * @param <C>
- * The type of client managed object configuration that
- * this reference refers to.
- * @param <S>
- * The type of server managed object configuration that
- * this reference refers to.
- * @param p
- * The path of the referenced managed object's parent.
- * @param rd
- * The instantiable relation in the parent which contains
- * the referenced managed object.
- * @param s
- * The DN string value.
- * @return Returns the new reference based on the provided DN string
- * value.
- * @throws IllegalArgumentException
- * If the DN string value could not be decoded as a DN or
- * if the provided DN did not correspond to the provided
- * path and relation.
- */
- public static <C extends ConfigurationClient, S extends Configuration>
- Reference<C, S> parseDN(
- ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd,
- String s) throws IllegalArgumentException {
- AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition();
- RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
- if (tmp != rd) {
- throw new IllegalArgumentException("The relation \"" + rd.getName()
- + "\" is not associated with the definition \"" + d.getName() + "\"");
+ /**
+ * Parses a DN string value as a reference using the provided managed object
+ * path and relation definition.
+ *
+ * @param <C>
+ * The type of client managed object configuration that this
+ * reference refers to.
+ * @param <S>
+ * The type of server managed object configuration that this
+ * reference refers to.
+ * @param path
+ * The path of the referenced managed object's parent.
+ * @param relationDef
+ * The instantiable relation in the parent which contains the
+ * referenced managed object.
+ * @param dnAsString
+ * The DN string value.
+ * @return Returns the new reference based on the provided DN string value.
+ * @throws IllegalArgumentException
+ * If the DN string value could not be decoded as a DN or if the
+ * provided DN did not correspond to the provided path and
+ * relation.
+ */
+ public static <C extends ConfigurationClient, S extends Configuration> Reference<C, S> parseDN(
+ ManagedObjectPath<?, ?> path, InstantiableRelationDefinition<C, S> relationDef, String dnAsString)
+ throws IllegalArgumentException {
+ AbstractManagedObjectDefinition<?, ?> definition = path.getManagedObjectDefinition();
+ RelationDefinition<?, ?> tmp = definition.getRelationDefinition(relationDef.getName());
+ if (tmp != relationDef) {
+ // TODO : i18n ?
+ throw new IllegalArgumentException("The relation \"" + relationDef.getName()
+ + "\" is not associated with the definition \"" + definition.getName() + "\"");
+ }
+
+ DN dn = DN.valueOf(dnAsString);
+ RDN rdn = dn.rdn();
+ if (rdn == null) {
+ // TODO : i18n ?
+ throw new IllegalArgumentException("Unabled to decode the DN string: \"" + dnAsString + "\"");
+ }
+
+ // Check that the DN was valid.
+ String name = rdn.getFirstAVA().getAttributeValue().toString();
+ DN expected = path.child(relationDef, name).toDN();
+ if (!dn.equals(expected)) {
+ // TODO : i18n ?
+ throw new IllegalArgumentException("Unabled to decode the DN string: \"" + dnAsString + "\"");
+ }
+
+ return new Reference<C, S>(path, relationDef, name);
}
- DN dn;
- try {
- dn = DN.decode(s);
- } catch (DirectoryException e) {
- throw new IllegalArgumentException("Unabled to decode the DN string: \""
- + s + "\"");
+ /**
+ * Parses a name as a reference using the provided managed object path and
+ * relation definition.
+ *
+ * @param <C>
+ * The type of client managed object configuration that this
+ * reference refers to.
+ * @param <S>
+ * The type of server managed object configuration that this
+ * reference refers to.
+ * @param p
+ * The path of the referenced managed object's parent.
+ * @param rd
+ * The instantiable relation in the parent which contains the
+ * referenced managed object.
+ * @param s
+ * The name of the referenced managed object.
+ * @return Returns the new reference based on the provided name.
+ * @throws IllegalArgumentException
+ * If the relation is not associated with the provided parent's
+ * definition, or if the provided name is empty.
+ */
+ public static <C extends ConfigurationClient, S extends Configuration> Reference<C, S> parseName(
+ ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd, String s)
+ throws IllegalArgumentException {
+ // Sanity checks.
+ AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition();
+ RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
+ if (tmp != rd) {
+ throw new IllegalArgumentException("The relation \"" + rd.getName()
+ + "\" is not associated with the definition \"" + d.getName() + "\"");
+ }
+
+ if (s.trim().length() == 0) {
+ throw new IllegalArgumentException("Empty names are not allowed");
+ }
+
+ return new Reference<C, S>(p, rd, s);
}
- RDN rdn = dn.getRDN();
- if (rdn == null) {
- throw new IllegalArgumentException("Unabled to decode the DN string: \""
- + s + "\"");
+ // The name of the referenced managed object.
+ private final String name;
+
+ // The path of the referenced managed object.
+ private final ManagedObjectPath<C, S> path;
+
+ // The instantiable relation in the parent which contains the
+ // referenced managed object.
+ private final InstantiableRelationDefinition<C, S> relation;
+
+ // Private constructor.
+ private Reference(ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> relation, String name)
+ throws IllegalArgumentException {
+ this.relation = relation;
+ this.name = name;
+ this.path = parent.child(relation, name);
}
- AttributeValue av = rdn.getAttributeValue(0);
- if (av == null) {
- throw new IllegalArgumentException("Unabled to decode the DN string: \""
- + s + "\"");
+ /**
+ * Gets the name of the referenced managed object.
+ *
+ * @return Returns the name of the referenced managed object.
+ */
+ public String getName() {
+ return name;
}
- String name = av.getValue().toString();
-
- // Check that the DN was valid.
- DN expected = p.child(rd, name).toDN();
- if (!dn.equals(expected)) {
- throw new IllegalArgumentException("Unabled to decode the DN string: \""
- + s + "\"");
+ /**
+ * Gets the normalized name of the referenced managed object.
+ *
+ * @return Returns the normalized name of the referenced managed object.
+ */
+ public String getNormalizedName() {
+ PropertyDefinition<?> pd = relation.getNamingPropertyDefinition();
+ return normalizeName(pd);
}
- return new Reference<C, S>(p, rd, name);
- }
-
-
-
- /**
- * Parses a name as a reference using the provided managed object
- * path and relation definition.
- *
- * @param <C>
- * The type of client managed object configuration that
- * this reference refers to.
- * @param <S>
- * The type of server managed object configuration that
- * this reference refers to.
- * @param p
- * The path of the referenced managed object's parent.
- * @param rd
- * The instantiable relation in the parent which contains
- * the referenced managed object.
- * @param s
- * The name of the referenced managed object.
- * @return Returns the new reference based on the provided name.
- * @throws IllegalArgumentException
- * If the relation is not associated with the provided
- * parent's definition, or if the provided name is empty.
- */
- public static <C extends ConfigurationClient, S extends Configuration>
- Reference<C, S> parseName(
- ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd,
- String s) throws IllegalArgumentException {
- // Sanity checks.
- AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition();
- RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
- if (tmp != rd) {
- throw new IllegalArgumentException("The relation \"" + rd.getName()
- + "\" is not associated with the definition \"" + d.getName() + "\"");
+ /**
+ * Gets the DN of the referenced managed object.
+ *
+ * @return Returns the DN of the referenced managed object.
+ */
+ public DN toDN() {
+ return path.toDN();
}
- if (s.trim().length() == 0) {
- throw new IllegalArgumentException("Empty names are not allowed");
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return name;
}
- return new Reference<C, S>(p, rd, s);
- }
+ // Normalize a value using the specified naming property definition
+ // if defined.
+ private <T> String normalizeName(PropertyDefinition<T> pd) {
+ if (pd != null) {
+ try {
+ T tvalue = pd.decodeValue(name);
+ return pd.normalizeValue(tvalue);
+ } catch (IllegalPropertyValueStringException e) {
+ // Fall through to default normalization.
+ }
+ }
- // The name of the referenced managed object.
- private final String name;
-
- // The path of the referenced managed object.
- private final ManagedObjectPath<C, S> path;
-
- // The instantiable relation in the parent which contains the
- // referenced managed object.
- private final InstantiableRelationDefinition<C, S> relation;
-
-
-
- // Private constructor.
- private Reference(ManagedObjectPath<?, ?> parent,
- InstantiableRelationDefinition<C, S> relation, String name)
- throws IllegalArgumentException {
- this.relation = relation;
- this.name = name;
- this.path = parent.child(relation, name);
- }
-
-
-
- /**
- * Gets the name of the referenced managed object.
- *
- * @return Returns the name of the referenced managed object.
- */
- public String getName() {
- return name;
- }
-
-
-
- /**
- * Gets the normalized name of the referenced managed object.
- *
- * @return Returns the normalized name of the referenced managed
- * object.
- */
- public String getNormalizedName() {
- PropertyDefinition<?> pd = relation.getNamingPropertyDefinition();
- return normalizeName(pd);
- }
-
-
-
- /**
- * Gets the DN of the referenced managed object.
- *
- * @return Returns the DN of the referenced managed object.
- */
- public DN toDN() {
- return path.toDN();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public String toString() {
- return name;
- }
-
-
-
- // Normalize a value using the specified naming property definition
- // if defined.
- private <T> String normalizeName(PropertyDefinition<T> pd) {
- if (pd != null) {
- try {
- T tvalue = pd.decodeValue(name);
- return pd.normalizeValue(tvalue);
- } catch (IllegalPropertyValueStringException e) {
- // Fall through to default normalization.
- }
+ // FIXME: should really use directory string normalizer.
+ String s = name.trim().replaceAll(" +", " ");
+ return toLowerCase(s);
}
-
- // FIXME: should really use directory string normalizer.
- String s = name.trim().replaceAll(" +", " ");
- return StaticUtils.toLowerCase(s);
- }
}
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java b/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java
index 7764f2a..df7834c 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/JNDIDirContextAdaptor.java
@@ -27,8 +27,6 @@
*/
package org.opends.server.admin.client.ldap;
-
-
import java.util.Collection;
import java.util.Hashtable;
import java.util.LinkedList;
@@ -48,290 +46,245 @@
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
-import org.opends.admin.ads.util.BlindTrustManager;
-import org.opends.admin.ads.util.ConnectionUtils;
-import org.opends.admin.ads.util.TrustedSocketFactory;
import org.opends.server.admin.client.AuthenticationException;
import org.opends.server.admin.client.AuthenticationNotSupportedException;
import org.opends.server.admin.client.CommunicationException;
-import org.opends.server.schema.SchemaConstants;
-
-
/**
- * An LDAP connection adaptor which maps LDAP requests onto an
- * underlying JNDI connection context.
+ * An LDAP connection adaptor which maps LDAP requests onto an underlying JNDI
+ * connection context.
*/
public final class JNDIDirContextAdaptor extends LDAPConnection {
- /**
- * Adapts the provided JNDI <code>DirContext</code>.
- *
- * @param dirContext
- * The JNDI connection.
- * @return Returns a new JNDI connection adaptor.
- */
- public static JNDIDirContextAdaptor adapt(DirContext dirContext) {
- return new JNDIDirContextAdaptor(dirContext);
- }
-
-
-
- /**
- * Creates a new JNDI connection adaptor by performing a simple bind
- * operation to the specified LDAP server.
- *
- * @param host
- * The host.
- * @param port
- * The port.
- * @param name
- * The LDAP bind DN.
- * @param password
- * The LDAP bind password.
- * @return Returns a new JNDI connection adaptor.
- * @throws CommunicationException
- * If the client cannot contact the server due to an
- * underlying communication problem.
- * @throws AuthenticationNotSupportedException
- * If the server does not support simple authentication.
- * @throws AuthenticationException
- * If authentication failed for some reason, usually due
- * to invalid credentials.
- */
- public static JNDIDirContextAdaptor simpleBind(String host, int port,
- String name, String password) throws CommunicationException,
- AuthenticationNotSupportedException, AuthenticationException {
- Hashtable<String, Object> env = new Hashtable<String, Object>();
- env
- .put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.ldap.LdapCtxFactory");
- String hostname = ConnectionUtils.getHostNameForLdapUrl(host) ;
- env.put(Context.PROVIDER_URL, "ldap://" + hostname + ":" + port);
- env.put(Context.SECURITY_PRINCIPAL, name);
- env.put(Context.SECURITY_CREDENTIALS, password);
-
- DirContext ctx;
- try {
- ctx = new InitialLdapContext(env, null);
- } catch (javax.naming.CommunicationException e) {
- throw new CommunicationException(e);
- } catch (javax.naming.AuthenticationException e) {
- throw new AuthenticationException(e);
- } catch (javax.naming.AuthenticationNotSupportedException e) {
- throw new AuthenticationNotSupportedException(e);
- } catch (NamingException e) {
- // Assume some kind of communication problem.
- throw new CommunicationException(e);
+ /**
+ * Adapts the provided JNDI <code>DirContext</code>.
+ *
+ * @param dirContext
+ * The JNDI connection.
+ * @return Returns a new JNDI connection adaptor.
+ */
+ public static JNDIDirContextAdaptor adapt(DirContext dirContext) {
+ return new JNDIDirContextAdaptor(dirContext);
}
- return new JNDIDirContextAdaptor(ctx);
- }
+ /**
+ * Creates a new JNDI connection adaptor by performing a simple bind
+ * operation to the specified LDAP server.
+ *
+ * @param host
+ * The host.
+ * @param port
+ * The port.
+ * @param name
+ * The LDAP bind DN.
+ * @param password
+ * The LDAP bind password.
+ * @return Returns a new JNDI connection adaptor.
+ * @throws CommunicationException
+ * If the client cannot contact the server due to an underlying
+ * communication problem.
+ * @throws AuthenticationNotSupportedException
+ * If the server does not support simple authentication.
+ * @throws AuthenticationException
+ * If authentication failed for some reason, usually due to
+ * invalid credentials.
+ */
+ public static JNDIDirContextAdaptor simpleBind(String host, int port, String name, String password)
+ throws CommunicationException, AuthenticationNotSupportedException, AuthenticationException {
+ Hashtable<String, Object> env = new Hashtable<String, Object>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ String hostname = ConnectionUtils.getHostNameForLdapUrl(host);
+ env.put(Context.PROVIDER_URL, "ldap://" + hostname + ":" + port);
+ env.put(Context.SECURITY_PRINCIPAL, name);
+ env.put(Context.SECURITY_CREDENTIALS, password);
- /**
- * Creates a new JNDI connection adaptor by performing a simple bind
- * operation to the specified LDAP server.
- *
- * @param host
- * The host.
- * @param port
- * The port.
- * @param name
- * The LDAP bind DN.
- * @param password
- * The LDAP bind password.
- * @return Returns a new JNDI connection adaptor.
- * @throws CommunicationException
- * If the client cannot contact the server due to an
- * underlying communication problem.
- * @throws AuthenticationNotSupportedException
- * If the server does not support simple authentication.
- * @throws AuthenticationException
- * If authentication failed for some reason, usually due
- * to invalid credentials.
- */
- public static JNDIDirContextAdaptor simpleSSLBind(String host, int port,
- String name, String password) throws CommunicationException,
- AuthenticationNotSupportedException, AuthenticationException {
- Hashtable<String, Object> env = new Hashtable<String, Object>();
- env.put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.ldap.LdapCtxFactory");
- String hostname = ConnectionUtils.getHostNameForLdapUrl(host) ;
- env.put(Context.PROVIDER_URL, "ldaps://" + hostname + ":" + port);
- env.put(Context.SECURITY_PRINCIPAL, name);
- env.put(Context.SECURITY_CREDENTIALS, password);
- env.put(Context.SECURITY_AUTHENTICATION, "simple");
- // Specify SSL
- env.put(Context.SECURITY_PROTOCOL, "ssl");
- env.put("java.naming.ldap.factory.socket",
- org.opends.admin.ads.util.TrustedSocketFactory.class.getName());
- TrustedSocketFactory.setCurrentThreadTrustManager(new BlindTrustManager(),
- null);
- DirContext ctx;
- try {
- ctx = new InitialLdapContext(env, null);
- } catch (javax.naming.CommunicationException e) {
- throw new CommunicationException(e);
- } catch (javax.naming.AuthenticationException e) {
- throw new AuthenticationException(e);
- } catch (javax.naming.AuthenticationNotSupportedException e) {
- throw new AuthenticationNotSupportedException(e);
- } catch (NamingException e) {
- // Assume some kind of communication problem.
- throw new CommunicationException(e);
- }
-
- return new JNDIDirContextAdaptor(ctx);
- }
-
-
- // The JNDI connection context.
- private final DirContext dirContext;
-
-
-
- // Create a new JNDI connection adaptor using the provider JNDI
- // DirContext.
- private JNDIDirContextAdaptor(DirContext dirContext) {
- this.dirContext = dirContext;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void createEntry(LdapName dn, Attributes attributes)
- throws NamingException {
- dirContext.createSubcontext(dn, attributes).close();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void deleteSubtree(LdapName dn) throws NamingException {
- // Delete the children first.
- for (LdapName child : listEntries(dn, null)) {
- deleteSubtree(child);
- }
-
- // Delete the named entry.
- dirContext.destroySubcontext(dn);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean entryExists(LdapName dn) throws NamingException {
- boolean entryExists = false;
- String filter = "(objectClass=*)";
- SearchControls controls = new SearchControls();
- controls.setSearchScope(SearchControls.OBJECT_SCOPE);
- controls
- .setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES });
- try {
- NamingEnumeration<SearchResult> results = dirContext.search(dn, filter,
- controls);
- try
- {
- while (results.hasMore()) {
- // To avoid having a systematic abandon in the server.
- results.next();
- entryExists = true;
+ DirContext ctx;
+ try {
+ ctx = new InitialLdapContext(env, null);
+ } catch (javax.naming.CommunicationException e) {
+ throw new CommunicationException(e);
+ } catch (javax.naming.AuthenticationException e) {
+ throw new AuthenticationException(e);
+ } catch (javax.naming.AuthenticationNotSupportedException e) {
+ throw new AuthenticationNotSupportedException(e);
+ } catch (NamingException e) {
+ // Assume some kind of communication problem.
+ throw new CommunicationException(e);
}
- }
- finally
- {
- results.close();
- }
- } catch (NameNotFoundException e) {
- // Fall through - entry not found.
- }
- return entryExists;
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Collection<LdapName> listEntries(LdapName dn, String filter)
- throws NamingException {
- if (filter == null) {
- filter = "(objectClass=*)";
+ return new JNDIDirContextAdaptor(ctx);
}
- SearchControls controls = new SearchControls();
- controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+ /**
+ * Creates a new JNDI connection adaptor by performing a simple bind
+ * operation to the specified LDAP server.
+ *
+ * @param host
+ * The host.
+ * @param port
+ * The port.
+ * @param name
+ * The LDAP bind DN.
+ * @param password
+ * The LDAP bind password.
+ * @return Returns a new JNDI connection adaptor.
+ * @throws CommunicationException
+ * If the client cannot contact the server due to an underlying
+ * communication problem.
+ * @throws AuthenticationNotSupportedException
+ * If the server does not support simple authentication.
+ * @throws AuthenticationException
+ * If authentication failed for some reason, usually due to
+ * invalid credentials.
+ */
+ public static JNDIDirContextAdaptor simpleSSLBind(String host, int port, String name, String password)
+ throws CommunicationException, AuthenticationNotSupportedException, AuthenticationException {
+ Hashtable<String, Object> env = new Hashtable<String, Object>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ String hostname = ConnectionUtils.getHostNameForLdapUrl(host);
+ env.put(Context.PROVIDER_URL, "ldaps://" + hostname + ":" + port);
+ env.put(Context.SECURITY_PRINCIPAL, name);
+ env.put(Context.SECURITY_CREDENTIALS, password);
+ env.put(Context.SECURITY_AUTHENTICATION, "simple");
+ // Specify SSL
+ env.put(Context.SECURITY_PROTOCOL, "ssl");
+ env.put("java.naming.ldap.factory.socket", org.opends.admin.ads.util.TrustedSocketFactory.class.getName());
+ TrustedSocketFactory.setCurrentThreadTrustManager(new BlindTrustManager(), null);
+ DirContext ctx;
+ try {
+ ctx = new InitialLdapContext(env, null);
+ } catch (javax.naming.CommunicationException e) {
+ throw new CommunicationException(e);
+ } catch (javax.naming.AuthenticationException e) {
+ throw new AuthenticationException(e);
+ } catch (javax.naming.AuthenticationNotSupportedException e) {
+ throw new AuthenticationNotSupportedException(e);
+ } catch (NamingException e) {
+ // Assume some kind of communication problem.
+ throw new CommunicationException(e);
+ }
- List<LdapName> children = new LinkedList<LdapName>();
- NamingEnumeration<SearchResult> results = dirContext.search(dn, filter,
- controls);
- try
- {
- while (results.hasMore()) {
- SearchResult sr = results.next();
- LdapName child = new LdapName(dn.getRdns());
- child.add(new Rdn(sr.getName()));
- children.add(child);
- }
- }
- finally
- {
- results.close();
+ return new JNDIDirContextAdaptor(ctx);
}
- return children;
- }
+ // The JNDI connection context.
+ private final DirContext dirContext;
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void modifyEntry(LdapName dn, Attributes mods) throws NamingException {
- ModificationItem[] modList = new ModificationItem[mods.size()];
- NamingEnumeration<? extends Attribute> ne = mods.getAll();
- for (int i = 0; ne.hasMore(); i++) {
- ModificationItem modItem = new ModificationItem(
- DirContext.REPLACE_ATTRIBUTE, ne.next());
- modList[i] = modItem;
+ // Create a new JNDI connection adaptor using the provider JNDI
+ // DirContext.
+ private JNDIDirContextAdaptor(DirContext dirContext) {
+ this.dirContext = dirContext;
}
- dirContext.modifyAttributes(dn, modList);
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Attributes readEntry(LdapName dn, Collection<String> attrIds)
- throws NamingException {
- String[] attrIdList = attrIds.toArray(new String[attrIds.size()]);
- return dirContext.getAttributes(dn, attrIdList);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void unbind() {
- try {
- dirContext.close();
- } catch (NamingException e) {
- // nothing to do
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void createEntry(LdapName dn, Attributes attributes) throws NamingException {
+ dirContext.createSubcontext(dn, attributes).close();
}
- }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void deleteSubtree(LdapName dn) throws NamingException {
+ // Delete the children first.
+ for (LdapName child : listEntries(dn, null)) {
+ deleteSubtree(child);
+ }
+
+ // Delete the named entry.
+ dirContext.destroySubcontext(dn);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean entryExists(LdapName dn) throws NamingException {
+ boolean entryExists = false;
+ String filter = "(objectClass=*)";
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope(SearchControls.OBJECT_SCOPE);
+ controls.setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES });
+ try {
+ NamingEnumeration<SearchResult> results = dirContext.search(dn, filter, controls);
+ try {
+ while (results.hasMore()) {
+ // To avoid having a systematic abandon in the server.
+ results.next();
+ entryExists = true;
+ }
+ } finally {
+ results.close();
+ }
+ } catch (NameNotFoundException e) {
+ // Fall through - entry not found.
+ }
+ return entryExists;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<LdapName> listEntries(LdapName dn, String filter) throws NamingException {
+ if (filter == null) {
+ filter = "(objectClass=*)";
+ }
+
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+
+ List<LdapName> children = new LinkedList<LdapName>();
+ NamingEnumeration<SearchResult> results = dirContext.search(dn, filter, controls);
+ try {
+ while (results.hasMore()) {
+ SearchResult sr = results.next();
+ LdapName child = new LdapName(dn.getRdns());
+ child.add(new Rdn(sr.getName()));
+ children.add(child);
+ }
+ } finally {
+ results.close();
+ }
+
+ return children;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyEntry(LdapName dn, Attributes mods) throws NamingException {
+ ModificationItem[] modList = new ModificationItem[mods.size()];
+ NamingEnumeration<? extends Attribute> ne = mods.getAll();
+ for (int i = 0; ne.hasMore(); i++) {
+ ModificationItem modItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, ne.next());
+ modList[i] = modItem;
+ }
+ dirContext.modifyAttributes(dn, modList);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Attributes readEntry(LdapName dn, Collection<String> attrIds) throws NamingException {
+ String[] attrIdList = attrIds.toArray(new String[attrIds.size()]);
+ return dirContext.getAttributes(dn, attrIdList);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void unbind() {
+ try {
+ dirContext.close();
+ } catch (NamingException e) {
+ // nothing to do
+ }
+ }
}
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java b/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
index 3adf831..4d5d13b 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
@@ -207,8 +207,7 @@
public boolean configAddIsAcceptable(ConfigEntry configEntry,
LocalizableMessageBuilder unacceptableReason) {
DN dn = configEntry.getDN();
- AttributeValue av = dn.rdn().getAttributeValue(0);
- String name = av.getValue().toString().trim();
+ String name = dn.rdn().getFirstAVA().getAttributeValue().toString().trim();
try {
ManagedObjectPath<?, ? extends S> childPath;
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java b/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
index 5b56f11..a7eeef8 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
@@ -33,7 +33,6 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
-import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.Constraint;
import org.opends.server.admin.DecodingException;
@@ -187,8 +186,7 @@
*/
public boolean configDeleteIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason) {
DN dn = configEntry.getDN();
- AttributeValue av = dn.rdn().getAttributeValue(0);
- String name = av.getValue().toString().trim();
+ String name = dn.rdn().getFirstAVA().getAttributeValue().toString().trim();
try {
ManagedObjectPath<?, ? extends S> childPath;
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagedObject.java b/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagedObject.java
index 678eb14..6cc8211 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagedObject.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagedObject.java
@@ -60,6 +60,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
/**
* A server-side managed object.
*
@@ -246,8 +247,7 @@
ConfigChangeListenerAdaptor<?> adaptor = (ConfigChangeListenerAdaptor<?>) l;
ServerManagedObjectChangeListener<?> l2 = adaptor.getServerManagedObjectChangeListener();
if (l2 instanceof ServerManagedObjectChangeListenerAdaptor<?>) {
- ServerManagedObjectChangeListenerAdaptor<?> adaptor2 =
- (ServerManagedObjectChangeListenerAdaptor<?>) l2;
+ ServerManagedObjectChangeListenerAdaptor<?> adaptor2 = (ServerManagedObjectChangeListenerAdaptor<?>) l2;
if (adaptor2.getConfigurationChangeListener() == listener) {
adaptor.finalizeChangeListener();
configEntry.deregisterChangeListener(adaptor);
@@ -797,6 +797,10 @@
ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(path, listener);
configEntry.registerChangeListener(adaptor);
+ // TODO : go toward this
+ // Entry entry;
+ // configBackend.registerChangeListener(entry.getName(), adapter));
+
// Change listener registration usually signifies that a managed
// object has been accepted and added to the server configuration
// during initialization post-add.
@@ -1030,8 +1034,7 @@
ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) l;
ServerManagedObjectAddListener<?> l2 = adaptor.getServerManagedObjectAddListener();
if (l2 instanceof ServerManagedObjectAddListenerAdaptor<?>) {
- ServerManagedObjectAddListenerAdaptor<?> adaptor2 =
- (ServerManagedObjectAddListenerAdaptor<?>) l2;
+ ServerManagedObjectAddListenerAdaptor<?> adaptor2 = (ServerManagedObjectAddListenerAdaptor<?>) l2;
if (adaptor2.getConfigurationAddListener() == listener) {
configEntry.deregisterAddListener(adaptor);
}
@@ -1050,8 +1053,7 @@
}
// Deregister an add listener.
- private <M extends Configuration> void deregisterAddListener(DN baseDN,
- ServerManagedObjectAddListener<M> listener) {
+ private <M extends Configuration> void deregisterAddListener(DN baseDN, ServerManagedObjectAddListener<M> listener) {
try {
ConfigEntry configEntry = getListenerConfigEntry(baseDN);
if (configEntry != null) {
@@ -1075,8 +1077,7 @@
}
// Deregister a delete listener.
- private <M extends Configuration> void deregisterDeleteListener(DN baseDN,
- ConfigurationDeleteListener<M> listener) {
+ private <M extends Configuration> void deregisterDeleteListener(DN baseDN, ConfigurationDeleteListener<M> listener) {
try {
ConfigEntry configEntry = getListenerConfigEntry(baseDN);
if (configEntry != null) {
@@ -1085,8 +1086,7 @@
ConfigDeleteListenerAdaptor<?> adaptor = (ConfigDeleteListenerAdaptor<?>) l;
ServerManagedObjectDeleteListener<?> l2 = adaptor.getServerManagedObjectDeleteListener();
if (l2 instanceof ServerManagedObjectDeleteListenerAdaptor<?>) {
- ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 =
- (ServerManagedObjectDeleteListenerAdaptor<?>) l2;
+ ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 = (ServerManagedObjectDeleteListenerAdaptor<?>) l2;
if (adaptor2.getConfigurationDeleteListener() == listener) {
configEntry.deregisterDeleteListener(adaptor);
}
@@ -1183,8 +1183,7 @@
// Deregister a delayed listener with the nearest existing parent
// entry to the provided base DN.
- private <M extends Configuration> void deregisterDelayedAddListener(DN baseDN,
- ConfigurationAddListener<M> listener)
+ private <M extends Configuration> void deregisterDelayedAddListener(DN baseDN, ConfigurationAddListener<M> listener)
throws ConfigException {
DN parentDN = baseDN.parent();
int delayWrappers = 0;
@@ -1222,8 +1221,7 @@
ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) delayedListener;
ServerManagedObjectAddListener<?> l2 = adaptor.getServerManagedObjectAddListener();
if (l2 instanceof ServerManagedObjectAddListenerAdaptor<?>) {
- ServerManagedObjectAddListenerAdaptor<?> adaptor2 =
- (ServerManagedObjectAddListenerAdaptor<?>) l2;
+ ServerManagedObjectAddListenerAdaptor<?> adaptor2 = (ServerManagedObjectAddListenerAdaptor<?>) l2;
if (adaptor2.getConfigurationAddListener() == listener) {
relationEntry.deregisterAddListener(l);
}
@@ -1276,8 +1274,7 @@
ConfigDeleteListenerAdaptor<?> adaptor = (ConfigDeleteListenerAdaptor<?>) delayedListener;
ServerManagedObjectDeleteListener<?> l2 = adaptor.getServerManagedObjectDeleteListener();
if (l2 instanceof ServerManagedObjectDeleteListenerAdaptor<?>) {
- ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 =
- (ServerManagedObjectDeleteListenerAdaptor<?>) l2;
+ ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 = (ServerManagedObjectDeleteListenerAdaptor<?>) l2;
if (adaptor2.getConfigurationDeleteListener() == listener) {
relationEntry.deregisterAddListener(l);
}
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagementContext.java b/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagementContext.java
index f923f4d..7956f5f 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagementContext.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/server/ServerManagementContext.java
@@ -28,11 +28,13 @@
package org.opends.server.admin.server;
import static com.forgerock.opendj.ldap.AdminMessages.*;
+import static com.forgerock.opendj.util.StaticUtils.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -54,7 +56,6 @@
import org.opends.server.admin.DefinitionResolver;
import org.opends.server.admin.IllegalPropertyValueException;
import org.opends.server.admin.IllegalPropertyValueStringException;
-import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.ManagedObjectPath;
@@ -68,7 +69,6 @@
import org.opends.server.admin.Reference;
import org.opends.server.admin.RelationDefinition;
import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
-import org.opends.server.admin.SetRelationDefinition;
import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.admin.UnknownPropertyDefinitionException;
import org.opends.server.admin.DefinitionDecodingException.Reason;
@@ -77,8 +77,13 @@
import org.opends.server.core.DirectoryServer;
import org.forgerock.opendj.admin.meta.RootCfgDefn;
import org.forgerock.opendj.admin.server.RootCfg;
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.AttributeDescription;
import org.forgerock.opendj.ldap.DN;
-import org.opends.server.types.DirectoryException;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.opends.server.util.DynamicConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Server management connection context.
@@ -173,9 +178,10 @@
}
// Find the default values for the next path/property.
- private Collection<T> find(ManagedObjectPath<?, ?> p, PropertyDefinition<T> pd) throws DefaultBehaviorException {
- nextPath = p;
- nextProperty = pd;
+ private Collection<T> find(ManagedObjectPath<?, ?> path, PropertyDefinition<T> propertyDef)
+ throws DefaultBehaviorException {
+ nextPath = path;
+ nextProperty = propertyDef;
Collection<T> values = nextProperty.getDefaultBehaviorProvider().accept(this, null);
@@ -183,8 +189,8 @@
throw exception;
}
- if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
- throw new DefaultBehaviorException(pd, new PropertyIsSingleValuedException(pd));
+ if (values.size() > 1 && !propertyDef.hasOption(PropertyOption.MULTI_VALUED)) {
+ throw new DefaultBehaviorException(propertyDef, new PropertyIsSingleValuedException(propertyDef));
}
return values;
@@ -192,18 +198,19 @@
// Get an inherited property value.
@SuppressWarnings("unchecked")
- private Collection<T> getInheritedProperty(ManagedObjectPath target, AbstractManagedObjectDefinition<?, ?> d,
- String propertyName) throws DefaultBehaviorException {
+ private Collection<T> getInheritedProperty(ManagedObjectPath target,
+ AbstractManagedObjectDefinition<?, ?> definition, String propertyName)
+ throws DefaultBehaviorException {
// First check that the requested type of managed object
// corresponds to the path.
AbstractManagedObjectDefinition<?, ?> supr = target.getManagedObjectDefinition();
- if (!supr.isParentOf(d)) {
+ if (!supr.isParentOf(definition)) {
throw new DefaultBehaviorException(nextProperty, new DefinitionDecodingException(supr,
Reason.WRONG_TYPE_INFORMATION));
}
// Save the current property in case of recursion.
- PropertyDefinition<T> pd1 = nextProperty;
+ PropertyDefinition<T> propDef1 = nextProperty;
try {
// Get the actual managed object definition.
@@ -216,12 +223,12 @@
}
DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
- ManagedObjectDefinition<?, ?> mod = d.resolveManagedObjectDefinition(resolver);
+ ManagedObjectDefinition<?, ?> mod = definition.resolveManagedObjectDefinition(resolver);
- PropertyDefinition<T> pd2;
+ PropertyDefinition<T> propDef2;
try {
- PropertyDefinition<?> pdTmp = mod.getPropertyDefinition(propertyName);
- pd2 = pd1.getClass().cast(pdTmp);
+ PropertyDefinition<?> propDefTmp = mod.getPropertyDefinition(propertyName);
+ propDef2 = propDef1.getClass().cast(propDefTmp);
} catch (IllegalArgumentException e) {
throw new PropertyNotFoundException(propertyName);
} catch (ClassCastException e) {
@@ -229,33 +236,33 @@
throw new PropertyNotFoundException(propertyName);
}
- List<AttributeValue> values = getAttribute(mod, pd2, configEntry);
- if (values.isEmpty()) {
- // Recursively retrieve this property's default values.
- Collection<T> tmp = find(target, pd2);
- Collection<T> pvalues = new ArrayList<T>(tmp.size());
- for (T value : tmp) {
- pd1.validateValue(value);
- pvalues.add(value);
+ Iterable<Attribute> attributes = getAttribute(mod, propDef2, configEntry);
+ if (attributes.iterator().hasNext()) {
+ Collection<T> pvalues = new ArrayList<T>();
+ for (Attribute attribute : attributes) {
+ pvalues.add(ValueDecoder.decode(propDef1, attribute));
}
return pvalues;
} else {
- Collection<T> pvalues = new ArrayList<T>(values.size());
- for (AttributeValue value : values) {
- pvalues.add(ValueDecoder.decode(pd1, value));
+ // Recursively retrieve this property's default values.
+ Collection<T> tmp = find(target, propDef2);
+ Collection<T> pvalues = new ArrayList<T>(tmp.size());
+ for (T value : tmp) {
+ propDef1.validateValue(value);
+ pvalues.add(value);
}
return pvalues;
}
} catch (DefinitionDecodingException e) {
- throw new DefaultBehaviorException(pd1, e);
+ throw new DefaultBehaviorException(propDef1, e);
} catch (PropertyNotFoundException e) {
- throw new DefaultBehaviorException(pd1, e);
+ throw new DefaultBehaviorException(propDef1, e);
} catch (IllegalPropertyValueException e) {
- throw new DefaultBehaviorException(pd1, e);
+ throw new DefaultBehaviorException(propDef1, e);
} catch (IllegalPropertyValueStringException e) {
- throw new DefaultBehaviorException(pd1, e);
+ throw new DefaultBehaviorException(propDef1, e);
} catch (ConfigException e) {
- throw new DefaultBehaviorException(pd1, e);
+ throw new DefaultBehaviorException(propDef1, e);
}
}
}
@@ -293,19 +300,19 @@
*
* @param <PD>
* The type of the property.
- * @param pd
+ * @param propertyDef
* The property definition.
- * @param value
+ * @param attribute
* The LDAP string representation.
* @return Returns the decoded LDAP value.
* @throws IllegalPropertyValueStringException
* If the property value could not be decoded because it was
* invalid.
*/
- public static <PD> PD decode(PropertyDefinition<PD> pd, AttributeValue value)
+ public static <PD> PD decode(PropertyDefinition<PD> propertyDef, Attribute attribute)
throws IllegalPropertyValueStringException {
- String s = value.getValue().toString();
- return pd.castValue(pd.accept(new ValueDecoder(), s));
+ String value = attribute.firstValueAsString();
+ return propertyDef.castValue(propertyDef.accept(new ValueDecoder(), value));
}
// Prevent instantiation.
@@ -339,7 +346,9 @@
}
}
- // Singleton instance.
+ private static final Logger debugLogger = LoggerFactory.getLogger(ServerManagementContext.class);
+
+ /** The singleton instance. **/
private final static ServerManagementContext INSTANCE = new ServerManagementContext();
/**
@@ -458,7 +467,7 @@
* The type of the property to be retrieved.
* @param path
* The path of the managed object containing the property.
- * @param pd
+ * @param propertyDef
* The property to be retrieved.
* @return Returns the property's effective values, or an empty set if there
* are no values defined.
@@ -474,15 +483,15 @@
*/
@SuppressWarnings("unchecked")
public <C extends ConfigurationClient, S extends Configuration, PD> SortedSet<PD> getPropertyValues(
- ManagedObjectPath<C, S> path, PropertyDefinition<PD> pd) throws IllegalArgumentException, ConfigException,
+ ManagedObjectPath<C, S> path, PropertyDefinition<PD> propertyDef) throws IllegalArgumentException, ConfigException,
PropertyException {
// Check that the requested property is from the definition
// associated with the path.
- AbstractManagedObjectDefinition<C, S> d = path.getManagedObjectDefinition();
- PropertyDefinition<?> tmp = d.getPropertyDefinition(pd.getName());
- if (tmp != pd) {
- throw new IllegalArgumentException("The property " + pd.getName() + " is not associated with a "
- + d.getName());
+ AbstractManagedObjectDefinition<C, S> definition = path.getManagedObjectDefinition();
+ PropertyDefinition<?> tmpPropertyDef = definition.getPropertyDefinition(propertyDef.getName());
+ if (tmpPropertyDef != propertyDef) {
+ throw new IllegalArgumentException("The property " + propertyDef.getName() + " is not associated with a "
+ + definition.getName());
}
// Determine the exact type of managed object referenced by the
@@ -491,10 +500,10 @@
ConfigEntry configEntry = getManagedObjectConfigEntry(dn);
DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
- ManagedObjectDefinition<? extends C, ? extends S> mod;
+ ManagedObjectDefinition<? extends C, ? extends S> managedObjDef;
try {
- mod = d.resolveManagedObjectDefinition(resolver);
+ managedObjDef = definition.resolveManagedObjectDefinition(resolver);
} catch (DefinitionDecodingException e) {
throw ConfigExceptionFactory.getInstance().createDecodingExceptionAdaptor(dn, e);
}
@@ -502,10 +511,10 @@
// Make sure we use the correct property definition, the
// provided one might have been overridden in the resolved
// definition.
- pd = (PropertyDefinition<PD>) mod.getPropertyDefinition(pd.getName());
+ propertyDef = (PropertyDefinition<PD>) managedObjDef.getPropertyDefinition(propertyDef.getName());
- List<AttributeValue> values = getAttribute(mod, pd, configEntry);
- return decodeProperty(path.asSubType(mod), pd, values, null);
+ Iterable<Attribute> attributes = getAttribute(managedObjDef, propertyDef, configEntry);
+ return decodeProperty(path.asSubType(managedObjDef), propertyDef, attributes, null);
}
/**
@@ -541,19 +550,19 @@
* relation definition refers to.
* @param parent
* The path of the parent managed object.
- * @param rd
- * The instantiable relation definition.
+ * @param relationDef
+ * The relation definition.
* @return Returns the names of the child managed objects.
* @throws IllegalArgumentException
* If the relation definition is not associated with the parent
* managed object's definition.
*/
public <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects(
- ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd) throws IllegalArgumentException {
- validateRelationDefinition(parent, rd);
+ ManagedObjectPath<?, ?> parent, RelationDefinition<C, S> relationDef) {
+ validateRelationDefinition(parent, relationDef);
// Get the target entry.
- DN targetDN = DNBuilder.create(parent, rd);
+ DN targetDN = DNBuilder.create(parent, relationDef);
ConfigEntry configEntry;
try {
configEntry = DirectoryServer.getConfigEntry(targetDN);
@@ -566,59 +575,12 @@
}
// Retrieve the children.
- Set<DN> children = configEntry.getChildren().keySet();
- ArrayList<String> names = new ArrayList<String>(children.size());
+ Set<DN> children = configEntry.getChildren();
+ List<String> names = new ArrayList<String>(children.size());
for (DN child : children) {
// Assume that RDNs are single-valued and can be trimmed.
- AttributeValue av = child.rdn().getAttributeValue(0);
- names.add(av.getValue().toString().trim());
- }
-
- return names.toArray(new String[names.size()]);
- }
-
- /**
- * Lists the child managed objects of the named parent managed object.
- *
- * @param <C>
- * The type of client managed object configuration that the
- * relation definition refers to.
- * @param <S>
- * The type of server managed object configuration that the
- * relation definition refers to.
- * @param parent
- * The path of the parent managed object.
- * @param rd
- * The set relation definition.
- * @return Returns the names of the child managed objects.
- * @throws IllegalArgumentException
- * If the relation definition is not associated with the parent
- * managed object's definition.
- */
- public <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects(
- ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd) throws IllegalArgumentException {
- validateRelationDefinition(parent, rd);
-
- // Get the target entry.
- DN targetDN = DNBuilder.create(parent, rd);
- ConfigEntry configEntry;
- try {
- configEntry = DirectoryServer.getConfigEntry(targetDN);
- } catch (ConfigException e) {
- return new String[0];
- }
-
- if (configEntry == null) {
- return new String[0];
- }
-
- // Retrieve the children.
- Set<DN> children = configEntry.getChildren().keySet();
- ArrayList<String> names = new ArrayList<String>(children.size());
- for (DN child : children) {
- // Assume that RDNs are single-valued and can be trimmed.
- AttributeValue av = child.rdn().getAttributeValue(0);
- names.add(av.toString().trim());
+ String name = child.rdn().getFirstAVA().getAttributeValue().toString().trim();
+ names.add(name);
}
return names.toArray(new String[names.size()]);
@@ -710,11 +672,11 @@
// Build the managed object's properties.
List<PropertyException> exceptions = new LinkedList<PropertyException>();
Map<PropertyDefinition<?>, SortedSet<?>> properties = new HashMap<PropertyDefinition<?>, SortedSet<?>>();
- for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
- List<AttributeValue> values = getAttribute(mod, pd, configEntry);
+ for (PropertyDefinition<?> propertyDef : mod.getAllPropertyDefinitions()) {
+ Iterable<Attribute> attributes = getAttribute(mod, propertyDef, configEntry);
try {
- SortedSet<?> pvalues = decodeProperty(path, pd, values, newConfigEntry);
- properties.put(pd, pvalues);
+ SortedSet<?> pvalues = decodeProperty(path, propertyDef, attributes, newConfigEntry);
+ properties.put(propertyDef, pvalues);
} catch (PropertyException e) {
exceptions.add(e);
}
@@ -739,16 +701,17 @@
}
// Create a property using the provided string values.
- private <T> SortedSet<T> decodeProperty(ManagedObjectPath<?, ?> path, PropertyDefinition<T> pd,
- List<AttributeValue> values, ConfigEntry newConfigEntry) throws PropertyException {
+ private <T> SortedSet<T> decodeProperty(ManagedObjectPath<?, ?> path, PropertyDefinition<T> propertyDef,
+ Iterable<Attribute> attributes, ConfigEntry newConfigEntry) throws PropertyException {
PropertyException exception = null;
- SortedSet<T> pvalues = new TreeSet<T>(pd);
+ SortedSet<T> pvalues = new TreeSet<T>(propertyDef);
- if (!values.isEmpty()) {
+ Iterator<Attribute> attributesIt = attributes.iterator();
+ if (attributesIt.hasNext()) {
// The property has values defined for it.
- for (AttributeValue value : values) {
+ for (Attribute attr : attributes) {
try {
- pvalues.add(ValueDecoder.decode(pd, value));
+ pvalues.add(ValueDecoder.decode(propertyDef, attr));
} catch (IllegalPropertyValueStringException e) {
exception = e;
}
@@ -756,24 +719,24 @@
} else {
// No values defined so get the defaults.
try {
- pvalues.addAll(getDefaultValues(path, pd, newConfigEntry));
+ pvalues.addAll(getDefaultValues(path, propertyDef, newConfigEntry));
} catch (DefaultBehaviorException e) {
exception = e;
}
}
- if (pvalues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ if (pvalues.size() > 1 && !propertyDef.hasOption(PropertyOption.MULTI_VALUED)) {
// This exception takes precedence over previous exceptions.
- exception = new PropertyIsSingleValuedException(pd);
+ exception = new PropertyIsSingleValuedException(propertyDef);
T value = pvalues.first();
pvalues.clear();
pvalues.add(value);
}
- if (pvalues.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+ if (pvalues.isEmpty() && propertyDef.hasOption(PropertyOption.MANDATORY)) {
// The values maybe empty because of a previous exception.
if (exception == null) {
- exception = new PropertyIsMandatoryException(pd);
+ exception = new PropertyIsMandatoryException(propertyDef);
}
}
@@ -785,28 +748,14 @@
}
// Gets the attribute associated with a property from a ConfigEntry.
- private List<AttributeValue> getAttribute(ManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd,
+ private Iterable<Attribute> getAttribute(ManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd,
ConfigEntry configEntry) {
// TODO: we create a default attribute type if it is
// undefined. We should log a warning here if this is the case
// since the attribute should have been defined.
String attrID = LDAPProfile.getInstance().getAttributeName(d, pd);
AttributeType type = DirectoryServer.getAttributeType(attrID, true);
- AttributeValueDecoder<AttributeValue> decoder = new AttributeValueDecoder<AttributeValue>() {
-
- public AttributeValue decode(AttributeValue value) throws DirectoryException {
- return value;
- }
- };
-
- List<AttributeValue> values = new LinkedList<AttributeValue>();
- try {
- configEntry.getEntry().getAttributeValues(type, decoder, values);
- } catch (DirectoryException e) {
- // Should not happen.
- throw new RuntimeException(e);
- }
- return values;
+ return configEntry.getEntry().getAllAttributes(AttributeDescription.create(type));
}
// Get the default values for the specified property.
@@ -823,12 +772,10 @@
try {
configEntry = DirectoryServer.getConfigEntry(dn);
} catch (ConfigException e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
+ debugLogger.trace("Unable to perform post add", e);
LocalizableMessage message = ERR_ADMIN_CANNOT_GET_MANAGED_OBJECT.get(String.valueOf(dn),
- stackTraceToSingleLineString(e));
+ stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD));
throw new ConfigException(message, e);
}
diff --git a/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/Aci.java b/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/Aci.java
index 0cb5eb4..de1b5df 100644
--- a/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/Aci.java
+++ b/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/Aci.java
@@ -27,15 +27,21 @@
*/
package org.opends.server.authorization.dseecompat;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DN;
+
/**
* The Aci class represents ACI strings.
*/
-public class Aci implements Comparable<Aci>
-{
+public class Aci implements Comparable<Aci> {
// TODO : to complete when implementing Aci support.
@Override
public int compareTo(Aci o) {
throw new RuntimeException("This class is not implemented");
}
- }
+
+ public static Aci decode(ByteString valueOf, DN rootDN) throws AciException {
+ throw new RuntimeException("This class is not implemented");
+ }
+}
diff --git a/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/AciException.java b/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/AciException.java
new file mode 100644
index 0000000..9c637f6
--- /dev/null
+++ b/opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/AciException.java
@@ -0,0 +1,78 @@
+/*
+ * 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 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.authorization.dseecompat;
+import org.forgerock.i18n.LocalizableMessage;
+import org.opends.server.types.IdentifiedException;
+
+
+/**
+ * The AciException class defines an exception that may be thrown
+ * either during ACI syntax verification of an "aci" attribute type value
+ * or during evaluation of an LDAP operation using a set of applicable
+ * ACIs.
+ */
+public class AciException extends IdentifiedException {
+ /**
+ * The serial version identifier required to satisfy the compiler because this
+ * class extends <CODE>java.lang.Exception</CODE>, which implements the
+ * <CODE>java.io.Serializable</CODE> interface. This value was generated
+ * using the <CODE>serialver</CODE> command-line utility included with the
+ * Java SDK.
+ */
+ private static final long serialVersionUID = -2763328522960628853L;
+
+ /**
+ * Constructs a new exception with <code>null</code> as its detail message.
+ * The cause is not initialized. Used to break out of a recursive bind rule
+ * decode and not print duplicate messages.
+ */
+ public AciException() {
+ super();
+ }
+
+ /**
+ * Creates a new ACI exception with the provided message.
+ *
+ * @param message The message to use for this ACI exception.
+ */
+ public AciException(LocalizableMessage message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new ACI exception with the provided message and root
+ * cause.
+ *
+ * @param message The message that explains the problem that occurred.
+ * @param cause The exception that was caught to trigger this
+ * exception.
+ */
+ public AciException(LocalizableMessage message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/opendj-admin/src/main/java/org/opends/server/config/ConfigEntry.java b/opendj-admin/src/main/java/org/opends/server/config/ConfigEntry.java
index a81424a..832668b 100644
--- a/opendj-admin/src/main/java/org/opends/server/config/ConfigEntry.java
+++ b/opendj-admin/src/main/java/org/opends/server/config/ConfigEntry.java
@@ -26,6 +26,7 @@
*/
package org.opends.server.config;
+import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.forgerock.opendj.ldap.DN;
@@ -59,14 +60,17 @@
/** The actual entry wrapped by this configuration entry. */
private Entry entry;
+ private final ConfigurationRepository configRepository;
+
/**
* Creates a new config entry with the provided entry.
*
* @param entry
* The entry that will be encapsulated by this config entry.
*/
- public ConfigEntry(Entry entry) {
+ public ConfigEntry(Entry entry, ConfigurationRepository configRepository) {
this.entry = entry;
+ this.configRepository = configRepository;
addListeners = new CopyOnWriteArrayList<ConfigAddListener>();
changeListeners = new CopyOnWriteArrayList<ConfigChangeListener>();
deleteListeners = new CopyOnWriteArrayList<ConfigDeleteListener>();
@@ -219,4 +223,13 @@
public String toString() {
return entry.getName().toNormalizedString();
}
+
+ /**
+ * Retrieves the set of children associated with this configuration entry.
+ *
+ * @return The set of children associated with this configuration entry.
+ */
+ public Set<DN> getChildren() {
+ return configRepository.getChildren(entry);
+ }
}
diff --git a/opendj-admin/src/main/java/org/opends/server/config/ConfigurationRepository.java b/opendj-admin/src/main/java/org/opends/server/config/ConfigurationRepository.java
new file mode 100644
index 0000000..f6eb5cd
--- /dev/null
+++ b/opendj-admin/src/main/java/org/opends/server/config/ConfigurationRepository.java
@@ -0,0 +1,47 @@
+/*
+ * 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 2013 ForgeRock AS.
+ */
+package org.opends.server.config;
+
+import java.util.Set;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Entry;
+
+/**
+ * Provides the configuration elements.
+ */
+public interface ConfigurationRepository {
+
+ /**
+ * Returns the set of children of the provided entry.
+ *
+ * @param entry
+ * The configuration entry.
+ * @return the set of children of the entry
+ */
+ Set<DN> getChildren(Entry entry);
+
+}
diff --git a/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/admin.properties b/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/admin.properties
index 0992c20..15d9a36 100644
--- a/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/admin.properties
+++ b/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/admin.properties
@@ -53,7 +53,7 @@
ERR_ADMIN_CANNOT_OPEN_JAR_FILE_9=The Directory Server jar file %s in \
directory %s cannot be loaded because an unexpected error occurred while \
trying to open the file for reading: %s
-MILD_ERR_ADMIN_NO_EXTENSIONS_DIR_12=The extensions directory %s does not \
+ERR_ADMIN_NO_EXTENSIONS_DIR_12=The extensions directory %s does not \
exist, therefore no extensions will be loaded
ERR_ADMIN_EXTENSIONS_DIR_NOT_DIRECTORY_13=Unable to read the Directory \
Server extensions because the extensions directory %s exists but is not a \
@@ -279,8 +279,7 @@
ERR_ADMIN_CERTIFICATE_GENERATION_MISSING_FILES_136=The administration \
connector self-signed certificate cannot be generated because the following \
files are missing: %s
-SEVERE_WARN_ADMIN_SET_PERMISSIONS_FAILED_137=Failed to set permissions \
+WARN_ADMIN_SET_PERMISSIONS_FAILED_137=Failed to set permissions \
on file %s
ERR_ADMIN_MERGING_138=The registry information of the servers could not \
- be merged
-
+ be merged
\ No newline at end of file
diff --git a/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/extension.properties b/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/extension.properties
new file mode 100644
index 0000000..dcc339a
--- /dev/null
+++ b/opendj-admin/src/main/resources/com/forgerock/opendj/ldap/extension.properties
@@ -0,0 +1,1016 @@
+# 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 2006-2010 Sun Microsystems, Inc.
+# Portions Copyright 2011-2013 ForgeRock AS
+
+#
+# Format string definitions
+#
+# Keys must be formatted as follows:
+#
+# [DESCRIPTION]_[ORDINAL]
+#
+# where:
+#
+# DESCRIPTION is an upper case string providing a hint as to the context of
+# the message in upper case with the underscore ('_') character serving as
+# word separator
+#
+# ORDINAL is an integer unique among other ordinals in this file
+#
+ERR_PWSCHEME_CANNOT_INITIALIZE_MESSAGE_DIGEST_1=An error occurred \
+ while attempting to initialize the message digest generator for the %s \
+ algorithm: %s
+ERR_PWSCHEME_CANNOT_BASE64_DECODE_STORED_PASSWORD_2=An error occurred \
+ while attempting to base64-decode the password value %s: %s
+ERR_PWSCHEME_NOT_REVERSIBLE_3=The %s password storage scheme is not \
+ reversible, so it is impossible to recover the plaintext version of an \
+ encoded password
+ERR_JMX_ALERT_HANDLER_CANNOT_REGISTER_4=An error occurred while trying \
+ to register the JMX alert handler with the MBean server: %s
+ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD_5=An unexpected error occurred while \
+ attempting to encode a password using the storage scheme defined in class %s: \
+ %s
+ERR_CACHE_INVALID_INCLUDE_FILTER_6=The ds-cfg-include-filter \
+ attribute of configuration entry %s, which specifies a set of search filters \
+ that may be used to control which entries are included in the cache, has an \
+ invalid value of "%s": %s
+ERR_CACHE_INVALID_EXCLUDE_FILTER_7=The ds-cfg-exclude-filter \
+ attribute of configuration entry %s, which specifies a set of search filters \
+ that may be used to control which entries are excluded from the cache, has an \
+ invalid value of "%s": %s
+ERR_FIFOCACHE_CANNOT_INITIALIZE_8=A fatal error occurred while trying \
+ to initialize fifo entry cache: %s
+ERR_SOFTREFCACHE_CANNOT_INITIALIZE_9=A fatal error occurred while \
+ trying to initialize soft reference entry cache: %s
+NOTE_CACHE_PRELOAD_PROGRESS_START_10=Starting the entry cache preload for \
+ %s backend
+NOTE_CACHE_PRELOAD_PROGRESS_REPORT_11=The entry cache preload for %s backend \
+ has processed %d entries, %d MB free heap memory available
+NOTE_CACHE_PRELOAD_PROGRESS_DONE_12=The entry cache preload for %s backend \
+ is complete with the total of %d entries processed
+WARN_CACHE_PRELOAD_INTERRUPTED_13=The entry cache preload for %s \
+ backend has been interrupted
+WARN_CACHE_PRELOAD_BACKEND_FAILED_14=The entry cache preload is not \
+ supported by %s backend, and as a result no entries from this backend will \
+ be preloaded into the entry cache
+ERR_CACHE_PRELOAD_ENTRY_FAILED_15=Failed to preload %s entry into \
+ the entry cache: %s
+ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST_33=An unexpected error occurred \
+ while attempting to decode the password modify extended request sequence: %s
+ERR_EXTOP_PASSMOD_NO_AUTH_OR_USERID_34=The password modify extended \
+ request cannot be processed because it does not contain an authorization ID \
+ and the underlying connection is not authenticated
+ERR_EXTOP_PASSMOD_CANNOT_LOCK_USER_ENTRY_35=The password modify \
+ extended request cannot be processed because the server was unable to obtain \
+ a write lock on user entry %s after multiple attempts
+ERR_EXTOP_PASSMOD_CANNOT_DECODE_AUTHZ_DN_36=The password modify extended \
+ request cannot be processed because the server cannot decode "%s" as a valid \
+ DN for use in the authorization ID for the operation
+ERR_EXTOP_PASSMOD_INVALID_AUTHZID_STRING_37=The password modify extended \
+ request cannot be processed because it contained an invalid userIdentity \
+ field. The provided userIdentity string was "%s"
+ERR_EXTOP_PASSMOD_NO_USER_ENTRY_BY_AUTHZID_38=The password modify \
+ extended request cannot be processed because it was not possible to identify \
+ the user entry to update based on the authorization DN of "%s"
+ERR_EXTOP_PASSMOD_INVALID_OLD_PASSWORD_41=The password modify extended \
+ operation cannot be processed because the current password provided for the \
+ user is invalid
+INFO_FILE_KEYMANAGER_DESCRIPTION_FILE_43=Path to the file \
+ containing the Directory Server keystore information. Changes to this \
+ configuration attribute will take effect the next time that the key manager \
+ is accessed
+ERR_FILE_KEYMANAGER_NO_SUCH_FILE_45=The keystore file %s specified in \
+ attribute ds-cfg-key-store-file of configuration entry %s does not exist
+ERR_FILE_KEYMANAGER_CANNOT_DETERMINE_FILE_46=An unexpected error \
+ occurred while trying to determine the value of configuration attribute \
+ ds-cfg-key-store-file in configuration entry %s: %s
+ERR_FILE_KEYMANAGER_PIN_PROPERTY_NOT_SET_50=Java property %s which is \
+ specified in attribute ds-cfg-key-store-pin-property of configuration entry \
+ %s should contain the PIN needed to access the file-based key manager, but \
+ this property is not set
+ERR_FILE_KEYMANAGER_PIN_ENVAR_NOT_SET_53=Environment variable %s which \
+ is specified in attribute ds-cfg-key-store-pin-environment-variable of \
+ configuration entry %s should contain the PIN needed to access the file-based \
+ key manager, but this property is not set
+ERR_FILE_KEYMANAGER_PIN_NO_SUCH_FILE_56=File %s specified in attribute \
+ ds-cfg-key-store-pin-file of configuration entry %s should contain the PIN \
+ needed to access the file-based key manager, but this file does not exist
+ERR_FILE_KEYMANAGER_PIN_FILE_CANNOT_READ_57=An error occurred while \
+ trying to read the keystore PIN from file %s specified in configuration \
+ attribute ds-cfg-key-store-pin-file of configuration entry %s: %s
+ERR_FILE_KEYMANAGER_PIN_FILE_EMPTY_58=File %s specified in attribute \
+ ds-cfg-key-store-pin-file of configuration entry %s should contain the PIN \
+ needed to access the file-based key manager, but this file is empty
+ERR_FILE_KEYMANAGER_CANNOT_DETERMINE_PIN_FROM_ATTR_60=An unexpected \
+ error occurred while trying to determine the value of configuration attribute \
+ ds-cfg-key-store-pin in configuration entry %s: %s
+ERR_FILE_KEYMANAGER_CANNOT_LOAD_62=An error occurred while trying to \
+ load the keystore contents from file %s: %s
+ERR_FILE_KEYMANAGER_INVALID_TYPE_63=The keystore type %s specified in \
+ attribute ds-cfg-key-store-type of configuration entry %s is not valid: %s
+ERR_PKCS11_KEYMANAGER_PIN_PROPERTY_NOT_SET_68=Java property %s which \
+ is specified in attribute ds-cfg-key-store-pin-property of configuration \
+ entry %s should contain the PIN needed to access the PKCS#11 key manager, but \
+ this property is not set
+ERR_PKCS11_KEYMANAGER_PIN_ENVAR_NOT_SET_71=Environment variable %s \
+ which is specified in attribute ds-cfg-key-store-pin-environment-variable of \
+ configuration entry %s should contain the PIN needed to access the PKCS#11 \
+ key manager, but this property is not set
+ERR_PKCS11_KEYMANAGER_PIN_NO_SUCH_FILE_74=File %s specified in \
+ attribute ds-cfg-key-store-pin-file of configuration entry %s should contain \
+ the PIN needed to access the PKCS#11 key manager, but this file does not \
+ exist
+ERR_PKCS11_KEYMANAGER_PIN_FILE_CANNOT_READ_75=An error occurred while \
+ trying to read the keystore PIN from file %s specified in configuration \
+ attribute ds-cfg-key-store-pin-file of configuration entry %s: %s
+ERR_PKCS11_KEYMANAGER_PIN_FILE_EMPTY_76=File %s specified in attribute \
+ ds-cfg-key-store-pin-file of configuration entry %s should contain the PIN \
+ needed to access the PKCS#11 key manager, but this file is empty
+ERR_PKCS11_KEYMANAGER_CANNOT_DETERMINE_PIN_FROM_ATTR_79=An unexpected \
+ error occurred while trying to determine the value of configuration attribute \
+ ds-cfg-key-store-pin in configuration entry %s: %s
+ERR_PKCS11_KEYMANAGER_CANNOT_LOAD_81=An error occurred while trying to \
+ access the PKCS#11 key manager: %s
+ERR_FILE_KEYMANAGER_CANNOT_CREATE_FACTORY_83=An error occurred while \
+ trying to create a key manager factory to access the contents of keystore \
+ file %s: %s
+ERR_PKCS11_KEYMANAGER_CANNOT_CREATE_FACTORY_84=An error occurred while \
+ trying to create a key manager factory to access the contents of the PKCS#11 \
+ keystore: %s
+ERR_FILE_TRUSTMANAGER_NO_SUCH_FILE_87=The trust store file %s \
+ specified in attribute ds-cfg-trust-store-file of configuration entry %s does \
+ not exist
+ERR_FILE_TRUSTMANAGER_CANNOT_DETERMINE_FILE_88=An unexpected error \
+ occurred while trying to determine the value of configuration attribute \
+ ds-cfg-trust-store-file in configuration entry %s: %s
+ERR_FILE_TRUSTMANAGER_PIN_PROPERTY_NOT_SET_92=Java property %s which \
+ is specified in attribute ds-cfg-trust-store-pin-property of configuration \
+ entry %s should contain the PIN needed to access the file-based trust \
+ manager, but this property is not set
+ERR_FILE_TRUSTMANAGER_PIN_ENVAR_NOT_SET_95=Environment variable %s \
+ which is specified in attribute ds-cfg-trust-store-pin-environment-variable \
+ of configuration entry %s should contain the PIN needed to access the \
+ file-based trust manager, but this property is not set
+ERR_FILE_TRUSTMANAGER_PIN_NO_SUCH_FILE_98=File %s specified in \
+ attribute ds-cfg-trust-store-pin-file of configuration entry %s should \
+ contain the PIN needed to access the file-based trust manager, but this file \
+ does not exist
+ERR_FILE_TRUSTMANAGER_PIN_FILE_CANNOT_READ_99=An error occurred while \
+ trying to read the trust store PIN from file %s specified in configuration \
+ attribute ds-cfg-trust-store-pin-file of configuration entry %s: %s
+ERR_FILE_TRUSTMANAGER_PIN_FILE_EMPTY_100=File %s specified in \
+ attribute ds-cfg-trust-store-pin-file of configuration entry %s should \
+ contain the PIN needed to access the file-based trust manager, but this file \
+ is empty
+ERR_FILE_TRUSTMANAGER_CANNOT_LOAD_104=An error occurred while trying \
+ to load the trust store contents from file %s: %s
+ERR_FILE_TRUSTMANAGER_CANNOT_CREATE_FACTORY_105=An error occurred \
+ while trying to create a trust manager factory to access the contents of \
+ trust store file %s: %s
+ERR_FILE_TRUSTMANAGER_INVALID_TYPE_106=The trust store type %s \
+ specified in attribute ds-cfg-trust-store-type of configuration entry %s is \
+ not valid: %s
+ERR_SEDCM_NO_PEER_CERTIFICATE_118=Could not map the provided certificate \
+ chain to a user entry because no peer certificate was available
+ERR_SEDCM_PEER_CERT_NOT_X509_119=Could not map the provided certificate \
+ chain to a user because the peer certificate was not an X.509 certificate \
+ (peer certificate format was %s)
+ERR_SEDCM_CANNOT_DECODE_SUBJECT_AS_DN_120=Could not map the provided \
+ certificate chain to a user because the peer certificate subject "%s" could \
+ not be decoded as an LDAP DN: %s
+ERR_SEDCM_CANNOT_GET_ENTRY_121=Could not map the provided certificate \
+ chain to a user because an error occurred while attempting to retrieve the \
+ user entry with DN "%s": %s
+ERR_SEDCM_NO_USER_FOR_DN_122=Could not map the provided certificate \
+ chain to a user because no user entry exists with a DN of %s
+ERR_SASLEXTERNAL_NO_CLIENT_CONNECTION_123=The SASL EXTERNAL bind request \
+ could not be processed because the associated bind request does not have a \
+ reference to the client connection
+ERR_SASLEXTERNAL_NOT_LDAP_CLIENT_INSTANCE_124=The SASL EXTERNAL bind \
+request could not be processed because the associated client connection \
+instance is not an instance of LDAPClientConnection
+ERR_SASLEXTERNAL_NO_CLIENT_CERT_126=The SASL EXTERNAL bind request could \
+ not be processed because the client did not present a certificate chain \
+ during SSL/TLS negotiation
+ERR_SASLEXTERNAL_NO_MAPPING_127=The SASL EXTERNAL bind request failed \
+ because the certificate chain presented by the client during SSL/TLS \
+ negotiation could not be mapped to a user entry in the Directory Server
+ERR_STARTTLS_NO_CLIENT_CONNECTION_128=StartTLS cannot be used on this \
+ connection because the underlying client connection is not available
+ERR_STARTTLS_NOT_TLS_CAPABLE_129=StartTLS cannot be used on this client \
+ connection because this connection type is not capable of using StartTLS to \
+ protect its communication
+ERR_SASLEXTERNAL_NO_CERT_IN_ENTRY_137=Unable to authenticate via SASL \
+ EXTERNAL because the mapped user entry %s does not have any certificates with \
+ which to verify the presented peer certificate
+ERR_SASLEXTERNAL_PEER_CERT_NOT_FOUND_138=Unable to authenticate via SASL \
+ EXTERNAL because the mapped user entry %s did not contain the peer \
+ certificate presented by the client
+ERR_SASLEXTERNAL_CANNOT_VALIDATE_CERT_139=An error occurred while \
+ attempting to validate the peer certificate presented by the client with a \
+ certificate from the user's entry %s: %s
+ERR_SASLPLAIN_NO_SASL_CREDENTIALS_147=SASL PLAIN authentication requires \
+ that SASL credentials be provided but none were included in the bind request
+ERR_SASLPLAIN_NO_NULLS_IN_CREDENTIALS_148=The SASL PLAIN bind request \
+ did not include any NULL characters. NULL characters are required as \
+ delimiters between the authorization ID and authentication ID, and also \
+ between the authentication ID and the password
+ERR_SASLPLAIN_NO_SECOND_NULL_149=The SASL PLAIN bind request did not \
+ include a second NULL character in the credentials, which is required as a \
+ delimiter between the authentication ID and the password
+ERR_SASLPLAIN_ZERO_LENGTH_AUTHCID_150=The authentication ID contained in \
+ the SASL PLAIN bind request had a length of zero characters, which is not \
+ allowed. SASL PLAIN authentication does not allow an empty string for use as \
+ the authentication ID
+ERR_SASLPLAIN_ZERO_LENGTH_PASSWORD_151=The password contained in the \
+ SASL PLAIN bind request had a length of zero characters, which is not \
+ allowed. SASL PLAIN authentication does not allow an empty string for use as \
+ the password
+ERR_SASLPLAIN_CANNOT_DECODE_AUTHCID_AS_DN_152=An error occurred while \
+ attempting to decode the SASL PLAIN authentication ID "%s" because it \
+ appeared to contain a DN but DN decoding failed: %s
+ERR_SASLPLAIN_AUTHCID_IS_NULL_DN_153=The authentication ID in the SASL \
+ PLAIN bind request appears to be an empty DN. This is not allowed
+ERR_SASLPLAIN_CANNOT_GET_ENTRY_BY_DN_154=An error occurred while \
+ attempting to retrieve user entry %s as specified in the DN-based \
+ authentication ID of a SASL PLAIN bind request: %s
+ERR_SASLPLAIN_NO_MATCHING_ENTRIES_157=The server was not able to find \
+ any user entries for the provided authentication ID of %s
+ERR_SASLPLAIN_INVALID_PASSWORD_160=The provided password is invalid
+INFO_SASLPLAIN_CANNOT_LOCK_ENTRY_163=The Directory Server was unable to \
+ obtain a read lock on user entry %s in order to retrieve that entry
+ERR_SEDCM_CANNOT_LOCK_ENTRY_164=The Directory Server was unable to \
+ obtain a read lock on user entry %s in order to retrieve that entry
+INFO_SASLANONYMOUS_TRACE_165=SASL ANONYMOUS bind operation (conn=%d, op=%d) \
+ provided trace information: %s
+ERR_SASLCRAMMD5_CANNOT_GET_MESSAGE_DIGEST_166=An unexpected error \
+ occurred while attempting to obtain an MD5 digest engine for use by the \
+ CRAM-MD5 SASL handler: %s
+ERR_SASLCRAMMD5_NO_STORED_CHALLENGE_172=The SASL CRAM-MD5 bind request \
+ contained SASL credentials but there is no stored challenge for this client \
+ connection. The first CRAM-MD5 bind request in the two-stage process must \
+ not contain client SASL credentials
+ERR_SASLCRAMMD5_INVALID_STORED_CHALLENGE_173=The SASL CRAM-MD5 bind \
+ request contained SASL credentials, but the stored SASL state information for \
+ this client connection is not in an appropriate form for the challenge
+ERR_SASLCRAMMD5_NO_SPACE_IN_CREDENTIALS_174=The SASL CRAM-MD5 bind \
+ request from the client included SASL credentials but there was no space to \
+ separate the username from the authentication digest
+ERR_SASLCRAMMD5_INVALID_DIGEST_LENGTH_175=The SASL CRAM-MD5 bind request \
+ included SASL credentials, but the decoded digest string had an invalid \
+ length of %d bytes rather than the %d bytes expected for a hex representation \
+ of an MD5 digest
+ERR_SASLCRAMMD5_INVALID_DIGEST_CONTENT_176=The SASL CRAM-MD5 bind \
+ request included SASL credentials, but the decoded digest was not comprised \
+ of only hexadecimal digits: %s
+ERR_SASLCRAMMD5_CANNOT_DECODE_USERNAME_AS_DN_177=An error occurred while \
+ attempting to decode the SASL CRAM-MD5 username "%s" because it appeared to \
+ contain a DN but DN decoding failed: %s
+ERR_SASLCRAMMD5_USERNAME_IS_NULL_DN_178=The username in the SASL \
+ CRAM-MD5 bind request appears to be an empty DN. This is not allowed
+INFO_SASLCRAMMD5_CANNOT_LOCK_ENTRY_179=The Directory Server was unable to \
+ obtain a read lock on user entry %s in order to retrieve that entry
+ERR_SASLCRAMMD5_CANNOT_GET_ENTRY_BY_DN_180=An error occurred while \
+ attempting to retrieve user entry %s as specified in the DN-based username of \
+ a SASL CRAM-MD5 bind request: %s
+ERR_SASLCRAMMD5_NO_MATCHING_ENTRIES_184=The server was not able to find \
+ any user entries for the provided username of %s
+ERR_SASLCRAMMD5_INVALID_PASSWORD_188=The provided password is invalid
+ERR_SASLCRAMMD5_NO_REVERSIBLE_PASSWORDS_189=SASL CRAM-MD5 authentication \
+ is not possible for user %s because none of the passwords in the user entry \
+ are stored in a reversible form
+INFO_SASL_UNSUPPORTED_CALLBACK_192=An unsupported or unexpected callback was \
+ provided to the SASL server for use during %s authentication: %s
+ERR_SASL_NO_CREDENTIALS_193=The client connection included \
+ %s state information, indicating that the client was in the process \
+ of performing a %s bind, but the bind request did not include any \
+ credentials
+ERR_SASL_CANNOT_GET_SERVER_FQDN_194=An unexpected error occurred \
+ while attempting to determine the value of the ds-cfg-server-fqdn attribute \
+ in configuration entry %s: %s
+ ERR_SASL_CONTEXT_CREATE_ERROR_195=An unexpected error occurred while \
+ trying to create an %s context: %s
+ERR_SASL_CANNOT_DECODE_USERNAME_AS_DN_196=An error occurred \
+ while attempting to decode the SASL %s username "%s" because it \
+ appeared to contain a DN but DN decoding failed: %s
+ERR_SASL_USERNAME_IS_NULL_DN_197=The username in the SASL \
+ %s bind request appears to be an empty DN. This is not allowed
+INFO_SASL_CANNOT_LOCK_ENTRY_198=The Directory Server was unable to \
+ obtain a read lock on user entry %s in order to retrieve that entry
+ERR_SASL_CANNOT_GET_ENTRY_BY_DN_199=An error occurred while \
+ attempting to retrieve user entry %s as specified in the DN-based username of \
+ a SASL %s bind request: %s
+ERR_SASL_ZERO_LENGTH_USERNAME_200=The username contained in the \
+ SASL %s bind request had a length of zero characters, which is not \
+ allowed. %s authentication does not allow an empty string for use as \
+ the username
+ERR_SASL_NO_MATCHING_ENTRIES_201=The server was not able to \
+ find any user entries for the provided username of %s
+ERR_SASL_AUTHZID_INVALID_DN_202=The provided authorization ID \
+ %s contained an invalid DN: %s
+ ERR_SASL_AUTHZID_NO_SUCH_ENTRY_203=The entry %s specified as \
+ the authorization identity does not exist
+ERR_SASL_AUTHZID_CANNOT_GET_ENTRY_204=The entry %s specified as \
+ the authorization identity could not be retrieved: %s
+ERR_SASL_AUTHZID_NO_MAPPED_ENTRY_205=The server was unable to \
+ find any entry corresponding to authorization ID %s
+ERR_SASL_CANNOT_GET_REVERSIBLE_PASSWORDS_207=An error occurred \
+ while attempting to retrieve the clear-text password(s) for user %s in order \
+ to perform SASL %s authentication: %s
+ERR_SASL_NO_REVERSIBLE_PASSWORDS_208=SASL %s \
+ authentication is not possible for user %s because none of the passwords in \
+ the user entry are stored in a reversible form
+ERR_SASL_PROTOCOL_ERROR_209=SASL %s protocol error: %s
+ERR_SASL_AUTHZID_INSUFFICIENT_PRIVILEGES_210=The authenticating \
+ user %s does not have sufficient privileges to assume a different \
+ authorization identity
+ERR_SASL_AUTHZID_INSUFFICIENT_ACCESS_211=The authenticating \
+ user %s does not have sufficient access to assume a different \
+ authorization identity
+ERR_SASL_AUTHENTRY_NO_MAPPED_ENTRY_212=The server was unable to \
+ find any entry corresponding to authentication ID %s
+ERR_SASLGSSAPI_KDC_REALM_NOT_DEFINED_213=The server was unable to \
+ because both the ds-cfg-kdc-address and ds-cfg-realm attributes must be \
+ defined or neither defined
+ERR_SASL_CANNOT_MAP_AUTHENTRY_214=An error occurred while \
+ attempting to map authorization ID %s to a user entry: %s
+ERR_SASLGSSAPI_CANNOT_CREATE_JAAS_CONFIG_215=An error occurred while \
+ attempting to write a temporary JAAS configuration file for use during GSSAPI \
+ processing: %s
+ERR_SASLGSSAPI_CANNOT_CREATE_LOGIN_CONTEXT_216=An error occurred while \
+ attempting to create the JAAS login context for GSSAPI authentication: %s
+ERR_SASLGSSAPI_NO_CLIENT_CONNECTION_217=No client connection was \
+ available for use in processing the GSSAPI bind request
+INFO_GSSAPI_PRINCIPAL_NAME_218=GSSAPI mechanism using a principal name of: %s
+INFO_GSSAPI_SERVER_FQDN_219=GSSAPI SASL mechanism using a server fully \
+ qualified domain name of: %s
+INFO_DIGEST_MD5_REALM_220=DIGEST-MD5 SASL mechanism using a realm of: %s
+NOTE_DIGEST_MD5_SERVER_FQDN_221=DIGEST-MD5 SASL mechanism using a server \
+ fully qualified domain name of: %s
+ERR_EXTOP_WHOAMI_PROXYAUTH_INSUFFICIENT_PRIVILEGES_277=You do not have \
+ sufficient privileges to use the proxied authorization control
+ERR_EXACTMAP_MULTIPLE_MATCHING_ENTRIES_306=ID string %s mapped to \
+ multiple users
+ERR_EXACTMAP_INEFFICIENT_SEARCH_307=The internal search based on ID \
+ string %s could not be processed efficiently: %s. Check the server \
+ configuration to ensure that all associated backends are properly configured \
+ for these types of searches
+ERR_EXACTMAP_SEARCH_FAILED_308=An internal failure occurred while \
+ attempting to resolve ID string %s to a user entry: %s
+ERR_SASLCRAMMD5_CANNOT_MAP_USERNAME_313=An error occurred while \
+ attempting to map username %s to a Directory Server entry: %s
+ERR_SASLDIGESTMD5_CANNOT_MAP_USERNAME_319=An error occurred while \
+ attempting to map username %s to a Directory Server entry: %s
+ERR_SASLPLAIN_CANNOT_MAP_USERNAME_325=An error occurred while attempting \
+ to map username %s to a Directory Server entry: %s
+ERR_EXTOP_CANCEL_NO_REQUEST_VALUE_327=Unable to process the cancel \
+ request because the extended operation did not include a request value
+ERR_EXTOP_CANCEL_CANNOT_DECODE_REQUEST_VALUE_328=An error occurred while \
+ attempting to decode the value of the cancel extended request: %s
+INFO_EXTOP_CANCEL_REASON_329=Processing on this operation was terminated as a \
+ result of receiving a cancel request (message ID %d)
+ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD_330=Password storage scheme \
+ %s does not support use with the authentication password attribute syntax
+ERR_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX_335=The configured minimum \
+ password length of %d characters is greater than the configured maximum \
+ password length of %d
+ERR_PWLENGTHVALIDATOR_TOO_SHORT_336=The provided password is shorter \
+ than the minimum required length of %d characters
+ERR_PWLENGTHVALIDATOR_TOO_LONG_337=The provided password is longer than \
+ the maximum allowed length of %d characters
+ERR_RANDOMPWGEN_NO_CHARSETS_341=Configuration entry "%s" does not \
+ contain attribute ds-cfg-password-character-set which specifies the sets of \
+ characters that should be used when generating the password. This is a \
+ required attribute
+ERR_RANDOMPWGEN_CHARSET_NAME_CONFLICT_342=Configuration entry "%s" \
+ contains multiple definitions for the %s character set
+ERR_RANDOMPWGEN_CANNOT_DETERMINE_CHARSETS_343=An error occurred while \
+ attempting to decode the value(s) of the configuration attribute \
+ ds-cfg-password-character-set, which is used to hold the character set(s) for \
+ use in generating the password: %s
+ERR_RANDOMPWGEN_UNKNOWN_CHARSET_346=The password format string "%s" \
+ references an undefined character set "%s"
+ERR_RANDOMPWGEN_INVALID_PWFORMAT_347=The password format string "%s" \
+ contains an invalid syntax. This value should be a comma-delimited sequence \
+ of elements, where each element is the name of a character set followed by a \
+ colon and the number of characters to choose at random from that character \
+ set
+ERR_RANDOMPWGEN_CANNOT_DETERMINE_PWFORMAT_348=An error occurred while \
+ attempting to decode the value for configuration attribute \
+ ds-cfg-password-format, which is used to specify the format for the generated \
+ passwords: %s
+ERR_EXTOP_PASSMOD_CANNOT_GET_PW_POLICY_354=An error occurred while \
+ attempting to get the password policy for user %s: %s
+ERR_EXTOP_PASSMOD_REQUIRE_CURRENT_PW_355=The current password must be \
+ provided for self password changes
+ERR_EXTOP_PASSMOD_SECURE_AUTH_REQUIRED_356=Password modify operations \
+ that supply the user's current password must be performed over a secure \
+ communication channel
+ERR_EXTOP_PASSMOD_USER_PW_CHANGES_NOT_ALLOWED_357=End users are not \
+ allowed to change their passwords
+ERR_EXTOP_PASSMOD_SECURE_CHANGES_REQUIRED_358=Password changes must be \
+ performed over a secure communication channel
+ERR_EXTOP_PASSMOD_IN_MIN_AGE_359=The password cannot be changed because \
+ the previous password change was too recent
+ERR_EXTOP_PASSMOD_PASSWORD_IS_EXPIRED_360=The password cannot be changed \
+ because it is expired
+ERR_EXTOP_PASSMOD_NO_PW_GENERATOR_361=No new password was provided, and \
+ no password generator has been defined that may be used to automatically \
+ create a new password
+ERR_EXTOP_PASSMOD_CANNOT_GENERATE_PW_362=An error occurred while \
+ attempting to create a new password using the password generator: %s
+ERR_EXTOP_PASSMOD_PRE_ENCODED_NOT_ALLOWED_363=The password policy does \
+ not allow users to supply pre-encoded passwords
+ERR_EXTOP_PASSMOD_UNACCEPTABLE_PW_364=The provided new password failed \
+ the validation checks defined in the server: %s
+ERR_EXTOP_PASSMOD_CANNOT_ENCODE_PASSWORD_365=Unable to encode the \
+ provided password using the default scheme(s): %s
+ERR_EXTOP_PASSMOD_NO_SUCH_ID_MAPPER_368=The identity mapper with \
+ configuration entry DN %s as specified for use with the password modify \
+ extended operation defined in entry %s either does not exist or is not \
+ enabled. The identity mapper is a required component, and the password \
+ modify extended operation will not be enabled
+ERR_EXTOP_PASSMOD_CANNOT_DETERMINE_ID_MAPPER_369=An error occurred while \
+ attempting to determine the identity mapper to use in conjunction with the \
+ password modify extended operation defined in configuration entry %s: %s. \
+ The password modify extended operation will not be enabled for use in the \
+ server
+ERR_EXTOP_PASSMOD_CANNOT_MAP_USER_370=The provided authorization ID \
+ string "%s" could not be mapped to any user in the directory
+ERR_EXTOP_PASSMOD_ERROR_MAPPING_USER_371=An error occurred while \
+ attempting to map authorization ID string "%s" to a user entry: %s
+NOTE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION_375=Account-Status-Notification \
+ type='%s' userdn='%s' id=%d msg='%s'
+
+ERR_SASLCRAMMD5_CANNOT_GET_REVERSIBLE_PASSWORDS_377=An error occurred \
+ while attempting to retrieve the clear-text password(s) for user %s in order \
+ to perform SASL CRAM-MD5 authentication: %s
+ERR_SASLPLAIN_CANNOT_CHECK_PASSWORD_VALIDITY_378=An error occurred while \
+ attempting to verify the password for user %s during SASL PLAIN \
+ authentication: %s
+WARN_EXTOP_PASSMOD_NOOP_380=The password modify operation was not \
+ actually performed in the Directory Server because the LDAP no-op control was \
+ present in the request
+ERR_EXTOP_PASSMOD_ACCOUNT_DISABLED_381=The user account has been \
+ administratively disabled
+ERR_EXTOP_PASSMOD_ACCOUNT_LOCKED_382=The user account is locked
+ERR_STATICMEMBERS_NO_SUCH_ENTRY_383=Unable to examine entry %s as a \
+ potential member of static group %s because that entry does not exist in the \
+ Directory Server
+ERR_STATICMEMBERS_CANNOT_GET_ENTRY_384=An error occurred while \
+ attempting to retrieve entry %s as a potential member of static group %s: %s
+ERR_STATICGROUP_INVALID_OC_COMBINATION_385=Entry %s cannot be parsed as \
+ a valid static group because static groups are not allowed to have both the \
+ %s and %s object classes
+ERR_STATICGROUP_NO_VALID_OC_386=Entry %s cannot be parsed as a valid \
+ static group because it does not contain exactly one of the %s or the %s \
+ object classes
+ERR_STATICGROUP_CANNOT_DECODE_MEMBER_VALUE_AS_DN_387=Value %s for \
+ attribute %s in entry %s cannot be parsed as a valid DN: %s. It will be \
+ excluded from the set of group members
+ERR_STATICGROUP_ADD_MEMBER_ALREADY_EXISTS_388=Cannot add user %s as a \
+ new member of static group %s because that user is already in the member list \
+ for the group
+ERR_STATICGROUP_REMOVE_MEMBER_NO_SUCH_MEMBER_389=Cannot remove user %s \
+ as a member of static group %s because that user is not included in the \
+ member list for the group
+ERR_STATICGROUP_ADD_MEMBER_UPDATE_FAILED_390=Cannot add user %s as a new \
+ member of static group %s because an error occurred while attempting to \
+ perform an internal modification to update the group: %s
+ERR_STATICGROUP_REMOVE_MEMBER_UPDATE_FAILED_391=Cannot remove user %s as \
+ a member of static group %s because an error occurred while attempting to \
+ perform an internal modification to update the group: %s
+ERR_EXTOP_PASSMOD_INSUFFICIENT_PRIVILEGES_392=You do not have sufficient \
+ privileges to perform password reset operations
+ERR_SASLDIGESTMD5_EMPTY_AUTHZID_393=The provided authorization ID was \
+ empty, which is not allowed for DIGEST-MD5 authentication
+ERR_SASLPLAIN_AUTHZID_INVALID_DN_400=The provided authorization ID %s \
+ contained an invalid DN: %s
+ERR_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES_401=The authenticating \
+ user %s does not have sufficient privileges to specify an alternate \
+ authorization ID
+ERR_SASLPLAIN_AUTHZID_NO_SUCH_ENTRY_402=The entry corresponding to \
+ authorization DN %s does not exist in the Directory Server
+ERR_SASLPLAIN_AUTHZID_CANNOT_GET_ENTRY_403=An error occurred while \
+ attempting to retrieve entry %s specified as the authorization ID: %s
+ERR_SASLPLAIN_AUTHZID_NO_MAPPED_ENTRY_404=No entry corresponding to \
+ authorization ID %s was found in the server
+ERR_SASLPLAIN_AUTHZID_CANNOT_MAP_AUTHZID_405=An error occurred while \
+ attempting to map authorization ID %s to a user entry: %s
+ERR_SDTUACM_NO_PEER_CERTIFICATE_417=Could not map the provided \
+ certificate chain to a user entry because no peer certificate was available
+ERR_SDTUACM_PEER_CERT_NOT_X509_418=Could not map the provided \
+ certificate chain to a user because the peer certificate was not an X.509 \
+ certificate (peer certificate format was %s)
+ERR_SDTUACM_MULTIPLE_MATCHING_ENTRIES_419=The certificate with subject \
+ %s could not be mapped to exactly one user. It maps to both %s and %s
+ERR_SATUACM_INVALID_MAP_FORMAT_422=Configuration entry %s has value \
+ '%s' which violates the format required for attribute mappings. The expected \
+ format is 'certattr:userattr'
+ERR_SATUACM_DUPLICATE_CERT_ATTR_423=Configuration entry %s contains \
+ multiple mappings for certificate attribute %s
+ERR_SATUACM_NO_SUCH_ATTR_424=Mapping %s in configuration entry %s \
+ references attribute %s which is not defined in the server schema
+ERR_SATUACM_DUPLICATE_USER_ATTR_425=Configuration entry %s contains \
+ multiple mappings for user attribute %s
+ERR_SATUACM_NO_PEER_CERTIFICATE_429=Could not map the provided \
+ certificate chain to a user entry because no peer certificate was available
+ERR_SATUACM_PEER_CERT_NOT_X509_430=Could not map the provided \
+ certificate chain to a user because the peer certificate was not an X.509 \
+ certificate (peer certificate format was %s)
+ERR_SATUACM_CANNOT_DECODE_SUBJECT_AS_DN_431=Unable to decode peer \
+ certificate subject %s as a DN: %s
+ERR_SATUACM_NO_MAPPABLE_ATTRIBUTES_432=Peer certificate subject %s \
+ does not contain any attributes for which a mapping has been established
+ERR_SATUACM_MULTIPLE_MATCHING_ENTRIES_433=The certificate with subject \
+ %s could not be mapped to exactly one user. It maps to both %s and %s
+ERR_FCM_NO_PEER_CERTIFICATE_443=Could not map the provided certificate \
+ chain to a user entry because no peer certificate was available
+ERR_FCM_PEER_CERT_NOT_X509_444=Could not map the provided certificate \
+ chain to a user because the peer certificate was not an X.509 certificate \
+ (peer certificate format was %s)
+ERR_FCM_CANNOT_CALCULATE_FINGERPRINT_445=An error occurred while \
+ attempting to calculate the fingerprint for the peer certificate with subject \
+ %s: %s
+ERR_FCM_MULTIPLE_MATCHING_ENTRIES_446=The certificate with fingerprint \
+ %s could not be mapped to exactly one user. It maps to both %s and %s
+ERR_DYNAMICGROUP_CANNOT_DECODE_MEMBERURL_447=Unable to decode value "%s" \
+ in entry "%s" as an LDAP URL: %s
+ERR_DYNAMICGROUP_NESTING_NOT_SUPPORTED_448=Dynamic groups do not support \
+ nested groups
+ERR_DYNAMICGROUP_ALTERING_MEMBERS_NOT_SUPPORTED_449=Dynamic groups do \
+ not support explicitly altering their membership
+WARN_DYNAMICGROUP_NONEXISTENT_BASE_DN_450=Base DN %s specified in \
+ dynamic group %s does not exist in the server
+ERR_DYNAMICGROUP_INTERNAL_SEARCH_FAILED_451=An error occurred while \
+ attempting perform an internal search with base DN %s and filter %s to \
+ resolve the member list for dynamic group %s: result code %s, error message \
+ %s
+ERR_DYNAMICGROUP_CANNOT_RETURN_ENTRY_452=The server encountered a \
+ timeout while attempting to add user %s to the member list for dynamic group \
+ %s
+ERR_PWDIFFERENCEVALIDATOR_TOO_SMALL_456=The provided password differs \
+ less than the minimum required difference of %d characters
+ERR_REPEATEDCHARS_VALIDATOR_TOO_MANY_CONSECUTIVE_457=The provided \
+ password contained too many instances of the same character appearing \
+ consecutively. The maximum number of times the same character may appear \
+ consecutively in a password is %d
+ERR_UNIQUECHARS_VALIDATOR_NOT_ENOUGH_UNIQUE_CHARS_458=The provided \
+ password does not contain enough unique characters. The minimum number of \
+ unique characters that may appear in a user password is %d
+ERR_VATTR_NOT_SEARCHABLE_459=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY_460=The provided \
+ password contained a word from the server's dictionary
+ERR_DICTIONARY_VALIDATOR_NO_SUCH_FILE_461=The specified dictionary file \
+ %s does not exist
+ERR_DICTIONARY_VALIDATOR_CANNOT_READ_FILE_462=An error occurred while \
+ attempting to load the dictionary from file %s: %s
+ERR_ATTRVALUE_VALIDATOR_PASSWORD_IN_ENTRY_463=The provided password was \
+ found in another attribute in the user entry
+ERR_CHARSET_VALIDATOR_ILLEGAL_CHARACTER_464=The provided password \
+ contained character '%s' which is not allowed for use in passwords
+ERR_CHARSET_VALIDATOR_TOO_FEW_CHARS_FROM_SET_465=The provided password \
+ did not contain enough characters from the character set '%s'. The minimum \
+ number of characters from that set that must be present in user passwords is \
+ %d
+ERR_CHARSET_VALIDATOR_NO_SET_COLON_466=The provided character set \
+ definition '%s' is invalid because it does not contain a colon to separate \
+ the minimum count from the character set
+ERR_CHARSET_VALIDATOR_NO_SET_CHARS_467=The provided character set definition \
+ '%s' is invalid because the provided character set is empty
+ERR_CHARSET_VALIDATOR_INVALID_SET_COUNT_468=The provided character set \
+ definition '%s' is invalid because the value before the colon must be an \
+ integer greater or equal to zero
+ERR_CHARSET_VALIDATOR_DUPLICATE_CHAR_469=The provided character set \
+ definition '%s' is invalid because it contains character '%s' which has \
+ already been used
+ERR_VIRTUAL_STATIC_GROUP_MULTIPLE_TARGETS_470=The virtual static group \
+ defined in entry %s contains multiple target group DNs, but only one is \
+ allowed
+ERR_VIRTUAL_STATIC_GROUP_CANNOT_DECODE_TARGET_471=Unable to decode "%s" \
+ as the target DN for group %s: %s
+ERR_VIRTUAL_STATIC_GROUP_NO_TARGET_472=The virtual static group defined \
+ in entry %s does not contain a target group definition
+ERR_VIRTUAL_STATIC_GROUP_NESTING_NOT_SUPPORTED_473=Virtual static groups \
+ do not support nesting
+ERR_VIRTUAL_STATIC_GROUP_NO_TARGET_GROUP_474=Target group %s referenced \
+ by virtual static group %s does not exist
+ERR_VIRTUAL_STATIC_GROUP_ALTERING_MEMBERS_NOT_SUPPORTED_475=Altering \
+ membership for virtual static group %s is not allowed
+ERR_VIRTUAL_STATIC_GROUP_TARGET_CANNOT_BE_VIRTUAL_476=Virtual static \
+ group %s references target group %s which is itself a virtual static group. \
+ One virtual static group is not allowed to reference another as its target \
+ group
+NOTE_FSCACHE_RESTORE_484=Staring persistent entry cache state restoration, \
+ this may take awhile
+NOTE_FSCACHE_SAVE_485=Making the entry cache state persistent, this may \
+ take awhile
+ERR_FSCACHE_CANNOT_INITIALIZE_486=A fatal error occurred while trying \
+ to initialize file system entry cache: %s
+ERR_FSCACHE_CANNOT_LOAD_PERSISTENT_DATA_487=An error occurred while \
+ trying to load persistent cache. Persistent cache will be flushed now
+ERR_FSCACHE_CANNOT_STORE_PERSISTENT_DATA_488=An error occurred while \
+ trying to store persistent cache. Persistent cache will be flushed now
+ERR_FSCACHE_CANNOT_STORE_ENTRY_489=Unable to store new cache entry in \
+ the file system entry cache
+ERR_FSCACHE_CANNOT_RETRIEVE_ENTRY_490=Unable to retrieve an existing \
+ cache entry from the file system entry cache
+ERR_FSCACHE_CANNOT_SET_JE_MEMORY_PCT_491=Internal error occurred while \
+ trying to set the entry cache backend internal cache size as percentage. The \
+ previous or default value will be used instead
+ERR_FSCACHE_CANNOT_SET_JE_MEMORY_SIZE_492=Internal error occurred \
+ while trying to set the entry cache backend internal cache size in bytes. The \
+ previous or default value will be used instead
+ERR_FSCACHE_CANNOT_SET_JE_PROPERTIES_493=Internal error occurred \
+ while trying to set the entry cache backend Berkeley DB JE properties: %s
+ERR_FSCACHE_HOMELESS_494=A fatal error occurred while trying to setup \
+ file system entry cache home. No suitable path can be found to host the cache \
+ home
+WARN_FSCACHE_SET_PERMISSIONS_FAILED_495=Unable to set file permissions \
+ for the file system entry cache backend database directory %s
+WARN_FSCACHE_OFFLINE_STATE_FAIL_496=%s backend current offline state \
+ does not match persistent cache last recorded offline state. All cached data \
+ for this backend is now discarded
+NOTE_FSCACHE_RESTORE_REPORT_497=Restored %d persistent cache entries into \
+ the entry cache
+NOTE_FSCACHE_SAVE_REPORT_498=Made persistent %d cache entries
+NOTE_FSCACHE_INDEX_NOT_FOUND_499=No previous persistent cache state can be \
+ found. Starting with an empty cache
+ERR_FSCACHE_INDEX_IMPAIRED_500=The persistent cache index is \
+ inconsistent or damaged. Persistent cache will be flushed now
+ERR_ENTRYUUID_VATTR_NOT_SEARCHABLE_501=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_PWPSTATE_EXTOP_NO_PRIVILEGE_502=You do not have sufficient \
+ privileges to use the password policy state extended operation
+ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE_503=The provided password policy \
+ state extended request did not include a request value
+ERR_PWPSTATE_EXTOP_DECODE_FAILURE_504=An unexpected error occurred \
+ while attempting to decode password policy state extended request value: %s
+ERR_PWPSTATE_EXTOP_MULTIPLE_ENTRIES_505=Multiple entries were found \
+ with DN %s
+ERR_PWPSTATE_EXTOP_INVALID_OP_ENCODING_506=An unexpected error \
+ occurred while attempting to decode an operation from the password policy \
+ state extended request: %s
+ERR_PWPSTATE_EXTOP_NO_DISABLED_VALUE_507=No value was provided for the \
+ password policy state operation intended to set the disabled state for the \
+ user. Exactly one value (either 'true' or 'false') must be given
+ERR_PWPSTATE_EXTOP_BAD_DISABLED_VALUE_COUNT_508=Multiple values were \
+ provided for the password policy state operation intended to set the disabled \
+ state for the user. Exactly one value (either 'true' or 'false') must be \
+ given
+ERR_PWPSTATE_EXTOP_BAD_DISABLED_VALUE_509=The value provided for the \
+ password policy state operation intended to set the disabled state for the \
+ user was invalid. The value must be either 'true' or 'false'
+ERR_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE_COUNT_510=Multiple values were \
+ provided for the password policy state operation intended to set the account \
+ expiration time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE_511=The value %s provided for \
+ the password policy state operation used to set the account expiration time \
+ was invalid: %s. The value should be specified using the generalized time \
+ format
+ERR_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE_COUNT_512=Multiple values \
+ were provided for the password policy state operation intended to set the \
+ password changed time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE_513=The value %s provided \
+ for the password policy state operation used to set the password changed time \
+ was invalid: %s. The value should be specified using the generalized time \
+ format
+ERR_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE_COUNT_514=Multiple values \
+ were provided for the password policy state operation intended to set the \
+ password warned time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE_515=The value %s provided \
+ for the password policy state operation used to set the password warned time \
+ was invalid: %s. The value should be specified using the generalized time \
+ format
+ERR_PWPSTATE_EXTOP_BAD_ADD_FAILURE_TIME_COUNT_516=Multiple values were \
+ provided for the password policy state operation intended to add an \
+ authentication failure time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME_517=The value %s provided for \
+ the password policy state operation used to update the authentication failure \
+ times was invalid: %s. The value should be specified using the generalized \
+ time format
+ERR_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME_COUNT_518=Multiple values were \
+ provided for the password policy state operation intended to set the last \
+ login time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME_519=The value %s provided for \
+ the password policy state operation used to set the last login time was \
+ invalid: %s. The value should be specified using the generalized time format
+ERR_PWPSTATE_EXTOP_NO_RESET_STATE_VALUE_520=No value was provided for \
+ the password policy state operation intended to set the reset state for the \
+ user. Exactly one value (either 'true' or 'false') must be given
+ERR_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE_COUNT_521=Multiple values \
+ were provided for the password policy state operation intended to set the \
+ reset state for the user. Exactly one value (either 'true' or 'false') must \
+ be given
+ERR_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE_522=The value provided for \
+ the password policy state operation intended to set the reset state for the \
+ user was invalid. The value must be either 'true' or 'false'
+ERR_PWPSTATE_EXTOP_BAD_ADD_GRACE_LOGIN_TIME_COUNT_523=Multiple values \
+ were provided for the password policy state operation intended to add a grace \
+ login use time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME_524=The value %s provided for \
+ the password policy state operation used to update the grace login use times \
+ was invalid: %s. The value should be specified using the generalized time \
+ format
+ERR_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME_COUNT_525=Multiple values \
+ were provided for the password policy state operation intended to set the \
+ required change time for the user. Exactly one value must be given
+ERR_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME_526=The value %s provided \
+ for the password policy state operation used to set the required change time \
+ was invalid: %s. The value should be specified using the generalized time \
+ format
+ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE_527=The password policy state \
+ extended request included an operation with an invalid or unsupported \
+ operation type of %s
+WARN_EXTOP_PASSMOD_CANNOT_UPDATE_PWP_STATE_528=An error occurred while \
+ attempting to update the password policy state information for user %s as \
+ part of a password modify extended operation (result code='%s', error \
+ message='%s')
+ERR_EXTOP_PASSMOD_PW_IN_HISTORY_530=The provided new password was \
+ already contained in the password history
+ERR_SMTPALERTHANDLER_NO_SMTP_SERVERS_531=The Directory Server is not \
+ configured with any SMTP servers. The SMTP alert handler cannot be used \
+ unless the Directory Server is configured with information about at least one \
+ SMTP server
+WARN_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE_532=An error occurred when \
+ trying to send an e-mail message for administrative alert with type %s and \
+ message %s: %s
+ERR_REGEXMAP_INVALID_MATCH_PATTERN_533=The provided match pattern "%s" \
+ could not be parsed as a regular expression: %s
+ERR_REGEXMAP_MULTIPLE_MATCHING_ENTRIES_535=The processed ID string %s \
+ mapped to multiple users
+ERR_REGEXMAP_INEFFICIENT_SEARCH_536=The internal search based on \
+ processed ID string %s could not be processed efficiently: %s. Check the \
+ server configuration to ensure that all associated backends are properly \
+ configured for these types of searches
+ERR_REGEXMAP_SEARCH_FAILED_537=An internal failure occurred while \
+ attempting to resolve processed ID string %s to a user entry: %s
+ERR_STATICGROUP_ADD_NESTED_GROUP_ALREADY_EXISTS_538=Cannot add group %s \
+ as a new nested group of static group %s because that group is already in the \
+ nested group list for the group
+ERR_STATICGROUP_REMOVE_NESTED_GROUP_NO_SUCH_GROUP_539=Cannot remove \
+ group %s as a nested group of static group %s because that group is not \
+ included in the nested group list for the group
+ERR_STATICGROUP_GROUP_INSTANCE_INVALID_540=Group instance with DN %s has \
+ been deleted and is no longer valid
+ERR_NUMSUBORDINATES_VATTR_NOT_SEARCHABLE_541=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_HASSUBORDINATES_VATTR_NOT_SEARCHABLE_542=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_SMTP_ASNH_NO_MAIL_SERVERS_CONFIGURED_543=The SMTP account status \
+ notification handler defined in configuration entry %s cannot be enabled \
+ unless the Directory Server is with information about one or more SMTP servers
+ERR_SMTP_ASNH_NO_RECIPIENTS_544=SMTP account status notification handler \
+ configuration entry '%s' does not include any email address attribute types \
+ or recipient addresses. At least one of these must be provided
+ERR_SMTP_ASNH_SUBJECT_NO_COLON_545=Unable to parse message subject value \
+ '%s' from configuration entry '%s' because the value does not contain a \
+ colon to separate the notification type from the subject
+ERR_SMTP_ASNH_SUBJECT_INVALID_NOTIFICATION_TYPE_546=Unable to parse \
+ message subject value '%s' from configuration entry '%s' because '%s' is not \
+ a valid account status notification type
+ERR_SMTP_ASNH_SUBJECT_DUPLICATE_TYPE_547=The message subject definitions \
+ contained in configuration entry '%s' have multiple subjects defined for \
+ notification type %s
+ERR_SMTP_ASNH_TEMPLATE_NO_COLON_548=Unable to parse message template \
+ file path value '%s' from configuration entry '%s' because the value does \
+ not contain a colon to separate the notification type from the template file \
+ path
+ERR_SMTP_ASNH_TEMPLATE_INVALID_NOTIFICATION_TYPE_549=Unable to parse \
+ message template file path value '%s' from configuration entry '%s' because \
+ '%s' is not a valid account status notification type
+ERR_SMTP_ASNH_TEMPLATE_DUPLICATE_TYPE_550=The message template file path \
+ definitions contained in configuration entry '%s' have multiple template \
+ file paths defined for notification type %s
+ERR_SMTP_ASNH_TEMPLATE_NO_SUCH_FILE_551=The message template file '%s' \
+ referenced in configuration entry '%s' does not exist
+ERR_SMTP_ASNH_TEMPLATE_UNCLOSED_TOKEN_552=An unclosed token was found \
+ starting at column %d of line %d
+ERR_SMTP_ASNH_TEMPLATE_UNDEFINED_ATTR_TYPE_553=The \
+ notification-user-attr token starting at column %d of line %d references \
+ undefined attribute type %s
+ERR_SMTP_ASNH_TEMPLATE_UNDEFINED_PROPERTY_554=The \
+ notification-property token starting at column %d of line %d references \
+ undefined notification property %s
+ERR_SMTP_ASNH_TEMPLATE_UNRECOGNIZED_TOKEN_555=An unrecognized token %s \
+ was found at column %d of line %d
+ERR_SMTP_ASNH_TEMPLATE_CANNOT_PARSE_556=An error occurred while \
+ attempting to parse message template file '%s' referenced in configuration \
+ entry '%s': %s
+INFO_SMTP_ASNH_DEFAULT_SUBJECT_557=Directory Account Status Notification
+ERR_SMTP_ASNH_CANNOT_SEND_MESSAGE_558=An error occurred while \
+ attempting to send an account status notification message for notification \
+ type %s for user entry %s: %s
+ERR_PWSCHEME_CANNOT_ENCRYPT_559=An error occurred while trying to \
+ encrypt a value using password storage scheme %s: %s
+ERR_PWSCHEME_CANNOT_DECRYPT_560=An error occurred while trying to \
+ decrypt a value using password storage scheme %s: %s
+ERR_GET_SYMMETRIC_KEY_NO_VALUE_561=Cannot decode the provided \
+ symmetric key extended operation because it does not have a value
+ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION_563=Cannot decode the \
+ provided symmetric key extended request: %s
+ERR_GET_SYMMETRIC_KEY_DECODE_EXCEPTION_564=An unexpected error occurred \
+ while attempting to decode the symmetric key extended request sequence: %s
+ERR_EXACTMAP_ATTR_UNINDEXED_565=The exact match identity mapper \
+ defined in configuration entry %s references attribute type %s which is does \
+ not have an equality index defined in backend %s
+ERR_REGEXMAP_ATTR_UNINDEXED_566=The regular expression identity mapper \
+ defined in configuration entry %s references attribute type %s which is does \
+ not have an equality index defined in backend %s
+WARN_SATUACM_ATTR_UNINDEXED_568=The subject attribute to user attribute \
+ certificate mapper defined in configuration entry %s references attribute \
+ type %s which is does not have an equality index defined in backend %s
+NOTE_LOG_EXTENSION_INFORMATION_571=Loaded extension from file '%s' (build %s, \
+ revision %s)
+ERR_SASL_CREATE_SASL_SERVER_FAILED_572=Failed to create a SASL server \
+ for SASL mechanism %s using a server FQDN of %s
+ERR_SASL_GSSAPI_KEYTAB_INVALID_573=GSSAPI SASL mechanism handler initalization \
+failed because the keytab file %s does not exist
+INFO_GSSAPI_STARTED_574=The GSSAPI SASL mechanism handler initialization \
+was successful
+INFO_GSSAPI_STOPPED_575=The GSSAPI SASL mechanism handler has been stopped
+ERR_COLLECTIVEATTRIBUTESUBENTRIES_VATTR_NOT_SEARCHABLE_576=The %s \
+ attribute is not searchable and should not be included in otherwise \
+ unindexed search filters
+ERR_PASSWORDPOLICYSUBENTRY_VATTR_NOT_SEARCHABLE_577=The %s \
+ attribute is not searchable and should not be included in otherwise \
+ unindexed search filters
+ERR_PWSCHEME_INVALID_BASE64_DECODED_STORED_PASSWORD_578=The password \
+value %s has been base64-decoded but is too short to be valid
+ERR_CHARSET_VALIDATOR_MIN_CHAR_SETS_TOO_SMALL_579=The provided minimum \
+ required number of character sets '%d' is invalid because it must include \
+ all mandatory character sets and at least one optional character set
+ERR_CHARSET_VALIDATOR_MIN_CHAR_SETS_TOO_BIG_580=The provided minimum \
+ required number of character sets '%d' is invalid because it is greater than \
+ the total number of defined character sets
+ERR_CHARSET_VALIDATOR_TOO_FEW_OPTIONAL_CHAR_SETS_581=The provided \
+ password did not contain characters from at least %d of the following \
+ character sets or ranges: %s
+ERR_STATICMEMBERS_CANNOT_DECODE_DN_582=An error occurred while \
+ attempting to decode member's DN %s of static group %s: %s
+ERR_SASL_ACCOUNT_NOT_LOCAL_583=SASL %s authentication \
+ is not supported for user %s because the account is not managed locally
+ERR_EXTOP_PASSMOD_ACCOUNT_NOT_LOCAL_584=Password modification is not \
+ supported for user %s because the account is not managed locally
+ERR_EXTOP_PWPSTATE_ACCOUNT_NOT_LOCAL_585=The password policy state \
+ extended operation is not supported for user %s because the account is not \
+ managed locally
+ERR_LDAP_PTA_MAPPING_ATTRIBUTE_NOT_FOUND_586=The user "%s" could not be \
+ authenticated using LDAP PTA policy "%s" because the following \
+ mapping attributes were not found in the user's entry: %s
+ERR_LDAP_PTA_MAPPED_SEARCH_TOO_MANY_CANDIDATES_587=The user "%s" could \
+ not be authenticated using LDAP PTA policy "%s" because the search of base \
+ DN "%s" returned more than one entry matching the filter "%s"
+ERR_LDAP_PTA_MAPPED_SEARCH_NO_CANDIDATES_588=The user "%s" could \
+ not be authenticated using LDAP PTA policy "%s" because the search did not \
+ return any entries matching the filter "%s"
+ERR_LDAP_PTA_MAPPED_SEARCH_FAILED_589=The user "%s" could \
+ not be authenticated using LDAP PTA policy "%s" because the search failed \
+ unexpectedly for the following reason: %s
+ERR_LDAP_PTA_MAPPED_BIND_FAILED_590=The user "%s" could \
+ not be authenticated using LDAP PTA policy "%s" because the bind failed \
+ unexpectedly for the following reason: %s
+ERR_LDAP_PTA_CONNECT_UNKNOWN_HOST_591=A connection could not be established \
+ to the remote LDAP server at %s:%d for LDAP PTA policy "%s" because the host name \
+ "%s" could not be resolved to an IP address
+ERR_LDAP_PTA_CONNECT_ERROR_592=A connection could not be established \
+ to the remote LDAP server at %s:%d for LDAP PTA policy "%s" because the connection \
+ was refused. This may indicate that the server is either offline or it is not \
+ listening on port %d
+ERR_LDAP_PTA_CONNECT_TIMEOUT_593=A connection could not be established \
+ to the remote LDAP server at %s:%d for LDAP PTA policy "%s" because the connection \
+ attempt timed out. This may indicate that the server is slow to respond, \
+ the network is slow, or that there is some other network problem
+ERR_LDAP_PTA_CONNECT_SSL_ERROR_594=A connection could not be established \
+ to the remote LDAP server at %s:%d for LDAP PTA policy "%s" because SSL \
+ negotiation failed for the following reason: %s
+ERR_LDAP_PTA_CONNECT_OTHER_ERROR_595=A connection could not be established \
+ to the remote LDAP server at %s:%d for LDAP PTA policy "%s" because an unexpected \
+ error occurred: %s
+ERR_LDAP_PTA_CONNECTION_OTHER_ERROR_596=The connection to the remote LDAP \
+ server at %s:%d for LDAP PTA policy "%s" has failed unexpectedly: %s
+ERR_LDAP_PTA_CONNECTION_CLOSED_597=The connection to the remote LDAP \
+ server at %s:%d for LDAP PTA policy "%s" has been closed unexpectedly
+ERR_LDAP_PTA_CONNECTION_TIMEOUT_598=The connection to the remote LDAP \
+ server at %s:%d for LDAP PTA policy "%s" has timed out and will be closed. This \
+ may indicate that the server is slow to respond, the network is slow, or \
+ that there is some other network problem
+ERR_LDAP_PTA_CONNECTION_DECODE_ERROR_599=The connection to the remote LDAP \
+ server at %s:%d for LDAP PTA policy "%s" has encountered a protocol error while \
+ decoding a response from the server and will be closed. The decoding error was: %s
+ERR_LDAP_PTA_CONNECTION_WRONG_RESPONSE_600=The connection to the remote LDAP \
+ server at %s:%d for LDAP PTA policy "%s" has received an unexpected response \
+ from the server and will be closed. The unexpected response message was: %s
+ERR_LDAP_PTA_CONNECTION_DISCONNECTING_601=The connection to the remote LDAP \
+ server at %s:%d for LDAP PTA policy "%s" has received a disconnect notification \
+ with response code %d (%s) and error message "%s"
+ERR_LDAP_PTA_CONNECTION_BIND_FAILED_602=The remote LDAP server at %s:%d \
+ for LDAP PTA policy "%s" has failed to authenticate user "%s", returning the \
+ response code %d (%s) and error message "%s"
+ERR_LDAP_PTA_CONNECTION_SEARCH_SIZE_LIMIT_603=The remote LDAP server at %s:%d \
+ for LDAP PTA policy "%s" returned multiple matching entries while searching \
+ "%s" using the filter "%s"
+ERR_LDAP_PTA_CONNECTION_SEARCH_NO_MATCHES_604=The remote LDAP server at %s:%d \
+ for LDAP PTA policy "%s" did not return any matching entries while searching \
+ "%s" using the filter "%s"
+ERR_LDAP_PTA_CONNECTION_SEARCH_FAILED_605=The remote LDAP server at %s:%d \
+ for LDAP PTA policy "%s" returned an error while searching "%s" using the \
+ filter "%s": response code %d (%s) and error message "%s"
+ERR_LDAP_PTA_INVALID_PORT_NUMBER_606=The configuration of LDAP PTA policy \
+ "%s" is invalid because the remote LDAP server address "%s" specifies a port \
+ number which is invalid. Port numbers should be greater than 0 and less than 65536
+ERR_LDAP_PTA_PWD_PROPERTY_NOT_SET_607=The configuration of LDAP PTA policy \
+ "%s" is invalid because the Java property %s which should contain the mapped \
+ search bind password is not set
+ERR_LDAP_PTA_PWD_ENVAR_NOT_SET_608=The configuration of LDAP PTA policy \
+ "%s" is invalid because the environment variable %s which should contain the mapped \
+ search bind password is not set
+ERR_LDAP_PTA_PWD_NO_SUCH_FILE_609=The configuration of LDAP PTA policy \
+ "%s" is invalid because the file %s which should contain the mapped search \
+ bind password does not exist
+ERR_LDAP_PTA_PWD_FILE_CANNOT_READ_610=The configuration of LDAP PTA policy \
+ "%s" is invalid because the file %s which should contain the mapped search \
+ bind password cannot be read for the following reason: %s
+ERR_LDAP_PTA_PWD_FILE_EMPTY_611=The configuration of LDAP PTA policy \
+ "%s" is invalid because the file %s which should contain the mapped search \
+ bind password is empty
+ERR_LDAP_PTA_NO_PWD_613=The configuration of LDAP PTA policy \
+ "%s" is invalid because it does not specify the a means for obtaining the mapped \
+ search bind password
+ERR_ETAG_VATTR_NOT_SEARCHABLE_614=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_PWDEXPTIME_VATTR_NOT_SEARCHABLE_615=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_SATUACM_MULTIPLE_SEARCH_MATCHING_ENTRIES_616=The certificate with \
+ subject %s mapped to multiple users
+ERR_SATUACM_INEFFICIENT_SEARCH_617=The internal search based on \
+ the certificate with subject %s could not be processed efficiently: %s. \
+ Check the server configuration to ensure that all associated backends are \
+ properly configured for these types of searches
+ERR_SATUACM_SEARCH_FAILED_618=An internal failure occurred while \
+ attempting to map the certificate with subject %s to a user entry: %s
+ERR_SDTUACM_MULTIPLE_SEARCH_MATCHING_ENTRIES_619=The certificate with \
+ subject %s mapped to multiple users
+ERR_SDTUACM_INEFFICIENT_SEARCH_620=The internal search based on \
+ the certificate with subject %s could not be processed efficiently: %s. \
+ Check the server configuration to ensure that all associated backends are \
+ properly configured for these types of searches
+ERR_SDTUACM_SEARCH_FAILED_621=An internal failure occurred while \
+ attempting to map the certificate with subject %s to a user entry: %s
+ERR_FCM_MULTIPLE_SEARCH_MATCHING_ENTRIES_622=The certificate with \
+ fingerprint %s mapped to multiple users
+ERR_FCM_INEFFICIENT_SEARCH_623=The internal search based on \
+ the certificate with fingerprint %s could not be processed efficiently: %s. \
+ Check the server configuration to ensure that all associated backends are \
+ properly configured for these types of searches
+ERR_FCM_SEARCH_FAILED_624=An internal failure occurred while \
+ attempting to map the certificate with fingerprint %s to a user entry: %s
+ERR_FIRSTCHANGENUMBER_VATTR_NOT_SEARCHABLE_625=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_LASTCHANGENUMBER_VATTR_NOT_SEARCHABLE_626=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_LASTCOOKIE_VATTR_NOT_SEARCHABLE_627=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_CHANGELOGBASEDN_VATTR_NOT_SEARCHABLE_628=The %s attribute is not \
+ searchable and should not be included in otherwise unindexed search filters
+ERR_CHARSET_VALIDATOR_TOO_FEW_CHARS_FROM_RANGE_629=The provided password \
+ did not contain enough characters from the character range '%s'. The minimum \
+ number of characters from that range that must be present in user passwords \
+ is %d
+ERR_CHARSET_VALIDATOR_NO_RANGE_COLON_630=The provided character range \
+ definition '%s' is invalid because it does not contain a colon to separate \
+ the minimum count from the character range
+ERR_CHARSET_VALIDATOR_NO_RANGE_CHARS_631=The provided character range \
+ definition '%s' is invalid because it does not contain a colon to separate \
+ the minimum count from the character range
+ERR_CHARSET_VALIDATOR_INVALID_RANGE_COUNT_632=The provided character \
+ range definition '%s' is invalid because the value before the colon must be \
+ an integer greater or equal to zero
+ERR_CHARSET_VALIDATOR_UNSORTED_RANGE_633=The provided character range \
+ definition '%s' is invalid because the range '%s' is reversed
+ERR_CHARSET_VALIDATOR_MALFORMED_RANGE_634=The provided character range \
+ definition '%s' is invalid because the range '%s' is missing the minus
+ERR_CHARSET_VALIDATOR_SHORT_RANGE_635=The provided character range \
+ definition '%s' is invalid because the range '%s' is too short
diff --git a/opendj-admin/src/main/resources/stylesheets/admin.xsd b/opendj-admin/src/main/resources/stylesheets/admin.xsd
index 01bb283..a0c813b 100644
--- a/opendj-admin/src/main/resources/stylesheets/admin.xsd
+++ b/opendj-admin/src/main/resources/stylesheets/admin.xsd
@@ -5,6 +5,8 @@
xmlns:tns="http://www.opends.org/admin">
<xsd:import namespace="http://www.opends.org/admin-ldap"
schemaLocation="admin-ldap.xsd" />
+ <xsd:import namespace="http://www.opends.org/admin-cli"
+ schemaLocation="admin-cli.xsd" />
<xsd:import namespace="http://www.opends.org/admin-preprocessor"
schemaLocation="admin-preprocessor.xsd" />
<xsd:annotation>
diff --git a/opendj-admin/src/main/resources/stylesheets/catalog.xml b/opendj-admin/src/main/resources/stylesheets/catalog.xml
new file mode 100644
index 0000000..01f9af0
--- /dev/null
+++ b/opendj-admin/src/main/resources/stylesheets/catalog.xml
@@ -0,0 +1,5 @@
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <system systemId="admin-ldap.xsd" uri="admin-ldap.xsd" />
+ <system systemId="admin-cli.xsd" uri="admin-cli.xsd" />
+ <system systemId="admin-preprocessor.xsd" uri="admin-preprocessor.xsd" />
+</catalog>
\ No newline at end of file
--
Gitblit v1.10.0