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.api;
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.TLV;
028import org.apache.directory.api.i18n.I18n;
029import org.apache.directory.api.ldap.codec.decorators.SingleReplyRequestDecorator;
030import org.apache.directory.api.ldap.model.message.Control;
031import org.apache.directory.api.ldap.model.message.ExtendedRequest;
032import org.apache.directory.api.util.Strings;
033
034
035/**
036 * A decorator for the ExtendedRequest message
037 *
038 * @param <Q> The extended request to decorate
039 * 
040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041 */
042public class ExtendedRequestDecorator<Q extends ExtendedRequest>
043    extends SingleReplyRequestDecorator<Q> implements ExtendedRequest
044{
045    /** The extended request length */
046    private int extendedRequestLength;
047
048    /** The OID bytes */
049    private byte[] requestNameBytes;
050
051    /** The ExtendedRequest value */
052    protected byte[] requestValue;
053
054
055    /**
056     * Makes a ExtendedRequest a MessageDecorator.
057     *
058     * @param codec The LDAP service instance
059     * @param decoratedMessage the decorated ExtendedRequest
060     */
061    public ExtendedRequestDecorator( LdapApiService codec, Q decoratedMessage )
062    {
063        super( codec, decoratedMessage );
064    }
065
066
067    //-------------------------------------------------------------------------
068    // The ExtendedRequest methods
069    //-------------------------------------------------------------------------
070
071    /**
072     * {@inheritDoc}
073     */
074    @Override
075    public String getRequestName()
076    {
077        return getDecorated().getRequestName();
078    }
079
080
081    /**
082     * {@inheritDoc}
083     */
084    @Override
085    public ExtendedRequest setRequestName( String oid )
086    {
087        getDecorated().setRequestName( oid );
088
089        return this;
090    }
091
092
093    /**
094     * Gets the Extended request payload 
095     * 
096     * @return The extended payload
097     */
098    public byte[] getRequestValue()
099    {
100        return requestValue;
101    }
102
103
104    /**
105     * sets the Extended request payload 
106     * 
107     * @param requestValue The extended payload
108     */
109    public void setRequestValue( byte[] requestValue )
110    {
111        this.requestValue = requestValue;
112    }
113
114
115    /**
116     * {@inheritDoc}
117     */
118    @Override
119    public ExtendedRequest setMessageId( int messageId )
120    {
121        super.setMessageId( messageId );
122
123        return this;
124    }
125
126
127    /**
128     * {@inheritDoc}
129     */
130    @Override
131    public ExtendedRequest addControl( Control control )
132    {
133        return ( ExtendedRequest ) super.addControl( control );
134    }
135
136
137    /**
138     * {@inheritDoc}
139     */
140    @Override
141    public ExtendedRequest addAllControls( Control[] controls )
142    {
143        return ( ExtendedRequest ) super.addAllControls( controls );
144    }
145
146
147    /**
148     * {@inheritDoc}
149     */
150    @Override
151    public ExtendedRequest removeControl( Control control )
152    {
153        return ( ExtendedRequest ) super.removeControl( control );
154    }
155
156
157    //-------------------------------------------------------------------------
158    // The Decorator methods
159    //-------------------------------------------------------------------------
160
161    /**
162     * Compute the ExtendedRequest length
163     * <br>
164     * ExtendedRequest :
165     * <pre>
166     * 0x77 L1
167     *  |
168     *  +--&gt; 0x80 L2 name
169     *  [+--&gt; 0x81 L3 value]
170     * 
171     * L1 = Length(0x80) + Length(L2) + L2
172     *      [+ Length(0x81) + Length(L3) + L3]
173     * 
174     * Length(ExtendedRequest) = Length(0x77) + Length(L1) + L1
175     * </pre>
176     */
177    @Override
178    public int computeLength()
179    {
180        requestNameBytes = Strings.getBytesUtf8( getRequestName() );
181
182        extendedRequestLength = 1 + TLV.getNbBytes( requestNameBytes.length ) + requestNameBytes.length;
183
184        if ( getRequestValue() != null )
185        {
186            extendedRequestLength += 1 + TLV.getNbBytes( getRequestValue().length )
187                + getRequestValue().length;
188        }
189
190        return 1 + TLV.getNbBytes( extendedRequestLength ) + extendedRequestLength;
191    }
192
193
194    /**
195     * Encode the ExtendedRequest message to a PDU. 
196     * 
197     * ExtendedRequest :
198     * 
199     * 0x80 LL resquest name
200     * [0x81 LL request value]
201     * 
202     * @param buffer The buffer where to put the PDU
203     * @return The PDU.
204     */
205    @Override
206    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
207    {
208        try
209        {
210            // The BindResponse Tag
211            buffer.put( LdapCodecConstants.EXTENDED_REQUEST_TAG );
212            buffer.put( TLV.getBytes( extendedRequestLength ) );
213
214            // The requestName, if any
215            if ( requestNameBytes == null )
216            {
217                throw new EncoderException( I18n.err( I18n.ERR_04043 ) );
218            }
219
220            buffer.put( ( byte ) LdapCodecConstants.EXTENDED_REQUEST_NAME_TAG );
221            buffer.put( TLV.getBytes( requestNameBytes.length ) );
222
223            if ( requestNameBytes.length != 0 )
224            {
225                buffer.put( requestNameBytes );
226            }
227
228            // The requestValue, if any
229            if ( getRequestValue() != null )
230            {
231                buffer.put( ( byte ) LdapCodecConstants.EXTENDED_REQUEST_VALUE_TAG );
232
233                buffer.put( TLV.getBytes( getRequestValue().length ) );
234
235                if ( getRequestValue().length != 0 )
236                {
237                    buffer.put( getRequestValue() );
238                }
239            }
240        }
241        catch ( BufferOverflowException boe )
242        {
243            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
244        }
245
246        return buffer;
247    }
248}