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 2006-2008 Sun Microsystems, Inc.
025 *      Portions Copyright 2012-2015 ForgeRock AS
026 */
027package org.opends.server.schema;
028import static org.opends.server.schema.SchemaConstants.*;
029
030import java.util.List;
031
032import org.forgerock.i18n.LocalizableMessage;
033import org.forgerock.opendj.config.server.ConfigChangeResult;
034import org.forgerock.opendj.config.server.ConfigException;
035import org.forgerock.opendj.ldap.schema.Schema;
036import org.forgerock.opendj.ldap.schema.SchemaOptions;
037import org.forgerock.opendj.ldap.schema.Syntax;
038import org.forgerock.util.Option;
039import org.opends.server.admin.server.ConfigurationChangeListener;
040import org.opends.server.admin.std.server.DirectoryStringAttributeSyntaxCfg;
041import org.opends.server.api.AttributeSyntax;
042import org.opends.server.core.ServerContext;
043
044
045/**
046 * This class defines the directory string attribute syntax, which is simply a
047 * set of UTF-8 characters.  By default, they will be treated in a
048 * case-insensitive manner, and equality, ordering, substring, and approximate
049 * matching will be allowed.
050 */
051public class DirectoryStringSyntax
052       extends AttributeSyntax<DirectoryStringAttributeSyntaxCfg>
053       implements ConfigurationChangeListener<DirectoryStringAttributeSyntaxCfg>
054{
055
056  /** Indicates whether we will allow zero-length values. */
057  private boolean allowZeroLengthValues;
058
059  /** The reference to the configuration for this directory string syntax. */
060  private DirectoryStringAttributeSyntaxCfg currentConfig;
061
062  private ServerContext serverContext;
063
064  /**
065   * Creates a new instance of this syntax.  Note that the only thing that
066   * should be done here is to invoke the default constructor for the
067   * superclass.  All initialization should be performed in the
068   * <CODE>initializeSyntax</CODE> method.
069   */
070  public DirectoryStringSyntax()
071  {
072    super();
073  }
074
075  /** {@inheritDoc} */
076  @Override
077  public void initializeSyntax(DirectoryStringAttributeSyntaxCfg configuration, ServerContext serverContext)
078         throws ConfigException
079  {
080    this.serverContext = serverContext;
081
082    // This syntax is one of the Directory Server's core syntaxes and therefore
083    // it may be instantiated at times without a configuration entry.  If that
084    // is the case, then we'll exit now before doing anything that could require
085    // access to that entry.
086    if (configuration == null)
087    {
088      return;
089    }
090
091    currentConfig = configuration;
092    currentConfig.addDirectoryStringChangeListener(this);
093    allowZeroLengthValues = currentConfig.isAllowZeroLengthValues();
094    updateNewSchema();
095  }
096
097  /** Update the option in new schema if it changes from current value. */
098  private void updateNewSchema()
099  {
100    Option<Boolean> option = SchemaOptions.ALLOW_ZERO_LENGTH_DIRECTORY_STRINGS;
101    if (allowZeroLengthValues != serverContext.getSchemaNG().getOption(option))
102    {
103      SchemaUpdater schemaUpdater = serverContext.getSchemaUpdater();
104      schemaUpdater.updateSchema(
105          schemaUpdater.getSchemaBuilder().setOption(option, allowZeroLengthValues).toSchema());
106    }
107  }
108
109  /** {@inheritDoc} */
110  @Override
111  public Syntax getSDKSyntax(Schema schema)
112  {
113    return schema.getSyntax(SchemaConstants.SYNTAX_DIRECTORY_STRING_OID);
114  }
115
116  /**
117   * Performs any finalization that may be necessary for this attribute syntax.
118   */
119  @Override
120  public void finalizeSyntax()
121  {
122    currentConfig.removeDirectoryStringChangeListener(this);
123  }
124
125  /**
126   * Retrieves the common name for this attribute syntax.
127   *
128   * @return  The common name for this attribute syntax.
129   */
130  @Override
131  public String getName()
132  {
133    return SYNTAX_DIRECTORY_STRING_NAME;
134  }
135
136  /**
137   * Retrieves the OID for this attribute syntax.
138   *
139   * @return  The OID for this attribute syntax.
140   */
141  @Override
142  public String getOID()
143  {
144    return SYNTAX_DIRECTORY_STRING_OID;
145  }
146
147  /**
148   * Retrieves a description for this attribute syntax.
149   *
150   * @return  A description for this attribute syntax.
151   */
152  @Override
153  public String getDescription()
154  {
155    return SYNTAX_DIRECTORY_STRING_DESCRIPTION;
156  }
157
158  /**
159   * Indicates whether zero-length values will be allowed.  This is technically
160   * forbidden by the LDAP specification, but it was allowed in earlier versions
161   * of the server, and the discussion of the directory string syntax in RFC
162   * 2252 does not explicitly state that they are not allowed.
163   *
164   * @return  <CODE>true</CODE> if zero-length values should be allowed for
165   *          attributes with a directory string syntax, or <CODE>false</CODE>
166   *          if not.
167   */
168  public boolean allowZeroLengthValues()
169  {
170    return allowZeroLengthValues;
171  }
172
173  /** {@inheritDoc} */
174  @Override
175  public boolean isConfigurationChangeAcceptable(
176                      DirectoryStringAttributeSyntaxCfg configuration,
177                      List<LocalizableMessage> unacceptableReasons)
178  {
179    // The configuration will always be acceptable.
180    return true;
181  }
182
183  /** {@inheritDoc} */
184  @Override
185  public ConfigChangeResult applyConfigurationChange(
186              DirectoryStringAttributeSyntaxCfg configuration)
187  {
188    currentConfig = configuration;
189    allowZeroLengthValues = configuration.isAllowZeroLengthValues();
190    updateNewSchema();
191
192    return new ConfigChangeResult();
193  }
194}
195