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.TLV;
028import org.apache.directory.api.i18n.I18n;
029import org.apache.directory.api.ldap.codec.api.LdapApiService;
030import org.apache.directory.api.ldap.codec.api.LdapConstants;
031import org.apache.directory.api.ldap.codec.api.MessageDecorator;
032import org.apache.directory.api.ldap.model.message.IntermediateResponse;
033import org.apache.directory.api.util.Strings;
034
035
036/**
037 * A decorator for the IntermediateResponse message
038 *
039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040 */
041public class IntermediateResponseDecorator extends MessageDecorator<IntermediateResponse>
042    implements IntermediateResponse
043{
044    /** The response name as a byte[] */
045    private byte[] responseNameBytes;
046
047    /** The encoded intermediateResponse length */
048    private int intermediateResponseLength;
049
050
051    /**
052     * Makes a IntermediateResponse encodable.
053     *
054     * @param decoratedMessage the decorated IntermediateResponse
055     */
056    public IntermediateResponseDecorator( LdapApiService codec, IntermediateResponse decoratedMessage )
057    {
058        super( codec, decoratedMessage );
059    }
060
061
062    /**
063     * Stores the encoded length for the IntermediateResponse
064     *
065     * @param intermediateResponseLength The encoded length
066     */
067    public void setIntermediateResponseLength( int intermediateResponseLength )
068    {
069        this.intermediateResponseLength = intermediateResponseLength;
070    }
071
072
073    /**
074     * @return The encoded IntermediateResponse's length
075     */
076    public int getIntermediateResponseLength()
077    {
078        return intermediateResponseLength;
079    }
080
081
082    /**
083     * Gets the ResponseName bytes
084     *
085     * @return the ResponseName bytes of the Intermediate response type.
086     */
087    public byte[] getResponseNameBytes()
088    {
089        return responseNameBytes;
090    }
091
092
093    /**
094     * Sets the ResponseName bytes
095     *
096     * @param responseNameBytes the ResponseName bytes of the Intermediate response type.
097     */
098    public void setResponseNameBytes( byte[] responseNameBytes )
099    {
100        this.responseNameBytes = responseNameBytes;
101    }
102
103
104    //-------------------------------------------------------------------------
105    // The IntermediateResponse methods
106    //-------------------------------------------------------------------------
107
108    /**
109     * {@inheritDoc}
110     */
111    public String getResponseName()
112    {
113        return getDecorated().getResponseName();
114    }
115
116
117    /**
118     * {@inheritDoc}
119     */
120    public void setResponseName( String oid )
121    {
122        getDecorated().setResponseName( oid );
123    }
124
125
126    /**
127     * {@inheritDoc}
128     */
129    public byte[] getResponseValue()
130    {
131        return getDecorated().getResponseValue();
132    }
133
134
135    /**
136     * {@inheritDoc}
137     */
138    public void setResponseValue( byte[] value )
139    {
140        getDecorated().setResponseValue( value );
141    }
142
143
144    //-------------------------------------------------------------------------
145    // The Decorator methods
146    //-------------------------------------------------------------------------
147    /**
148     * Compute the intermediateResponse length
149     * 
150     * intermediateResponse :
151     * 
152     * 0x79 L1
153     *  |
154     * [+--> 0x80 L2 name
155     * [+--> 0x81 L3 response]]
156     * 
157     * L1 = [ + Length(0x80) + Length(L2) + L2
158     *      [ + Length(0x81) + Length(L3) + L3]]
159     * 
160     * Length(IntermediateResponse) = Length(0x79) + Length(L1) + L1
161     * 
162     * @return The IntermediateResponse length
163     */
164    public int computeLength()
165    {
166        int intermediateResponseLength = 0;
167
168        if ( !Strings.isEmpty( getResponseName() ) )
169        {
170            byte[] responseNameBytes = Strings.getBytesUtf8( getResponseName() );
171
172            int responseNameLength = responseNameBytes.length;
173            intermediateResponseLength += 1 + TLV.getNbBytes( responseNameLength ) + responseNameLength;
174            setResponseNameBytes( responseNameBytes );
175        }
176
177        byte[] encodedValue = getResponseValue();
178
179        if ( encodedValue != null )
180        {
181            intermediateResponseLength += 1 + TLV.getNbBytes( encodedValue.length ) + encodedValue.length;
182        }
183
184        setIntermediateResponseLength( intermediateResponseLength );
185
186        return 1 + TLV.getNbBytes( intermediateResponseLength ) + intermediateResponseLength;
187    }
188
189
190    /**
191     * Encode the IntermediateResponse message to a PDU. 
192     * IntermediateResponse :
193     *   0x79 LL
194     *     [0x80 LL response name]
195     *     [0x81 LL responseValue]
196     * 
197     * @param buffer The buffer where to put the PDU
198     */
199    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
200    {
201        try
202        {
203            // The ExtendedResponse Tag
204            buffer.put( LdapConstants.INTERMEDIATE_RESPONSE_TAG );
205            buffer.put( TLV.getBytes( getIntermediateResponseLength() ) );
206
207            // The responseName, if any
208            byte[] responseNameBytes = getResponseNameBytes();
209
210            if ( ( responseNameBytes != null ) && ( responseNameBytes.length != 0 ) )
211            {
212                buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_NAME_TAG );
213                buffer.put( TLV.getBytes( responseNameBytes.length ) );
214                buffer.put( responseNameBytes );
215            }
216
217            // The encodedValue, if any
218            byte[] encodedValue = getResponseValue();
219
220            if ( encodedValue != null )
221            {
222                buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG );
223
224                buffer.put( TLV.getBytes( encodedValue.length ) );
225
226                if ( encodedValue.length != 0 )
227                {
228                    buffer.put( encodedValue );
229                }
230            }
231        }
232        catch ( BufferOverflowException boe )
233        {
234            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
235        }
236
237        return buffer;
238    }
239}