001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.protocols.ldap;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.ArrayList;
033    
034    import org.opends.server.protocols.asn1.ASN1Boolean;
035    import org.opends.server.protocols.asn1.ASN1Element;
036    import org.opends.server.protocols.asn1.ASN1OctetString;
037    import org.opends.server.protocols.asn1.ASN1Sequence;
038    import org.opends.server.types.DebugLogLevel;
039    import org.opends.server.types.LDAPException;
040    
041    import static org.opends.server.loggers.debug.DebugLogger.*;
042    import org.opends.server.loggers.debug.DebugTracer;
043    import static org.opends.messages.ProtocolMessages.*;
044    import static org.opends.server.protocols.ldap.LDAPConstants.*;
045    import static org.opends.server.protocols.ldap.LDAPResultCode.*;
046    import static org.opends.server.util.ServerConstants.*;
047    
048    
049    /**
050     * This class defines the structures and methods for an LDAP modify DN request
051     * protocol op, which is used to move or rename an entry or subtree within the
052     * Directory Server.
053     */
054    public class ModifyDNRequestProtocolOp
055           extends ProtocolOp
056    {
057      /**
058       * The tracer object for the debug logger.
059       */
060      private static final DebugTracer TRACER = getTracer();
061    
062      // The current entry DN for this modify DN request.
063      private ASN1OctetString entryDN;
064    
065      // The new RDN for this modify DN request.
066      private ASN1OctetString newRDN;
067    
068      // The new superior DN for this modify DN request.
069      private ASN1OctetString newSuperior;
070    
071      // Indicates whether to delete the current RDN value(s).
072      private boolean deleteOldRDN;
073    
074    
075    
076      /**
077       * Creates a new modify DN request protocol op with the provided information.
078       *
079       * @param  entryDN       The current entry DN for this modify DN request.
080       * @param  newRDN        The new RDN for this modify DN request.
081       * @param  deleteOldRDN  Indicates whether to delete the current RDN value(s).
082       */
083      public ModifyDNRequestProtocolOp(ASN1OctetString entryDN,
084                                       ASN1OctetString newRDN, boolean deleteOldRDN)
085      {
086        this.entryDN      = entryDN;
087        this.newRDN       = newRDN;
088        this.deleteOldRDN = deleteOldRDN;
089        this.newSuperior  = null;
090      }
091    
092    
093    
094      /**
095       * Creates a new modify DN request protocol op with the provided information.
096       *
097       * @param  entryDN       The current entry DN for this modify DN request.
098       * @param  newRDN        The new RDN for this modify DN request.
099       * @param  deleteOldRDN  Indicates whether to delete the current RDN value(s).
100       * @param  newSuperior   The new superior DN for this modify DN request.
101       */
102      public ModifyDNRequestProtocolOp(ASN1OctetString entryDN,
103                                       ASN1OctetString newRDN, boolean deleteOldRDN,
104                                       ASN1OctetString newSuperior)
105      {
106        this.entryDN      = entryDN;
107        this.newRDN       = newRDN;
108        this.deleteOldRDN = deleteOldRDN;
109        this.newSuperior  = newSuperior;
110      }
111    
112    
113    
114      /**
115       * Retrieves the current entry DN for this modify DN request.
116       *
117       * @return  The current entry DN for this modify DN request.
118       */
119      public ASN1OctetString getEntryDN()
120      {
121        return entryDN;
122      }
123    
124    
125    
126      /**
127       * Specifies the current entry DN for this modify DN request.
128       *
129       * @param  entryDN  The current entry DN for this modify DN request.
130       */
131      public void setEntryDN(ASN1OctetString entryDN)
132      {
133        this.entryDN = entryDN;
134      }
135    
136    
137    
138      /**
139       * Retrieves the new RDN for this modify DN request.
140       *
141       * @return  The new RDN for this modify DN request.
142       */
143      public ASN1OctetString getNewRDN()
144      {
145        return newRDN;
146      }
147    
148    
149    
150      /**
151       * Specifies the new RDN for this modify DN request.
152       *
153       * @param  newRDN  The new RDN for this modify DN request.
154       */
155      public void setNewRDN(ASN1OctetString newRDN)
156      {
157        this.newRDN = newRDN;
158      }
159    
160    
161    
162      /**
163       * Indicates whether the current RDN value(s) should be deleted.
164       *
165       * @return  <CODE>true</CODE> if the current RDN value(s) should be deleted,
166       *          or <CODE>false</CODE> if not.
167       */
168      public boolean deleteOldRDN()
169      {
170        return deleteOldRDN;
171      }
172    
173    
174    
175      /**
176       * Specifies whether the current RDN value(s) should be deleted.
177       *
178       * @param  deleteOldRDN  Specifies whether the current RDN value(s) should be
179       *                       deleted.
180       */
181      public void setDeleteOldRDN(boolean deleteOldRDN)
182      {
183        this.deleteOldRDN = deleteOldRDN;
184      }
185    
186    
187    
188      /**
189       * Retrieves the new superior DN for this modify DN request.
190       *
191       * @return  The new superior DN for this modify DN request, or
192       *          <CODE>null</CODE> if none was provided.
193       */
194      public ASN1OctetString getNewSuperior()
195      {
196        return newSuperior;
197      }
198    
199    
200    
201      /**
202       * Specifies the new superior DN for this modify DN request.
203       *
204       * @param  newSuperior  The new superior DN for this modify DN request.
205       */
206      public void setNewSuperior(ASN1OctetString newSuperior)
207      {
208        this.newSuperior = newSuperior;
209      }
210    
211    
212    
213      /**
214       * Retrieves the BER type for this protocol op.
215       *
216       * @return  The BER type for this protocol op.
217       */
218      public byte getType()
219      {
220        return OP_TYPE_MODIFY_DN_REQUEST;
221      }
222    
223    
224    
225      /**
226       * Retrieves the name for this protocol op type.
227       *
228       * @return  The name for this protocol op type.
229       */
230      public String getProtocolOpName()
231      {
232        return "Modify DN Request";
233      }
234    
235    
236    
237      /**
238       * Encodes this protocol op to an ASN.1 element suitable for including in an
239       * LDAP message.
240       *
241       * @return  The ASN.1 element containing the encoded protocol op.
242       */
243      public ASN1Element encode()
244      {
245        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(4);
246        elements.add(entryDN);
247        elements.add(newRDN);
248        elements.add(new ASN1Boolean(deleteOldRDN));
249    
250        if (newSuperior != null)
251        {
252          newSuperior.setType(TYPE_MODIFY_DN_NEW_SUPERIOR);
253          elements.add(newSuperior);
254        }
255    
256        return new ASN1Sequence(OP_TYPE_MODIFY_DN_REQUEST, elements);
257      }
258    
259    
260    
261      /**
262       * Decodes the provided ASN.1 element as a modify DN request protocol op.
263       *
264       * @param  element  The ASN.1 element to decode.
265       *
266       * @return  The decoded modify DN request protocol op.
267       *
268       * @throws  LDAPException  If a problem occurs while trying to decode the
269       *                         provided ASN.1 element as an LDAP modify DN request
270       *                         protocol op.
271       */
272      public static ModifyDNRequestProtocolOp decodeModifyDNRequest(ASN1Element
273                                                                         element)
274             throws LDAPException
275      {
276        ArrayList<ASN1Element> elements;
277        try
278        {
279          elements = element.decodeAsSequence().elements();
280        }
281        catch (Exception e)
282        {
283          if (debugEnabled())
284          {
285            TRACER.debugCaught(DebugLogLevel.ERROR, e);
286          }
287    
288          Message message =
289              ERR_LDAP_MODIFY_DN_REQUEST_DECODE_SEQUENCE.get(String.valueOf(e));
290          throw new LDAPException(PROTOCOL_ERROR, message, e);
291        }
292    
293    
294        int numElements = elements.size();
295        if ((numElements < 3) || (numElements > 4))
296        {
297          Message message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_INVALID_ELEMENT_COUNT.
298              get(numElements);
299          throw new LDAPException(PROTOCOL_ERROR, message);
300        }
301    
302    
303        ASN1OctetString entryDN;
304        try
305        {
306          entryDN = elements.get(0).decodeAsOctetString();
307        }
308        catch (Exception e)
309        {
310          if (debugEnabled())
311          {
312            TRACER.debugCaught(DebugLogLevel.ERROR, e);
313          }
314    
315          Message message =
316              ERR_LDAP_MODIFY_DN_REQUEST_DECODE_DN.get(String.valueOf(e));
317          throw new LDAPException(PROTOCOL_ERROR, message, e);
318        }
319    
320    
321        ASN1OctetString newRDN;
322        try
323        {
324          newRDN = elements.get(1).decodeAsOctetString();
325        }
326        catch (Exception e)
327        {
328          if (debugEnabled())
329          {
330            TRACER.debugCaught(DebugLogLevel.ERROR, e);
331          }
332    
333          Message message =
334              ERR_LDAP_MODIFY_DN_REQUEST_DECODE_NEW_RDN.get(String.valueOf(e));
335          throw new LDAPException(PROTOCOL_ERROR, message, e);
336        }
337    
338    
339        boolean deleteOldRDN;
340        try
341        {
342          deleteOldRDN = elements.get(2).decodeAsBoolean().booleanValue();
343        }
344        catch (Exception e)
345        {
346          if (debugEnabled())
347          {
348            TRACER.debugCaught(DebugLogLevel.ERROR, e);
349          }
350    
351          Message message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_DELETE_OLD_RDN.get(
352              String.valueOf(e));
353          throw new LDAPException(PROTOCOL_ERROR, message, e);
354        }
355    
356    
357        ASN1OctetString newSuperior;
358        if (numElements == 4)
359        {
360          try
361          {
362            newSuperior = elements.get(3).decodeAsOctetString();
363          }
364          catch (Exception e)
365          {
366            if (debugEnabled())
367            {
368              TRACER.debugCaught(DebugLogLevel.ERROR, e);
369            }
370    
371            Message message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_NEW_SUPERIOR.get(
372                String.valueOf(e));
373            throw new LDAPException(PROTOCOL_ERROR, message, e);
374          }
375        }
376        else
377        {
378          newSuperior = null;
379        }
380    
381    
382        return new ModifyDNRequestProtocolOp(entryDN, newRDN, deleteOldRDN,
383                                             newSuperior);
384      }
385    
386    
387    
388      /**
389       * Appends a string representation of this LDAP protocol op to the provided
390       * buffer.
391       *
392       * @param  buffer  The buffer to which the string should be appended.
393       */
394      public void toString(StringBuilder buffer)
395      {
396        buffer.append("ModifyDNRequest(dn=");
397        entryDN.toString(buffer);
398        buffer.append(", newRDN=");
399        newRDN.toString(buffer);
400        buffer.append(", deleteOldRDN=");
401        buffer.append(deleteOldRDN);
402    
403        if (newSuperior != null)
404        {
405          buffer.append(", newSuperior=");
406          newSuperior.toString(buffer);
407        }
408    
409        buffer.append(")");
410      }
411    
412    
413    
414      /**
415       * Appends a multi-line string representation of this LDAP protocol op to the
416       * provided buffer.
417       *
418       * @param  buffer  The buffer to which the information should be appended.
419       * @param  indent  The number of spaces from the margin that the lines should
420       *                 be indented.
421       */
422      public void toString(StringBuilder buffer, int indent)
423      {
424        StringBuilder indentBuf = new StringBuilder(indent);
425        for (int i=0 ; i < indent; i++)
426        {
427          indentBuf.append(' ');
428        }
429    
430        buffer.append(indentBuf);
431        buffer.append("Modify DN Request");
432        buffer.append(EOL);
433    
434        buffer.append(indentBuf);
435        buffer.append("  Entry DN:  ");
436        entryDN.toString(buffer);
437        buffer.append(EOL);
438    
439        buffer.append(indentBuf);
440        buffer.append("  New RDN:  ");
441        newRDN.toString(buffer);
442        buffer.append(EOL);
443    
444        buffer.append(indentBuf);
445        buffer.append("  Delete Old RDN:  ");
446        buffer.append(deleteOldRDN);
447        buffer.append(EOL);
448    
449        if (newSuperior != null)
450        {
451          buffer.append(indentBuf);
452          buffer.append("  New Superior:  ");
453          newSuperior.toString(buffer);
454          buffer.append(EOL);
455        }
456      }
457    }
458