001    /*
002     * Copyright 2009-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2016 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.protocol;
022    
023    
024    
025    import java.util.ArrayList;
026    import java.util.Collections;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    import com.unboundid.asn1.ASN1Buffer;
031    import com.unboundid.asn1.ASN1BufferSequence;
032    import com.unboundid.asn1.ASN1Element;
033    import com.unboundid.asn1.ASN1OctetString;
034    import com.unboundid.asn1.ASN1Sequence;
035    import com.unboundid.asn1.ASN1StreamReader;
036    import com.unboundid.asn1.ASN1StreamReaderSequence;
037    import com.unboundid.ldap.sdk.Control;
038    import com.unboundid.ldap.sdk.LDAPException;
039    import com.unboundid.ldap.sdk.Modification;
040    import com.unboundid.ldap.sdk.ModifyRequest;
041    import com.unboundid.ldap.sdk.ResultCode;
042    import com.unboundid.util.NotMutable;
043    import com.unboundid.util.InternalUseOnly;
044    import com.unboundid.util.ThreadSafety;
045    import com.unboundid.util.ThreadSafetyLevel;
046    
047    import static com.unboundid.ldap.protocol.ProtocolMessages.*;
048    import static com.unboundid.util.Debug.*;
049    import static com.unboundid.util.StaticUtils.*;
050    import static com.unboundid.util.Validator.*;
051    
052    
053    
054    /**
055     * This class provides an implementation of an LDAP modify request protocol op.
056     */
057    @InternalUseOnly()
058    @NotMutable()
059    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
060    public final class ModifyRequestProtocolOp
061           implements ProtocolOp
062    {
063      /**
064       * The serial version UID for this serializable class.
065       */
066      private static final long serialVersionUID = -6294739625253826184L;
067    
068    
069    
070      // The list of modifications for this modify request.
071      private final List<Modification> modifications;
072    
073      // The entry DN for this modify request.
074      private final String dn;
075    
076    
077    
078      /**
079       * Creates a new modify request protocol op with the provided information.
080       *
081       * @param  dn             The entry DN for this modify request.
082       * @param  modifications  The list of modifications to include in this modify
083       *                        request.
084       */
085      public ModifyRequestProtocolOp(final String dn,
086                                     final List<Modification> modifications)
087      {
088        this.dn            = dn;
089        this.modifications = Collections.unmodifiableList(modifications);
090      }
091    
092    
093    
094      /**
095       * Creates a new modify request protocol op from the provided modify request
096       * object.
097       *
098       * @param  request  The modify request object to use to create this protocol
099       *                  op.
100       */
101      public ModifyRequestProtocolOp(final ModifyRequest request)
102      {
103        dn            = request.getDN();
104        modifications = request.getModifications();
105      }
106    
107    
108    
109      /**
110       * Creates a new modify request protocol op read from the provided ASN.1
111       * stream reader.
112       *
113       * @param  reader  The ASN.1 stream reader from which to read the modify
114       *                 request protocol op.
115       *
116       * @throws  LDAPException  If a problem occurs while reading or parsing the
117       *                         modify request.
118       */
119      ModifyRequestProtocolOp(final ASN1StreamReader reader)
120           throws LDAPException
121      {
122        try
123        {
124          reader.beginSequence();
125          dn = reader.readString();
126          ensureNotNull(dn);
127    
128          final ArrayList<Modification> mods = new ArrayList<Modification>(5);
129          final ASN1StreamReaderSequence modSequence = reader.beginSequence();
130          while (modSequence.hasMoreElements())
131          {
132            mods.add(Modification.readFrom(reader));
133          }
134    
135          modifications = Collections.unmodifiableList(mods);
136        }
137        catch (LDAPException le)
138        {
139          debugException(le);
140          throw le;
141        }
142        catch (Exception e)
143        {
144          debugException(e);
145    
146          throw new LDAPException(ResultCode.DECODING_ERROR,
147               ERR_MODIFY_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e);
148        }
149      }
150    
151    
152    
153      /**
154       * Retrieves the target entry DN for this modify request.
155       *
156       * @return  The target entry DN for this modify request.
157       */
158      public String getDN()
159      {
160        return dn;
161      }
162    
163    
164    
165      /**
166       * Retrieves the list of modifications for this modify request.
167       *
168       * @return  The list of modifications for this modify request.
169       */
170      public List<Modification> getModifications()
171      {
172        return modifications;
173      }
174    
175    
176    
177      /**
178       * {@inheritDoc}
179       */
180      public byte getProtocolOpType()
181      {
182        return LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST;
183      }
184    
185    
186    
187      /**
188       * {@inheritDoc}
189       */
190      public ASN1Element encodeProtocolOp()
191      {
192        final ArrayList<ASN1Element> modElements =
193             new ArrayList<ASN1Element>(modifications.size());
194        for (final Modification m : modifications)
195        {
196          modElements.add(m.encode());
197        }
198    
199        return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST,
200             new ASN1OctetString(dn),
201             new ASN1Sequence(modElements));
202      }
203    
204    
205    
206      /**
207       * Decodes the provided ASN.1 element as a modify request protocol op.
208       *
209       * @param  element  The ASN.1 element to be decoded.
210       *
211       * @return  The decoded modify request protocol op.
212       *
213       * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
214       *                         a modify request protocol op.
215       */
216      public static ModifyRequestProtocolOp decodeProtocolOp(
217                                                 final ASN1Element element)
218             throws LDAPException
219      {
220        try
221        {
222          final ASN1Element[] elements =
223               ASN1Sequence.decodeAsSequence(element).elements();
224          final String dn =
225               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
226    
227          final ASN1Element[] modElements =
228               ASN1Sequence.decodeAsSequence(elements[1]).elements();
229          final ArrayList<Modification> mods =
230               new ArrayList<Modification>(modElements.length);
231          for (final ASN1Element e : modElements)
232          {
233            mods.add(Modification.decode(ASN1Sequence.decodeAsSequence(e)));
234          }
235    
236          return new ModifyRequestProtocolOp(dn, mods);
237        }
238        catch (final Exception e)
239        {
240          debugException(e);
241          throw new LDAPException(ResultCode.DECODING_ERROR,
242               ERR_MODIFY_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)),
243               e);
244        }
245      }
246    
247    
248    
249      /**
250       * {@inheritDoc}
251       */
252      public void writeTo(final ASN1Buffer writer)
253      {
254        final ASN1BufferSequence opSequence =
255             writer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST);
256        writer.addOctetString(dn);
257    
258        final ASN1BufferSequence modSequence = writer.beginSequence();
259        for (final Modification m : modifications)
260        {
261          m.writeTo(writer);
262        }
263        modSequence.end();
264        opSequence.end();
265      }
266    
267    
268    
269      /**
270       * Creates a modify request from this protocol op.
271       *
272       * @param  controls  The set of controls to include in the modify request.
273       *                   It may be empty or {@code null} if no controls should be
274       *                   included.
275       *
276       * @return  The modify request that was created.
277       */
278      public ModifyRequest toModifyRequest(final Control... controls)
279      {
280        return new ModifyRequest(dn, modifications, controls);
281      }
282    
283    
284    
285      /**
286       * Retrieves a string representation of this protocol op.
287       *
288       * @return  A string representation of this protocol op.
289       */
290      @Override()
291      public String toString()
292      {
293        final StringBuilder buffer = new StringBuilder();
294        toString(buffer);
295        return buffer.toString();
296      }
297    
298    
299    
300      /**
301       * {@inheritDoc}
302       */
303      public void toString(final StringBuilder buffer)
304      {
305        buffer.append("ModifyRequestProtocolOp(dn='");
306        buffer.append(dn);
307        buffer.append("', mods={");
308    
309        final Iterator<Modification> iterator = modifications.iterator();
310        while (iterator.hasNext())
311        {
312          iterator.next().toString(buffer);
313          if (iterator.hasNext())
314          {
315            buffer.append(',');
316          }
317        }
318    
319        buffer.append("})");
320      }
321    }