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