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.List; 032 033 import org.opends.server.admin.std.server.SubstringMatchingRuleCfg; 034 import org.opends.server.api.SubstringMatchingRule; 035 import org.opends.server.config.ConfigException; 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 041 import static org.opends.server.schema.SchemaConstants.*; 042 import static org.opends.server.util.StaticUtils.*; 043 044 045 046 /** 047 * This class defines the octetStringSubstringsMatch matching rule defined in 048 * X.520. It will be used as the default substring matching rule for the binary 049 * and octet string syntaxes. 050 */ 051 public class OctetStringSubstringMatchingRule 052 extends SubstringMatchingRule 053 { 054 /** 055 * Creates a new instance of this octetStringSubstringsMatch matching rule. 056 */ 057 public OctetStringSubstringMatchingRule() 058 { 059 super(); 060 } 061 062 063 064 /** 065 * {@inheritDoc} 066 */ 067 public void initializeMatchingRule(SubstringMatchingRuleCfg configuration) 068 throws ConfigException, InitializationException 069 { 070 // No initialization is required. 071 } 072 073 074 075 /** 076 * Retrieves the common name for this matching rule. 077 * 078 * @return The common name for this matching rule, or <CODE>null</CODE> if 079 * it does not have a name. 080 */ 081 public String getName() 082 { 083 return SMR_OCTET_STRING_NAME; 084 } 085 086 087 088 /** 089 * Retrieves the OID for this matching rule. 090 * 091 * @return The OID for this matching rule. 092 */ 093 public String getOID() 094 { 095 return SMR_OCTET_STRING_OID; 096 } 097 098 099 100 /** 101 * Retrieves the description for this matching rule. 102 * 103 * @return The description for this matching rule, or <CODE>null</CODE> if 104 * there is none. 105 */ 106 public String getDescription() 107 { 108 // There is no standard description for this matching rule. 109 return null; 110 } 111 112 113 114 /** 115 * Retrieves the OID of the syntax with which this matching rule is 116 * associated. 117 * 118 * @return The OID of the syntax with which this matching rule is associated. 119 */ 120 public String getSyntaxOID() 121 { 122 return SYNTAX_SUBSTRING_ASSERTION_OID; 123 } 124 125 126 127 /** 128 * Retrieves the normalized form of the provided value, which is best suited 129 * for efficiently performing matching operations on that value. 130 * 131 * @param value The value to be normalized. 132 * 133 * @return The normalized version of the provided value. 134 * 135 * @throws DirectoryException If the provided value is invalid according to 136 * the associated attribute syntax. 137 */ 138 public ByteString normalizeValue(ByteString value) 139 throws DirectoryException 140 { 141 return new ASN1OctetString(value.value()); 142 } 143 144 145 146 /** 147 * Normalizes the provided value fragment into a form that can be used to 148 * efficiently compare values. 149 * 150 * @param substring The value fragment to be normalized. 151 * 152 * @return The normalized form of the value fragment. 153 * 154 * @throws DirectoryException If the provided value fragment is not 155 * acceptable according to the associated syntax. 156 */ 157 public ByteString normalizeSubstring(ByteString substring) 158 throws DirectoryException 159 { 160 // This is exactly the same as normalizing a full value. 161 return new ASN1OctetString(substring.value()); 162 } 163 164 165 166 /** 167 * Determines whether the provided value matches the given substring filter 168 * components. Note that any of the substring filter components may be 169 * <CODE>null</CODE> but at least one of them must be non-<CODE>null</CODE>. 170 * 171 * @param value The normalized value against which to compare the 172 * substring components. 173 * @param subInitial The normalized substring value fragment that should 174 * appear at the beginning of the target value. 175 * @param subAnyElements The normalized substring value fragments that 176 * should appear in the middle of the target value. 177 * @param subFinal The normalized substring value fragment that should 178 * appear at the end of the target value. 179 * 180 * @return <CODE>true</CODE> if the provided value does match the given 181 * substring components, or <CODE>false</CODE> if not. 182 */ 183 public boolean valueMatchesSubstring(ByteString value, ByteString subInitial, 184 List<ByteString> subAnyElements, 185 ByteString subFinal) 186 { 187 byte[] valueBytes = value.value(); 188 int valueLength = valueBytes.length; 189 190 int pos = 0; 191 if (subInitial != null) 192 { 193 byte[] initialBytes = subInitial.value(); 194 int initialLength = initialBytes.length; 195 if (initialLength > valueLength) 196 { 197 return false; 198 } 199 200 for (; pos < initialLength; pos++) 201 { 202 if (initialBytes[pos] != valueBytes[pos]) 203 { 204 return false; 205 } 206 } 207 } 208 209 210 if ((subAnyElements != null) && (! subAnyElements.isEmpty())) 211 { 212 for (ByteString element : subAnyElements) 213 { 214 byte[] anyBytes = element.value(); 215 int anyLength = anyBytes.length; 216 217 int end = valueLength - anyLength; 218 boolean match = false; 219 for (; pos <= end; pos++) 220 { 221 if (anyBytes[0] == valueBytes[pos]) 222 { 223 boolean subMatch = true; 224 for (int i=1; i < anyLength; i++) 225 { 226 if (anyBytes[i] != valueBytes[pos+i]) 227 { 228 subMatch = false; 229 break; 230 } 231 } 232 233 if (subMatch) 234 { 235 match = subMatch; 236 break; 237 } 238 } 239 } 240 241 if (match) 242 { 243 pos += anyLength; 244 } 245 else 246 { 247 return false; 248 } 249 } 250 } 251 252 253 if (subFinal != null) 254 { 255 byte[] finalBytes = subFinal.value(); 256 int finalLength = finalBytes.length; 257 258 if ((valueLength - finalLength) < pos) 259 { 260 return false; 261 } 262 263 pos = valueLength - finalLength; 264 for (int i=0; i < finalLength; i++,pos++) 265 { 266 if (finalBytes[i] != valueBytes[pos]) 267 { 268 return false; 269 } 270 } 271 } 272 273 274 return true; 275 } 276 } 277