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.asn1.ber.tlv.Value;
029import org.apache.directory.shared.i18n.I18n;
030import org.apache.directory.shared.ldap.codec.api.LdapApiService;
031import org.apache.directory.shared.ldap.codec.api.LdapConstants;
032import org.apache.directory.shared.ldap.model.exception.MessageException;
033import org.apache.directory.shared.ldap.model.message.Control;
034import org.apache.directory.shared.ldap.model.message.ModifyDnRequest;
035import org.apache.directory.shared.ldap.model.message.ModifyDnResponse;
036import org.apache.directory.shared.ldap.model.name.Dn;
037import org.apache.directory.shared.ldap.model.name.Rdn;
038import org.apache.directory.shared.util.Strings;
039
040
041/**
042 * A decorator for the ModifyDnRequest message
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 */
046public class ModifyDnRequestDecorator extends SingleReplyRequestDecorator<ModifyDnRequest,ModifyDnResponse> 
047    implements ModifyDnRequest
048{
049    /** The modify Dn request length */
050    private int modifyDnRequestLength;
051
052
053    /**
054     * Makes a ModifyDnRequest encodable.
055     *
056     * @param decoratedMessage the decorated ModifyDnRequest
057     */
058    public ModifyDnRequestDecorator( LdapApiService codec, ModifyDnRequest decoratedMessage )
059    {
060        super( codec, decoratedMessage );
061    }
062
063
064    /**
065     * @param modifyDnRequestLength The encoded ModifyDnRequest's length
066     */
067    public void setModifyDnRequestLength( int modifyDnRequestLength )
068    {
069        this.modifyDnRequestLength = modifyDnRequestLength;
070    }
071
072
073    /**
074     * Stores the encoded length for the ModifyDnRequest
075     * @return the encoded length
076     */
077    public int getModifyDnResponseLength()
078    {
079        return modifyDnRequestLength;
080    }
081
082
083    //-------------------------------------------------------------------------
084    // The ModifyDnResponse methods
085    //-------------------------------------------------------------------------
086    
087    
088    /**
089     * {@inheritDoc}
090     */
091    public Dn getName()
092    {
093        return getDecorated().getName();
094    }
095
096
097    /**
098     * {@inheritDoc}
099     */
100    public ModifyDnRequest setName( Dn name )
101    {
102        getDecorated().setName( name );
103        
104        return this;
105    }
106
107
108    /**
109     * {@inheritDoc}
110     */
111    public Rdn getNewRdn()
112    {
113        return getDecorated().getNewRdn();
114    }
115
116
117    /**
118     * {@inheritDoc}
119     */
120    public ModifyDnRequest setNewRdn( Rdn newRdn )
121    {
122        getDecorated().setNewRdn( newRdn );
123        
124        return this;
125    }
126
127
128    /**
129     * {@inheritDoc}
130     */
131    public boolean getDeleteOldRdn()
132    {
133        return getDecorated().getDeleteOldRdn();
134    }
135
136
137    /**
138     * {@inheritDoc}
139     */
140    public ModifyDnRequest setDeleteOldRdn( boolean deleteOldRdn )
141    {
142        getDecorated().setDeleteOldRdn( deleteOldRdn );
143        
144        return this;
145    }
146
147
148    /**
149     * {@inheritDoc}
150     */
151    public Dn getNewSuperior()
152    {
153        return getDecorated().getNewSuperior();
154    }
155
156
157    /**
158     * {@inheritDoc}
159     */
160    public ModifyDnRequest setNewSuperior( Dn newSuperior )
161    {
162        getDecorated().setNewSuperior( newSuperior );
163        
164        return this;
165    }
166
167
168    /**
169     * {@inheritDoc}
170     */
171    public boolean isMove()
172    {
173        return getDecorated().isMove();
174    }
175    
176    
177    /**
178     * {@inheritDoc}
179     */
180    public ModifyDnRequest setMessageId( int messageId )
181    {
182        super.setMessageId( messageId );
183        
184        return this;
185    }
186
187    
188    /**
189     * {@inheritDoc}
190     */
191    public ModifyDnRequest addControl( Control control ) throws MessageException
192    {
193        return (ModifyDnRequest)super.addControl( control );
194    }
195    
196    
197    /**
198     * {@inheritDoc}
199     */
200    public ModifyDnRequest addAllControls( Control[] controls ) throws MessageException
201    {
202        return (ModifyDnRequest)super.addAllControls( controls );
203    }
204    
205    
206    /**
207     * {@inheritDoc}
208     */
209    public ModifyDnRequest removeControl( Control control ) throws MessageException
210    {
211        return (ModifyDnRequest)super.removeControl( control );
212    }
213
214    
215    //-------------------------------------------------------------------------
216    // The Decorator methods
217    //-------------------------------------------------------------------------
218    
219    
220    /**
221     * Compute the ModifyDNRequest length
222     * 
223     * ModifyDNRequest :
224     * <pre>
225     * 0x6C L1
226     *  |
227     *  +--> 0x04 L2 entry
228     *  +--> 0x04 L3 newRDN
229     *  +--> 0x01 0x01 (true/false) deleteOldRDN (3 bytes)
230     * [+--> 0x80 L4 newSuperior ] 
231     * 
232     * L2 = Length(0x04) + Length(Length(entry)) + Length(entry) 
233     * L3 = Length(0x04) + Length(Length(newRDN)) + Length(newRDN) 
234     * L4 = Length(0x80) + Length(Length(newSuperior)) + Length(newSuperior)
235     * L1 = L2 + L3 + 3 [+ L4] 
236     * 
237     * Length(ModifyDNRequest) = Length(0x6C) + Length(L1) + L1
238     * </pre>
239     * 
240     * @return The PDU's length of a ModifyDN Request
241     */
242    public int computeLength()
243    {
244        int newRdnlength = Strings.getBytesUtf8( getNewRdn().getName() ).length;
245
246        int modifyDNRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( getName() ) )
247            + Dn.getNbBytes( getName() ) + 1 + TLV.getNbBytes( newRdnlength ) + newRdnlength + 1 + 1
248            + 1; // deleteOldRDN
249
250        if ( getNewSuperior() != null )
251        {
252            modifyDNRequestLength += 1 + TLV.getNbBytes( Dn.getNbBytes( getNewSuperior() ) )
253                + Dn.getNbBytes( getNewSuperior() );
254        }
255
256        setModifyDnRequestLength( modifyDNRequestLength );
257
258        return 1 + TLV.getNbBytes( modifyDNRequestLength ) + modifyDNRequestLength;
259    }
260
261
262    /**
263     * Encode the ModifyDNRequest message to a PDU. 
264     * 
265     * ModifyDNRequest :
266     * <pre>
267     * 0x6C LL
268     *   0x04 LL entry
269     *   0x04 LL newRDN
270     *   0x01 0x01 deleteOldRDN
271     *   [0x80 LL newSuperior]
272     * </pre>
273     * @param buffer The buffer where to put the PDU
274     * @return The PDU.
275     */
276    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
277    {
278        try
279        {
280            // The ModifyDNRequest Tag
281            buffer.put( LdapConstants.MODIFY_DN_REQUEST_TAG );
282            buffer.put( TLV.getBytes( getModifyDnResponseLength() ) );
283
284            // The entry
285
286            Value.encode( buffer, Dn.getBytes( getName() ) );
287
288            // The newRDN
289            Value.encode( buffer, getNewRdn().getName() );
290
291            // The flag deleteOldRdn
292            Value.encode( buffer, getDeleteOldRdn() );
293
294            // The new superior, if any
295            if ( getNewSuperior() != null )
296            {
297                // Encode the reference
298                buffer.put( ( byte ) LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG );
299
300                int newSuperiorLength = Dn.getNbBytes( getNewSuperior() );
301
302                buffer.put( TLV.getBytes( newSuperiorLength ) );
303
304                if ( newSuperiorLength != 0 )
305                {
306                    buffer.put( Dn.getBytes( getNewSuperior() ) );
307                }
308            }
309        }
310        catch ( BufferOverflowException boe )
311        {
312            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
313        }
314
315        return buffer;
316    }
317}