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 2014-2016 ForgeRock AS.
015 */
016package org.opends.server.schema;
017
018import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
019
020import java.util.List;
021
022import org.forgerock.i18n.LocalizableMessage;
023import org.forgerock.opendj.config.server.ConfigChangeResult;
024import org.forgerock.opendj.config.server.ConfigException;
025import org.forgerock.opendj.config.server.ConfigurationChangeListener;
026import org.forgerock.opendj.ldap.schema.Schema;
027import org.forgerock.opendj.ldap.schema.SchemaBuilder;
028import org.forgerock.opendj.server.config.server.CoreSchemaCfg;
029import org.opends.server.core.DirectoryServer;
030import org.opends.server.core.ServerContext;
031import org.opends.server.types.DirectoryException;
032import org.opends.server.types.InitializationException;
033import org.opends.server.types.Schema.SchemaUpdater;
034
035/** Provides the core schema, which includes core matching rules and syntaxes. */
036public class CoreSchemaProvider implements SchemaProvider<CoreSchemaCfg>,
037  ConfigurationChangeListener<CoreSchemaCfg>
038{
039  private static final String NONE_ELEMENT = "NONE";
040
041  /** The current configuration of core schema. */
042  private CoreSchemaCfg currentConfig;
043  private ServerContext serverContext;
044
045  @Override
046  public void initialize(final ServerContext serverContext, final CoreSchemaCfg configuration,
047      final SchemaBuilder initialSchemaBuilder) throws ConfigException, InitializationException
048  {
049    this.serverContext = serverContext;
050    this.currentConfig = configuration;
051
052    updateSchemaFromConfiguration(initialSchemaBuilder, configuration);
053
054    currentConfig.addCoreSchemaChangeListener(this);
055  }
056
057  /**
058   * Update the provided schema builder with the provided configuration.
059   *
060   * @param schemaBuilder
061   *          The schema builder to update.
062   * @param configuration
063   *          The configuration to use for update.
064   */
065  private void updateSchemaFromConfiguration(final SchemaBuilder schemaBuilder, final CoreSchemaCfg configuration)
066  {
067    schemaBuilder
068      .setOption(ALLOW_ZERO_LENGTH_DIRECTORY_STRINGS, configuration.isAllowZeroLengthValuesDirectoryString())
069      .setOption(STRICT_FORMAT_FOR_COUNTRY_STRINGS, configuration.isStrictFormatCountryString())
070      .setOption(STRIP_UPPER_BOUND_FOR_ATTRIBUTE_TYPE,
071          configuration.isStripSyntaxMinUpperBoundAttributeTypeDescription());
072    // TODO : add the missing methods in schema builder for those properties
073    // schemaBuilder.allowMalformedJPEGPhotos(configuration.)
074    // schemaBuilder.allowMalformedNamesAndOptions(configuration.)
075    // ...
076
077    for (final String oid : configuration.getDisabledMatchingRule())
078    {
079      if (!oid.equals(NONE_ELEMENT))
080      {
081        schemaBuilder.removeMatchingRule(oid);
082      }
083    }
084
085    for (final String oid : configuration.getDisabledSyntax())
086    {
087      if (!oid.equals(NONE_ELEMENT))
088      {
089        schemaBuilder.removeSyntax(oid);
090      }
091    }
092  }
093
094  @Override
095  public void finalizeProvider()
096  {
097    currentConfig.removeCoreSchemaChangeListener(this);
098  }
099
100  @Override
101  public boolean isConfigurationAcceptable(final CoreSchemaCfg configuration,
102      final List<LocalizableMessage> unacceptableReasons)
103  {
104    // TODO : check that elements to disable are present in the schema ?
105    return true;
106  }
107
108  @Override
109  public boolean isConfigurationChangeAcceptable(final CoreSchemaCfg configuration,
110      final List<LocalizableMessage> unacceptableReasons)
111  {
112    if (!configuration.isEnabled())
113    {
114      // TODO : fix message
115      unacceptableReasons.add(LocalizableMessage.raw("The core schema must always be enabled"));
116      return false;
117    }
118    // TODO : check that elements to disable are present in the schema ?
119    return true;
120  }
121
122  @Override
123  public ConfigChangeResult applyConfigurationChange(final CoreSchemaCfg configuration)
124  {
125    final ConfigChangeResult ccr = new ConfigChangeResult();
126    // TODO : the server schema should probably be renamed to something like ServerSchema
127    // Even after migration to SDK schema, it will be probably be kept
128    try
129    {
130      serverContext.getSchema().updateSchema(new SchemaUpdater()
131      {
132        @Override
133        public Schema update(SchemaBuilder builder)
134        {
135          updateSchemaFromConfiguration(builder, configuration);
136          return builder.toSchema();
137        }
138      });
139    }
140    catch (DirectoryException e)
141    {
142      ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
143      ccr.addMessage(e.getMessageObject());
144    }
145    return ccr;
146  }
147}