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
029
030
031 import org.opends.server.admin.std.server.AttributeSyntaxCfg;
032 import org.opends.server.api.ApproximateMatchingRule;
033 import org.opends.server.api.AttributeSyntax;
034 import org.opends.server.api.EqualityMatchingRule;
035 import org.opends.server.api.OrderingMatchingRule;
036 import org.opends.server.api.SubstringMatchingRule;
037 import org.opends.server.config.ConfigException;
038 import org.opends.server.core.DirectoryServer;
039 import org.opends.server.types.ByteString;
040 import org.opends.server.types.DN;
041
042
043
044 import static org.opends.server.loggers.debug.DebugLogger.*;
045 import org.opends.server.loggers.debug.DebugTracer;
046 import static org.opends.server.loggers.ErrorLogger.*;
047 import org.opends.server.types.DebugLogLevel;
048 import static org.opends.messages.SchemaMessages.*;
049 import org.opends.messages.MessageBuilder;
050 import static org.opends.server.schema.SchemaConstants.*;
051 import static org.opends.server.util.StaticUtils.*;
052
053
054 /**
055 * This class implements the name and optional UID attribute syntax, which holds
056 * values consisting of a DN, optionally followed by an octothorpe (#) and a bit
057 * string value.
058 */
059 public class NameAndOptionalUIDSyntax
060 extends AttributeSyntax<AttributeSyntaxCfg>
061 {
062 /**
063 * The tracer object for the debug logger.
064 */
065 private static final DebugTracer TRACER = getTracer();
066
067
068
069 // The default equality matching rule for this syntax.
070 private EqualityMatchingRule defaultEqualityMatchingRule;
071
072 // The default substring matching rule for this syntax.
073 private SubstringMatchingRule defaultSubstringMatchingRule;
074
075
076
077 /**
078 * Creates a new instance of this syntax. Note that the only thing that
079 * should be done here is to invoke the default constructor for the
080 * superclass. All initialization should be performed in the
081 * <CODE>initializeSyntax</CODE> method.
082 */
083 public NameAndOptionalUIDSyntax()
084 {
085 super();
086 }
087
088
089
090 /**
091 * {@inheritDoc}
092 */
093 public void initializeSyntax(AttributeSyntaxCfg configuration)
094 throws ConfigException
095 {
096 defaultEqualityMatchingRule =
097 DirectoryServer.getEqualityMatchingRule(EMR_UNIQUE_MEMBER_OID);
098 if (defaultEqualityMatchingRule == null)
099 {
100 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(
101 EMR_UNIQUE_MEMBER_OID, SYNTAX_NAME_AND_OPTIONAL_UID_NAME));
102 }
103
104 defaultSubstringMatchingRule =
105 DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_OID);
106 if (defaultSubstringMatchingRule == null)
107 {
108 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
109 SMR_CASE_IGNORE_OID, SYNTAX_NAME_AND_OPTIONAL_UID_NAME));
110 }
111 }
112
113
114
115 /**
116 * Retrieves the common name for this attribute syntax.
117 *
118 * @return The common name for this attribute syntax.
119 */
120 public String getSyntaxName()
121 {
122 return SYNTAX_NAME_AND_OPTIONAL_UID_NAME;
123 }
124
125
126
127 /**
128 * Retrieves the OID for this attribute syntax.
129 *
130 * @return The OID for this attribute syntax.
131 */
132 public String getOID()
133 {
134 return SYNTAX_NAME_AND_OPTIONAL_UID_OID;
135 }
136
137
138
139 /**
140 * Retrieves a description for this attribute syntax.
141 *
142 * @return A description for this attribute syntax.
143 */
144 public String getDescription()
145 {
146 return SYNTAX_NAME_AND_OPTIONAL_UID_DESCRIPTION;
147 }
148
149
150
151 /**
152 * Retrieves the default equality matching rule that will be used for
153 * attributes with this syntax.
154 *
155 * @return The default equality matching rule that will be used for
156 * attributes with this syntax, or <CODE>null</CODE> if equality
157 * matches will not be allowed for this type by default.
158 */
159 public EqualityMatchingRule getEqualityMatchingRule()
160 {
161 return defaultEqualityMatchingRule;
162 }
163
164
165
166 /**
167 * Retrieves the default ordering matching rule that will be used for
168 * attributes with this syntax.
169 *
170 * @return The default ordering matching rule that will be used for
171 * attributes with this syntax, or <CODE>null</CODE> if ordering
172 * matches will not be allowed for this type by default.
173 */
174 public OrderingMatchingRule getOrderingMatchingRule()
175 {
176 // There is no ordering matching rule by default.
177 return null;
178 }
179
180
181
182 /**
183 * Retrieves the default substring matching rule that will be used for
184 * attributes with this syntax.
185 *
186 * @return The default substring matching rule that will be used for
187 * attributes with this syntax, or <CODE>null</CODE> if substring
188 * matches will not be allowed for this type by default.
189 */
190 public SubstringMatchingRule getSubstringMatchingRule()
191 {
192 return defaultSubstringMatchingRule;
193 }
194
195
196
197 /**
198 * Retrieves the default approximate matching rule that will be used for
199 * attributes with this syntax.
200 *
201 * @return The default approximate matching rule that will be used for
202 * attributes with this syntax, or <CODE>null</CODE> if approximate
203 * matches will not be allowed for this type by default.
204 */
205 public ApproximateMatchingRule getApproximateMatchingRule()
206 {
207 // There is no approximate matching rule by default.
208 return null;
209 }
210
211
212
213 /**
214 * Indicates whether the provided value is acceptable for use in an attribute
215 * with this syntax. If it is not, then the reason may be appended to the
216 * provided buffer.
217 *
218 * @param value The value for which to make the determination.
219 * @param invalidReason The buffer to which the invalid reason should be
220 * appended.
221 *
222 * @return <CODE>true</CODE> if the provided value is acceptable for use with
223 * this syntax, or <CODE>false</CODE> if not.
224 */
225 public boolean valueIsAcceptable(ByteString value,
226 MessageBuilder invalidReason)
227 {
228 String valueString = value.stringValue().trim();
229 int valueLength = valueString.length();
230
231
232 // See if the value contains the "optional uid" portion. If we think it
233 // does, then mark its location.
234 int dnEndPos = valueLength;
235 int sharpPos = -1;
236 if (valueString.endsWith("'B") || valueString.endsWith("'b"))
237 {
238 sharpPos = valueString.lastIndexOf("#'");
239 if (sharpPos > 0)
240 {
241 dnEndPos = sharpPos;
242 }
243 }
244
245
246 // Take the DN portion of the string and try to normalize it.
247 try
248 {
249 DN.decode(valueString.substring(0, dnEndPos));
250 }
251 catch (Exception e)
252 {
253 if (debugEnabled())
254 {
255 TRACER.debugCaught(DebugLogLevel.ERROR, e);
256 }
257
258 // We couldn't normalize the DN for some reason. The value cannot be
259 // acceptable.
260
261 invalidReason.append(ERR_ATTR_SYNTAX_NAMEANDUID_INVALID_DN.get(
262 valueString, getExceptionMessage(e)));
263 return false;
264 }
265
266
267
268 // If there is an "optional uid", then normalize it and make sure it only
269 // contains valid binary digits.
270 if (sharpPos > 0)
271 {
272 int endPos = valueLength - 2;
273 for (int i=sharpPos+2; i < endPos; i++)
274 {
275 char c = valueString.charAt(i);
276 if (! ((c == '0') || (c == '1')))
277 {
278
279 invalidReason.append(
280 ERR_ATTR_SYNTAX_NAMEANDUID_ILLEGAL_BINARY_DIGIT.get(
281 valueString, String.valueOf(c), i));
282 return false;
283 }
284 }
285 }
286
287
288 // If we've gotten here, then the value is acceptable.
289 return true;
290 }
291 }
292