/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2008-2010 Sun Microsystems, Inc. * Portions Copyright 2013-2016 ForgeRock AS. */ package org.opends.guitools.controlpanel.util; import static org.opends.messages.ConfigMessages.*; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.LocalizedIllegalArgumentException; import org.forgerock.opendj.config.server.ConfigException; import org.forgerock.opendj.ldap.ResultCode; import org.forgerock.opendj.ldap.schema.AttributeType; import org.forgerock.opendj.ldap.schema.MatchingRule; import org.forgerock.opendj.ldap.schema.SchemaBuilder; import org.forgerock.opendj.ldap.schema.Syntax; import org.opends.server.config.ConfigConstants; import org.opends.server.core.DirectoryServer; import org.opends.server.core.SchemaConfigManager; import org.opends.server.schema.SchemaConstants; import org.opends.server.types.DirectoryException; import org.opends.server.types.InitializationException; import org.opends.server.types.ObjectClass; import org.opends.server.types.Schema; import com.forgerock.opendj.util.OperatingSystem; /** Class used to retrieve the schema from the schema files. */ public class SchemaLoader { private Schema schema; private static final String[] ATTRIBUTES_TO_KEEP = { ConfigConstants.ATTR_ATTRIBUTE_TYPES_LC, ConfigConstants.ATTR_OBJECTCLASSES_LC, ConfigConstants.ATTR_NAME_FORMS_LC, ConfigConstants.ATTR_DIT_CONTENT_RULES_LC, ConfigConstants.ATTR_DIT_STRUCTURE_RULES_LC, ConfigConstants.ATTR_MATCHING_RULE_USE_LC }; private static final String[] OBJECTCLASS_TO_KEEP = { SchemaConstants.TOP_OBJECTCLASS_NAME }; private final List objectclassesToKeep = new ArrayList<>(); private final List attributesToKeep = new ArrayList<>(); /** List of matching rules to keep in the schema. */ protected final List matchingRulesToKeep = new ArrayList<>(); /** List of attribute syntaxes to keep in the schema. */ protected final List syntaxesToKeep = new ArrayList<>(); /** Constructor. */ public SchemaLoader() { Schema sc = DirectoryServer.getSchema(); for (String name : OBJECTCLASS_TO_KEEP) { ObjectClass oc = sc.getObjectClass(name.toLowerCase()); if (oc != null) { objectclassesToKeep.add(oc); } } for (String name : ATTRIBUTES_TO_KEEP) { if (sc.hasAttributeType(name)) { attributesToKeep.add(sc.getAttributeType(name)); } } matchingRulesToKeep.addAll(sc.getMatchingRules()); syntaxesToKeep.addAll(sc.getSyntaxes()); } private static String getSchemaDirectoryPath() { File schemaDir = DirectoryServer.getEnvironmentConfig().getSchemaDirectory(); return schemaDir != null ? schemaDir.getAbsolutePath() : null; } /** * Reads the schema. * * @throws ConfigException * if an error occurs reading the schema. * @throws InitializationException * if an error occurs trying to find out the schema files. * @throws DirectoryException * if there is an error registering the minimal objectclasses. */ public void readSchema() throws DirectoryException, ConfigException, InitializationException { schema = getBaseSchema(); String[] fileNames; String schemaDirPath = getSchemaDirectoryPath(); try { // Load install directory schema File schemaDir = new File(schemaDirPath); if (schemaDirPath == null || !schemaDir.exists()) { LocalizableMessage message = ERR_CONFIG_SCHEMA_NO_SCHEMA_DIR.get(schemaDirPath); throw new InitializationException(message); } else if (!schemaDir.isDirectory()) { LocalizableMessage message = ERR_CONFIG_SCHEMA_DIR_NOT_DIRECTORY.get(schemaDirPath); throw new InitializationException(message); } FileFilter ldifFilesFilter = new FileFilter() { @Override public boolean accept(File f) { if (f != null) { if (f.isDirectory()) { return true; } return OperatingSystem.isWindows() ? f.getName().toLowerCase().endsWith(".ldif") : f.getName().endsWith(".ldif"); } return false; } }; File[] schemaFiles = schemaDir.listFiles(ldifFilesFilter); List fileList = new ArrayList<>(schemaFiles.length); for (File f : schemaFiles) { if (f.isFile()) { fileList.add(f.getName()); } } fileNames = new String[fileList.size()]; fileList.toArray(fileNames); Arrays.sort(fileNames); } catch (InitializationException ie) { throw ie; } catch (Exception e) { throw new InitializationException(ERR_CONFIG_SCHEMA_CANNOT_LIST_FILES.get(schemaDirPath, e.getMessage()), e); } // 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) { SchemaConfigManager.loadSchemaFile(schema, schemaFile); } } /** * Returns a basic version of the schema. The schema is created and contains * enough definitions for the schema to be loaded. * * @return a basic version of the schema. * @throws DirectoryException * if there is an error registering the minimal objectclasses. */ protected Schema getBaseSchema() throws DirectoryException { try { SchemaBuilder builder = new SchemaBuilder(org.forgerock.opendj.ldap.schema.Schema.getDefaultSchema()); for (Syntax syntax : syntaxesToKeep) { builder.buildSyntax(syntax).addToSchemaOverwrite(); } for (MatchingRule mr : matchingRulesToKeep) { builder.buildMatchingRule(mr).addToSchemaOverwrite(); } for (AttributeType attr : attributesToKeep) { builder.buildAttributeType(attr).addToSchemaOverwrite(); } Schema schema = new Schema(builder.toSchema()); for (ObjectClass oc : objectclassesToKeep) { schema.registerObjectClass(oc, true); } return schema; } catch (LocalizedIllegalArgumentException e) { throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e); } } /** * Returns the schema that was read. * * @return the schema that was read. */ public Schema getSchema() { return schema; } }