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 java.util.Arrays;
032
033 import org.opends.server.admin.std.server.EqualityMatchingRuleCfg;
034 import org.opends.server.api.EqualityMatchingRule;
035 import org.opends.server.config.ConfigException;
036 import org.opends.server.core.DirectoryServer;
037
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.server.loggers.ErrorLogger.*;
045 import static org.opends.messages.SchemaMessages.*;
046 import org.opends.messages.Message;
047 import static org.opends.server.schema.SchemaConstants.*;
048
049
050
051 /**
052 * This class defines the uuidMatch matching rule defined in RFC 4530. It will
053 * be used as the default equality matching rule for the UUID syntax.
054 */
055 public class UUIDEqualityMatchingRule
056 extends EqualityMatchingRule
057 {
058 /**
059 * Creates a new instance of this caseExactMatch matching rule.
060 */
061 public UUIDEqualityMatchingRule()
062 {
063 super();
064 }
065
066
067
068 /**
069 * {@inheritDoc}
070 */
071 public void initializeMatchingRule(EqualityMatchingRuleCfg configuration)
072 throws ConfigException, InitializationException
073 {
074 // No initialization is required.
075 }
076
077
078
079 /**
080 * Retrieves the common name for this matching rule.
081 *
082 * @return The common name for this matching rule, or <CODE>null</CODE> if
083 * it does not have a name.
084 */
085 public String getName()
086 {
087 return EMR_UUID_NAME;
088 }
089
090
091
092 /**
093 * Retrieves the OID for this matching rule.
094 *
095 * @return The OID for this matching rule.
096 */
097 public String getOID()
098 {
099 return EMR_UUID_OID;
100 }
101
102
103
104 /**
105 * Retrieves the description for this matching rule.
106 *
107 * @return The description for this matching rule, or <CODE>null</CODE> if
108 * there is none.
109 */
110 public String getDescription()
111 {
112 // There is no standard description for this matching rule.
113 return null;
114 }
115
116
117
118 /**
119 * Retrieves the OID of the syntax with which this matching rule is
120 * associated.
121 *
122 * @return The OID of the syntax with which this matching rule is associated.
123 */
124 public String getSyntaxOID()
125 {
126 return SYNTAX_UUID_OID;
127 }
128
129
130
131 /**
132 * Retrieves the normalized form of the provided value, which is best suited
133 * for efficiently performing matching operations on that value.
134 *
135 * @param value The value to be normalized.
136 *
137 * @return The normalized version of the provided value.
138 *
139 * @throws DirectoryException If the provided value is invalid according to
140 * the associated attribute syntax.
141 */
142 public ByteString normalizeValue(ByteString value)
143 throws DirectoryException
144 {
145 byte[] valueBytes = value.value();
146 if (valueBytes.length != 36)
147 {
148 Message message = WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH.get(
149 value.stringValue(), valueBytes.length);
150 switch (DirectoryServer.getSyntaxEnforcementPolicy())
151 {
152 case REJECT:
153 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
154 message);
155 case WARN:
156 logError(message);
157 return new ASN1OctetString(valueBytes);
158 default:
159 return new ASN1OctetString(valueBytes);
160 }
161 }
162
163 byte[] normBytes = new byte[36];
164 System.arraycopy(valueBytes, 0, normBytes, 0, 36);
165 for (int i=0; i < 36; i++)
166 {
167 // The 9th, 14th, 19th, and 24th characters must be dashes. All others
168 // must be hex. Convert all uppercase hex characters to lowercase.
169 switch (i)
170 {
171 case 8:
172 case 13:
173 case 18:
174 case 23:
175 if (normBytes[i] != '-')
176 {
177 Message message = WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH.get(
178 value.stringValue(), i, String.valueOf(normBytes[i]));
179 switch (DirectoryServer.getSyntaxEnforcementPolicy())
180 {
181 case REJECT:
182 throw new DirectoryException(
183 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
184 case WARN:
185 logError(
186 message);
187 return new ASN1OctetString(valueBytes);
188 default:
189 return new ASN1OctetString(valueBytes);
190 }
191 }
192 break;
193 default:
194 switch (normBytes[i])
195 {
196 case '0':
197 case '1':
198 case '2':
199 case '3':
200 case '4':
201 case '5':
202 case '6':
203 case '7':
204 case '8':
205 case '9':
206 case 'a':
207 case 'b':
208 case 'c':
209 case 'd':
210 case 'e':
211 case 'f':
212 // These are all fine.
213 break;
214 case 'A':
215 normBytes[i] = 'a';
216 break;
217 case 'B':
218 normBytes[i] = 'b';
219 break;
220 case 'C':
221 normBytes[i] = 'c';
222 break;
223 case 'D':
224 normBytes[i] = 'd';
225 break;
226 case 'E':
227 normBytes[i] = 'e';
228 break;
229 case 'F':
230 normBytes[i] = 'f';
231 break;
232 default:
233 Message message = WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX.get(
234 value.stringValue(), i, String.valueOf(normBytes[i]));
235 switch (DirectoryServer.getSyntaxEnforcementPolicy())
236 {
237 case REJECT:
238 throw new DirectoryException(
239 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
240 case WARN:
241 logError(
242 message);
243 return new ASN1OctetString(valueBytes);
244 default:
245 return new ASN1OctetString(valueBytes);
246 }
247 }
248 }
249 }
250
251 return new ASN1OctetString(normBytes);
252 }
253
254
255
256 /**
257 * Indicates whether the two provided normalized values are equal to each
258 * other.
259 *
260 * @param value1 The normalized form of the first value to compare.
261 * @param value2 The normalized form of the second value to compare.
262 *
263 * @return <CODE>true</CODE> if the provided values are equal, or
264 * <CODE>false</CODE> if not.
265 */
266 public boolean areEqual(ByteString value1, ByteString value2)
267 {
268 // Since the values are already normalized, we just need to compare the
269 // associated byte arrays.
270 return Arrays.equals(value1.value(), value2.value());
271 }
272 }
273