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
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.schema;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.List;
033
034 import org.opends.server.admin.server.ConfigurationChangeListener;
035 import org.opends.server.admin.std.server.DirectoryStringAttributeSyntaxCfg;
036 import org.opends.server.api.ApproximateMatchingRule;
037 import org.opends.server.api.AttributeSyntax;
038 import org.opends.server.api.AttributeValueDecoder;
039 import org.opends.server.api.EqualityMatchingRule;
040 import org.opends.server.api.OrderingMatchingRule;
041 import org.opends.server.api.SubstringMatchingRule;
042 import org.opends.server.config.ConfigException;
043 import org.opends.server.core.DirectoryServer;
044 import org.opends.server.types.AttributeValue;
045 import org.opends.server.types.ByteString;
046 import org.opends.server.types.ConfigChangeResult;
047 import org.opends.server.types.DirectoryException;
048
049
050 import org.opends.server.types.ResultCode;
051
052 import static org.opends.server.loggers.ErrorLogger.*;
053 import static org.opends.messages.SchemaMessages.*;
054
055 import org.opends.messages.MessageBuilder;
056 import static org.opends.server.schema.SchemaConstants.*;
057
058
059 /**
060 * This class defines the directory string attribute syntax, which is simply a
061 * set of UTF-8 characters. By default, they will be treated in a
062 * case-insensitive manner, and equality, ordering, substring, and approximate
063 * matching will be allowed.
064 */
065 public class DirectoryStringSyntax
066 extends AttributeSyntax<DirectoryStringAttributeSyntaxCfg>
067 implements ConfigurationChangeListener<DirectoryStringAttributeSyntaxCfg>
068 {
069 // The default approximate matching rule for this syntax.
070 private ApproximateMatchingRule defaultApproximateMatchingRule;
071
072 // Indicates whether we will allow zero-length values.
073 private boolean allowZeroLengthValues;
074
075 // The reference to the configuration for this directory string syntax.
076 private DirectoryStringAttributeSyntaxCfg currentConfig;
077
078 // The default equality matching rule for this syntax.
079 private EqualityMatchingRule defaultEqualityMatchingRule;
080
081 // The default ordering matching rule for this syntax.
082 private OrderingMatchingRule defaultOrderingMatchingRule;
083
084 // The default substring matching rule for this syntax.
085 private SubstringMatchingRule defaultSubstringMatchingRule;
086
087
088
089 /**
090 * A {@link String} attribute value decoder for this syntax.
091 */
092 public static final AttributeValueDecoder<String> DECODER =
093 new AttributeValueDecoder<String>()
094 {
095 /**
096 * {@inheritDoc}
097 */
098 public String decode(AttributeValue value) throws DirectoryException
099 {
100 // Make sure that the value is valid.
101 value.getNormalizedValue();
102 return value.getStringValue();
103 }
104 };
105
106
107
108 /**
109 * Creates a new instance of this syntax. Note that the only thing that
110 * should be done here is to invoke the default constructor for the
111 * superclass. All initialization should be performed in the
112 * <CODE>initializeSyntax</CODE> method.
113 */
114 public DirectoryStringSyntax()
115 {
116 super();
117 }
118
119
120
121 /**
122 * {@inheritDoc}
123 */
124 public void initializeSyntax(DirectoryStringAttributeSyntaxCfg configuration)
125 throws ConfigException
126 {
127 defaultApproximateMatchingRule =
128 DirectoryServer.getApproximateMatchingRule(AMR_DOUBLE_METAPHONE_OID);
129 if (defaultApproximateMatchingRule == null)
130 {
131 logError(ERR_ATTR_SYNTAX_UNKNOWN_APPROXIMATE_MATCHING_RULE.get(
132 AMR_DOUBLE_METAPHONE_OID, SYNTAX_DIRECTORY_STRING_NAME));
133 }
134
135 defaultEqualityMatchingRule =
136 DirectoryServer.getEqualityMatchingRule(EMR_CASE_IGNORE_OID);
137 if (defaultEqualityMatchingRule == null)
138 {
139 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(
140 EMR_CASE_IGNORE_OID, SYNTAX_DIRECTORY_STRING_NAME));
141 }
142
143 defaultOrderingMatchingRule =
144 DirectoryServer.getOrderingMatchingRule(OMR_CASE_IGNORE_OID);
145 if (defaultOrderingMatchingRule == null)
146 {
147 logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get(
148 OMR_CASE_IGNORE_OID, SYNTAX_DIRECTORY_STRING_NAME));
149 }
150
151 defaultSubstringMatchingRule =
152 DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_OID);
153 if (defaultSubstringMatchingRule == null)
154 {
155 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
156 SMR_CASE_IGNORE_OID, SYNTAX_DIRECTORY_STRING_NAME));
157 }
158
159
160 // This syntax is one of the Directory Server's core syntaxes and therefore
161 // it may be instantiated at times without a configuration entry. If that
162 // is the case, then we'll exit now before doing anything that could require
163 // access to that entry.
164 if (configuration == null)
165 {
166 return;
167 }
168
169 currentConfig = configuration;
170 currentConfig.addDirectoryStringChangeListener(this);
171 allowZeroLengthValues = currentConfig.isAllowZeroLengthValues();
172 }
173
174
175
176 /**
177 * Performs any finalization that may be necessary for this attribute syntax.
178 */
179 public void finalizeSyntax()
180 {
181 currentConfig.removeDirectoryStringChangeListener(this);
182 }
183
184
185
186 /**
187 * Retrieves the common name for this attribute syntax.
188 *
189 * @return The common name for this attribute syntax.
190 */
191 public String getSyntaxName()
192 {
193 return SYNTAX_DIRECTORY_STRING_NAME;
194 }
195
196
197
198 /**
199 * Retrieves the OID for this attribute syntax.
200 *
201 * @return The OID for this attribute syntax.
202 */
203 public String getOID()
204 {
205 return SYNTAX_DIRECTORY_STRING_OID;
206 }
207
208
209
210 /**
211 * Retrieves a description for this attribute syntax.
212 *
213 * @return A description for this attribute syntax.
214 */
215 public String getDescription()
216 {
217 return SYNTAX_DIRECTORY_STRING_DESCRIPTION;
218 }
219
220
221
222 /**
223 * Retrieves the default equality matching rule that will be used for
224 * attributes with this syntax.
225 *
226 * @return The default equality matching rule that will be used for
227 * attributes with this syntax, or <CODE>null</CODE> if equality
228 * matches will not be allowed for this type by default.
229 */
230 public EqualityMatchingRule getEqualityMatchingRule()
231 {
232 return defaultEqualityMatchingRule;
233 }
234
235
236
237 /**
238 * Retrieves the default ordering matching rule that will be used for
239 * attributes with this syntax.
240 *
241 * @return The default ordering matching rule that will be used for
242 * attributes with this syntax, or <CODE>null</CODE> if ordering
243 * matches will not be allowed for this type by default.
244 */
245 public OrderingMatchingRule getOrderingMatchingRule()
246 {
247 return defaultOrderingMatchingRule;
248 }
249
250
251
252 /**
253 * Retrieves the default substring matching rule that will be used for
254 * attributes with this syntax.
255 *
256 * @return The default substring matching rule that will be used for
257 * attributes with this syntax, or <CODE>null</CODE> if substring
258 * matches will not be allowed for this type by default.
259 */
260 public SubstringMatchingRule getSubstringMatchingRule()
261 {
262 return defaultSubstringMatchingRule;
263 }
264
265
266
267 /**
268 * Retrieves the default approximate matching rule that will be used for
269 * attributes with this syntax.
270 *
271 * @return The default approximate matching rule that will be used for
272 * attributes with this syntax, or <CODE>null</CODE> if approximate
273 * matches will not be allowed for this type by default.
274 */
275 public ApproximateMatchingRule getApproximateMatchingRule()
276 {
277 return defaultApproximateMatchingRule;
278 }
279
280
281
282 /**
283 * Indicates whether the provided value is acceptable for use in an attribute
284 * with this syntax. If it is not, then the reason may be appended to the
285 * provided buffer.
286 *
287 * @param value The value for which to make the determination.
288 * @param invalidReason The buffer to which the invalid reason should be
289 * appended.
290 *
291 * @return <CODE>true</CODE> if the provided value is acceptable for use with
292 * this syntax, or <CODE>false</CODE> if not.
293 */
294 public boolean valueIsAcceptable(ByteString value,
295 MessageBuilder invalidReason)
296 {
297 if (allowZeroLengthValues || (value.value().length > 0))
298 {
299 return true;
300 }
301 else
302 {
303 invalidReason.append(
304 ERR_ATTR_SYNTAX_DIRECTORYSTRING_INVALID_ZEROLENGTH_VALUE.get());
305 return false;
306 }
307 }
308
309
310
311 /**
312 * Indicates whether zero-length values will be allowed. This is technically
313 * forbidden by the LDAP specification, but it was allowed in earlier versions
314 * of the server, and the discussion of the directory string syntax in RFC
315 * 2252 does not explicitly state that they are not allowed.
316 *
317 * @return <CODE>true</CODE> if zero-length values should be allowed for
318 * attributes with a directory string syntax, or <CODE>false</CODE>
319 * if not.
320 */
321 public boolean allowZeroLengthValues()
322 {
323 return allowZeroLengthValues;
324 }
325
326
327
328 /**
329 * {@inheritDoc}
330 */
331 public boolean isConfigurationChangeAcceptable(
332 DirectoryStringAttributeSyntaxCfg configuration,
333 List<Message> unacceptableReasons)
334 {
335 // The configuration will always be acceptable.
336 return true;
337 }
338
339
340
341 /**
342 * {@inheritDoc}
343 */
344 public ConfigChangeResult applyConfigurationChange(
345 DirectoryStringAttributeSyntaxCfg configuration)
346 {
347 currentConfig = configuration;
348 allowZeroLengthValues = configuration.isAllowZeroLengthValues();
349
350 return new ConfigChangeResult(ResultCode.SUCCESS, false);
351 }
352 }
353