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