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.i18n.I18n;
030 import org.apache.directory.shared.ldap.codec.LdapConstants;
031 import org.apache.directory.shared.ldap.util.StringTools;
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 * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Dim, 21 fév 2010) $,
039 */
040 public class ExtensibleMatchFilter extends Filter
041 {
042 // ~ Instance fields
043 // ----------------------------------------------------------------------------
044
045 /** The expected lenth of the Matching Rule Assertion */
046 private int expectedMatchingRuleLength;
047
048 /** Matching rule */
049 private String matchingRule;
050
051 /** Matching rule bytes */
052 private byte[] matchingRuleBytes;
053
054 /** Matching rule type */
055 private String type;
056
057 private byte[] typeBytes;
058
059 /** Matching rule value */
060 private org.apache.directory.shared.ldap.entry.Value<?> matchValue;
061
062 /** The dnAttributes flag */
063 private boolean dnAttributes = false;
064
065 /** The extensible match length */
066 private int extensibleMatchLength;
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.shared.ldap.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.shared.ldap.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 = StringTools.getBytesUtf8( matchingRule );
218 extensibleMatchLength = 1 + TLV.getNbBytes( matchingRuleBytes.length ) + matchingRuleBytes.length;
219 }
220
221 if ( type != null )
222 {
223 typeBytes = StringTools.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( Value.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 }