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