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
026 import org.apache.directory.shared.asn1.ber.tlv.TLV;
027 import org.apache.directory.shared.asn1.ber.tlv.Value;
028 import org.apache.directory.shared.asn1.codec.EncoderException;
029 import org.apache.directory.shared.ldap.codec.LdapConstants;
030 import org.apache.directory.shared.ldap.util.StringTools;
031
032
033 /**
034 * The search request filter Matching Rule assertion
035 *
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 * @version $Rev: 798550 $, $Date: 2009-07-28 16:54:01 +0200 (Mar, 28 jul 2009) $,
038 */
039 public 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.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.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.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 = StringTools.getBytesUtf8( matchingRule );
217 extensibleMatchLength = 1 + TLV.getNbBytes( matchingRuleBytes.length ) + matchingRuleBytes.length;
218 }
219
220 if ( type != null )
221 {
222 typeBytes = StringTools.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( "Cannot put a PDU in a null buffer !" );
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( "Cannot have a null matching rule and a null type" );
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( "The PDU buffer size is too small !" );
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 }