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.i18n.I18n;
029import org.apache.directory.shared.ldap.codec.api.LdapApiService;
030import org.apache.directory.shared.ldap.codec.api.LdapConstants;
031import org.apache.directory.shared.ldap.codec.api.MessageDecorator;
032import org.apache.directory.shared.ldap.model.message.IntermediateResponse;
033import org.apache.directory.shared.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    /**
110     * {@inheritDoc}
111     */
112    public String getResponseName()
113    {
114        return getDecorated().getResponseName();
115    }
116
117
118    /**
119     * {@inheritDoc}
120     */
121    public void setResponseName( String oid )
122    {
123        getDecorated().setResponseName( oid );
124    }
125
126
127    /**
128     * {@inheritDoc}
129     */
130    public byte[] getResponseValue()
131    {
132        return getDecorated().getResponseValue();
133    }
134
135
136    /**
137     * {@inheritDoc}
138     */
139    public void setResponseValue( byte[] value )
140    {
141        getDecorated().setResponseValue( value );
142    }
143    
144    
145    //-------------------------------------------------------------------------
146    // The Decorator methods
147    //-------------------------------------------------------------------------
148    /**
149     * Compute the intermediateResponse length
150     * 
151     * intermediateResponse :
152     * 
153     * 0x79 L1
154     *  |
155     * [+--> 0x80 L2 name
156     * [+--> 0x81 L3 response]]
157     * 
158     * L1 = [ + Length(0x80) + Length(L2) + L2
159     *      [ + Length(0x81) + Length(L3) + L3]]
160     * 
161     * Length(IntermediateResponse) = Length(0x79) + Length(L1) + L1
162     * 
163     * @return The IntermediateResponse length
164     */
165    public int computeLength()
166    {
167        int intermediateResponseLength = 0;
168
169        if ( !Strings.isEmpty( getResponseName() ) )
170        {
171            byte[] responseNameBytes = Strings.getBytesUtf8( getResponseName() );
172
173            int responseNameLength = responseNameBytes.length;
174            intermediateResponseLength += 1 + TLV.getNbBytes( responseNameLength ) + responseNameLength;
175            setResponseNameBytes( responseNameBytes );
176        }
177
178        byte[] encodedValue = getResponseValue();
179
180        if ( encodedValue != null )
181        {
182            intermediateResponseLength += 1 + TLV.getNbBytes( encodedValue.length ) + encodedValue.length;
183        }
184
185        setIntermediateResponseLength( intermediateResponseLength );
186
187        return 1 + TLV.getNbBytes( intermediateResponseLength ) + intermediateResponseLength;
188    }
189
190
191    /**
192     * Encode the IntermediateResponse message to a PDU. 
193     * IntermediateResponse :
194     *   0x79 LL
195     *     [0x80 LL response name]
196     *     [0x81 LL responseValue]
197     * 
198     * @param buffer The buffer where to put the PDU
199     */
200    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
201    {
202        try
203        {
204            // The ExtendedResponse Tag
205            buffer.put( LdapConstants.INTERMEDIATE_RESPONSE_TAG );
206            buffer.put( TLV.getBytes( getIntermediateResponseLength() ) );
207
208            // The responseName, if any
209            byte[] responseNameBytes = getResponseNameBytes();
210
211            if ( ( responseNameBytes != null ) && ( responseNameBytes.length != 0 ) )
212            {
213                buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_NAME_TAG );
214                buffer.put( TLV.getBytes( responseNameBytes.length ) );
215                buffer.put( responseNameBytes );
216            }
217
218            // The encodedValue, if any
219            byte[] encodedValue = getResponseValue();
220
221            if ( encodedValue != null )
222            {
223                buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG );
224
225                buffer.put( TLV.getBytes( encodedValue.length ) );
226
227                if ( encodedValue.length != 0 )
228                {
229                    buffer.put( encodedValue );
230                }
231            }
232        }
233        catch ( BufferOverflowException boe )
234        {
235            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
236        }
237        
238        return buffer;
239    }
240}