001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2014 ForgeRock AS. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.server.schema; 028 029import static org.forgerock.opendj.ldap.schema.SchemaOptions.*; 030 031import java.util.List; 032 033import org.forgerock.i18n.LocalizableMessage; 034import org.forgerock.opendj.config.server.ConfigChangeResult; 035import org.forgerock.opendj.config.server.ConfigException; 036import org.forgerock.opendj.config.server.ConfigurationChangeListener; 037import org.forgerock.opendj.ldap.ResultCode; 038import org.forgerock.opendj.ldap.schema.SchemaBuilder; 039import org.forgerock.opendj.server.config.server.CoreSchemaCfg; 040import org.opends.server.types.InitializationException; 041 042/** 043 * Provides the core schema, which includes core matching rules and syntaxes. 044 */ 045public class CoreSchemaProvider implements SchemaProvider<CoreSchemaCfg>, 046 ConfigurationChangeListener<CoreSchemaCfg> 047{ 048 private static final String NONE_ELEMENT = "NONE"; 049 050 /** The current configuration of core schema. */ 051 private CoreSchemaCfg currentConfig; 052 053 /** The current schema builder. */ 054 private SchemaBuilder currentSchemaBuilder; 055 056 /** Updater to notify schema update when configuration changes. */ 057 private SchemaUpdater schemaUpdater; 058 059 /** {@inheritDoc} */ 060 @Override 061 public void initialize(final CoreSchemaCfg configuration, final SchemaBuilder initialSchemaBuilder, 062 final SchemaUpdater schemaUpdater) throws ConfigException, InitializationException 063 { 064 this.currentConfig = configuration; 065 this.currentSchemaBuilder = initialSchemaBuilder; 066 this.schemaUpdater = schemaUpdater; 067 068 updateSchemaFromConfiguration(initialSchemaBuilder, configuration); 069 070 currentConfig.addCoreSchemaChangeListener(this); 071 } 072 073 /** 074 * Update the provided schema builder with the provided configuration. 075 * 076 * @param schemaBuilder 077 * The schema builder to update. 078 * @param configuration 079 * The configuration to use for update. 080 */ 081 private void updateSchemaFromConfiguration(final SchemaBuilder schemaBuilder, final CoreSchemaCfg configuration) 082 { 083 schemaBuilder 084 .setOption(ALLOW_ZERO_LENGTH_DIRECTORY_STRINGS, configuration.isAllowZeroLengthValuesDirectoryString()) 085 .setOption(STRICT_FORMAT_FOR_COUNTRY_STRINGS, configuration.isStrictFormatCountryString()) 086 .setOption(STRIP_UPPER_BOUND_FOR_ATTRIBUTE_TYPE, 087 configuration.isStripSyntaxMinUpperBoundAttributeTypeDescription()); 088 // TODO : add the missing methods in schema builder for those properties 089 // schemaBuilder.allowMalformedJPEGPhotos(configuration.) 090 // schemaBuilder.allowMalformedNamesAndOptions(configuration.) 091 // ... 092 093 for (final String oid : configuration.getDisabledMatchingRule()) 094 { 095 if (!oid.equals(NONE_ELEMENT)) 096 { 097 schemaBuilder.removeMatchingRule(oid); 098 } 099 } 100 101 for (final String oid : configuration.getDisabledSyntax()) 102 { 103 if (!oid.equals(NONE_ELEMENT)) 104 { 105 schemaBuilder.removeSyntax(oid); 106 } 107 } 108 } 109 110 /** {@inheritDoc} */ 111 @Override 112 public void finalizeProvider() 113 { 114 currentConfig.removeCoreSchemaChangeListener(this); 115 } 116 117 /** {@inheritDoc} */ 118 @Override 119 public boolean isConfigurationAcceptable(final CoreSchemaCfg configuration, 120 final List<LocalizableMessage> unacceptableReasons) 121 { 122 // TODO : check that elements to disable are present in the schema ? 123 return true; 124 } 125 126 /** {@inheritDoc} */ 127 @Override 128 public SchemaBuilder getSchema() 129 { 130 return currentSchemaBuilder; 131 } 132 133 /** {@inheritDoc} */ 134 @Override 135 public boolean isConfigurationChangeAcceptable(final CoreSchemaCfg configuration, 136 final List<LocalizableMessage> unacceptableReasons) 137 { 138 if (!configuration.isEnabled()) 139 { 140 // TODO : fix message 141 unacceptableReasons.add(LocalizableMessage.raw("The core schema must always be enabled")); 142 return false; 143 } 144 // TODO : check that elements to disable are present in the schema ? 145 return true; 146 } 147 148 /** {@inheritDoc} */ 149 @Override 150 public ConfigChangeResult applyConfigurationChange(final CoreSchemaCfg configuration) 151 { 152 currentSchemaBuilder = schemaUpdater.getSchemaBuilder(); 153 154 updateSchemaFromConfiguration(currentSchemaBuilder, configuration); 155 156 final boolean isUpdated = schemaUpdater.updateSchema(currentSchemaBuilder.toSchema()); 157 158 // TODO : fix result code + log an error in case of failure 159 final ConfigChangeResult result = new ConfigChangeResult(); 160 result.setResultCode(isUpdated ? ResultCode.SUCCESS : ResultCode.OTHER); 161 return result; 162 } 163 164}