View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.codec.search;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  
26  import org.apache.directory.api.asn1.EncoderException;
27  import org.apache.directory.api.asn1.ber.tlv.BerValue;
28  import org.apache.directory.api.asn1.ber.tlv.TLV;
29  import org.apache.directory.api.i18n.I18n;
30  import org.apache.directory.api.ldap.codec.api.LdapConstants;
31  import org.apache.directory.api.util.Strings;
32  
33  
34  /**
35   * The search request filter Matching Rule assertion
36   * 
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   */
39  public class ExtensibleMatchFilter extends Filter
40  {
41      // ~ Instance fields
42      // ----------------------------------------------------------------------------
43  
44      /** The expected lenth of the Matching Rule Assertion */
45      private int expectedMatchingRuleLength;
46  
47      /** Matching rule */
48      private String matchingRule;
49  
50      /** Matching rule bytes */
51      private byte[] matchingRuleBytes;
52  
53      /** Matching rule type */
54      private String type;
55  
56      private byte[] typeBytes;
57  
58      /** Matching rule value */
59      private org.apache.directory.api.ldap.model.entry.Value<?> matchValue;
60  
61      /** The dnAttributes flag */
62      private boolean dnAttributes = false;
63  
64      /** The extensible match length */
65      private int extensibleMatchLength;
66  
67  
68      // ~ Constructors
69      // -------------------------------------------------------------------------------
70      /**
71       * Creates a new ExtensibleMatchFilter object. The dnAttributes flag
72       * defaults to false.
73       */
74      public ExtensibleMatchFilter( int tlvId )
75      {
76          super( tlvId );
77      }
78  
79  
80      /**
81       * Creates a new ExtensibleMatchFilter object. The dnAttributes flag
82       * defaults to false.
83       */
84      public ExtensibleMatchFilter()
85      {
86          super();
87      }
88  
89  
90      // ~ Methods
91      // ------------------------------------------------------------------------------------
92  
93      /**
94       * Get the dnAttributes flag
95       * 
96       * @return Returns the dnAttributes.
97       */
98      public boolean isDnAttributes()
99      {
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 }