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> 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; 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; } 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; } } 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: 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); } } } 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); } } 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 } } } 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; 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; 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); } 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); } 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"); } } opendj-admin/src/main/java/org/opends/server/authorization/dseecompat/AciException.java
New file @@ -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); } } 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); } } opendj-admin/src/main/java/org/opends/server/config/ConfigurationRepository.java
New file @@ -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); } 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 opendj-admin/src/main/resources/com/forgerock/opendj/ldap/extension.properties
New file @@ -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 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> opendj-admin/src/main/resources/stylesheets/catalog.xml
New file @@ -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>