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-2016 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.Arrays; 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.SchemaBuilder; 034import org.forgerock.opendj.ldap.schema.Syntax; 035import org.opends.server.config.ConfigConstants; 036import org.opends.server.core.DirectoryServer; 037import org.opends.server.core.SchemaConfigManager; 038import org.opends.server.schema.SchemaConstants; 039import org.opends.server.types.DirectoryException; 040import org.opends.server.types.InitializationException; 041import org.opends.server.types.ObjectClass; 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.toLowerCase()); 073 if (oc != null) 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 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 List<String> fileList = new ArrayList<>(schemaFiles.length); 144 for (File f : schemaFiles) 145 { 146 if (f.isFile()) 147 { 148 fileList.add(f.getName()); 149 } 150 } 151 152 fileNames = new String[fileList.size()]; 153 fileList.toArray(fileNames); 154 Arrays.sort(fileNames); 155 } 156 catch (InitializationException ie) 157 { 158 throw ie; 159 } 160 catch (Exception e) 161 { 162 throw new InitializationException(ERR_CONFIG_SCHEMA_CANNOT_LIST_FILES.get(schemaDirPath, e.getMessage()), e); 163 } 164 165 // Iterate through the schema files and read them as an LDIF file 166 // containing a single entry. Then get the attributeTypes and 167 // objectClasses attributes from that entry and parse them to 168 // initialize the server schema. 169 for (String schemaFile : fileNames) 170 { 171 SchemaConfigManager.loadSchemaFile(schema, schemaFile); 172 } 173 } 174 175 /** 176 * Returns a basic version of the schema. The schema is created and contains 177 * enough definitions for the schema to be loaded. 178 * 179 * @return a basic version of the schema. 180 * @throws DirectoryException 181 * if there is an error registering the minimal objectclasses. 182 */ 183 protected Schema getBaseSchema() throws DirectoryException 184 { 185 try 186 { 187 SchemaBuilder builder = new SchemaBuilder(org.forgerock.opendj.ldap.schema.Schema.getDefaultSchema()); 188 for (Syntax syntax : syntaxesToKeep) 189 { 190 builder.buildSyntax(syntax).addToSchemaOverwrite(); 191 } 192 for (MatchingRule mr : matchingRulesToKeep) 193 { 194 builder.buildMatchingRule(mr).addToSchemaOverwrite(); 195 } 196 for (AttributeType attr : attributesToKeep) 197 { 198 builder.buildAttributeType(attr).addToSchemaOverwrite(); 199 } 200 Schema schema = new Schema(builder.toSchema()); 201 for (ObjectClass oc : objectclassesToKeep) 202 { 203 schema.registerObjectClass(oc, true); 204 } 205 return schema; 206 } 207 catch (LocalizedIllegalArgumentException e) 208 { 209 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e); 210 } 211 } 212 213 /** 214 * Returns the schema that was read. 215 * 216 * @return the schema that was read. 217 */ 218 public Schema getSchema() 219 { 220 return schema; 221 } 222}