/* * 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 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2015 ForgeRock AS */ package org.opends.server.core; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.config.server.ConfigException; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ModificationType; import org.forgerock.opendj.ldap.schema.CoreSchema; import org.forgerock.opendj.ldap.schema.SchemaBuilder; import org.forgerock.opendj.ldap.schema.Syntax; import org.opends.server.schema.*; import org.opends.server.types.*; import org.opends.server.util.LDIFReader; import org.opends.server.util.StaticUtils; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.schema.SchemaConstants.*; import static org.opends.server.types.CommonSchemaElements.*; 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 { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** The schema that has been parsed from the server configuration. */ private Schema schema; private final ServerContext serverContext; /** * Creates a new instance of this schema config manager. * * @param serverContext * The server context. */ public SchemaConfigManager(ServerContext serverContext) { this.serverContext = serverContext; 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() { File schemaDir = DirectoryServer.getEnvironmentConfig().getSchemaDirectory(); if (schemaDir != null) { return schemaDir.getAbsolutePath(); } return null; } /** * 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 <CODE>initializeMatchingRules</CODE>, * <CODE>initializeAttributeSyntaxes</CODE>, and * <CODE>initializeAttributeTypesAndObjectClasses</CODE> methods have been * called. * * @return A reference to the schema information that has been read from the * server configuration. */ public Schema 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 { MatchingRuleConfigManager matchingRuleConfigManager = new MatchingRuleConfigManager(); matchingRuleConfigManager.initializeMatchingRules(); } /** * 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 { AttributeSyntaxConfigManager syntaxConfigManager = new AttributeSyntaxConfigManager(serverContext); syntaxConfigManager.initializeAttributeSyntaxes(); } /** * Filter implementation that accepts only ldif files. */ public static class SchemaFileFilter implements FilenameFilter { /** {@inheritDoc} */ @Override public boolean accept(File directory, String filename) { return filename.endsWith(".ldif"); } } /** * Initializes all the attribute type, object class, name form, DIT content * rule, DIT structure rule, and matching rule use definitions by reading the * server schema files. These files will be located in a single directory and * will be processed in lexicographic 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 schema * element initialization to fail. * * @throws InitializationException If a problem occurs while initializing * the schema elements that is not related * to the server configuration. */ public void initializeSchemaFromFiles() throws ConfigException, InitializationException { // 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 schemaInstanceDirPath = getSchemaDirectoryPath(); File schemaInstanceDir = null; try { if (schemaInstanceDirPath != null) { schemaInstanceDir = new File(schemaInstanceDirPath); } } catch (Exception e) { schemaInstanceDir = null; } long oldestModificationTime = -1L; long youngestModificationTime = -1L; String[] fileNames; try { if (schemaInstanceDir == null || ! schemaInstanceDir.exists()) { LocalizableMessage message = ERR_CONFIG_SCHEMA_NO_SCHEMA_DIR.get(schemaInstanceDirPath); throw new InitializationException(message); } if (! schemaInstanceDir.isDirectory()) { LocalizableMessage message = ERR_CONFIG_SCHEMA_DIR_NOT_DIRECTORY.get(schemaInstanceDirPath); throw new InitializationException(message); } FilenameFilter filter = new SchemaFileFilter(); File[] schemaInstanceDirFiles = schemaInstanceDir.listFiles(filter); int fileNumber = schemaInstanceDirFiles.length ; ArrayList<String> fileList = new ArrayList<>(fileNumber); for (File f : schemaInstanceDirFiles) { if (f.isFile()) { fileList.add(f.getName()); } 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) { logger.traceException(ie); throw ie; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = ERR_CONFIG_SCHEMA_CANNOT_LIST_FILES.get( schemaInstanceDirPath, getExceptionMessage(e)); throw new InitializationException(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) { loadSchemaFile(serverContext, schema, schemaFile, false); } } /** * Loads the contents of the specified schema file into the provided schema. * * @param serverContext * The server context. * * @param schema The schema in which the contents of the schema file are * to be loaded. * @param schemaFile The name of the schema file to be loaded into the * provided schema. * * @return A list of the modifications that could be performed in order to * obtain the contents of the file. * * @throws ConfigException If a configuration problem causes the schema * element initialization to fail. * * @throws InitializationException If a problem occurs while initializing * the schema elements that is not related * to the server configuration. */ public static List<Modification> loadSchemaFile(ServerContext serverContext, Schema schema, String schemaFile) throws ConfigException, InitializationException { return loadSchemaFile(serverContext, schema, schemaFile, true); } /** * Loads the contents of the specified schema file into the provided schema. * * @param schema The schema in which the contents of the schema file * are to be loaded. * @param schemaFile The name of the schema file to be loaded into the * provided schema. * @param failOnError If {@code true}, indicates that this method should * throw an exception if certain kinds of errors occur. * If {@code false}, indicates that this method should * log an error message and return without an exception. * This should only be {@code false} when called from * {@code initializeSchemaFromFiles}. * * @return A list of the modifications that could be performed in order to * obtain the contents of the file, or {@code null} if a problem * occurred and {@code failOnError} is {@code false}. * * @throws ConfigException If a configuration problem causes the schema * element initialization to fail. * * @throws InitializationException If a problem occurs while initializing * the schema elements that is not related * to the server configuration. */ private static List<Modification> loadSchemaFile(ServerContext serverContext, Schema schema, String schemaFile, boolean failOnError) throws ConfigException, InitializationException { // Create an LDIF reader to use when reading the files. String schemaDirPath = getSchemaDirectoryPath(); File f = new File(schemaDirPath, schemaFile); LDIFReader reader; try { reader = new LDIFReader(new LDIFImportConfig(f.getAbsolutePath())); } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_OPEN_FILE.get( schemaFile, schemaDirPath, getExceptionMessage(e)); if (failOnError) { throw new ConfigException(message); } else { logger.error(message); return null; } } // 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. reader.close(); return new LinkedList<>(); } } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_READ_LDIF_ENTRY.get( schemaFile, schemaDirPath, getExceptionMessage(e)); if (failOnError) { throw new InitializationException(message, e); } else { logger.error(message); StaticUtils.close(reader); return null; } } // If there are any more entries in the file, then print a warning message. try { Entry e = reader.readEntry(false); if (e != null) { logger.warn(WARN_CONFIG_SCHEMA_MULTIPLE_ENTRIES_IN_FILE, schemaFile, schemaDirPath); } } catch (Exception e) { logger.traceException(e); logger.warn(WARN_CONFIG_SCHEMA_UNPARSEABLE_EXTRA_DATA_IN_FILE, schemaFile, schemaDirPath, getExceptionMessage(e)); } finally { StaticUtils.close(reader); } // Get the attributeTypes attribute from the entry. List<Modification> mods = new LinkedList<>(); //parse the syntaxes first because attributes rely on these. List<Attribute> ldapSyntaxList = getLdapSyntaxesAttributes(schema, entry, mods); List<Attribute> attrList = getAttributeTypeAttributes(schema, entry, mods); List<Attribute> ocList = getObjectClassesAttributes(schema, entry, mods); List<Attribute> nfList = getNameFormsAttributes(schema, entry, mods); List<Attribute> dcrList = getDITContentRulesAttributes(schema, entry, mods); List<Attribute> dsrList = getDITStructureRulesAttributes(schema, entry, mods); List<Attribute> mruList = getMatchingRuleUsesAttributes(schema, entry, mods); // Loop on all the attribute of the schema entry to // find the extra attribute that should be loaded in the Schema. for (Attribute attribute : entry.getAttributes()) { if (!isSchemaAttribute(attribute)) { schema.addExtraAttribute(attribute.getName(), attribute); } } parseLdapSyntaxesDefinitions(serverContext, schema, schemaFile, failOnError, ldapSyntaxList); parseAttributeTypeDefinitions(schema, schemaFile, failOnError, attrList); parseObjectclassDefinitions(schema, schemaFile, failOnError, ocList); parseNameFormDefinitions(schema, schemaFile, failOnError, nfList); parseDITContentRuleDefinitions(schema, schemaFile, failOnError, dcrList); parseDITStructureRuleDefinitions(schema, schemaFile, failOnError, dsrList); parseMatchingRuleUseDefinitions(schema, schemaFile, failOnError, mruList); return mods; } private static List<Attribute> getLdapSyntaxesAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException { Syntax syntax = schema.getSyntax(SYNTAX_LDAP_SYNTAX_OID); if (syntax == null) { syntax = CoreSchema.getLDAPSyntaxDescriptionSyntax(); } AttributeType ldapSyntaxAttrType = getAttributeType(schema, ATTR_LDAP_SYNTAXES, ATTR_LDAP_SYNTAXES_LC, syntax); return createAddModifications(entry, mods, ldapSyntaxAttrType); } private static List<Attribute> getAttributeTypeAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException, InitializationException { Syntax syntax = schema.getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID); if (syntax == null) { syntax = CoreSchema.getAttributeTypeDescriptionSyntax(); } AttributeType attributeAttrType = getAttributeType( schema, ATTR_ATTRIBUTE_TYPES, ATTR_ATTRIBUTE_TYPES_LC, syntax); return createAddModifications(entry, mods, attributeAttrType); } /** Get the objectClasses attribute from the entry. */ private static List<Attribute> getObjectClassesAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException, InitializationException { Syntax syntax = schema.getSyntax(SYNTAX_OBJECTCLASS_OID); if (syntax == null) { syntax = CoreSchema.getObjectClassDescriptionSyntax(); } AttributeType objectclassAttrType = getAttributeType(schema, ATTR_OBJECTCLASSES, ATTR_OBJECTCLASSES_LC, syntax); return createAddModifications(entry, mods, objectclassAttrType); } /** Get the name forms attribute from the entry. */ private static List<Attribute> getNameFormsAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException, InitializationException { Syntax syntax = schema.getSyntax(SYNTAX_NAME_FORM_OID); if (syntax == null) { syntax = CoreSchema.getNameFormDescriptionSyntax(); } AttributeType nameFormAttrType = getAttributeType( schema, ATTR_NAME_FORMS, ATTR_NAME_FORMS_LC, syntax); return createAddModifications(entry, mods, nameFormAttrType); } /** Get the DIT content rules attribute from the entry. */ private static List<Attribute> getDITContentRulesAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException, InitializationException { Syntax syntax = schema.getSyntax(SYNTAX_DIT_CONTENT_RULE_OID); if (syntax == null) { syntax = CoreSchema.getDITContentRuleDescriptionSyntax(); } AttributeType dcrAttrType = getAttributeType( schema, ATTR_DIT_CONTENT_RULES, ATTR_DIT_CONTENT_RULES_LC, syntax); return createAddModifications(entry, mods, dcrAttrType); } /** Get the DIT structure rules attribute from the entry. */ private static List<Attribute> getDITStructureRulesAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException, InitializationException { Syntax syntax = schema.getSyntax(SYNTAX_DIT_STRUCTURE_RULE_OID); if (syntax == null) { syntax = CoreSchema.getDITStructureRuleDescriptionSyntax(); } AttributeType dsrAttrType = getAttributeType(schema, ATTR_DIT_STRUCTURE_RULES, ATTR_DIT_STRUCTURE_RULES_LC, syntax); return createAddModifications(entry, mods, dsrAttrType); } /** Get the matching rule uses attribute from the entry. */ private static List<Attribute> getMatchingRuleUsesAttributes(Schema schema, Entry entry, List<Modification> mods) throws ConfigException, InitializationException { Syntax syntax = schema.getSyntax(SYNTAX_MATCHING_RULE_USE_OID); if (syntax == null) { syntax = CoreSchema.getMatchingRuleUseDescriptionSyntax(); } AttributeType mruAttrType = getAttributeType(schema, ATTR_MATCHING_RULE_USE, ATTR_MATCHING_RULE_USE_LC, syntax); return createAddModifications(entry, mods, mruAttrType); } private static AttributeType getAttributeType(Schema schema, String attrName, String attrLowerName, Syntax syntax) { final AttributeType attrType = schema.getAttributeType(attrLowerName); if (attrType != null) { return attrType; } return DirectoryServer.getDefaultAttributeType(attrName, syntax); } private static List<Attribute> createAddModifications(Entry entry, List<Modification> mods, AttributeType attrType) { List<Attribute> attributes = entry.getAttribute(attrType); if (attributes != null && !attributes.isEmpty()) { for (Attribute a : attributes) { mods.add(new Modification(ModificationType.ADD, a)); } } return attributes; } /** Parse the ldapsyntaxes definitions if there are any. */ private static void parseLdapSyntaxesDefinitions(ServerContext serverContext, Schema schema, String schemaFile, boolean failOnError, List<Attribute> ldapSyntaxList) throws ConfigException { if (ldapSyntaxList != null) { for (Attribute a : ldapSyntaxList) { for (ByteString v : a) { LDAPSyntaxDescription syntaxDescription; try { syntaxDescription = LDAPSyntaxDescriptionSyntax.decodeLDAPSyntax(v, serverContext, schema, false, false); setExtraProperty(syntaxDescription, SCHEMA_PROPERTY_FILENAME, null); setSchemaFile(syntaxDescription, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_LDAP_SYNTAX.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_LDAP_SYNTAX.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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.registerLdapSyntaxDescription(syntaxDescription, failOnError); registerLdapSyntaxInSchemaNG(serverContext, syntaxDescription, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_LDAP_SYNTAX, schemaFile, de.getMessageObject()); try { schema.registerLdapSyntaxDescription(syntaxDescription, true); registerLdapSyntaxInSchemaNG(serverContext, syntaxDescription, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } private static void registerLdapSyntaxInSchemaNG(ServerContext serverContext, LDAPSyntaxDescription syntaxDescription, boolean overwrite) { // The server context may be null when this code is reached through non-server code (e.g. gui tools) if (serverContext != null) { SchemaUpdater schemaUpdater = serverContext.getSchemaUpdater(); Syntax.Builder builder = schemaUpdater.getSchemaBuilder().buildSyntax(syntaxDescription.getSyntax()); SchemaBuilder schemaBuilder = overwrite ? builder.addToSchemaOverwrite() : builder.addToSchema(); schemaUpdater.updateSchema(schemaBuilder.toSchema()); } } /** Parse the attribute type definitions if there are any. */ private static void parseAttributeTypeDefinitions(Schema schema, String schemaFile, boolean failOnError, List<Attribute> attrList) throws ConfigException { if (attrList != null) { for (Attribute a : attrList) { for (ByteString v : a) { // Parse the attribute type. AttributeType attrType; try { attrType = AttributeTypeSyntax.decodeAttributeType(v, schema, false); setExtraProperty(attrType, SCHEMA_PROPERTY_FILENAME, null); setSchemaFile(attrType, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_ATTR_TYPE, schemaFile, de.getMessageObject()); try { schema.registerAttributeType(attrType, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } /** Parse the objectclass definitions if there are any. */ private static void parseObjectclassDefinitions(Schema schema, String schemaFile, boolean failOnError, List<Attribute> ocList) throws ConfigException { if (ocList != null) { for (Attribute a : ocList) { for (ByteString v : a) { // Parse the objectclass. ObjectClass oc; try { oc = ObjectClassSyntax.decodeObjectClass(v, schema, false); setExtraProperty(oc, SCHEMA_PROPERTY_FILENAME, null); setSchemaFile(oc, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_OC, schemaFile, de.getMessageObject()); try { schema.registerObjectClass(oc, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } /** Parse the name form definitions if there are any. */ private static void parseNameFormDefinitions(Schema schema, String schemaFile, boolean failOnError, List<Attribute> nfList) throws ConfigException { if (nfList != null) { for (Attribute a : nfList) { for (ByteString v : a) { // Parse the name form. NameForm nf; try { nf = NameFormSyntax.decodeNameForm(v, schema, false); nf.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); setSchemaFile(nf, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_NAME_FORM, schemaFile, de.getMessageObject()); try { schema.registerNameForm(nf, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } /** Parse the DIT content rule definitions if there are any. */ private static void parseDITContentRuleDefinitions(Schema schema, String schemaFile, boolean failOnError, List<Attribute> dcrList) throws ConfigException { if (dcrList != null) { for (Attribute a : dcrList) { for (ByteString v : a) { // Parse the DIT content rule. DITContentRule dcr; try { dcr = DITContentRuleSyntax.decodeDITContentRule(v, schema, false); dcr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); setSchemaFile(dcr, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_DCR, schemaFile, de.getMessageObject()); try { schema.registerDITContentRule(dcr, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } private static void reportError(boolean failOnError, Exception e, LocalizableMessage message) throws ConfigException { if (failOnError) { throw new ConfigException(message, e); } logger.error(message); } /** Parse the DIT structure rule definitions if there are any. */ private static void parseDITStructureRuleDefinitions(Schema schema, String schemaFile, boolean failOnError, List<Attribute> dsrList) throws ConfigException { if (dsrList != null) { for (Attribute a : dsrList) { for (ByteString v : a) { // Parse the DIT content rule. DITStructureRule dsr; try { dsr = DITStructureRuleSyntax.decodeDITStructureRule(v, schema, false); dsr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); setSchemaFile(dsr, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DSR.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DSR.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_DSR, schemaFile, de.getMessageObject()); try { schema.registerDITStructureRule(dsr, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } /** Parse the matching rule use definitions if there are any. */ private static void parseMatchingRuleUseDefinitions(Schema schema, String schemaFile, boolean failOnError, List<Attribute> mruList) throws ConfigException { if (mruList != null) { for (Attribute a : mruList) { for (ByteString v : a) { // Parse the matching rule use definition. MatchingRuleUse mru; try { mru = MatchingRuleUseSyntax.decodeMatchingRuleUse(v, schema, false); mru.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); setSchemaFile(mru, schemaFile); } catch (DirectoryException de) { logger.traceException(de); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get( schemaFile, de.getMessageObject()); reportError(failOnError, de, message); continue; } catch (Exception e) { logger.traceException(e); LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get( schemaFile, v + ": " + getExceptionMessage(e)); reportError(failOnError, e, message); 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, failOnError); } catch (DirectoryException de) { logger.traceException(de); logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_MRU, schemaFile, de.getMessageObject()); try { schema.registerMatchingRuleUse(mru, true); } catch (Exception e) { // This should never happen. logger.traceException(e); } } } } } } /** * This method checks if a given attribute is an attribute that * is used by the definition of the schema. * * @param attribute The attribute to be checked. * @return true if the attribute is part of the schema definition, * false if the attribute is not part of the schema * definition. */ public static boolean isSchemaAttribute(Attribute attribute) { String attributeOid = attribute.getAttributeType().getOID(); return attributeOid.equals("2.5.21.1") || attributeOid.equals("2.5.21.2") || attributeOid.equals("2.5.21.4") || attributeOid.equals("2.5.21.5") || attributeOid.equals("2.5.21.6") || attributeOid.equals("2.5.21.7") || attributeOid.equals("2.5.21.8") || attributeOid.equals("2.5.4.3") || attributeOid.equals("1.3.6.1.4.1.1466.101.120.16") || attributeOid.equals("cn-oid") || attributeOid.equals("attributetypes-oid") || attributeOid.equals("objectclasses-oid") || attributeOid.equals("matchingrules-oid") || attributeOid.equals("matchingruleuse-oid") || attributeOid.equals("nameformdescription-oid") || attributeOid.equals("ditcontentrules-oid") || attributeOid.equals("ditstructurerules-oid") || attributeOid.equals("ldapsyntaxes-oid"); } }