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     */
020    package org.apache.directory.shared.ldap.codec.intermediate;
021    
022    
023    import java.nio.BufferOverflowException;
024    import java.nio.ByteBuffer;
025    
026    import org.apache.directory.shared.asn1.ber.tlv.TLV;
027    import org.apache.directory.shared.asn1.codec.EncoderException;
028    import org.apache.directory.shared.asn1.primitives.OID;
029    import org.apache.directory.shared.i18n.I18n;
030    import org.apache.directory.shared.ldap.codec.LdapConstants;
031    import org.apache.directory.shared.ldap.codec.LdapResponseCodec;
032    import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
033    import org.apache.directory.shared.ldap.util.StringTools;
034    import org.slf4j.Logger;
035    import org.slf4j.LoggerFactory;
036    
037    
038    /**
039     * A IntermediateResponse Message. Its syntax is :
040     *   IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
041     *              responseName     [0] LDAPOID OPTIONAL,
042     *              responseValue    [1] OCTET STRING OPTIONAL }
043     * 
044     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045     * @version $Rev: 664290 $, $Date: 2008-06-07 08:28:06 +0200 (Sat, 07 Jun 2008) $, 
046     */
047    public class IntermediateResponseCodec extends LdapResponseCodec
048    {
049        /** The logger */
050        private static Logger LOGGER = LoggerFactory.getLogger( IntermediateResponseCodec.class );
051    
052        /** Speedup for logs */
053        private static final boolean IS_DEBUG = LOGGER.isDebugEnabled();
054    
055        /** The name */
056        private OID responseName;
057    
058        /** The response */
059        private byte[] responseValue;
060    
061        /** The extended response length */
062        private int intermediateResponseLength;
063    
064        /** The OID length */
065        private int responseNameLength;
066    
067    
068        // ~ Constructors
069        // -------------------------------------------------------------------------------
070    
071        /**
072         * Creates a new IntermediateResponse object.
073         */
074        public IntermediateResponseCodec()
075        {
076            super();
077        }
078    
079    
080        // ~ Methods
081        // ------------------------------------------------------------------------------------
082    
083        /**
084         * Get the message type
085         * 
086         * @return Returns the type.
087         */
088        public MessageTypeEnum getMessageType()
089        {
090            return MessageTypeEnum.INTERMEDIATE_RESPONSE;
091        }
092    
093        
094        /**
095         * {@inheritDoc}
096         */
097        public String getMessageTypeName()
098        {
099            return "INTERMEDIATE_RESPONSE";
100        }
101    
102    
103        /**
104         * Get the intermediate response name
105         * 
106         * @return Returns the name.
107         */
108        public String getResponseName()
109        {
110            return ( ( responseName == null ) ? "" : responseName.toString() );
111        }
112    
113    
114        /**
115         * Set the intermediate response name
116         * 
117         * @param responseName The name to set.
118         */
119        public void setResponseName( OID responseName )
120        {
121            this.responseName = responseName;
122        }
123    
124    
125        /**
126         * Get the intermediate response value
127         * 
128         * @return Returns the intermediate response value.
129         */
130        public byte[] getResponseValue()
131        {
132            return responseValue;
133        }
134    
135    
136        /**
137         * Set the intermediate response value
138         * 
139         * @param responseValue The intermediate response value to set.
140         */
141        public void setResponseValue( byte[] responseValue )
142        {
143            this.responseValue = responseValue;
144        }
145    
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        protected int computeLengthProtocolOp()
165        {
166            intermediateResponseLength = 0;
167    
168            if ( responseName != null )
169            {
170                responseNameLength = responseName.toString().length();
171                intermediateResponseLength += 1 + TLV.getNbBytes( responseNameLength ) + responseNameLength;
172            }
173    
174            if ( responseValue != null )
175            {
176                intermediateResponseLength += 1 + TLV.getNbBytes( responseValue.length )
177                        + responseValue.length;
178            }
179    
180            int length = 1 + TLV.getNbBytes( intermediateResponseLength ) + intermediateResponseLength;
181    
182            if ( IS_DEBUG )
183            {
184                LOGGER.debug( "Intermediate response length : {}", Integer.valueOf( length ) );
185            }
186    
187            return length;
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         * @return The PDU.
200         */
201        protected void encodeProtocolOp( ByteBuffer buffer ) throws EncoderException
202        {
203            try
204            {
205                // The IntermediateResponse Tag
206                buffer.put( LdapConstants.INTERMEDIATE_RESPONSE_TAG );
207                buffer.put( TLV.getBytes( intermediateResponseLength ) );
208    
209                // The responseName, if any
210                if ( responseName != null )
211                {
212                    buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_NAME_TAG );
213                    buffer.put( TLV.getBytes( responseNameLength ) );
214    
215                    if ( responseName.getOIDLength() != 0 )
216                    {
217                        buffer.put( StringTools.getBytesUtf8( responseName.toString() ) );
218                    }
219                }
220    
221                // The response, if any
222                if ( responseValue != null )
223                {
224                    buffer.put( ( byte ) LdapConstants.INTERMEDIATE_RESPONSE_VALUE_TAG );
225    
226                    buffer.put( TLV.getBytes( responseValue.length ) );
227    
228                    if ( responseValue.length != 0 )
229                    {
230                        buffer.put( responseValue );
231                    }
232                }
233            }
234            catch ( BufferOverflowException boe )
235            {
236                String msg = I18n.err( I18n.ERR_04005 );
237                LOGGER.error( msg );
238                throw new EncoderException( msg );
239            }
240        }
241    
242        
243        /**
244         * Get a String representation of an IntermediateResponse
245         * 
246         * @return An IntermediateResponse String
247         */
248        public String toString()
249        {
250    
251            StringBuffer sb = new StringBuffer();
252    
253            sb.append( "    Intermediate Response\n" );
254            sb.append( super.toString() );
255    
256            if ( responseName != null )
257            {
258                sb.append( "        Response name :'" ).append( responseName ).append( "'\n" );
259            }
260    
261            if ( responseValue != null )
262            {
263                sb.append( "        ResponseValue :'" );
264                sb.append( StringTools.dumpBytes( responseValue ) );
265                sb.append( "'\n" );
266            }
267    
268            return sb.toString();
269        }
270    }