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 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.config.ConfigException; 037 import org.opends.server.core.DirectoryServer; 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.messages.SchemaMessages.*; 045 import static org.opends.server.schema.SchemaConstants.*; 046 import org.opends.server.loggers.ErrorLogger; 047 048 049 /** 050 * This class defines the integerMatch matching rule defined in X.520 and 051 * referenced in RFC 2252. 052 */ 053 public class IntegerEqualityMatchingRule 054 extends EqualityMatchingRule 055 { 056 /** 057 * Creates a new instance of this integerMatch matching rule. 058 */ 059 public IntegerEqualityMatchingRule() 060 { 061 super(); 062 } 063 064 065 066 /** 067 * {@inheritDoc} 068 */ 069 public void initializeMatchingRule(EqualityMatchingRuleCfg configuration) 070 throws ConfigException, InitializationException 071 { 072 // No initialization is required. 073 } 074 075 076 077 /** 078 * Retrieves the common name for this matching rule. 079 * 080 * @return The common name for this matching rule, or <CODE>null</CODE> if 081 * it does not have a name. 082 */ 083 public String getName() 084 { 085 return EMR_INTEGER_NAME; 086 } 087 088 089 090 /** 091 * Retrieves the OID for this matching rule. 092 * 093 * @return The OID for this matching rule. 094 */ 095 public String getOID() 096 { 097 return EMR_INTEGER_OID; 098 } 099 100 101 102 /** 103 * Retrieves the description for this matching rule. 104 * 105 * @return The description for this matching rule, or <CODE>null</CODE> if 106 * there is none. 107 */ 108 public String getDescription() 109 { 110 // There is no standard description for this matching rule. 111 return null; 112 } 113 114 115 116 /** 117 * Retrieves the OID of the syntax with which this matching rule is 118 * associated. 119 * 120 * @return The OID of the syntax with which this matching rule is associated. 121 */ 122 public String getSyntaxOID() 123 { 124 return SYNTAX_INTEGER_OID; 125 } 126 127 128 129 /** 130 * Retrieves the normalized form of the provided value, which is best suited 131 * for efficiently performing matching operations on that value. 132 * 133 * @param value The value to be normalized. 134 * 135 * @return The normalized version of the provided value. 136 * 137 * @throws DirectoryException If the provided value is invalid according to 138 * the associated attribute syntax. 139 */ 140 public ByteString normalizeValue(ByteString value) 141 throws DirectoryException 142 { 143 byte[] valueBytes = value.value(); 144 145 int length = valueBytes.length; 146 StringBuilder buffer = new StringBuilder(length); 147 148 boolean logged = false; 149 for (int i=0; i < length; i++) 150 { 151 switch (valueBytes[i]) 152 { 153 case '0': 154 switch (buffer.length()) 155 { 156 case 0: 157 // This is only OK if the value is zero 158 if (i == (length-1)) 159 { 160 buffer.append("0"); 161 } 162 else 163 { 164 Message message = WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get( 165 value.stringValue()); 166 167 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 168 { 169 case REJECT: 170 throw new DirectoryException( 171 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); 172 case WARN: 173 if (! logged) 174 { 175 logged = true; 176 ErrorLogger.logError(message); 177 } 178 break; 179 } 180 } 181 break; 182 case 1: 183 // This is OK as long as the first character isn't a dash. 184 if (buffer.charAt(0) == '-') 185 { 186 Message message = WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get( 187 value.stringValue()); 188 189 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 190 { 191 case REJECT: 192 throw new DirectoryException( 193 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); 194 case WARN: 195 if (! logged) 196 { 197 logged = true; 198 ErrorLogger.logError(message); 199 } 200 break; 201 } 202 } 203 else 204 { 205 buffer.append("0"); 206 } 207 break; 208 default: 209 // This is always fine. 210 buffer.append("0"); 211 break; 212 } 213 break; 214 case '1': 215 buffer.append('1'); 216 break; 217 case '2': 218 buffer.append('2'); 219 break; 220 case '3': 221 buffer.append('3'); 222 break; 223 case '4': 224 buffer.append('4'); 225 break; 226 case '5': 227 buffer.append('5'); 228 break; 229 case '6': 230 buffer.append('6'); 231 break; 232 case '7': 233 buffer.append('7'); 234 break; 235 case '8': 236 buffer.append('8'); 237 break; 238 case '9': 239 buffer.append('9'); 240 break; 241 case '-': 242 // This is only OK if the buffer is empty. 243 if (buffer.length() == 0) 244 { 245 buffer.append("-"); 246 } 247 else 248 { 249 Message message = WARN_ATTR_SYNTAX_INTEGER_MISPLACED_DASH.get( 250 value.stringValue()); 251 252 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 253 { 254 case REJECT: 255 throw new DirectoryException( 256 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); 257 case WARN: 258 if (! logged) 259 { 260 logged = true; 261 ErrorLogger.logError(message); 262 } 263 break; 264 } 265 } 266 break; 267 default: 268 Message message = WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get( 269 value.stringValue(), 270 ((char) valueBytes[i]), i); 271 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 272 { 273 case REJECT: 274 throw new DirectoryException( 275 ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); 276 case WARN: 277 if (! logged) 278 { 279 logged = true; 280 ErrorLogger.logError(message); 281 } 282 break; 283 } 284 } 285 } 286 287 if (buffer.length() == 0) 288 { 289 Message message = WARN_ATTR_SYNTAX_INTEGER_EMPTY_VALUE.get( 290 value.stringValue()); 291 292 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 293 { 294 case REJECT: 295 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, 296 message); 297 298 case WARN: 299 if (! logged) 300 { 301 logged = true; 302 ErrorLogger.logError(message); 303 } 304 305 buffer.append("0"); 306 break; 307 308 default: 309 buffer.append("0"); 310 break; 311 } 312 } 313 else if ((buffer.length() == 1) && (buffer.charAt(0) == '-')) 314 { 315 Message message = WARN_ATTR_SYNTAX_INTEGER_DASH_NEEDS_VALUE.get( 316 value.stringValue()); 317 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 318 { 319 case REJECT: 320 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, 321 message); 322 323 case WARN: 324 if (! logged) 325 { 326 logged = true; 327 ErrorLogger.logError(message); 328 } 329 330 buffer.setCharAt(0, '0'); 331 break; 332 333 default: 334 buffer.setCharAt(0, '0'); 335 break; 336 } 337 } 338 339 return new ASN1OctetString(buffer.toString()); 340 } 341 342 343 344 /** 345 * Indicates whether the two provided normalized values are equal to each 346 * other. 347 * 348 * @param value1 The normalized form of the first value to compare. 349 * @param value2 The normalized form of the second value to compare. 350 * 351 * @return <CODE>true</CODE> if the provided values are equal, or 352 * <CODE>false</CODE> if not. 353 */ 354 public boolean areEqual(ByteString value1, ByteString value2) 355 { 356 // Since the values are already normalized, we just need to compare the 357 // associated byte arrays. 358 return Arrays.equals(value1.value(), value2.value()); 359 } 360 } 361