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.Arrays;
033
034 import org.opends.server.admin.std.server.EqualityMatchingRuleCfg;
035 import org.opends.server.api.EqualityMatchingRule;
036 import org.opends.server.config.ConfigException;
037 import org.opends.server.core.DirectoryServer;
038 import org.opends.server.protocols.asn1.ASN1OctetString;
039 import org.opends.server.types.ByteString;
040 import org.opends.server.types.DirectoryException;
041 import org.opends.server.types.InitializationException;
042 import org.opends.server.types.ResultCode;
043
044 import static org.opends.messages.SchemaMessages.*;
045 import static org.opends.server.schema.SchemaConstants.*;
046 import org.opends.server.loggers.ErrorLogger;
047
048
049 /**
050 * This class defines the integerMatch matching rule defined in X.520 and
051 * referenced in RFC 2252.
052 */
053 public class IntegerEqualityMatchingRule
054 extends EqualityMatchingRule
055 {
056 /**
057 * Creates a new instance of this integerMatch matching rule.
058 */
059 public IntegerEqualityMatchingRule()
060 {
061 super();
062 }
063
064
065
066 /**
067 * {@inheritDoc}
068 */
069 public void initializeMatchingRule(EqualityMatchingRuleCfg configuration)
070 throws ConfigException, InitializationException
071 {
072 // No initialization is required.
073 }
074
075
076
077 /**
078 * Retrieves the common name for this matching rule.
079 *
080 * @return The common name for this matching rule, or <CODE>null</CODE> if
081 * it does not have a name.
082 */
083 public String getName()
084 {
085 return EMR_INTEGER_NAME;
086 }
087
088
089
090 /**
091 * Retrieves the OID for this matching rule.
092 *
093 * @return The OID for this matching rule.
094 */
095 public String getOID()
096 {
097 return EMR_INTEGER_OID;
098 }
099
100
101
102 /**
103 * Retrieves the description for this matching rule.
104 *
105 * @return The description for this matching rule, or <CODE>null</CODE> if
106 * there is none.
107 */
108 public String getDescription()
109 {
110 // There is no standard description for this matching rule.
111 return null;
112 }
113
114
115
116 /**
117 * Retrieves the OID of the syntax with which this matching rule is
118 * associated.
119 *
120 * @return The OID of the syntax with which this matching rule is associated.
121 */
122 public String getSyntaxOID()
123 {
124 return SYNTAX_INTEGER_OID;
125 }
126
127
128
129 /**
130 * Retrieves the normalized form of the provided value, which is best suited
131 * for efficiently performing matching operations on that value.
132 *
133 * @param value The value to be normalized.
134 *
135 * @return The normalized version of the provided value.
136 *
137 * @throws DirectoryException If the provided value is invalid according to
138 * the associated attribute syntax.
139 */
140 public ByteString normalizeValue(ByteString value)
141 throws DirectoryException
142 {
143 byte[] valueBytes = value.value();
144
145 int length = valueBytes.length;
146 StringBuilder buffer = new StringBuilder(length);
147
148 boolean logged = false;
149 for (int i=0; i < length; i++)
150 {
151 switch (valueBytes[i])
152 {
153 case '0':
154 switch (buffer.length())
155 {
156 case 0:
157 // This is only OK if the value is zero
158 if (i == (length-1))
159 {
160 buffer.append("0");
161 }
162 else
163 {
164 Message message = WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get(
165 value.stringValue());
166
167 switch (DirectoryServer.getSyntaxEnforcementPolicy())
168 {
169 case REJECT:
170 throw new DirectoryException(
171 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
172 case WARN:
173 if (! logged)
174 {
175 logged = true;
176 ErrorLogger.logError(message);
177 }
178 break;
179 }
180 }
181 break;
182 case 1:
183 // This is OK as long as the first character isn't a dash.
184 if (buffer.charAt(0) == '-')
185 {
186 Message message = WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get(
187 value.stringValue());
188
189 switch (DirectoryServer.getSyntaxEnforcementPolicy())
190 {
191 case REJECT:
192 throw new DirectoryException(
193 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
194 case WARN:
195 if (! logged)
196 {
197 logged = true;
198 ErrorLogger.logError(message);
199 }
200 break;
201 }
202 }
203 else
204 {
205 buffer.append("0");
206 }
207 break;
208 default:
209 // This is always fine.
210 buffer.append("0");
211 break;
212 }
213 break;
214 case '1':
215 buffer.append('1');
216 break;
217 case '2':
218 buffer.append('2');
219 break;
220 case '3':
221 buffer.append('3');
222 break;
223 case '4':
224 buffer.append('4');
225 break;
226 case '5':
227 buffer.append('5');
228 break;
229 case '6':
230 buffer.append('6');
231 break;
232 case '7':
233 buffer.append('7');
234 break;
235 case '8':
236 buffer.append('8');
237 break;
238 case '9':
239 buffer.append('9');
240 break;
241 case '-':
242 // This is only OK if the buffer is empty.
243 if (buffer.length() == 0)
244 {
245 buffer.append("-");
246 }
247 else
248 {
249 Message message = WARN_ATTR_SYNTAX_INTEGER_MISPLACED_DASH.get(
250 value.stringValue());
251
252 switch (DirectoryServer.getSyntaxEnforcementPolicy())
253 {
254 case REJECT:
255 throw new DirectoryException(
256 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
257 case WARN:
258 if (! logged)
259 {
260 logged = true;
261 ErrorLogger.logError(message);
262 }
263 break;
264 }
265 }
266 break;
267 default:
268 Message message = WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
269 value.stringValue(),
270 ((char) valueBytes[i]), i);
271 switch (DirectoryServer.getSyntaxEnforcementPolicy())
272 {
273 case REJECT:
274 throw new DirectoryException(
275 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
276 case WARN:
277 if (! logged)
278 {
279 logged = true;
280 ErrorLogger.logError(message);
281 }
282 break;
283 }
284 }
285 }
286
287 if (buffer.length() == 0)
288 {
289 Message message = WARN_ATTR_SYNTAX_INTEGER_EMPTY_VALUE.get(
290 value.stringValue());
291
292 switch (DirectoryServer.getSyntaxEnforcementPolicy())
293 {
294 case REJECT:
295 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
296 message);
297
298 case WARN:
299 if (! logged)
300 {
301 logged = true;
302 ErrorLogger.logError(message);
303 }
304
305 buffer.append("0");
306 break;
307
308 default:
309 buffer.append("0");
310 break;
311 }
312 }
313 else if ((buffer.length() == 1) && (buffer.charAt(0) == '-'))
314 {
315 Message message = WARN_ATTR_SYNTAX_INTEGER_DASH_NEEDS_VALUE.get(
316 value.stringValue());
317 switch (DirectoryServer.getSyntaxEnforcementPolicy())
318 {
319 case REJECT:
320 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
321 message);
322
323 case WARN:
324 if (! logged)
325 {
326 logged = true;
327 ErrorLogger.logError(message);
328 }
329
330 buffer.setCharAt(0, '0');
331 break;
332
333 default:
334 buffer.setCharAt(0, '0');
335 break;
336 }
337 }
338
339 return new ASN1OctetString(buffer.toString());
340 }
341
342
343
344 /**
345 * Indicates whether the two provided normalized values are equal to each
346 * other.
347 *
348 * @param value1 The normalized form of the first value to compare.
349 * @param value2 The normalized form of the second value to compare.
350 *
351 * @return <CODE>true</CODE> if the provided values are equal, or
352 * <CODE>false</CODE> if not.
353 */
354 public boolean areEqual(ByteString value1, ByteString value2)
355 {
356 // Since the values are already normalized, we just need to compare the
357 // associated byte arrays.
358 return Arrays.equals(value1.value(), value2.value());
359 }
360 }
361