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.decorators;
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.UniversalTag;
029import org.apache.directory.shared.i18n.I18n;
030import org.apache.directory.shared.ldap.codec.api.LdapApiService;
031import org.apache.directory.shared.ldap.codec.api.LdapConstants;
032import org.apache.directory.shared.ldap.model.entry.BinaryValue;
033import org.apache.directory.shared.ldap.model.entry.Value;
034import org.apache.directory.shared.ldap.model.exception.MessageException;
035import org.apache.directory.shared.ldap.model.message.CompareRequest;
036import org.apache.directory.shared.ldap.model.message.CompareResponse;
037import org.apache.directory.shared.ldap.model.message.Control;
038import org.apache.directory.shared.ldap.model.name.Dn;
039import org.apache.directory.shared.util.Strings;
040
041
042/**
043 * A decorator for the CompareRequest message
044 *
045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
046 */
047public class CompareRequestDecorator extends SingleReplyRequestDecorator<CompareRequest, CompareResponse> 
048    implements CompareRequest
049{
050    /** The bytes of the attribute id used in the comparison */
051    private byte[] attrIdBytes;
052
053    /** The bytes of the attribute value used in the comparison */
054    private byte[] attrValBytes;
055
056    /** The compare request length */
057    private int compareRequestLength;
058
059    /** The attribute value assertion length */
060    private int avaLength;
061
062
063    /**
064     * Makes a CompareRequest a MessageDecorator.
065     *
066     * @param decoratedMessage the decorated CompareRequest
067     */
068    public CompareRequestDecorator( LdapApiService codec, CompareRequest decoratedMessage )
069    {
070        super( codec, decoratedMessage );
071    }
072
073
074    /**
075     * Stores the encoded length for the CompareRequest
076     * @param compareRequestLength The encoded length
077     */
078    public void setCompareRequestLength( int compareRequestLength )
079    {
080        this.compareRequestLength = compareRequestLength;
081    }
082
083
084    /**
085     * @return The encoded CompareRequest length
086     */
087    public int getCompareRequestLength()
088    {
089        return compareRequestLength;
090    }
091
092
093    /**
094     * Stores the encoded length for the ava
095     * @param avaLength The encoded length
096     */
097    public void setAvaLength( int avaLength )
098    {
099        this.avaLength = avaLength;
100    }
101
102
103    /**
104     * @return The encoded ava length
105     */
106    public int getAvaLength()
107    {
108        return avaLength;
109    }
110
111
112    /**
113     * Gets the attribute id bytes use in making the comparison.
114     *
115     * @return the attribute id bytes used in comparison.
116     */
117    public byte[] getAttrIdBytes()
118    {
119        return attrIdBytes;
120    }
121
122
123    /**
124     * Sets the attribute id bytes used in the comparison.
125     *
126     * @param attrIdBytes the attribute id bytes used in comparison.
127     */
128    public void setAttrIdBytes( byte[] attrIdBytes )
129    {
130        this.attrIdBytes = attrIdBytes;
131    }
132
133
134    /**
135     * Gets the attribute value bytes use in making the comparison.
136     *
137     * @return the attribute value bytes used in comparison.
138     */
139    public byte[] getAttrValBytes()
140    {
141        return attrValBytes;
142    }
143
144
145    /**
146     * Sets the attribute value bytes used in the comparison.
147     *
148     * @param attrValBytes the attribute value bytes used in comparison.
149     */
150    public void setAttrValBytes( byte[] attrValBytes )
151    {
152        this.attrValBytes = attrValBytes;
153    }
154
155
156    //-------------------------------------------------------------------------
157    // The CompareRequest methods
158    //-------------------------------------------------------------------------
159
160    
161    /**
162     * {@inheritDoc}
163     */
164    public Dn getName()
165    {
166        return getDecorated().getName();
167    }
168
169
170    /**
171     * {@inheritDoc}
172     */
173    public CompareRequest setName( Dn name )
174    {
175        getDecorated().setName( name );
176        
177        return this;
178    }
179
180
181    /**
182     * {@inheritDoc}
183     */
184    public Value<?> getAssertionValue()
185    {
186        return getDecorated().getAssertionValue();
187    }
188
189
190    /**
191     * {@inheritDoc}
192     */
193    public CompareRequest setAssertionValue( String value )
194    {
195        getDecorated().setAssertionValue( value );
196        
197        return this;
198    }
199
200
201    /**
202     * {@inheritDoc}
203     */
204    public CompareRequest setAssertionValue( byte[] value )
205    {
206        getDecorated().setAssertionValue( value );
207        
208        return this;
209    }
210
211
212    /**
213     * {@inheritDoc}
214     */
215    public String getAttributeId()
216    {
217        return getDecorated().getAttributeId();
218    }
219
220
221    /**
222     * {@inheritDoc}
223     */
224    public CompareRequest setAttributeId( String attrId )
225    {
226        getDecorated().setAttributeId( attrId );
227        
228        return this;
229    }
230    
231    
232    /**
233     * {@inheritDoc}
234     */
235    public CompareRequest setMessageId( int messageId )
236    {
237        super.setMessageId( messageId );
238        
239        return this;
240    }
241
242    
243    /**
244     * {@inheritDoc}
245     */
246    public CompareRequest addControl( Control control ) throws MessageException
247    {
248        return (CompareRequest)super.addControl( control );
249    }
250    
251    
252    /**
253     * {@inheritDoc}
254     */
255    public CompareRequest addAllControls( Control[] controls ) throws MessageException
256    {
257        return (CompareRequest)super.addAllControls( controls );
258    }
259    
260    
261    /**
262     * {@inheritDoc}
263     */
264    public CompareRequest removeControl( Control control ) throws MessageException
265    {
266        return (CompareRequest)super.removeControl( control );
267    }
268
269    
270    //-------------------------------------------------------------------------
271    // The Decorator methods
272    //-------------------------------------------------------------------------
273    /**
274     * Compute the CompareRequest length 
275     * 
276     * CompareRequest : 
277     * 0x6E L1 
278     *   | 
279     *   +--> 0x04 L2 entry 
280     *   +--> 0x30 L3 (ava) 
281     *         | 
282     *         +--> 0x04 L4 attributeDesc 
283     *         +--> 0x04 L5 assertionValue 
284     *         
285     * L3 = Length(0x04) + Length(L4) + L4 + Length(0x04) +
286     *      Length(L5) + L5 
287     * Length(CompareRequest) = Length(0x6E) + Length(L1) + L1 +
288     *      Length(0x04) + Length(L2) + L2 + Length(0x30) + Length(L3) + L3
289     * 
290     * @return The CompareRequest PDU's length
291     */
292    public int computeLength()
293    {
294        // The entry Dn
295        Dn entry = getName();
296        int compareRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( entry ) ) + Dn.getNbBytes( entry );
297
298        // The attribute value assertion
299        byte[] attributeIdBytes = Strings.getBytesUtf8( getAttributeId() );
300        int avaLength = 1 + TLV.getNbBytes( attributeIdBytes.length ) + attributeIdBytes.length;
301        setAttrIdBytes( attributeIdBytes );
302
303        org.apache.directory.shared.ldap.model.entry.Value<?> assertionValue = getAssertionValue();
304
305        if ( assertionValue instanceof BinaryValue )
306        {
307            byte[] value = getAssertionValue().getBytes();
308            avaLength += 1 + TLV.getNbBytes( value.length ) + value.length;
309            setAttrValBytes( value );
310        }
311        else
312        {
313            byte[] value = Strings.getBytesUtf8( getAssertionValue().getString() );
314            avaLength += 1 + TLV.getNbBytes( value.length ) + value.length;
315            setAttrValBytes( value );
316        }
317
318        setAvaLength( avaLength );
319        compareRequestLength += 1 + TLV.getNbBytes( avaLength ) + avaLength;
320        setCompareRequestLength( compareRequestLength );
321
322        return 1 + TLV.getNbBytes( compareRequestLength ) + compareRequestLength;
323    }
324
325
326    /**
327     * Encode the CompareRequest message to a PDU. 
328     * 
329     * CompareRequest : 
330     *   0x6E LL 
331     *     0x04 LL entry 
332     *     0x30 LL attributeValueAssertion 
333     *       0x04 LL attributeDesc 
334     *       0x04 LL assertionValue
335     * 
336     * @param buffer The buffer where to put the PDU
337     */
338    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
339    {
340        try
341        {
342            // The CompareRequest Tag
343            buffer.put( LdapConstants.COMPARE_REQUEST_TAG );
344            buffer.put( TLV.getBytes( getCompareRequestLength() ) );
345
346            // The entry
347            org.apache.directory.shared.asn1.ber.tlv.Value.encode( buffer, Dn.getBytes( getName() ) );
348
349            // The attributeValueAssertion sequence Tag
350            buffer.put( UniversalTag.SEQUENCE.getValue() );
351            buffer.put( TLV.getBytes( getAvaLength() ) );
352        }
353        catch ( BufferOverflowException boe )
354        {
355            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
356        }
357
358        // The attributeDesc
359        org.apache.directory.shared.asn1.ber.tlv.Value.encode( buffer, getAttrIdBytes() );
360
361        // The assertionValue
362        org.apache.directory.shared.asn1.ber.tlv.Value.encode( buffer, ( byte[] ) getAttrValBytes() );
363        
364        return buffer;
365    }
366 }