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.LdapMessageCodec;
032    import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
033    import org.apache.directory.shared.ldap.util.StringTools;
034    
035    
036    /**
037     * A ExtendedRequest Message. Its syntax is :
038     *   ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
039     *              requestName      [0] LDAPOID,
040     *              requestValue     [1] OCTET STRING OPTIONAL }
041     * 
042     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043     * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Sun, 21 Feb 2010) $, 
044     */
045    public class ExtendedRequestCodec extends LdapMessageCodec
046    {
047        // ~ Instance fields
048        // ----------------------------------------------------------------------------
049    
050        /** The name */
051        private OID requestName;
052    
053        /** The value */
054        private byte[] requestValue;
055    
056        /** The extended request length */
057        private int extendedRequestLength;
058    
059        /** The OID length */
060        private int oidLength;
061    
062    
063        // ~ Constructors
064        // -------------------------------------------------------------------------------
065    
066        /**
067         * Creates a new ExtendedRequest object.
068         */
069        public ExtendedRequestCodec()
070        {
071            super();
072        }
073    
074    
075        // ~ Methods
076        // ------------------------------------------------------------------------------------
077    
078        /**
079         * Get the message type
080         * 
081         * @return Returns the type.
082         */
083        public MessageTypeEnum getMessageType()
084        {
085            return MessageTypeEnum.EXTENDED_REQUEST;
086        }
087    
088        
089        /**
090         * {@inheritDoc}
091         */
092        public String getMessageTypeName()
093        {
094            return "EXTENDED_REQUEST";
095        }
096    
097    
098        /**
099         * Get the extended request name
100         * 
101         * @return Returns the request name.
102         */
103        public String getRequestName()
104        {
105            return ( ( requestName == null ) ? "" : requestName.toString() );
106        }
107    
108    
109        /**
110         * Set the extended request name
111         * 
112         * @param requestName The request name to set.
113         */
114        public void setRequestName( OID requestName )
115        {
116            this.requestName = requestName;
117        }
118    
119    
120        /**
121         * Get the extended request value
122         * 
123         * @return Returns the request value.
124         */
125        public byte[] getRequestValue()
126        {
127            if ( requestValue == null )
128            {
129                return null;
130            }
131    
132            final byte[] copy = new byte[ requestValue.length ];
133            System.arraycopy( requestValue, 0, copy, 0, requestValue.length );
134            return copy;
135        }
136    
137    
138        /**
139         * Set the extended request value
140         * 
141         * @param requestValue The request value to set.
142         */
143        public void setRequestValue( byte[] requestValue )
144        {
145            if ( requestValue != null )
146            {
147                this.requestValue = new byte[ requestValue.length ];
148                System.arraycopy( requestValue, 0, this.requestValue, 0, requestValue.length );
149            } else {
150                this.requestValue = null;
151            }
152        }
153    
154    
155        /**
156         * Compute the ExtendedRequest length
157         * 
158         * ExtendedRequest :
159         * 
160         * 0x77 L1
161         *  |
162         *  +--> 0x80 L2 name
163         *  [+--> 0x81 L3 value]
164         * 
165         * L1 = Length(0x80) + Length(L2) + L2
166         *      [+ Length(0x81) + Length(L3) + L3]
167         * 
168         * Length(ExtendedRequest) = Length(0x77) + Length(L1) + L1
169         */
170        protected int computeLengthProtocolOp()
171        {
172            oidLength = requestName.toString().length();
173            extendedRequestLength = 1 + TLV.getNbBytes( oidLength ) + oidLength;
174    
175            if ( requestValue != null )
176            {
177                extendedRequestLength += 1 + TLV.getNbBytes( requestValue.length )
178                    + requestValue.length;
179            }
180    
181            return 1 + TLV.getNbBytes( extendedRequestLength ) + extendedRequestLength;
182        }
183    
184    
185        /**
186         * Encode the ExtendedRequest message to a PDU. 
187         * 
188         * ExtendedRequest :
189         * 
190         * 0x80 LL resquest name
191         * [0x81 LL request value]
192         * 
193         * @param buffer The buffer where to put the PDU
194         * @return The PDU.
195         */
196        protected void encodeProtocolOp( ByteBuffer buffer ) throws EncoderException
197        {
198            try
199            {
200                // The BindResponse Tag
201                buffer.put( LdapConstants.EXTENDED_REQUEST_TAG );
202                buffer.put( TLV.getBytes( extendedRequestLength ) );
203    
204                // The requestName, if any
205                if ( requestName == null )
206                {
207                    throw new EncoderException( I18n.err( I18n.ERR_04043 ) );
208                }
209    
210                buffer.put( ( byte ) LdapConstants.EXTENDED_REQUEST_NAME_TAG );
211                buffer.put( TLV.getBytes( oidLength ) );
212    
213                if ( requestName.getOIDLength() != 0 )
214                {
215                    buffer.put( StringTools.getBytesUtf8( requestName.toString() ) );
216                }
217    
218                // The requestValue, if any
219                if ( requestValue != null )
220                {
221                    buffer.put( ( byte ) LdapConstants.EXTENDED_REQUEST_VALUE_TAG );
222    
223                    buffer.put( TLV.getBytes( requestValue.length ) );
224    
225                    if ( requestValue.length != 0 )
226                    {
227                        buffer.put( requestValue );
228                    }
229                }
230            }
231            catch ( BufferOverflowException boe )
232            {
233                throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
234            }
235        }
236    
237    
238        /**
239         * Get a String representation of an Extended Request
240         * 
241         * @return an Extended Request String
242         */
243        public String toString()
244        {
245            StringBuffer sb = new StringBuffer();
246    
247            sb.append( "    Extended request\n" );
248            sb.append( "        Request name : '" ).append( requestName ).append( "'\n" );
249    
250            if ( requestValue != null )
251            {
252                sb.append( "        Request value : '" ).
253                    append( StringTools.dumpBytes( requestValue ) ).
254                    append( "'\n" );
255            }
256    
257            return sb.toString();
258        }
259    }