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 import org.opends.messages.MessageBuilder; 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.api.MatchingRule; 037 import org.opends.server.config.ConfigException; 038 import org.opends.server.core.DirectoryServer; 039 import org.opends.server.protocols.asn1.ASN1OctetString; 040 import org.opends.server.types. AttributeType; 041 import org.opends.server.types.ByteString; 042 import org.opends.server.types.DirectoryException; 043 import org.opends.server.types.InitializationException; 044 import org.opends.server.types.NameForm; 045 import org.opends.server.types.ObjectClass; 046 import org.opends.server.types.ResultCode; 047 048 import static org.opends.messages.SchemaMessages.*; 049 import static org.opends.server.schema.SchemaConstants.*; 050 import static org.opends.server.util.StaticUtils.*; 051 import org.opends.server.loggers.ErrorLogger; 052 053 054 /** 055 * This class defines the objectIdentifierMatch matching rule defined in X.520 056 * and referenced in RFC 2252. This expects to work on OIDs and will match 057 * either an attribute/objectclass name or a numeric OID. 058 */ 059 public class ObjectIdentifierEqualityMatchingRule 060 extends EqualityMatchingRule 061 { 062 /** 063 * Creates a new instance of this objectIdentifierMatch matching rule. 064 */ 065 public ObjectIdentifierEqualityMatchingRule() 066 { 067 super(); 068 } 069 070 071 072 /** 073 * {@inheritDoc} 074 */ 075 public void initializeMatchingRule(EqualityMatchingRuleCfg configuration) 076 throws ConfigException, InitializationException 077 { 078 // No initialization is required. 079 } 080 081 082 083 /** 084 * Retrieves the common name for this matching rule. 085 * 086 * @return The common name for this matching rule, or <CODE>null</CODE> if 087 * it does not have a name. 088 */ 089 public String getName() 090 { 091 return EMR_OID_NAME; 092 } 093 094 095 096 /** 097 * Retrieves the OID for this matching rule. 098 * 099 * @return The OID for this matching rule. 100 */ 101 public String getOID() 102 { 103 return EMR_OID_OID; 104 } 105 106 107 108 /** 109 * Retrieves the description for this matching rule. 110 * 111 * @return The description for this matching rule, or <CODE>null</CODE> if 112 * there is none. 113 */ 114 public String getDescription() 115 { 116 // There is no standard description for this matching rule. 117 return null; 118 } 119 120 121 122 /** 123 * Retrieves the OID of the syntax with which this matching rule is 124 * associated. 125 * 126 * @return The OID of the syntax with which this matching rule is associated. 127 */ 128 public String getSyntaxOID() 129 { 130 return SYNTAX_OID_OID; 131 } 132 133 134 135 /** 136 * Retrieves the normalized form of the provided value, which is best suited 137 * for efficiently performing matching operations on that value. 138 * 139 * @param value The value to be normalized. 140 * 141 * @return The normalized version of the provided value. 142 * 143 * @throws DirectoryException If the provided value is invalid according to 144 * the associated attribute syntax. 145 */ 146 public ByteString normalizeValue(ByteString value) 147 throws DirectoryException 148 { 149 StringBuilder buffer = new StringBuilder(); 150 toLowerCase(value.value(), buffer, true); 151 String lowerValue = buffer.toString(); 152 153 // Normalize OIDs into schema names, and secondary schema names into 154 // primary schema names. 155 156 String schemaName = null; 157 158 AttributeType attributeType = DirectoryServer.getAttributeType(lowerValue); 159 if (attributeType != null) 160 { 161 schemaName = attributeType.getNameOrOID(); 162 } 163 164 if (schemaName == null) 165 { 166 ObjectClass objectClass = DirectoryServer.getObjectClass(lowerValue); 167 if (objectClass != null) 168 { 169 schemaName = objectClass.getNameOrOID(); 170 } 171 } 172 173 if (schemaName == null) 174 { 175 MatchingRule matchingRule = DirectoryServer.getMatchingRule(lowerValue); 176 if (matchingRule != null) 177 { 178 schemaName = matchingRule.getNameOrOID(); 179 } 180 } 181 182 if (schemaName == null) 183 { 184 NameForm nameForm = DirectoryServer.getNameForm(lowerValue); 185 if (nameForm != null) 186 { 187 schemaName = nameForm.getNameOrOID(); 188 } 189 } 190 191 if (schemaName != null) 192 { 193 return new ASN1OctetString(toLowerCase(schemaName)); 194 } 195 196 // There were no schema matches so we must check the syntax. 197 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 198 { 199 case REJECT: 200 MessageBuilder invalidReason = new MessageBuilder(); 201 if (isValidSchemaElement(lowerValue, 0, lowerValue.length(), 202 invalidReason)) 203 { 204 return new ASN1OctetString(lowerValue); 205 } 206 else 207 { 208 Message message = ERR_ATTR_SYNTAX_OID_INVALID_VALUE.get( 209 lowerValue, invalidReason.toString()); 210 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, 211 message); 212 } 213 214 case WARN: 215 invalidReason = new MessageBuilder(); 216 if (! isValidSchemaElement(lowerValue, 0, lowerValue.length(), 217 invalidReason)) 218 { 219 Message message = ERR_ATTR_SYNTAX_OID_INVALID_VALUE.get( 220 lowerValue, invalidReason.toString()); 221 ErrorLogger.logError(message); 222 } 223 224 return new ASN1OctetString(lowerValue); 225 226 default: 227 return new ASN1OctetString(lowerValue); 228 } 229 } 230 231 232 233 /** 234 * Indicates whether the two provided normalized values are equal to each 235 * other. 236 * 237 * @param value1 The normalized form of the first value to compare. 238 * @param value2 The normalized form of the second value to compare. 239 * 240 * @return <CODE>true</CODE> if the provided values are equal, or 241 * <CODE>false</CODE> if not. 242 */ 243 public boolean areEqual(ByteString value1, ByteString value2) 244 { 245 // First, compare the normalized values to see if they are the same. 246 if (Arrays.equals(value1.value(), value2.value())) 247 { 248 return true; 249 } 250 251 252 // The following code implies that the normalized values cannot be 253 // compared byte-for-byte, which would require that the generateHashCode 254 // method of EqualityMatchingRule be overridden to avoid using the 255 // normalized value. Instead, values are now normalized such that they 256 // can be compared byte-for-byte. There are still some rare cases where 257 // comparison fails. For example, say there is an object class with primary 258 // name "a" and secondary name "b", and there is also an attribute type with 259 // primary name "b". In this case comparing "a" with "b" returns false even 260 // though the two values are equivalent in an object class context. 261 262 /* 263 // It is possible that they are different names referring to the same 264 // schema element. See if we can find a case where that is true in the 265 // server configuration for all of the following schema element types: 266 // - Attribute Types 267 // - Objectclasses 268 // - Attribute syntaxes 269 // - Matching Rules 270 // - Name Forms 271 String valueStr1 = value1.stringValue(); 272 AttributeType attrType1 = DirectoryServer.getAttributeType(valueStr1); 273 if (attrType1 != null) 274 { 275 String valueStr2 = value2.stringValue(); 276 AttributeType attrType2 = DirectoryServer.getAttributeType(valueStr2); 277 if (attrType2 == null) 278 { 279 return false; 280 } 281 else 282 { 283 return attrType1.equals(attrType2); 284 } 285 } 286 287 ObjectClass oc1 = DirectoryServer.getObjectClass(valueStr1); 288 if (oc1 != null) 289 { 290 String valueStr2 = value2.stringValue(); 291 ObjectClass oc2 = DirectoryServer.getObjectClass(valueStr2); 292 if (oc2 == null) 293 { 294 return false; 295 } 296 else 297 { 298 return oc1.equals(oc2); 299 } 300 } 301 302 AttributeSyntax syntax1 = DirectoryServer.getAttributeSyntax(valueStr1, 303 false); 304 if (syntax1 != null) 305 { 306 String valueStr2 = value2.stringValue(); 307 AttributeSyntax syntax2 = DirectoryServer.getAttributeSyntax(valueStr2, 308 false); 309 if (syntax2 == null) 310 { 311 return false; 312 } 313 else 314 { 315 return syntax1.equals(syntax2); 316 } 317 } 318 319 320 MatchingRule mr1 = DirectoryServer.getMatchingRule(valueStr1); 321 if (mr1 != null) 322 { 323 String valueStr2 = value2.stringValue(); 324 MatchingRule mr2 = DirectoryServer.getMatchingRule(valueStr2); 325 if (mr2 == null) 326 { 327 return false; 328 } 329 else 330 { 331 return mr1.equals(mr2); 332 } 333 } 334 335 336 NameForm nf1 = DirectoryServer.getNameForm(valueStr1); 337 if (nf1 != null) 338 { 339 String valueStr2 = value2.stringValue(); 340 NameForm nf2 = DirectoryServer.getNameForm(valueStr2); 341 if (nf2 == null) 342 { 343 return false; 344 } 345 else 346 { 347 return nf1.equals(nf2); 348 } 349 } 350 */ 351 352 353 // If we've gotten here, then we've exhausted all reasonable checking and 354 // we can't consider them equal. 355 return false; 356 } 357 358 } 359