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.extended;
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.ldap.codec.LdapConstants;
030    import org.apache.directory.shared.ldap.codec.LdapResponseCodec;
031    import org.apache.directory.shared.ldap.util.StringTools;
032    
033    
034    /**
035     * A ExtendedResponse Message. Its syntax is :
036     *   ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
037     *              COMPONENTS OF LDAPResult,
038     *              responseName     [10] LDAPOID OPTIONAL,
039     *              response         [11] OCTET STRING OPTIONAL }
040     * 
041     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042     * @version $Rev: 764131 $, $Date: 2009-04-11 03:03:00 +0200 (Sam, 11 avr 2009) $, 
043     */
044    public class ExtendedResponseCodec extends LdapResponseCodec
045    {
046        // ~ Instance fields
047        // ----------------------------------------------------------------------------
048    
049        /** The name */
050        private OID responseName;
051    
052        /** The response */
053        private Object response;
054    
055        /** The extended response length */
056        private int extendedResponseLength;
057    
058        /** The OID length */
059        private int responseNameLength;
060    
061    
062        // ~ Constructors
063        // -------------------------------------------------------------------------------
064    
065        /**
066         * Creates a new ExtendedResponse object.
067         */
068        public ExtendedResponseCodec()
069        {
070            super();
071        }
072    
073    
074        // ~ Methods
075        // ------------------------------------------------------------------------------------
076    
077        /**
078         * Get the message type
079         * 
080         * @return Returns the type.
081         */
082        public int getMessageType()
083        {
084            return LdapConstants.EXTENDED_RESPONSE;
085        }
086    
087    
088        /**
089         * Get the extended response name
090         * 
091         * @return Returns the name.
092         */
093        public String getResponseName()
094        {
095            return ( ( responseName == null ) ? "" : responseName.toString() );
096        }
097    
098    
099        /**
100         * Set the extended response name
101         * 
102         * @param responseName The name to set.
103         */
104        public void setResponseName( OID responseName )
105        {
106            this.responseName = responseName;
107        }
108    
109    
110        /**
111         * Get the extended response
112         * 
113         * @return Returns the response.
114         */
115        public Object getResponse()
116        {
117            return response;
118        }
119    
120    
121        /**
122         * Set the extended response
123         * 
124         * @param response The response to set.
125         */
126        public void setResponse( Object response )
127        {
128            this.response = response;
129        }
130    
131    
132        /**
133         * Compute the ExtendedResponse length
134         * 
135         * ExtendedResponse :
136         * 
137         * 0x78 L1
138         *  |
139         *  +--> LdapResult
140         * [+--> 0x8A L2 name
141         * [+--> 0x8B L3 response]]
142         * 
143         * L1 = Length(LdapResult)
144         *      [ + Length(0x8A) + Length(L2) + L2
145         *       [ + Length(0x8B) + Length(L3) + L3]]
146         * 
147         * Length(ExtendedResponse) = Length(0x78) + Length(L1) + L1
148         * 
149         * @return The ExtendedResponse length
150         */
151        public int computeLength()
152        {
153            extendedResponseLength = super.computeLength();
154    
155            if ( responseName != null )
156            {
157                responseNameLength = responseName.toString().length();
158                extendedResponseLength += 1 + TLV.getNbBytes( responseNameLength ) + responseNameLength;
159            }
160    
161            if ( response != null )
162            {
163                if ( response instanceof String )
164                {
165                    int responseLength = StringTools.getBytesUtf8( ( String ) response ).length;
166                    extendedResponseLength += 1 + TLV.getNbBytes( responseLength ) + responseLength;
167                }
168                else
169                {
170                    extendedResponseLength += 1 + TLV.getNbBytes( ( ( byte[] ) response ).length )
171                        + ( ( byte[] ) response ).length;
172                }
173            }
174    
175            return 1 + TLV.getNbBytes( extendedResponseLength ) + extendedResponseLength;
176        }
177    
178    
179        /**
180         * Encode the ExtendedResponse message to a PDU. 
181         * ExtendedResponse :
182         * LdapResult.encode()
183         * [0x8A LL response name]
184         * [0x8B LL response]
185         * 
186         * @param buffer
187         *            The buffer where to put the PDU
188         * @return The PDU.
189         */
190        public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
191        {
192            if ( buffer == null )
193            {
194                throw new EncoderException( "Cannot put a PDU in a null buffer !" );
195            }
196    
197            try
198            {
199                // The ExtendedResponse Tag
200                buffer.put( LdapConstants.EXTENDED_RESPONSE_TAG );
201                buffer.put( TLV.getBytes( extendedResponseLength ) );
202    
203                // The LdapResult
204                super.encode( buffer );
205    
206                // The responseName, if any
207                if ( responseName != null )
208                {
209                    buffer.put( ( byte ) LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG );
210                    buffer.put( TLV.getBytes( responseNameLength ) );
211    
212                    if ( responseName.getOIDLength() != 0 )
213                    {
214                        buffer.put( StringTools.getBytesUtf8( responseName.toString() ) );
215                    }
216                }
217    
218                // The response, if any
219                if ( response != null )
220                {
221                    buffer.put( ( byte ) LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG );
222    
223                    if ( response instanceof String )
224                    {
225                        byte[] responseBytes = StringTools.getBytesUtf8( ( String ) response );
226                        buffer.put( TLV.getBytes( responseBytes.length ) );
227    
228                        if ( responseBytes.length != 0 )
229                        {
230                            buffer.put( responseBytes );
231                        }
232                    }
233                    else
234                    {
235                        buffer.put( TLV.getBytes( ( ( byte[] ) response ).length ) );
236    
237                        if ( ( ( byte[] ) response ).length != 0 )
238                        {
239                            buffer.put( ( byte[] ) response );
240                        }
241                    }
242                }
243            }
244            catch ( BufferOverflowException boe )
245            {
246                throw new EncoderException( "The PDU buffer size is too small !" );
247            }
248    
249            return buffer;
250        }
251    
252    
253        /**
254         * Get a String representation of an ExtendedResponse
255         * 
256         * @return An ExtendedResponse String
257         */
258        public String toString()
259        {
260    
261            StringBuffer sb = new StringBuffer();
262    
263            sb.append( "    Extended Response\n" );
264            sb.append( super.toString() );
265    
266            if ( responseName != null )
267            {
268                sb.append( "        Response name :'" ).append( responseName ).append( "'\n" );
269            }
270    
271            if ( response != null )
272            {
273                sb.append( "        Response :'" ).append( response ).append( "'\n" );
274            }
275    
276            return sb.toString();
277        }
278    }