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