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 */ 020package org.apache.directory.api.ldap.codec.search; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025 026import org.apache.directory.api.asn1.EncoderException; 027import org.apache.directory.api.asn1.ber.tlv.BerValue; 028import org.apache.directory.api.asn1.ber.tlv.TLV; 029import org.apache.directory.api.i18n.I18n; 030import org.apache.directory.api.ldap.codec.api.LdapConstants; 031import org.apache.directory.api.util.Strings; 032 033 034/** 035 * The search request filter Matching Rule assertion 036 * 037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 038 */ 039public class ExtensibleMatchFilter extends Filter 040{ 041 // ~ Instance fields 042 // ---------------------------------------------------------------------------- 043 044 /** The expected lenth of the Matching Rule Assertion */ 045 private int expectedMatchingRuleLength; 046 047 /** Matching rule */ 048 private String matchingRule; 049 050 /** Matching rule bytes */ 051 private byte[] matchingRuleBytes; 052 053 /** Matching rule type */ 054 private String type; 055 056 private byte[] typeBytes; 057 058 /** Matching rule value */ 059 private org.apache.directory.api.ldap.model.entry.Value<?> matchValue; 060 061 /** The dnAttributes flag */ 062 private boolean dnAttributes = false; 063 064 /** The extensible match length */ 065 private int extensibleMatchLength; 066 067 068 // ~ Constructors 069 // ------------------------------------------------------------------------------- 070 /** 071 * Creates a new ExtensibleMatchFilter object. The dnAttributes flag 072 * defaults to false. 073 */ 074 public ExtensibleMatchFilter( int tlvId ) 075 { 076 super( tlvId ); 077 } 078 079 080 /** 081 * Creates a new ExtensibleMatchFilter object. The dnAttributes flag 082 * defaults to false. 083 */ 084 public ExtensibleMatchFilter() 085 { 086 super(); 087 } 088 089 090 // ~ Methods 091 // ------------------------------------------------------------------------------------ 092 093 /** 094 * Get the dnAttributes flag 095 * 096 * @return Returns the dnAttributes. 097 */ 098 public boolean isDnAttributes() 099 { 100 return dnAttributes; 101 } 102 103 104 /** 105 * Set the dnAttributes flag 106 * 107 * @param dnAttributes The dnAttributes to set. 108 */ 109 public void setDnAttributes( boolean dnAttributes ) 110 { 111 this.dnAttributes = dnAttributes; 112 } 113 114 115 /** 116 * Get the matchingRule 117 * 118 * @return Returns the matchingRule. 119 */ 120 public String getMatchingRule() 121 { 122 return matchingRule; 123 } 124 125 126 /** 127 * Set the matchingRule 128 * 129 * @param matchingRule The matchingRule to set. 130 */ 131 public void setMatchingRule( String matchingRule ) 132 { 133 this.matchingRule = matchingRule; 134 } 135 136 137 /** 138 * Get the matchValue 139 * 140 * @return Returns the matchValue. 141 */ 142 public org.apache.directory.api.ldap.model.entry.Value<?> getMatchValue() 143 { 144 return matchValue; 145 } 146 147 148 /** 149 * Set the matchValue 150 * 151 * @param matchValue The matchValue to set. 152 */ 153 public void setMatchValue( org.apache.directory.api.ldap.model.entry.Value<?> matchValue ) 154 { 155 this.matchValue = matchValue; 156 } 157 158 159 /** 160 * Get the type 161 * 162 * @return Returns the type. 163 */ 164 public String getType() 165 { 166 return type; 167 } 168 169 170 /** 171 * Set the type 172 * 173 * @param type The type to set. 174 */ 175 public void setType( String type ) 176 { 177 this.type = type; 178 } 179 180 181 /** 182 * get the expectedMatchingRuleLength 183 * 184 * @return Returns the expectedMatchingRuleLength. 185 */ 186 public int getExpectedMatchingRuleLength() 187 { 188 return expectedMatchingRuleLength; 189 } 190 191 192 /** 193 * Set the expectedMatchingRuleLength 194 * 195 * @param expectedMatchingRuleLength The expectedMatchingRuleLength to set. 196 */ 197 public void setExpectedMatchingRuleLength( int expectedMatchingRuleLength ) 198 { 199 this.expectedMatchingRuleLength = expectedMatchingRuleLength; 200 } 201 202 203 /** 204 * Compute the ExtensibleMatchFilter length 205 * ExtensibleMatchFilter : 206 * 0xA9 L1 207 * | 208 * [+--> 0x81 L3 matchingRule] 209 * [+--> 0x82 L4 type] 210 * [+--> 0x83 L5 matchValue] 211 * [+--> 0x01 0x01 dnAttributes] 212 */ 213 public int computeLength() 214 { 215 if ( matchingRule != null ) 216 { 217 matchingRuleBytes = Strings.getBytesUtf8( matchingRule ); 218 extensibleMatchLength = 1 + TLV.getNbBytes( matchingRuleBytes.length ) + matchingRuleBytes.length; 219 } 220 221 if ( type != null ) 222 { 223 typeBytes = Strings.getBytesUtf8( type ); 224 extensibleMatchLength += 1 + TLV.getNbBytes( typeBytes.length ) + typeBytes.length; 225 } 226 227 if ( matchValue != null ) 228 { 229 int bytesLength = matchValue.getBytes().length; 230 extensibleMatchLength += 1 + TLV.getNbBytes( bytesLength ) + bytesLength; 231 } 232 233 if ( dnAttributes ) 234 { 235 extensibleMatchLength += 1 + 1 + 1; 236 } 237 238 return 1 + TLV.getNbBytes( extensibleMatchLength ) + extensibleMatchLength; 239 } 240 241 242 /** 243 * Encode the ExtensibleMatch Filters to a PDU. 244 * 245 * ExtensibleMatch filter : 246 * 247 * 0xA9 LL 248 * | 0x81 LL matchingRule 249 * | / | 0x82 LL Type 250 * | / | /0x83 LL matchValue 251 * +--+ +-+ 252 * | \ \ 253 * | \ 0x83 LL MatchValue 254 * | 0x82 LL type 255 * | 0x83 LL matchValue 256 * +--[0x84 0x01 dnAttributes] 257 * 258 * @param buffer The buffer where to put the PDU 259 * @return The PDU. 260 */ 261 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 262 { 263 if ( buffer == null ) 264 { 265 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 266 } 267 268 try 269 { 270 // The ExtensibleMatch Tag 271 buffer.put( ( byte ) LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG ); 272 buffer.put( TLV.getBytes( extensibleMatchLength ) ); 273 274 if ( ( matchingRule == null ) && ( type == null ) ) 275 { 276 throw new EncoderException( I18n.err( I18n.ERR_04056 ) ); 277 } 278 279 // The matching rule 280 if ( matchingRule != null ) 281 { 282 buffer.put( ( byte ) LdapConstants.MATCHING_RULE_ID_TAG ); 283 buffer.put( TLV.getBytes( matchingRuleBytes.length ) ); 284 buffer.put( matchingRuleBytes ); 285 } 286 287 // The type 288 if ( type != null ) 289 { 290 buffer.put( ( byte ) LdapConstants.MATCHING_RULE_TYPE_TAG ); 291 buffer.put( TLV.getBytes( typeBytes.length ) ); 292 buffer.put( typeBytes ); 293 } 294 295 // The match value 296 if ( matchValue != null ) 297 { 298 buffer.put( ( byte ) LdapConstants.MATCH_VALUE_TAG ); 299 300 byte[] bytes = matchValue.getBytes(); 301 int bytesLength = bytes.length; 302 buffer.put( TLV.getBytes( bytesLength ) ); 303 304 if ( bytesLength != 0 ) 305 { 306 buffer.put( bytes ); 307 } 308 309 } 310 311 // The dnAttributes flag, if true only 312 if ( dnAttributes ) 313 { 314 buffer.put( ( byte ) LdapConstants.DN_ATTRIBUTES_FILTER_TAG ); 315 buffer.put( ( byte ) 1 ); 316 buffer.put( BerValue.TRUE_VALUE ); 317 } 318 } 319 catch ( BufferOverflowException boe ) 320 { 321 throw new EncoderException( I18n.err( I18n.ERR_04005 ) ); 322 } 323 324 return buffer; 325 } 326 327 328 /** 329 * Return a String representing an extended filter as of RFC 2254 330 * 331 * @return An Extened Filter String 332 */ 333 public String toString() 334 { 335 336 StringBuffer sb = new StringBuffer(); 337 338 if ( type != null ) 339 { 340 sb.append( type ); 341 } 342 343 if ( dnAttributes ) 344 { 345 sb.append( ":dn" ); 346 } 347 348 if ( matchingRule == null ) 349 { 350 351 if ( type == null ) 352 { 353 return "Extended Filter wrong syntax"; 354 } 355 } 356 else 357 { 358 sb.append( ':' ).append( matchingRule ); 359 } 360 361 sb.append( ":=" ).append( matchValue ); 362 363 return sb.toString(); 364 } 365}