001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.shared.ldap.codec.search; 021 022 023 import java.nio.BufferOverflowException; 024 import java.nio.ByteBuffer; 025 import java.util.ArrayList; 026 import java.util.List; 027 028 import org.apache.directory.shared.asn1.ber.tlv.TLV; 029 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag; 030 import org.apache.directory.shared.asn1.ber.tlv.Value; 031 import org.apache.directory.shared.asn1.codec.EncoderException; 032 import org.apache.directory.shared.i18n.I18n; 033 import org.apache.directory.shared.ldap.codec.LdapConstants; 034 import org.apache.directory.shared.ldap.util.StringTools; 035 036 037 /** 038 * A Object that stores the substring filter. 039 * 040 * A substring filter follow this 041 * grammar : 042 * 043 * substring = attr "=" ( ([initial] any [final] | 044 * (initial [any] [final) | 045 * ([initial] [any] final) ) 046 * 047 * initial = value 048 * any = "*" *(value "*") 049 * final = value 050 * 051 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 052 * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Sun, 21 Feb 2010) $, 053 */ 054 public class SubstringFilter extends Filter 055 { 056 // ~ Instance fields 057 // ---------------------------------------------------------------------------- 058 059 /** The substring filter type (an attributeDescription) */ 060 private String type; 061 062 /** The type length */ 063 private int typeLength; 064 065 /** 066 * This member is used to control the length of the three parts of the 067 * substring filter 068 */ 069 private int substringsLength; 070 071 /** The initial filter */ 072 private String initialSubstrings; 073 074 /** The any filter. It's a list of LdapString */ 075 private List<String> anySubstrings = new ArrayList<String>( 1 ); 076 077 /** The final filter */ 078 private String finalSubstrings; 079 080 /** Temporary storage for substringsFilter length */ 081 private int substringsFilterLength; 082 083 /** Temporary storage for substringsFilter sequence length */ 084 private int substringsFilterSequenceLength; 085 086 087 // ~ Methods 088 // ------------------------------------------------------------------------------------ 089 090 /** 091 * The constructor. We will create the 'any' subsring arraylist with only 092 * one element. 093 */ 094 public SubstringFilter( int tlvId ) 095 { 096 super( tlvId ); 097 } 098 099 100 /** 101 * The constructor. We will create the 'any' subsring arraylist with only 102 * one element. 103 */ 104 public SubstringFilter() 105 { 106 super(); 107 } 108 109 110 /** 111 * Get the internal substrings 112 * 113 * @return Returns the anySubstrings. 114 */ 115 public List<String> getAnySubstrings() 116 { 117 return anySubstrings; 118 } 119 120 121 /** 122 * Add a internal substring 123 * 124 * @param any The anySubstrings to set. 125 */ 126 public void addAnySubstrings( String any ) 127 { 128 this.anySubstrings.add( any ); 129 } 130 131 132 /** 133 * Get the final substring 134 * 135 * @return Returns the finalSubstrings. 136 */ 137 public String getFinalSubstrings() 138 { 139 return finalSubstrings; 140 } 141 142 143 /** 144 * Set the final substring 145 * 146 * @param finalSubstrings The finalSubstrings to set. 147 */ 148 public void setFinalSubstrings( String finalSubstrings ) 149 { 150 this.finalSubstrings = finalSubstrings; 151 } 152 153 154 /** 155 * Get the initial substring 156 * 157 * @return Returns the initialSubstrings. 158 */ 159 public String getInitialSubstrings() 160 { 161 return initialSubstrings; 162 } 163 164 165 /** 166 * Set the initial substring 167 * 168 * @param initialSubstrings The initialSubstrings to set. 169 */ 170 public void setInitialSubstrings( String initialSubstrings ) 171 { 172 this.initialSubstrings = initialSubstrings; 173 } 174 175 176 /** 177 * Get the attribute 178 * 179 * @return Returns the type. 180 */ 181 public String getType() 182 { 183 return type; 184 } 185 186 187 /** 188 * Set the attribute to match 189 * 190 * @param type The type to set. 191 */ 192 public void setType( String type ) 193 { 194 this.type = type; 195 } 196 197 198 /** 199 * @return Returns the substringsLength. 200 */ 201 public int getSubstringsLength() 202 { 203 return substringsLength; 204 } 205 206 207 /** 208 * @param substringsLength The substringsLength to set. 209 */ 210 public void setSubstringsLength( int substringsLength ) 211 { 212 this.substringsLength = substringsLength; 213 } 214 215 216 /** 217 * Compute the SubstringFilter length 218 * 219 * SubstringFilter : 220 * 0xA4 L1 221 * | 222 * +--> 0x04 L2 type 223 * +--> 0x30 L3 224 * | 225 * [+--> 0x80 L4 initial] 226 * [+--> 0x81 L5-1 any] 227 * [+--> 0x81 L5-2 any] 228 * [+--> ... 229 * [+--> 0x81 L5-i any] 230 * [+--> ... 231 * [+--> 0x81 L5-n any] 232 * [+--> 0x82 L6 final] 233 */ 234 public int computeLength() 235 { 236 // The type 237 typeLength = StringTools.getBytesUtf8( type ).length; 238 239 substringsFilterLength = 1 + TLV.getNbBytes( typeLength ) + typeLength; 240 substringsFilterSequenceLength = 0; 241 242 if ( initialSubstrings != null ) 243 { 244 int initialLength = StringTools.getBytesUtf8( initialSubstrings ).length; 245 substringsFilterSequenceLength += 1 + TLV.getNbBytes( initialLength ) 246 + initialLength; 247 } 248 249 if ( anySubstrings != null ) 250 { 251 for ( String any:anySubstrings ) 252 { 253 int anyLength = StringTools.getBytesUtf8( any ).length; 254 substringsFilterSequenceLength += 1 + TLV.getNbBytes( anyLength ) + anyLength; 255 } 256 } 257 258 if ( finalSubstrings != null ) 259 { 260 int finalLength = StringTools.getBytesUtf8( finalSubstrings ).length; 261 substringsFilterSequenceLength += 1 + TLV.getNbBytes( finalLength ) 262 + finalLength; 263 } 264 265 substringsFilterLength += 1 + TLV.getNbBytes( substringsFilterSequenceLength ) 266 + substringsFilterSequenceLength; 267 268 return 1 + TLV.getNbBytes( substringsFilterLength ) + substringsFilterLength; 269 } 270 271 272 /** 273 * Encode the Substrings Filter to a PDU. 274 * 275 * Substrings Filter : 276 * 277 * 0xA4 LL 278 * 0x30 LL substringsFilter 279 * 0x04 LL type 280 * 0x30 LL substrings sequence 281 * | 0x80 LL initial 282 * | / [0x81 LL any]* 283 * |/ [0x82 LL final] 284 * +--[0x81 LL any]+ 285 * \ [0x82 LL final] 286 * \ 287 * 0x82 LL final 288 * 289 * @param buffer The buffer where to put the PDU 290 * @return The PDU. 291 */ 292 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 293 { 294 if ( buffer == null ) 295 { 296 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 297 } 298 299 try 300 { 301 // The SubstringFilter Tag 302 buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_TAG ); 303 buffer.put( TLV.getBytes( substringsFilterLength ) ); 304 305 // The type 306 Value.encode( buffer, type.getBytes() ); 307 308 // The SubstringSequenceFilter Tag 309 buffer.put( UniversalTag.SEQUENCE_TAG ); 310 buffer.put( TLV.getBytes( substringsFilterSequenceLength ) ); 311 312 if ( ( initialSubstrings == null ) && ( ( anySubstrings == null ) || ( anySubstrings.size() == 0 ) ) 313 && ( finalSubstrings == null ) ) 314 { 315 throw new EncoderException( I18n.err( I18n.ERR_04058 ) ); 316 } 317 318 // The initial substring 319 if ( initialSubstrings != null ) 320 { 321 byte[] initialBytes = StringTools.getBytesUtf8( initialSubstrings ); 322 buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG ); 323 buffer.put( TLV.getBytes( initialBytes.length ) ); 324 buffer.put( initialBytes ); 325 } 326 327 // The any substrings 328 if ( anySubstrings != null ) 329 { 330 for ( String any:anySubstrings ) 331 { 332 byte[] anyBytes = StringTools.getBytesUtf8( any ); 333 buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_ANY_TAG ); 334 buffer.put( TLV.getBytes( anyBytes.length ) ); 335 buffer.put( anyBytes ); 336 } 337 } 338 339 // The final substring 340 if ( finalSubstrings != null ) 341 { 342 byte[] finalBytes = StringTools.getBytesUtf8( finalSubstrings ); 343 buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG ); 344 buffer.put( TLV.getBytes( finalBytes.length ) ); 345 buffer.put( finalBytes ); 346 } 347 } 348 catch ( BufferOverflowException boe ) 349 { 350 throw new EncoderException( I18n.err( I18n.ERR_04005 ) ); 351 } 352 353 return buffer; 354 } 355 356 357 /** 358 * Return a string compliant with RFC 2254 representing a Substring filter 359 * 360 * @return The substring filter string 361 */ 362 public String toString() 363 { 364 365 StringBuffer sb = new StringBuffer(); 366 367 if ( initialSubstrings != null ) 368 { 369 sb.append( initialSubstrings ); 370 } 371 372 sb.append( '*' ); 373 374 if ( anySubstrings != null ) 375 { 376 for ( String any:anySubstrings ) 377 { 378 sb.append( any ).append( '*' ); 379 } 380 } 381 382 if ( finalSubstrings != null ) 383 { 384 sb.append( finalSubstrings ); 385 } 386 387 return sb.toString(); 388 } 389 }