001    /*
002     * Copyright 2009-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2015 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.AddRequest;
038    import com.unboundid.ldap.sdk.Attribute;
039    import com.unboundid.ldap.sdk.Control;
040    import com.unboundid.ldap.sdk.LDAPException;
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 add request protocol op.
056     */
057    @InternalUseOnly()
058    @NotMutable()
059    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
060    public final class AddRequestProtocolOp
061           implements ProtocolOp
062    {
063      /**
064       * The serial version UID for this serializable class.
065       */
066      private static final long serialVersionUID = -1195296296055518601L;
067    
068    
069    
070      // The list of attributes for this add request.
071      private final List<Attribute> attributes;
072    
073      // The entry DN for this add request.
074      private final String dn;
075    
076    
077    
078      /**
079       * Creates a new add request protocol op with the provided information.
080       *
081       * @param  dn          The entry DN for this add request.
082       * @param  attributes  The list of attributes to include in this add request.
083       */
084      public AddRequestProtocolOp(final String dn, final List<Attribute> attributes)
085      {
086        this.dn         = dn;
087        this.attributes = Collections.unmodifiableList(attributes);
088      }
089    
090    
091    
092      /**
093       * Creates a new add request protocol op from the provided add request object.
094       *
095       * @param  request  The add request object to use to create this protocol op.
096       */
097      public AddRequestProtocolOp(final AddRequest request)
098      {
099        dn          = request.getDN();
100        attributes = request.getAttributes();
101      }
102    
103    
104    
105      /**
106       * Creates a new add request protocol op read from the provided ASN.1 stream
107       * reader.
108       *
109       * @param  reader  The ASN.1 stream reader from which to read the add request
110       *                 protocol op.
111       *
112       * @throws  LDAPException  If a problem occurs while reading or parsing the
113       *                         add request.
114       */
115      AddRequestProtocolOp(final ASN1StreamReader reader)
116           throws LDAPException
117      {
118        try
119        {
120          reader.beginSequence();
121          dn = reader.readString();
122          ensureNotNull(dn);
123    
124          final ArrayList<Attribute> attrs = new ArrayList<Attribute>(10);
125          final ASN1StreamReaderSequence attrSequence = reader.beginSequence();
126          while (attrSequence.hasMoreElements())
127          {
128            attrs.add(Attribute.readFrom(reader));
129          }
130    
131          attributes = Collections.unmodifiableList(attrs);
132        }
133        catch (LDAPException le)
134        {
135          debugException(le);
136          throw le;
137        }
138        catch (Exception e)
139        {
140          debugException(e);
141    
142          throw new LDAPException(ResultCode.DECODING_ERROR,
143               ERR_ADD_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e);
144        }
145      }
146    
147    
148    
149      /**
150       * Retrieves the target entry DN for this add request.
151       *
152       * @return  The target entry DN for this add request.
153       */
154      public String getDN()
155      {
156        return dn;
157      }
158    
159    
160    
161      /**
162       * Retrieves the list of attributes for this add request.
163       *
164       * @return  The list of attributes for this add request.
165       */
166      public List<Attribute> getAttributes()
167      {
168        return attributes;
169      }
170    
171    
172    
173      /**
174       * {@inheritDoc}
175       */
176      public byte getProtocolOpType()
177      {
178        return LDAPMessage.PROTOCOL_OP_TYPE_ADD_REQUEST;
179      }
180    
181    
182    
183      /**
184       * {@inheritDoc}
185       */
186      public ASN1Element encodeProtocolOp()
187      {
188        final ArrayList<ASN1Element> attrElements =
189             new ArrayList<ASN1Element>(attributes.size());
190        for (final Attribute a : attributes)
191        {
192          attrElements.add(a.encode());
193        }
194    
195        return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_ADD_REQUEST,
196             new ASN1OctetString(dn),
197             new ASN1Sequence(attrElements));
198      }
199    
200    
201    
202      /**
203       * Decodes the provided ASN.1 element as an add request protocol op.
204       *
205       * @param  element  The ASN.1 element to be decoded.
206       *
207       * @return  The decoded add request protocol op.
208       *
209       * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
210       *                         an add request protocol op.
211       */
212      public static AddRequestProtocolOp decodeProtocolOp(final ASN1Element element)
213             throws LDAPException
214      {
215        try
216        {
217          final ASN1Element[] elements =
218               ASN1Sequence.decodeAsSequence(element).elements();
219          final String dn =
220               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
221    
222          final ASN1Element[] attrElements =
223               ASN1Sequence.decodeAsSequence(elements[1]).elements();
224          final ArrayList<Attribute> attributes =
225               new ArrayList<Attribute>(attrElements.length);
226          for (final ASN1Element ae : attrElements)
227          {
228            attributes.add(Attribute.decode(ASN1Sequence.decodeAsSequence(ae)));
229          }
230    
231          return new AddRequestProtocolOp(dn, attributes);
232        }
233        catch (final Exception e)
234        {
235          debugException(e);
236          throw new LDAPException(ResultCode.DECODING_ERROR,
237               ERR_ADD_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)),
238               e);
239        }
240      }
241    
242    
243    
244      /**
245       * {@inheritDoc}
246       */
247      public void writeTo(final ASN1Buffer buffer)
248      {
249        final ASN1BufferSequence opSequence =
250             buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_ADD_REQUEST);
251        buffer.addOctetString(dn);
252    
253        final ASN1BufferSequence attrSequence = buffer.beginSequence();
254        for (final Attribute a : attributes)
255        {
256          a.writeTo(buffer);
257        }
258        attrSequence.end();
259        opSequence.end();
260      }
261    
262    
263    
264      /**
265       * Creates an add request from this protocol op.
266       *
267       * @param  controls  The set of controls to include in the add request.  It
268       *                   may be empty or {@code null} if no controls should be
269       *                   included.
270       *
271       * @return  The add request that was created.
272       */
273      public AddRequest toAddRequest(final Control... controls)
274      {
275        return new AddRequest(dn, attributes, controls);
276      }
277    
278    
279    
280      /**
281       * Retrieves a string representation of this protocol op.
282       *
283       * @return  A string representation of this protocol op.
284       */
285      @Override()
286      public String toString()
287      {
288        final StringBuilder buffer = new StringBuilder();
289        toString(buffer);
290        return buffer.toString();
291      }
292    
293    
294    
295      /**
296       * {@inheritDoc}
297       */
298      public void toString(final StringBuilder buffer)
299      {
300        buffer.append("AddRequestProtocolOp(dn='");
301        buffer.append(dn);
302        buffer.append("', attrs={");
303    
304        final Iterator<Attribute> iterator = attributes.iterator();
305        while (iterator.hasNext())
306        {
307          iterator.next().toString(buffer);
308          if (iterator.hasNext())
309          {
310            buffer.append(',');
311          }
312        }
313    
314        buffer.append("})");
315      }
316    }