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.modifyDn;
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.ber.tlv.Value;
028    import org.apache.directory.shared.asn1.codec.EncoderException;
029    import org.apache.directory.shared.ldap.codec.LdapConstants;
030    import org.apache.directory.shared.ldap.codec.LdapMessageCodec;
031    import org.apache.directory.shared.ldap.name.LdapDN;
032    import org.apache.directory.shared.ldap.name.Rdn;
033    import org.apache.directory.shared.ldap.util.StringTools;
034    
035    
036    /**
037     * A ModifyDNRequest Message. Its syntax is :
038     * ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
039     *                 entry           LDAPDN,
040     *                 newrdn          RelativeLDAPDN,
041     *                 deleteoldrdn    BOOLEAN,
042     *                 newSuperior     [0] LDAPDN OPTIONAL }
043     * 
044     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045     * @version $Rev: 764131 $, $Date: 2009-04-11 03:03:00 +0200 (Sam, 11 avr 2009) $, 
046     */
047    public class ModifyDNRequestCodec extends LdapMessageCodec
048    {
049        // ~ Instance fields
050        // ----------------------------------------------------------------------------
051    
052        /** The DN to be modified. */
053        private LdapDN entry;
054    
055        /** The new RDN to be added to the RDN or to the new superior, if present */
056        private Rdn newRDN;
057    
058        /** If the previous RDN is to be deleted, this flag will be set to true */
059        private boolean deleteOldRDN;
060    
061        /** The optional superior, which will be concatened to the newRdn */
062        private LdapDN newSuperior;
063    
064        /** The modify DN request length */
065        private int modifyDNRequestLength;
066    
067    
068        // ~ Constructors
069        // -------------------------------------------------------------------------------
070    
071        /**
072         * Creates a new ModifyDNRequest object.
073         */
074        public ModifyDNRequestCodec()
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 int getMessageType()
089        {
090            return LdapConstants.MODIFYDN_REQUEST;
091        }
092    
093    
094        /**
095         * Get the modification's DN
096         * 
097         * @return Returns the entry.
098         */
099        public LdapDN getEntry()
100        {
101            return entry;
102        }
103    
104    
105        /**
106         * Set the modification DN.
107         * 
108         * @param entry The entry to set.
109         */
110        public void setEntry( LdapDN entry )
111        {
112            this.entry = entry;
113        }
114    
115    
116        /**
117         * Tells if the old RDN is to be deleted
118         * 
119         * @return Returns the deleteOldRDN.
120         */
121        public boolean isDeleteOldRDN()
122        {
123            return deleteOldRDN;
124        }
125    
126    
127        /**
128         * Set the flag to delete the old RDN
129         * 
130         * @param deleteOldRDN The deleteOldRDN to set.
131         */
132        public void setDeleteOldRDN( boolean deleteOldRDN )
133        {
134            this.deleteOldRDN = deleteOldRDN;
135        }
136    
137    
138        /**
139         * Get the new RDN
140         * 
141         * @return Returns the newRDN.
142         */
143        public Rdn getNewRDN()
144        {
145            return newRDN;
146        }
147    
148    
149        /**
150         * Set the new RDN
151         * 
152         * @param newRDN The newRDN to set.
153         */
154        public void setNewRDN( Rdn newRDN )
155        {
156            this.newRDN = newRDN;
157        }
158    
159    
160        /**
161         * Get the newSuperior
162         * 
163         * @return Returns the newSuperior.
164         */
165        public LdapDN getNewSuperior()
166        {
167            return newSuperior;
168        }
169    
170    
171        /**
172         * Set the new superior
173         * 
174         * @param newSuperior The newSuperior to set.
175         */
176        public void setNewSuperior( LdapDN newSuperior )
177        {
178            this.newSuperior = newSuperior;
179        }
180    
181    
182        /**
183         * Compute the ModifyDNRequest length
184         * 
185         * ModifyDNRequest :
186         * 
187         * 0x6C L1
188         *  |
189         *  +--> 0x04 L2 entry
190         *  +--> 0x04 L3 newRDN
191         *  +--> 0x01 0x01 (true/false) deleteOldRDN (3 bytes)
192         * [+--> 0x80 L4 newSuperior ] 
193         * 
194         * L2 = Length(0x04) + Length(Length(entry)) + Length(entry) 
195         * L3 = Length(0x04) + Length(Length(newRDN)) + Length(newRDN) 
196         * L4 = Length(0x80) + Length(Length(newSuperior)) + Length(newSuperior)
197         * L1 = L2 + L3 + 3 [+ L4] 
198         * 
199         * Length(ModifyDNRequest) = Length(0x6C) + Length(L1) + L1
200         * 
201         * @return The PDU's length of a ModifyDN Request
202         */
203        public int computeLength()
204        {
205            int newRdnlength = StringTools.getBytesUtf8( newRDN.toString() ).length;
206            modifyDNRequestLength = 1 + TLV.getNbBytes( LdapDN.getNbBytes( entry ) ) + LdapDN.getNbBytes( entry ) + 1
207                + TLV.getNbBytes( newRdnlength ) + newRdnlength + 1 + 1 + 1; // deleteOldRDN
208    
209            if ( newSuperior != null )
210            {
211                modifyDNRequestLength += 1 + TLV.getNbBytes( LdapDN.getNbBytes( newSuperior ) )
212                    + LdapDN.getNbBytes( newSuperior );
213            }
214    
215            return 1 + TLV.getNbBytes( modifyDNRequestLength ) + modifyDNRequestLength;
216        }
217    
218    
219        /**
220         * Encode the ModifyDNRequest message to a PDU. 
221         * 
222         * ModifyDNRequest :
223         * 
224         * 0x6C LL
225         *   0x04 LL entry
226         *   0x04 LL newRDN
227         *   0x01 0x01 deleteOldRDN
228         *   [0x80 LL newSuperior]
229         * 
230         * @param buffer The buffer where to put the PDU
231         * @return The PDU.
232         */
233        public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
234        {
235            if ( buffer == null )
236            {
237                throw new EncoderException( "Cannot put a PDU in a null buffer !" );
238            }
239    
240            try
241            {
242                // The ModifyDNRequest Tag
243                buffer.put( LdapConstants.MODIFY_DN_REQUEST_TAG );
244                buffer.put( TLV.getBytes( modifyDNRequestLength ) );
245    
246                // The entry
247    
248                Value.encode( buffer, LdapDN.getBytes( entry ) );
249    
250                // The newRDN
251                Value.encode( buffer, newRDN.toString() );
252    
253                // The flag deleteOldRdn
254                Value.encode( buffer, deleteOldRDN );
255    
256                // The new superior, if any
257                if ( newSuperior != null )
258                {
259                    // Encode the reference
260                    buffer.put( ( byte ) LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG );
261    
262                    int newSuperiorLength = LdapDN.getNbBytes( newSuperior );
263    
264                    buffer.put( TLV.getBytes( newSuperiorLength ) );
265    
266                    if ( newSuperiorLength != 0 )
267                    {
268                        buffer.put( LdapDN.getBytes( newSuperior ) );
269                    }
270                }
271            }
272            catch ( BufferOverflowException boe )
273            {
274                throw new EncoderException( "The PDU buffer size is too small !" );
275            }
276    
277            return buffer;
278        }
279    
280    
281        /**
282         * Get a String representation of a ModifyDNRequest
283         * 
284         * @return A ModifyDNRequest String
285         */
286        public String toString()
287        {
288    
289            StringBuffer sb = new StringBuffer();
290    
291            sb.append( "    ModifyDN Response\n" );
292            sb.append( "        Entry : '" ).append( entry ).append( "'\n" );
293            sb.append( "        New RDN : '" ).append( newRDN ).append( "'\n" );
294            sb.append( "        Delete old RDN : " ).append( deleteOldRDN ).append( "\n" );
295    
296            if ( newSuperior != null )
297            {
298                sb.append( "        New superior : '" ).append( newSuperior ).append( "'\n" );
299            }
300    
301            return sb.toString();
302        }
303    }