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