001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2017 ForgeRock AS. 016 */ 017package org.opends.guitools.controlpanel.util; 018 019import static org.opends.messages.ConfigMessages.*; 020 021import java.io.File; 022import java.io.FileFilter; 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.List; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.forgerock.i18n.LocalizedIllegalArgumentException; 029import org.forgerock.opendj.config.server.ConfigException; 030import org.forgerock.opendj.ldap.ResultCode; 031import org.forgerock.opendj.ldap.schema.AttributeType; 032import org.forgerock.opendj.ldap.schema.MatchingRule; 033import org.forgerock.opendj.ldap.schema.ObjectClass; 034import org.forgerock.opendj.ldap.schema.SchemaBuilder; 035import org.forgerock.opendj.ldap.schema.Syntax; 036import org.opends.server.config.ConfigConstants; 037import org.opends.server.core.DirectoryServer; 038import org.opends.server.core.SchemaConfigManager; 039import org.opends.server.schema.SchemaConstants; 040import org.opends.server.types.DirectoryException; 041import org.opends.server.types.InitializationException; 042import org.opends.server.types.Schema; 043 044import com.forgerock.opendj.util.OperatingSystem; 045 046/** Class used to retrieve the schema from the schema files. */ 047public class SchemaLoader 048{ 049 private Schema schema; 050 private static final String[] ATTRIBUTES_TO_KEEP = { 051 ConfigConstants.ATTR_ATTRIBUTE_TYPES_LC, 052 ConfigConstants.ATTR_OBJECTCLASSES_LC, 053 ConfigConstants.ATTR_NAME_FORMS_LC, 054 ConfigConstants.ATTR_DIT_CONTENT_RULES_LC, 055 ConfigConstants.ATTR_DIT_STRUCTURE_RULES_LC, 056 ConfigConstants.ATTR_MATCHING_RULE_USE_LC }; 057 private static final String[] OBJECTCLASS_TO_KEEP = { SchemaConstants.TOP_OBJECTCLASS_NAME }; 058 059 private final List<ObjectClass> objectclassesToKeep = new ArrayList<>(); 060 private final List<AttributeType> attributesToKeep = new ArrayList<>(); 061 /** List of matching rules to keep in the schema. */ 062 protected final List<MatchingRule> matchingRulesToKeep = new ArrayList<>(); 063 /** List of attribute syntaxes to keep in the schema. */ 064 protected final List<Syntax> syntaxesToKeep = new ArrayList<>(); 065 066 /** Constructor. */ 067 public SchemaLoader() 068 { 069 Schema sc = DirectoryServer.getSchema(); 070 for (String name : OBJECTCLASS_TO_KEEP) 071 { 072 ObjectClass oc = sc.getObjectClass(name); 073 if (!oc.isPlaceHolder()) 074 { 075 objectclassesToKeep.add(oc); 076 } 077 } 078 for (String name : ATTRIBUTES_TO_KEEP) 079 { 080 if (sc.hasAttributeType(name)) 081 { 082 attributesToKeep.add(sc.getAttributeType(name)); 083 } 084 } 085 matchingRulesToKeep.addAll(sc.getMatchingRules()); 086 syntaxesToKeep.addAll(sc.getSyntaxes()); 087 } 088 089 private static String getSchemaDirectoryPath() 090 { 091 File schemaDir = DirectoryServer.getEnvironmentConfig().getSchemaDirectory(); 092 return schemaDir != null ? schemaDir.getAbsolutePath() : null; 093 } 094 095 /** 096 * Reads the schema. 097 * 098 * @throws ConfigException 099 * if an error occurs reading the schema. 100 * @throws InitializationException 101 * if an error occurs trying to find out the schema files. 102 * @throws DirectoryException 103 * if there is an error registering the minimal objectclasses. 104 */ 105 public void readSchema() throws DirectoryException, ConfigException, InitializationException 106 { 107 schema = getBaseSchema(); 108 109 List<String> fileNames; 110 String schemaDirPath = getSchemaDirectoryPath(); 111 try 112 { 113 // Load install directory schema 114 File schemaDir = new File(schemaDirPath); 115 if (schemaDirPath == null || !schemaDir.exists()) 116 { 117 LocalizableMessage message = ERR_CONFIG_SCHEMA_NO_SCHEMA_DIR.get(schemaDirPath); 118 throw new InitializationException(message); 119 } 120 else if (!schemaDir.isDirectory()) 121 { 122 LocalizableMessage message = ERR_CONFIG_SCHEMA_DIR_NOT_DIRECTORY.get(schemaDirPath); 123 throw new InitializationException(message); 124 } 125 FileFilter ldifFilesFilter = new FileFilter() 126 { 127 @Override 128 public boolean accept(File f) 129 { 130 if (f != null) 131 { 132 if (f.isDirectory()) 133 { 134 return true; 135 } 136 return OperatingSystem.isWindows() ? f.getName().toLowerCase().endsWith(".ldif") 137 : f.getName().endsWith(".ldif"); 138 } 139 return false; 140 } 141 }; 142 File[] schemaFiles = schemaDir.listFiles(ldifFilesFilter); 143 fileNames = new ArrayList<>(schemaFiles.length); 144 for (File f : schemaFiles) 145 { 146 if (f.isFile()) 147 { 148 fileNames.add(f.getName()); 149 } 150 } 151 152 Collections.sort(fileNames); 153 } 154 catch (InitializationException ie) 155 { 156 throw ie; 157 } 158 catch (Exception e) 159 { 160 throw new InitializationException(ERR_CONFIG_SCHEMA_CANNOT_LIST_FILES.get(schemaDirPath, e.getMessage()), e); 161 } 162 163 // Iterate through the schema files and read them as an LDIF file containing a single entry. 164 // Then get the attributeTypes and objectClasses attributes from that entry 165 // and parse them to initialize the server schema. 166 for (String schemaFile : fileNames) 167 { 168 SchemaConfigManager.loadSchemaFile(schema, null, schemaFile); 169 } 170 } 171 172 /** 173 * Returns a basic version of the schema. The schema is created and contains 174 * enough definitions for the schema to be loaded. 175 * 176 * @return a basic version of the schema. 177 * @throws DirectoryException 178 * if there is an error registering the minimal objectclasses. 179 */ 180 protected Schema getBaseSchema() throws DirectoryException 181 { 182 try 183 { 184 SchemaBuilder builder = new SchemaBuilder(org.forgerock.opendj.ldap.schema.Schema.getDefaultSchema()); 185 for (Syntax syntax : syntaxesToKeep) 186 { 187 builder.buildSyntax(syntax).addToSchemaOverwrite(); 188 } 189 for (MatchingRule mr : matchingRulesToKeep) 190 { 191 builder.buildMatchingRule(mr).addToSchemaOverwrite(); 192 } 193 for (AttributeType attr : attributesToKeep) 194 { 195 builder.buildAttributeType(attr).addToSchemaOverwrite(); 196 } 197 for (ObjectClass oc : objectclassesToKeep) 198 { 199 builder.buildObjectClass(oc).addToSchemaOverwrite(); 200 } 201 return new Schema(builder.toSchema()); 202 } 203 catch (LocalizedIllegalArgumentException e) 204 { 205 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e); 206 } 207 } 208 209 /** 210 * Returns the schema that was read. 211 * 212 * @return the schema that was read. 213 */ 214 public Schema getSchema() 215 { 216 return schema; 217 } 218}