/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.core; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.opends.server.api.AttributeSyntax; import org.opends.server.api.ConfigAddListener; import org.opends.server.api.ConfigChangeListener; import org.opends.server.api.ConfigDeleteListener; import org.opends.server.api.ConfigHandler; import org.opends.server.api.MatchingRule; import org.opends.server.config.BooleanConfigAttribute; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.config.StringConfigAttribute; import org.opends.server.schema.AttributeTypeSyntax; import org.opends.server.schema.DITContentRuleSyntax; import org.opends.server.schema.DITStructureRuleSyntax; import org.opends.server.schema.MatchingRuleUseSyntax; import org.opends.server.schema.NameFormSyntax; import org.opends.server.schema.ObjectClassSyntax; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DirectoryException; import org.opends.server.types.DITContentRule; import org.opends.server.types.DITStructureRule; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.ErrorLogCategory; import org.opends.server.types.ErrorLogSeverity; import org.opends.server.types.InitializationException; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.MatchingRuleUse; import org.opends.server.types.NameForm; import org.opends.server.types.ObjectClass; import org.opends.server.types.ResultCode; import org.opends.server.types.Schema; import org.opends.server.util.LDIFReader; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.loggers.Debug.*; import static org.opends.server.loggers.Error.*; import static org.opends.server.messages.ConfigMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.schema.SchemaConstants.*; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; /** * This class defines a utility that will be used to manage the interaction with * the Directory Server schema. It will be used to initially load all of the * matching rules and attribute syntaxes that have been defined in the * configuration, and will then read the actual schema definitions. At present, * only attribute types and objectclasses are supported in the schema config * files. Other components like DIT content rules, DIT structure rules, name * forms, and matching rule use definitions will be ignored. */ public class SchemaConfigManager implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener { /** * The fully-qualified name of this class for debugging purposes. */ private static final String CLASS_NAME = "org.opends.server.core.SchemaConfigManager"; // The schema that has been parsed from the server configuration. private Schema schema; // The configuration handler for the Directory Server. private ConfigHandler configHandler; /** * Creates a new instance of this schema config manager. */ public SchemaConfigManager() { assert debugConstructor(CLASS_NAME); configHandler = DirectoryServer.getConfigHandler(); schema = new Schema(); } /** * Retrieves the path to the directory containing the server schema files. * * @return The path to the directory containing the server schema files. */ public static String getSchemaDirectoryPath() { assert debugEnter(CLASS_NAME, "getSchemaDirectoryPath"); String schemaDirPath = System.getProperty(PROPERTY_SCHEMA_DIRECTORY); if ((schemaDirPath == null) || (schemaDirPath.length() == 0)) { schemaDirPath = DirectoryServer.getServerRoot() + File.separator + PATH_SCHEMA_DIR; } return schemaDirPath; } /** * Retrieves a reference to the schema information that has been read from the * server configuration. Note that this information will not be complete * until the initializeMatchingRules, * initializeAttributeSyntaxes, and * initializeAttributeTypesAndObjectClasses methods have been * called. * * @return A reference to the schema information that has been read from the * server configuration. */ public Schema getSchema() { assert debugEnter(CLASS_NAME, "getSchema"); return schema; } /** * Initializes all the matching rules defined in the Directory Server * configuration. This should only be called at Directory Server startup. * * @throws ConfigException If a configuration problem causes the matching * rule initialization process to fail. * * @throws InitializationException If a problem occurs while initializing * the matching rules that is not related to * the server configuration. */ public void initializeMatchingRules() throws ConfigException, InitializationException { assert debugEnter(CLASS_NAME, "initializeMatchingRules"); // First, get the matching rule configuration base entry. ConfigEntry matchingRuleBaseEntry; try { DN matchingRuleBaseDN = DN.decode(DN_MATCHING_RULE_CONFIG_BASE); matchingRuleBaseEntry = configHandler.getConfigEntry(matchingRuleBaseDN); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeMatchingRules", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_GET_MR_BASE; String message = getMessage(msgID, String.valueOf(e)); throw new ConfigException(msgID, message, e); } if (matchingRuleBaseEntry == null) { // The matching rule base entry does not exist. This is not acceptable, // so throw an exception. int msgID = MSGID_CONFIG_SCHEMA_MR_BASE_DOES_NOT_EXIST; String message = getMessage(msgID); throw new ConfigException(msgID, message); } // Register add and delete listeners with the matching rule base entry. We // don't care about modifications to it. matchingRuleBaseEntry.registerAddListener(this); matchingRuleBaseEntry.registerDeleteListener(this); // See if the matching rule base has any children. If not, then this is // very bad, since we won't know how to make any comparisons. if (! matchingRuleBaseEntry.hasChildren()) { int msgID = MSGID_CONFIG_SCHEMA_NO_MATCHING_RULES; String message = getMessage(msgID); throw new ConfigException(msgID, message); } // Iterate through the child entries and process them as matching rule // entries. for (ConfigEntry childEntry : matchingRuleBaseEntry.getChildren().values()) { DN mrEntryDN = childEntry.getDN(); // Register as a change listener for this matching rule entry so that we // will be notified of any changes that may be made to it. childEntry.registerChangeListener(this); // Check to see if this entry appears to contain a matching rule // configuration. If not, log a warning and skip it. if (! childEntry.hasObjectClass(OC_MATCHING_RULE)) { int msgID = MSGID_CONFIG_SCHEMA_ENTRY_DOES_NOT_HAVE_MR_CONFIG; String message = getMessage(msgID, String.valueOf(mrEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // See if the entry contains an attribute that indicates whether the // matching rule should be enabled. If it does not, or if it is not set // to "true", then skip it. int msgID = MSGID_CONFIG_SCHEMA_MR_ATTR_DESCRIPTION_ENABLED; BooleanConfigAttribute enabledStub = new BooleanConfigAttribute(ATTR_MATCHING_RULE_ENABLED, getMessage(msgID), false); try { BooleanConfigAttribute enabledAttr = (BooleanConfigAttribute) childEntry.getConfigAttribute(enabledStub); if (enabledAttr == null) { // The attribute is not present, so this matching rule will be // disabled. Log a message and continue. msgID = MSGID_CONFIG_SCHEMA_MR_NO_ENABLED_ATTR; String message = getMessage(msgID, String.valueOf(mrEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } else if (! enabledAttr.activeValue()) { // The matching rule is explicitly disabled. Log a mild warning and // continue. msgID = MSGID_CONFIG_SCHEMA_MR_DISABLED; String message = getMessage(msgID, String.valueOf(mrEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.INFORMATIONAL, message, msgID); continue; } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeMatchingRules", e); msgID = MSGID_CONFIG_SCHEMA_MR_UNABLE_TO_DETERMINE_ENABLED_STATE; String message = getMessage(msgID, String.valueOf(mrEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // See if the entry contains an attribute that specifies the class name // for the matching rule implementation. If it does, then load it and // make sure that it's a valid matching rule implementation. If there is // no such attribute, the specified class cannot be loaded, or it does not // contain a valid matching rule implementation, then log an error and // skip it. String className; msgID = MSGID_CONFIG_SCHEMA_MR_ATTR_DESCRIPTION_CLASS; StringConfigAttribute classStub = new StringConfigAttribute(ATTR_MATCHING_RULE_CLASS, getMessage(msgID), true, false, true); try { StringConfigAttribute classAttr = (StringConfigAttribute) childEntry.getConfigAttribute(classStub); if (classAttr == null) { msgID = MSGID_CONFIG_SCHEMA_MR_NO_CLASS_ATTR; String message = getMessage(msgID, String.valueOf(mrEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } else { className = classAttr.activeValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeMatchingRules", e); msgID = MSGID_CONFIG_SCHEMA_MR_CANNOT_GET_CLASS; String message = getMessage(msgID, String.valueOf(mrEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } MatchingRule matchingRule; try { // FIXME -- Should we use a custom class loader for this? Class matchingRuleClass = Class.forName(className); matchingRule = (MatchingRule) matchingRuleClass.newInstance(); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeMatchingRules", e); msgID = MSGID_CONFIG_SCHEMA_MR_CANNOT_INSTANTIATE; String message = getMessage(msgID, String.valueOf(className), String.valueOf(mrEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // Perform the necessary initialization for the matching rule. try { matchingRule.initializeMatchingRule(childEntry); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeMatchingRules", e); msgID = MSGID_CONFIG_SCHEMA_MR_CANNOT_INITIALIZE; String message = getMessage(msgID, String.valueOf(className), String.valueOf(mrEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // Register the matching rule with the server schema. try { schema.registerMatchingRule(matchingRule, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeMatchingRules", de); msgID = MSGID_CONFIG_SCHEMA_MR_CONFLICTING_MR; String message = getMessage(msgID, String.valueOf(mrEntryDN), de.getErrorMessage()); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } } } /** * Initializes all the attribute syntaxes defined in the Directory Server * configuration. This should only be called at Directory Server startup. * * @throws ConfigException If a configuration problem causes the syntax * initialization process to fail. * * @throws InitializationException If a problem occurs while initializing * the syntaxes that is not related to the * server configuration. */ public void initializeAttributeSyntaxes() throws ConfigException, InitializationException { assert debugEnter(CLASS_NAME, "initializeAttributeSyntaxes"); // First, get the attribute syntax configuration base entry. ConfigEntry syntaxBaseEntry; try { DN syntaxBaseDN = DN.decode(DN_SYNTAX_CONFIG_BASE); syntaxBaseEntry = configHandler.getConfigEntry(syntaxBaseDN); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeAttributeSyntaxes", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_GET_SYNTAX_BASE; String message = getMessage(msgID, String.valueOf(e)); throw new ConfigException(msgID, message, e); } if (syntaxBaseEntry == null) { // The syntax base entry does not exist. This is not acceptable, so throw // an exception. int msgID = MSGID_CONFIG_SCHEMA_SYNTAX_BASE_DOES_NOT_EXIST; String message = getMessage(msgID); throw new ConfigException(msgID, message); } // Register add and delete listeners with the syntax base entry. We don't // care about modifications to it. syntaxBaseEntry.registerAddListener(this); syntaxBaseEntry.registerDeleteListener(this); // See if the syntax base has any children. If not, then this is very // bad, since we won't know how to deal with any attribute types. if (! syntaxBaseEntry.hasChildren()) { int msgID = MSGID_CONFIG_SCHEMA_NO_SYNTAXES; String message = getMessage(msgID); throw new ConfigException(msgID, message); } // Iterate through the child entries and process them as syntax entries. for (ConfigEntry childEntry : syntaxBaseEntry.getChildren().values()) { DN syntaxEntryDN = childEntry.getDN(); // Register as a change listener for this syntax entry so that we will be // notified of any changes that may be made to it. childEntry.registerChangeListener(this); // Check to see if this entry appears to contain an attribute syntax // configuration. If not, log a warning and skip it. if (! childEntry.hasObjectClass(OC_ATTRIBUTE_SYNTAX)) { int msgID = MSGID_CONFIG_SCHEMA_ENTRY_DOES_NOT_HAVE_SYNTAX_CONFIG; String message = getMessage(msgID, String.valueOf(syntaxEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // See if the entry contains an attribute that indicates whether the // syntax should be enabled. If it does not, or if it is not set to // "true", then skip it. int msgID = MSGID_CONFIG_SCHEMA_SYNTAX_ATTR_DESCRIPTION_ENABLED; BooleanConfigAttribute enabledStub = new BooleanConfigAttribute(ATTR_SYNTAX_ENABLED, getMessage(msgID), false); try { BooleanConfigAttribute enabledAttr = (BooleanConfigAttribute) childEntry.getConfigAttribute(enabledStub); if (enabledAttr == null) { // The attribute is not present, so this syntax will be disabled. Log // a message and continue. msgID = MSGID_CONFIG_SCHEMA_SYNTAX_NO_ENABLED_ATTR; String message = getMessage(msgID, String.valueOf(syntaxEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } else if (! enabledAttr.activeValue()) { // The syntax is explicitly disabled. Log a mild warning and // continue. msgID = MSGID_CONFIG_SCHEMA_SYNTAX_DISABLED; String message = getMessage(msgID, String.valueOf(syntaxEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.INFORMATIONAL, message, msgID); continue; } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeAttributeSyntaxes", e); msgID = MSGID_CONFIG_SCHEMA_SYNTAX_UNABLE_TO_DETERMINE_ENABLED_STATE; String message = getMessage(msgID, String.valueOf(syntaxEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // See if the entry contains an attribute that specifies the class name // for the syntax implementation. If it does, then load it and make sure // that it's a valid syntax implementation. If there is no such // attribute, the specified class cannot be loaded, or it does not contain // a valid syntax implementation, then log an error and skip it. String className; msgID = MSGID_CONFIG_SCHEMA_SYNTAX_ATTR_DESCRIPTION_CLASS; StringConfigAttribute classStub = new StringConfigAttribute(ATTR_SYNTAX_CLASS, getMessage(msgID), true, false, true); try { StringConfigAttribute classAttr = (StringConfigAttribute) childEntry.getConfigAttribute(classStub); if (classAttr == null) { msgID = MSGID_CONFIG_SCHEMA_SYNTAX_NO_CLASS_ATTR; String message = getMessage(msgID, String.valueOf(syntaxEntryDN)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } else { className = classAttr.activeValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeAttributeSyntaxes", e); msgID = MSGID_CONFIG_SCHEMA_SYNTAX_CANNOT_GET_CLASS; String message = getMessage(msgID, String.valueOf(syntaxEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } AttributeSyntax syntax; try { // FIXME -- Should we use a custom class loader for this? Class syntaxClass = Class.forName(className); syntax = (AttributeSyntax) syntaxClass.newInstance(); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeAttributeSyntaxes", e); msgID = MSGID_CONFIG_SCHEMA_SYNTAX_CANNOT_INSTANTIATE; String message = getMessage(msgID, String.valueOf(className), String.valueOf(syntaxEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // Perform the necessary initialization for the syntax. try { syntax.initializeSyntax(childEntry); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeAttributeSyntaxes", e); msgID = MSGID_CONFIG_SCHEMA_SYNTAX_CANNOT_INITIALIZE; String message = getMessage(msgID, String.valueOf(className), String.valueOf(syntaxEntryDN), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // Register the syntax with the server schema. try { schema.registerSyntax(syntax, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeAttributeSyntaxes", de); msgID = MSGID_CONFIG_SCHEMA_SYNTAX_CONFLICTING_SYNTAX; String message = getMessage(msgID, String.valueOf(syntaxEntryDN), de.getErrorMessage()); logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } } } /** * Initializes all the attribute type and objectclass definitions by reading * the server schema files. These files will be located in a single directory * and will be processed in alphabetic order. However, to make the order * easier to understand, they may be prefixed with a two digit number (with a * leading zero if necessary) so that they will be read in numeric order. * This should only be called at Directory Server startup. * * @throws ConfigException If a configuration problem causes the attribute * type or objectclass initialization to fail. * * @throws InitializationException If a problem occurs while initializing * the attribute types/objectclasses that is * not related to the server configuration. */ public void initializeSchemaFromFiles() throws ConfigException, InitializationException { assert debugEnter(CLASS_NAME, "initializeSchemaFromFiles"); // Construct the path to the directory that should contain the schema files // and make sure that it exists and is a directory. Get a list of the files // in that directory sorted in alphabetic order. String schemaDirPath = getSchemaDirectoryPath(); File schemaDir = new File(schemaDirPath); long oldestModificationTime = -1L; long youngestModificationTime = -1L; String[] fileNames; try { if (! schemaDir.exists()) { int msgID = MSGID_CONFIG_SCHEMA_NO_SCHEMA_DIR; String message = getMessage(msgID, schemaDirPath); throw new InitializationException(msgID, message); } else if (! schemaDir.isDirectory()) { int msgID = MSGID_CONFIG_SCHEMA_DIR_NOT_DIRECTORY; String message = getMessage(msgID, schemaDirPath); throw new InitializationException(msgID, message); } File[] schemaDirFiles = schemaDir.listFiles(); ArrayList fileList = new ArrayList(schemaDirFiles.length); for (File f : schemaDirFiles) { if (f.isFile()) { fileList.add(f.getAbsolutePath()); } long modificationTime = f.lastModified(); if ((oldestModificationTime <= 0L) || (modificationTime < oldestModificationTime)) { oldestModificationTime = modificationTime; } if ((youngestModificationTime <= 0) || (modificationTime > youngestModificationTime)) { youngestModificationTime = modificationTime; } } fileNames = new String[fileList.size()]; fileList.toArray(fileNames); Arrays.sort(fileNames); } catch (InitializationException ie) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", ie); throw ie; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_LIST_FILES; String message = getMessage(msgID, schemaDirPath, stackTraceToSingleLineString(e)); throw new InitializationException(msgID, message, e); } // If the oldest and youngest modification timestamps didn't get set for // some reason, then set them to the current time. if (oldestModificationTime <= 0) { oldestModificationTime = System.currentTimeMillis(); } if (youngestModificationTime <= 0) { youngestModificationTime = oldestModificationTime; } schema.setOldestModificationTime(oldestModificationTime); schema.setYoungestModificationTime(youngestModificationTime); // Iterate through the schema files and read them as an LDIF file containing // a single entry. Then get the attributeTypes and objectClasses attributes // from that entry and parse them to initialize the server schema. for (String schemaFile : fileNames) { // Create an LDIF reader to use when reading the files. LDIFReader reader; try { reader = new LDIFReader(new LDIFImportConfig(schemaFile)); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_OPEN_FILE; String message = getMessage(msgID, schemaFile, schemaDirPath, stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } // Read the LDIF entry from the file and close the file. Entry entry; try { entry = reader.readEntry(false); if (entry == null) { // The file was empty -- skip it. continue; } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_READ_LDIF_ENTRY; String message = getMessage(msgID, schemaFile, schemaDirPath, stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_ERROR, message, msgID); continue; } try { reader.close(); } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } // Get the attributeTypes attribute from the entry. AttributeTypeSyntax attrTypeSyntax; try { attrTypeSyntax = (AttributeTypeSyntax) schema.getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID); if (attrTypeSyntax == null) { attrTypeSyntax = new AttributeTypeSyntax(); attrTypeSyntax.initializeSyntax(null); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); attrTypeSyntax = new AttributeTypeSyntax(); attrTypeSyntax.initializeSyntax(null); } AttributeType attributeAttrType = schema.getAttributeType(ATTR_ATTRIBUTE_TYPES_LC); if (attributeAttrType == null) { attributeAttrType = DirectoryServer.getDefaultAttributeType(ATTR_ATTRIBUTE_TYPES, attrTypeSyntax); } List attrList = entry.getAttribute(attributeAttrType); // Get the objectClasses attribute from the entry. ObjectClassSyntax ocSyntax; try { ocSyntax = (ObjectClassSyntax) schema.getSyntax(SYNTAX_OBJECTCLASS_OID); if (ocSyntax == null) { ocSyntax = new ObjectClassSyntax(); ocSyntax.initializeSyntax(null); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); ocSyntax = new ObjectClassSyntax(); ocSyntax.initializeSyntax(null); } AttributeType objectclassAttrType = schema.getAttributeType(ATTR_OBJECTCLASSES_LC); if (objectclassAttrType == null) { objectclassAttrType = DirectoryServer.getDefaultAttributeType(ATTR_OBJECTCLASSES, ocSyntax); } List ocList = entry.getAttribute(objectclassAttrType); // Get the name forms attribute from the entry. NameFormSyntax nfSyntax; try { nfSyntax = (NameFormSyntax) schema.getSyntax(SYNTAX_NAME_FORM_OID); if (nfSyntax == null) { nfSyntax = new NameFormSyntax(); nfSyntax.initializeSyntax(null); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); nfSyntax = new NameFormSyntax(); nfSyntax.initializeSyntax(null); } AttributeType nameFormAttrType = schema.getAttributeType(ATTR_NAME_FORMS_LC); if (nameFormAttrType == null) { nameFormAttrType = DirectoryServer.getDefaultAttributeType(ATTR_NAME_FORMS, nfSyntax); } List nfList = entry.getAttribute(nameFormAttrType); // Get the DIT content rules attribute from the entry. DITContentRuleSyntax dcrSyntax; try { dcrSyntax = (DITContentRuleSyntax) schema.getSyntax(SYNTAX_DIT_CONTENT_RULE_OID); if (dcrSyntax == null) { dcrSyntax = new DITContentRuleSyntax(); dcrSyntax.initializeSyntax(null); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); dcrSyntax = new DITContentRuleSyntax(); dcrSyntax.initializeSyntax(null); } AttributeType dcrAttrType = schema.getAttributeType(ATTR_DIT_CONTENT_RULES_LC); if (dcrAttrType == null) { dcrAttrType = DirectoryServer.getDefaultAttributeType(ATTR_DIT_CONTENT_RULES, dcrSyntax); } List dcrList = entry.getAttribute(dcrAttrType); // Get the DIT structure rules attribute from the entry. DITStructureRuleSyntax dsrSyntax; try { dsrSyntax = (DITStructureRuleSyntax) schema.getSyntax(SYNTAX_DIT_STRUCTURE_RULE_OID); if (dsrSyntax == null) { dsrSyntax = new DITStructureRuleSyntax(); dsrSyntax.initializeSyntax(null); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); dsrSyntax = new DITStructureRuleSyntax(); dsrSyntax.initializeSyntax(null); } AttributeType dsrAttrType = schema.getAttributeType(ATTR_DIT_STRUCTURE_RULES_LC); if (dsrAttrType == null) { dsrAttrType = DirectoryServer.getDefaultAttributeType(ATTR_DIT_STRUCTURE_RULES, dsrSyntax); } List dsrList = entry.getAttribute(dsrAttrType); // Get the matching rule uses attribute from the entry. MatchingRuleUseSyntax mruSyntax; try { mruSyntax = (MatchingRuleUseSyntax) schema.getSyntax(SYNTAX_MATCHING_RULE_USE_OID); if (mruSyntax == null) { mruSyntax = new MatchingRuleUseSyntax(); mruSyntax.initializeSyntax(null); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); mruSyntax = new MatchingRuleUseSyntax(); mruSyntax.initializeSyntax(null); } AttributeType mruAttrType = schema.getAttributeType(ATTR_MATCHING_RULE_USE_LC); if (mruAttrType == null) { mruAttrType = DirectoryServer.getDefaultAttributeType(ATTR_MATCHING_RULE_USE, mruSyntax); } List mruList = entry.getAttribute(mruAttrType); // Parse the attribute type definitions if there are any. if (attrList != null) { for (Attribute a : attrList) { for (AttributeValue v : a.getValues()) { // Parse the attribute type. AttributeType attrType; try { attrType = attrTypeSyntax.decodeAttributeType(v.getValue(), schema); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE; String message = getMessage(msgID, schemaFile, v.getStringValue() + ": " + stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // Register it with the schema. We will allow duplicates, with the // later definition overriding any earlier definition, but we want // to trap them and log a warning. try { schema.registerAttributeType(attrType, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CONFLICTING_ATTR_TYPE; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); try { schema.registerAttributeType(attrType, true); } catch (Exception e) { // This should never happen. assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } } } } } // Parse the objectclass definitions if there are any. if (ocList != null) { for (Attribute a : ocList) { for (AttributeValue v : a.getValues()) { // Parse the objectclass. ObjectClass oc; try { oc = ocSyntax.decodeObjectClass(v.getValue(), schema); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_OC; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_OC; String message = getMessage(msgID, schemaFile, v.getStringValue() + ": " + stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // Register it with the schema. We will allow duplicates, with the // later definition overriding any earlier definition, but we want // to trap them and log a warning. try { schema.registerObjectClass(oc, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CONFLICTING_OC; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); try { schema.registerObjectClass(oc, true); } catch (Exception e) { // This should never happen. assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } } } } } // Parse the name form definitions if there are any. if (nfList != null) { for (Attribute a : nfList) { for (AttributeValue v : a.getValues()) { // Parse the name form. NameForm nf; try { nf = nfSyntax.decodeNameForm(v.getValue(), schema); nf.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); nf.setSchemaFile(schemaFile); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM; String message = getMessage(msgID, schemaFile, v.getStringValue() + ": " + stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // Register it with the schema. We will allow duplicates, with the // later definition overriding any earlier definition, but we want // to trap them and log a warning. try { schema.registerNameForm(nf, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CONFLICTING_NAME_FORM; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); try { schema.registerNameForm(nf, true); } catch (Exception e) { // This should never happen. assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } } } } } // Parse the DIT content rule definitions if there are any. if (dcrList != null) { for (Attribute a : dcrList) { for (AttributeValue v : a.getValues()) { // Parse the DIT content rule. DITContentRule dcr; try { dcr = dcrSyntax.decodeDITContentRule(v.getValue(), schema); dcr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); dcr.setSchemaFile(schemaFile); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_DCR; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_DCR; String message = getMessage(msgID, schemaFile, v.getStringValue() + ": " + stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // Register it with the schema. We will allow duplicates, with the // later definition overriding any earlier definition, but we want // to trap them and log a warning. try { schema.registerDITContentRule(dcr, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CONFLICTING_DCR; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); try { schema.registerDITContentRule(dcr, true); } catch (Exception e) { // This should never happen. assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } } } } } // Parse the DIT structure rule definitions if there are any. if (dsrList != null) { for (Attribute a : dsrList) { for (AttributeValue v : a.getValues()) { // Parse the DIT content rule. DITStructureRule dsr; try { dsr = dsrSyntax.decodeDITStructureRule(v.getValue(), schema, false); dsr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); dsr.setSchemaFile(schemaFile); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_DSR; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_DSR; String message = getMessage(msgID, schemaFile, v.getStringValue() + ": " + stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // Register it with the schema. We will allow duplicates, with the // later definition overriding any earlier definition, but we want // to trap them and log a warning. try { schema.registerDITStructureRule(dsr, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CONFLICTING_DSR; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); try { schema.registerDITStructureRule(dsr, true); } catch (Exception e) { // This should never happen. assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } } } } } // Parse the matching rule use definitions if there are any. if (mruList != null) { for (Attribute a : mruList) { for (AttributeValue v : a.getValues()) { // Parse the matching rule use definition. MatchingRuleUse mru; try { mru = mruSyntax.decodeMatchingRuleUse(v.getValue(), schema); mru.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); mru.setSchemaFile(schemaFile); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_MRU; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } catch (Exception e) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); int msgID = MSGID_CONFIG_SCHEMA_CANNOT_PARSE_MRU; String message = getMessage(msgID, schemaFile, v.getStringValue() + ": " + stackTraceToSingleLineString(e)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); continue; } // Register it with the schema. We will allow duplicates, with the // later definition overriding any earlier definition, but we want // to trap them and log a warning. try { schema.registerMatchingRuleUse(mru, false); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "initializeSchemaFromFiles", de); int msgID = MSGID_CONFIG_SCHEMA_CONFLICTING_MRU; String message = getMessage(msgID, schemaFile, de.getErrorMessage()); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); try { schema.registerMatchingRuleUse(mru, true); } catch (Exception e) { // This should never happen. assert debugException(CLASS_NAME, "initializeSchemaFromFiles", e); } } } } } } } /** * Indicates whether the configuration entry that will result from a proposed * modification is acceptable to this change listener. * * @param configEntry The configuration entry that will result from * the requested update. * @param unacceptableReason A buffer to which this method can append a * human-readable message explaining why the * proposed change is not acceptable. * * @return true if the proposed entry contains an acceptable * configuration, or false if it does not. */ public boolean configChangeIsAcceptable(ConfigEntry configEntry, StringBuilder unacceptableReason) { assert debugEnter(CLASS_NAME, "configChangeIsAcceptable", String.valueOf(configEntry), "java.lang.StringBuilder"); // NYI // If we've gotten here then the monitor entry appears to be acceptable. return true; } /** * Attempts to apply a new configuration to this Directory Server component * based on the provided changed entry. * * @param configEntry The configuration entry that containing the updated * configuration for this component. * * @return Information about the result of processing the configuration * change. */ public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) { assert debugEnter(CLASS_NAME, "applyConfigurationChange", String.valueOf(configEntry)); DN configEntryDN = configEntry.getDN(); ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList messages = new ArrayList(); // NYI // If we've gotten here, then there haven't been any changes to anything // that we care about. return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * Indicates whether the configuration entry that will result from a proposed * add is acceptable to this add listener. * * @param configEntry The configuration entry that will result from * the requested add. * @param unacceptableReason A buffer to which this method can append a * human-readable message explaining why the * proposed entry is not acceptable. * * @return true if the proposed entry contains an acceptable * configuration, or false if it does not. */ public boolean configAddIsAcceptable(ConfigEntry configEntry, StringBuilder unacceptableReason) { assert debugEnter(CLASS_NAME, "configAddIsAcceptable", String.valueOf(configEntry), "java.lang.StringBuilder"); // NYI // If we've gotten here then the monitor entry appears to be acceptable. return true; } /** * Attempts to apply a new configuration based on the provided added entry. * * @param configEntry The new configuration entry that contains the * configuration to apply. * * @return Information about the result of processing the configuration * change. */ public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) { assert debugEnter(CLASS_NAME, "applyConfigurationAdd", String.valueOf(configEntry)); DN configEntryDN = configEntry.getDN(); ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList messages = new ArrayList(); // NYI return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * Indicates whether it is acceptable to remove the provided configuration * entry. * * @param configEntry The configuration entry that will be removed * from the configuration. * @param unacceptableReason A buffer to which this method can append a * human-readable message explaining why the * proposed delete is not acceptable. * * @return true if the proposed entry may be removed from the * configuration, or false if not. */ public boolean configDeleteIsAcceptable(ConfigEntry configEntry, StringBuilder unacceptableReason) { assert debugEnter(CLASS_NAME, "configDeleteIsAcceptable", String.valueOf(configEntry), "java.lang.StringBuilder"); // NYI -- Should we allow deletes of elements with this as superior? return true; } /** * Attempts to apply a new configuration based on the provided deleted entry. * * @param configEntry The new configuration entry that has been deleted. * * @return Information about the result of processing the configuration * change. */ public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) { assert debugEnter(CLASS_NAME, "applyConfigurationDelete", String.valueOf(configEntry)); DN configEntryDN = configEntry.getDN(); ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; // NYI return new ConfigChangeResult(resultCode, adminActionRequired); } }