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 org.opends.server.admin.std.server.OrderingMatchingRuleCfg;
033 import org.opends.server.api.OrderingMatchingRule;
034 import org.opends.server.config.ConfigException;
035 import org.opends.server.core.DirectoryServer;
036 import org.opends.server.protocols.asn1.ASN1OctetString;
037 import org.opends.server.types.ByteString;
038 import org.opends.server.types.DirectoryException;
039 import org.opends.server.types.InitializationException;
040 import org.opends.server.types.ResultCode;
041
042 import static org.opends.messages.SchemaMessages.*;
043 import static org.opends.server.schema.SchemaConstants.*;
044 import org.opends.server.loggers.ErrorLogger;
045
046
047 /**
048 * This class defines the uuidOrderingMatch matching rule defined in RFC 4530.
049 * This will be the default ordering matching rule for the UUID syntax.
050 */
051 public class UUIDOrderingMatchingRule
052 extends OrderingMatchingRule
053 {
054 /**
055 * The serial version identifier required to satisfy the compiler because this
056 * class implements the <CODE>java.io.Serializable</CODE> interface. This
057 * value was generated using the <CODE>serialver</CODE> command-line utility
058 * included with the Java SDK.
059 */
060 private static final long serialVersionUID = -3877941142853469687L;
061
062
063
064 /**
065 * Creates a new instance of this uuidOrderingMatch matching rule.
066 */
067 public UUIDOrderingMatchingRule()
068 {
069 super();
070 }
071
072
073
074 /**
075 * {@inheritDoc}
076 */
077 public void initializeMatchingRule(OrderingMatchingRuleCfg configuration)
078 throws ConfigException, InitializationException
079 {
080 // No initialization is required.
081 }
082
083
084
085 /**
086 * Retrieves the common name for this matching rule.
087 *
088 * @return The common name for this matching rule, or <CODE>null</CODE> if
089 * it does not have a name.
090 */
091 public String getName()
092 {
093 return OMR_UUID_NAME;
094 }
095
096
097
098 /**
099 * Retrieves the OID for this matching rule.
100 *
101 * @return The OID for this matching rule.
102 */
103 public String getOID()
104 {
105 return OMR_UUID_OID;
106 }
107
108
109
110 /**
111 * Retrieves the description for this matching rule.
112 *
113 * @return The description for this matching rule, or <CODE>null</CODE> if
114 * there is none.
115 */
116 public String getDescription()
117 {
118 // There is no standard description for this matching rule.
119 return null;
120 }
121
122
123
124 /**
125 * Retrieves the OID of the syntax with which this matching rule is
126 * associated.
127 *
128 * @return The OID of the syntax with which this matching rule is associated.
129 */
130 public String getSyntaxOID()
131 {
132 return SYNTAX_UUID_OID;
133 }
134
135
136
137 /**
138 * Retrieves the normalized form of the provided value, which is best suited
139 * for efficiently performing matching operations on that value.
140 *
141 * @param value The value to be normalized.
142 *
143 * @return The normalized version of the provided value.
144 *
145 * @throws DirectoryException If the provided value is invalid according to
146 * the associated attribute syntax.
147 */
148 public ByteString normalizeValue(ByteString value)
149 throws DirectoryException
150 {
151 byte[] valueBytes = value.value();
152 if (valueBytes.length != 36)
153 {
154 Message message = WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH.get(
155 value.stringValue(), valueBytes.length);
156 switch (DirectoryServer.getSyntaxEnforcementPolicy())
157 {
158 case REJECT:
159 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
160 message);
161 case WARN:
162 ErrorLogger.logError(message);
163 return new ASN1OctetString(valueBytes);
164 default:
165 return new ASN1OctetString(valueBytes);
166 }
167 }
168
169 byte[] normBytes = new byte[36];
170 System.arraycopy(valueBytes, 0, normBytes, 0, 36);
171 for (int i=0; i < 36; i++)
172 {
173 // The 9th, 14th, 19th, and 24th characters must be dashes. All others
174 // must be hex. Convert all uppercase hex characters to lowercase.
175 switch (i)
176 {
177 case 8:
178 case 13:
179 case 18:
180 case 23:
181 if (normBytes[i] != '-')
182 {
183 Message message = WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH.get(
184 value.stringValue(), i, String.valueOf(normBytes[i]));
185 switch (DirectoryServer.getSyntaxEnforcementPolicy())
186 {
187 case REJECT:
188 throw new DirectoryException(
189 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
190 case WARN:
191 ErrorLogger.logError(message);
192 return new ASN1OctetString(valueBytes);
193 default:
194 return new ASN1OctetString(valueBytes);
195 }
196 }
197 break;
198 default:
199 switch (normBytes[i])
200 {
201 case '0':
202 case '1':
203 case '2':
204 case '3':
205 case '4':
206 case '5':
207 case '6':
208 case '7':
209 case '8':
210 case '9':
211 case 'a':
212 case 'b':
213 case 'c':
214 case 'd':
215 case 'e':
216 case 'f':
217 // These are all fine.
218 break;
219 case 'A':
220 normBytes[i] = 'a';
221 break;
222 case 'B':
223 normBytes[i] = 'b';
224 break;
225 case 'C':
226 normBytes[i] = 'c';
227 break;
228 case 'D':
229 normBytes[i] = 'd';
230 break;
231 case 'E':
232 normBytes[i] = 'e';
233 break;
234 case 'F':
235 normBytes[i] = 'f';
236 break;
237 default:
238 Message message = WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX.get(
239 value.stringValue(), i, String.valueOf(normBytes[i]));
240 switch (DirectoryServer.getSyntaxEnforcementPolicy())
241 {
242 case REJECT:
243 throw new DirectoryException(
244 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
245 case WARN:
246 ErrorLogger.logError(message);
247 return new ASN1OctetString(valueBytes);
248 default:
249 return new ASN1OctetString(valueBytes);
250 }
251 }
252 }
253 }
254
255 return new ASN1OctetString(normBytes);
256 }
257
258
259
260 /**
261 * Compares the first value to the second and returns a value that indicates
262 * their relative order.
263 *
264 * @param value1 The normalized form of the first value to compare.
265 * @param value2 The normalized form of the second value to compare.
266 *
267 * @return A negative integer if <CODE>value1</CODE> should come before
268 * <CODE>value2</CODE> in ascending order, a positive integer if
269 * <CODE>value1</CODE> should come after <CODE>value2</CODE> in
270 * ascending order, or zero if there is no difference between the
271 * values with regard to ordering.
272 */
273 public int compareValues(ByteString value1, ByteString value2)
274 {
275 return compare(value1.value(), value2.value());
276 }
277
278
279
280 /**
281 * Compares the contents of the provided byte arrays to determine their
282 * relative order.
283 *
284 * @param b1 The first byte array to use in the comparison.
285 * @param b2 The second byte array to use in the comparison.
286 *
287 * @return A negative integer if <CODE>b1</CODE> should come before
288 * <CODE>b2</CODE> in ascending order, a positive integer if
289 * <CODE>b1</CODE> should come after <CODE>b2</CODE> in ascending
290 * order, or zero if there is no difference between the values with
291 * regard to ordering.
292 */
293 public int compare(byte[] b1, byte[] b2)
294 {
295 int minLength = Math.min(b1.length, b2.length);
296
297 for (int i=0; i < minLength; i++)
298 {
299 if (b1[i] == b2[i])
300 {
301 continue;
302 }
303 else if (b1[i] < b2[i])
304 {
305 return -1;
306 }
307 else if (b1[i] > b2[i])
308 {
309 return 1;
310 }
311 }
312
313 if (b1.length == b2.length)
314 {
315 return 0;
316 }
317 else if (b1.length < b2.length)
318 {
319 return -1;
320 }
321 else
322 {
323 return 1;
324 }
325 }
326 }
327