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    import java.util.Iterator;
034    
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    import org.opends.server.types.RawModification;
041    
042    import static org.opends.server.loggers.debug.DebugLogger.*;
043    import org.opends.server.loggers.debug.DebugTracer;
044    import static org.opends.messages.ProtocolMessages.*;
045    import static org.opends.server.protocols.ldap.LDAPConstants.*;
046    import static org.opends.server.protocols.ldap.LDAPResultCode.*;
047    import static org.opends.server.util.ServerConstants.*;
048    
049    
050    /**
051     * This class defines the structures and methods for an LDAP modify request
052     * protocol op, which is used to alter the contents of an entry in the Directory
053     * Server.
054     */
055    public class ModifyRequestProtocolOp
056           extends ProtocolOp
057    {
058      /**
059       * The tracer object for the debug logger.
060       */
061      private static final DebugTracer TRACER = getTracer();
062    
063      // The set of modifications for this modify request.
064      private ArrayList<RawModification> modifications;
065    
066      // The DN for this modify request.
067      private ASN1OctetString dn;
068    
069    
070    
071      /**
072       * Creates a new LDAP modify request protocol op with the specified DN and no
073       * modifications.
074       *
075       * @param  dn  The DN for this modify request.
076       */
077      public ModifyRequestProtocolOp(ASN1OctetString dn)
078      {
079        this.dn            = dn;
080        this.modifications = new ArrayList<RawModification>();
081      }
082    
083    
084    
085      /**
086       * Creates a new LDAP modify request protocol op with the specified DN and set
087       * of modifications.
088       *
089       * @param  dn             The DN for this modify request.
090       * @param  modifications  The set of modifications for this modify request.
091       */
092      public ModifyRequestProtocolOp(ASN1OctetString dn,
093                                     ArrayList<RawModification> modifications)
094      {
095        this.dn = dn;
096    
097        if (modifications == null)
098        {
099          this.modifications = new ArrayList<RawModification>();
100        }
101        else
102        {
103          this.modifications = modifications;
104        }
105      }
106    
107    
108    
109      /**
110       * Retrieves the DN for this modify request.
111       *
112       * @return  The DN for this modify request.
113       */
114      public ASN1OctetString getDN()
115      {
116        return dn;
117      }
118    
119    
120    
121      /**
122       * Specifies the DN for this modify request.
123       *
124       * @param  dn  The DN for this modify request.
125       */
126      public void setDN(ASN1OctetString dn)
127      {
128        this.dn = dn;
129      }
130    
131    
132    
133      /**
134       * Retrieves the set of modifications for this modify request.  The returned
135       * list may be altered by the caller.
136       *
137       * @return  The set of modifications for this modify request.
138       */
139      public ArrayList<RawModification> getModifications()
140      {
141        return modifications;
142      }
143    
144    
145    
146      /**
147       * Retrieves the BER type for this protocol op.
148       *
149       * @return  The BER type for this protocol op.
150       */
151      public byte getType()
152      {
153        return OP_TYPE_MODIFY_REQUEST;
154      }
155    
156    
157    
158      /**
159       * Retrieves the name for this protocol op type.
160       *
161       * @return  The name for this protocol op type.
162       */
163      public String getProtocolOpName()
164      {
165        return "Modify Request";
166      }
167    
168    
169    
170      /**
171       * Encodes this protocol op to an ASN.1 element suitable for including in an
172       * LDAP message.
173       *
174       * @return  The ASN.1 element containing the encoded protocol op.
175       */
176      public ASN1Element encode()
177      {
178        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
179        elements.add(dn);
180    
181    
182        ArrayList<ASN1Element> modElements =
183             new ArrayList<ASN1Element>(modifications.size());
184        for (RawModification mod : modifications)
185        {
186          modElements.add(mod.encode());
187        }
188        elements.add(new ASN1Sequence(modElements));
189    
190    
191        return new ASN1Sequence(OP_TYPE_MODIFY_REQUEST, elements);
192      }
193    
194    
195    
196      /**
197       * Decodes the provided ASN.1 element as an LDAP modify request protocol op.
198       *
199       * @param  element  The ASN.1 element to be decoded.
200       *
201       * @return  The decoded modify request protocol op.
202       *
203       * @throws  LDAPException  If a problem occurs while decoding the provided
204       *                         ASN.1 element as an LDAP modify request protocol
205       *                         op.
206       */
207      public static ModifyRequestProtocolOp decodeModifyRequest(ASN1Element element)
208             throws LDAPException
209      {
210        ArrayList<ASN1Element> elements;
211        try
212        {
213          elements = element.decodeAsSequence().elements();
214        }
215        catch (Exception e)
216        {
217          if (debugEnabled())
218          {
219            TRACER.debugCaught(DebugLogLevel.ERROR, e);
220          }
221    
222          Message message =
223              ERR_LDAP_MODIFY_REQUEST_DECODE_SEQUENCE.get(String.valueOf(e));
224          throw new LDAPException(PROTOCOL_ERROR, message, e);
225        }
226    
227    
228        int numElements = elements.size();
229        if (numElements != 2)
230        {
231          Message message =
232              ERR_LDAP_MODIFY_REQUEST_DECODE_INVALID_ELEMENT_COUNT.get(numElements);
233          throw new LDAPException(PROTOCOL_ERROR, message);
234        }
235    
236    
237        ASN1OctetString dn;
238        try
239        {
240          dn = elements.get(0).decodeAsOctetString();
241        }
242        catch (Exception e)
243        {
244          if (debugEnabled())
245          {
246            TRACER.debugCaught(DebugLogLevel.ERROR, e);
247          }
248    
249          Message message =
250              ERR_LDAP_MODIFY_REQUEST_DECODE_DN.get(String.valueOf(e));
251          throw new LDAPException(PROTOCOL_ERROR, message, e);
252        }
253    
254    
255    
256        ArrayList<RawModification> modifications;
257        try
258        {
259          ArrayList<ASN1Element> modElements =
260               elements.get(1).decodeAsSequence().elements();
261          modifications = new ArrayList<RawModification>(modElements.size());
262          for (ASN1Element e : modElements)
263          {
264            modifications.add(LDAPModification.decode(e));
265          }
266        }
267        catch (Exception e)
268        {
269          if (debugEnabled())
270          {
271            TRACER.debugCaught(DebugLogLevel.ERROR, e);
272          }
273    
274          Message message =
275              ERR_LDAP_MODIFY_REQUEST_DECODE_MODS.get(String.valueOf(e));
276          throw new LDAPException(PROTOCOL_ERROR, message, e);
277        }
278    
279    
280        return new ModifyRequestProtocolOp(dn, modifications);
281      }
282    
283    
284    
285      /**
286       * Appends a string representation of this LDAP protocol op to the provided
287       * buffer.
288       *
289       * @param  buffer  The buffer to which the string should be appended.
290       */
291      public void toString(StringBuilder buffer)
292      {
293        buffer.append("ModifyRequest(dn=");
294        dn.toString(buffer);
295        buffer.append(", mods={");
296    
297        if (! modifications.isEmpty())
298        {
299          Iterator<RawModification> iterator = modifications.iterator();
300          iterator.next().toString(buffer);
301    
302          while (iterator.hasNext())
303          {
304            buffer.append(", ");
305            iterator.next().toString(buffer);
306          }
307        }
308    
309        buffer.append("})");
310      }
311    
312    
313    
314      /**
315       * Appends a multi-line string representation of this LDAP protocol op to the
316       * provided buffer.
317       *
318       * @param  buffer  The buffer to which the information should be appended.
319       * @param  indent  The number of spaces from the margin that the lines should
320       *                 be indented.
321       */
322      public void toString(StringBuilder buffer, int indent)
323      {
324        StringBuilder indentBuf = new StringBuilder(indent);
325        for (int i=0 ; i < indent; i++)
326        {
327          indentBuf.append(' ');
328        }
329    
330        buffer.append(indentBuf);
331        buffer.append("Modify Request");
332        buffer.append(EOL);
333    
334        buffer.append(indentBuf);
335        buffer.append("  DN:  ");
336        dn.toString(buffer);
337        buffer.append(EOL);
338    
339        buffer.append("  Modifications:");
340        buffer.append(EOL);
341    
342        for (RawModification mod : modifications)
343        {
344          mod.toString(buffer, indent+4);
345        }
346      }
347    }
348