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