001/*
002 * Copyright 2014-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
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 */
021package com.unboundid.ldap.sdk.unboundidds.extensions;
022
023
024
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.List;
029
030import com.unboundid.asn1.ASN1Element;
031import com.unboundid.asn1.ASN1Enumerated;
032import com.unboundid.asn1.ASN1OctetString;
033import com.unboundid.asn1.ASN1Sequence;
034import com.unboundid.ldap.sdk.Control;
035import com.unboundid.ldap.sdk.ExtendedRequest;
036import com.unboundid.ldap.sdk.LDAPException;
037import com.unboundid.ldap.sdk.ResultCode;
038import com.unboundid.util.Debug;
039import com.unboundid.util.NotMutable;
040import com.unboundid.util.StaticUtils;
041import com.unboundid.util.ThreadSafety;
042import com.unboundid.util.ThreadSafetyLevel;
043import com.unboundid.util.Validator;
044
045import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
046
047
048
049/**
050 * This class provides an extended request that may be used to create or update
051 * a notification destination.
052 * <BR>
053 * <BLOCKQUOTE>
054 *   <B>NOTE:</B>  This class, and other classes within the
055 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
056 *   supported for use against Ping Identity, UnboundID, and
057 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
058 *   for proprietary functionality or for external specifications that are not
059 *   considered stable or mature enough to be guaranteed to work in an
060 *   interoperable way with other types of LDAP servers.
061 * </BLOCKQUOTE>
062 * <BR>
063 * The request has an OID of 1.3.6.1.4.1.30221.2.6.36 and a value with the
064 * following encoding:
065 * <BR><BR>
066 * <PRE>
067 *   SetNotificationDestinationRequest ::= SEQUENCE {
068 *        notificationManagerID         OCTET STRING,
069 *        notificationDestinationID     OCTET STRING,
070 *        destinationDetails            SEQUENCE OF OCTET STRING,
071 *        changeType                    [0] ENUMERATED {
072 *             replace (0),
073 *             add (1),
074 *             delete (2) } DEFAULT replace }
075 * </PRE>
076 */
077@NotMutable()
078@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
079public final class SetNotificationDestinationExtendedRequest
080       extends ExtendedRequest
081{
082  /**
083   * The OID (1.3.6.1.4.1.30221.2.6.36) for the set notification destination
084   * extended request.
085   */
086  public static final String SET_NOTIFICATION_DESTINATION_REQUEST_OID =
087       "1.3.6.1.4.1.30221.2.6.36";
088
089
090
091  /**
092   * The BER type for the value sequence element that specifies the destination
093   * details change type.
094   */
095  private static final byte BER_TYPE_CHANGE_TYPE = (byte) 0x80;
096
097
098
099  /**
100   * The serial version UID for this serializable class.
101   */
102  private static final long serialVersionUID = 8651862605802389433L;
103
104
105
106  // The implementation-specific details for the notification destination.
107  private final List<ASN1OctetString> destinationDetails;
108
109  // The change type for the destination details.
110  private final SetNotificationDestinationChangeType changeType;
111
112  // The notification destination ID.
113  private final String destinationID;
114
115  // The notification manager ID.
116  private final String managerID;
117
118
119
120  /**
121   * Creates a new set notification destination extended request with the
122   * provided information.
123   *
124   * @param  managerID           The notification manager ID.  It must not be
125   *                             {@code null}.
126   * @param  destinationID       The notification destination ID.  It must not
127   *                             be {@code null}.
128   * @param  destinationDetails  The implementation-specific details for the
129   *                             notification destination.  At least one detail
130   *                             value must be provided.
131   */
132  public SetNotificationDestinationExtendedRequest(final String managerID,
133              final String destinationID,
134              final ASN1OctetString... destinationDetails)
135  {
136    this(managerID, destinationID, StaticUtils.toList(destinationDetails),
137         SetNotificationDestinationChangeType.REPLACE);
138  }
139
140
141
142  /**
143   * Creates a new set notification destination extended request with the
144   * provided information.
145   *
146   * @param  managerID           The notification manager ID.  It must not be
147   *                             {@code null}.
148   * @param  destinationID       The notification destination ID.  It must not
149   *                             be {@code null}.
150   * @param  destinationDetails  The implementation-specific details for the
151   *                             notification destination.  At least one detail
152   *                             value must be provided.
153   * @param  controls            The set of controls to include in the request.
154   *                             It may be {@code null} or empty if no controls
155   *                             are needed.
156   */
157  public SetNotificationDestinationExtendedRequest(final String managerID,
158              final String destinationID,
159              final Collection<ASN1OctetString> destinationDetails,
160              final Control... controls)
161  {
162    this(managerID, destinationID, destinationDetails,
163         SetNotificationDestinationChangeType.REPLACE, controls);
164  }
165
166
167
168  /**
169   * Creates a new set notification destination extended request with the
170   * provided information.
171   *
172   * @param  managerID           The notification manager ID.  It must not be
173   *                             {@code null}.
174   * @param  destinationID       The notification destination ID.  It must not
175   *                             be {@code null}.
176   * @param  destinationDetails  The implementation-specific details for the
177   *                             notification destination.  At least one detail
178   *                             value must be provided.
179   * @param  changeType          The change type for the destination details.
180   * @param  controls            The set of controls to include in the request.
181   *                             It may be {@code null} or empty if no controls
182   *                             are needed.
183   */
184  public SetNotificationDestinationExtendedRequest(final String managerID,
185              final String destinationID,
186              final Collection<ASN1OctetString> destinationDetails,
187              final SetNotificationDestinationChangeType changeType,
188              final Control... controls)
189  {
190    super(SET_NOTIFICATION_DESTINATION_REQUEST_OID,
191         encodeValue(managerID, destinationID, destinationDetails, changeType),
192         controls);
193
194    this.managerID = managerID;
195    this.destinationID = destinationID;
196    this.destinationDetails =
197         Collections.unmodifiableList(new ArrayList<>(destinationDetails));
198
199    if (changeType == null)
200    {
201      this.changeType = SetNotificationDestinationChangeType.REPLACE;
202    }
203    else
204    {
205      this.changeType = changeType;
206    }
207  }
208
209
210
211  /**
212   * Creates a new set notification destination extended request from the
213   * provided generic extended request.
214   *
215   * @param  extendedRequest  The generic extended request to use to create this
216   *                          set notification destination extended request.
217   *
218   * @throws  LDAPException  If a problem occurs while decoding the request.
219   */
220  public SetNotificationDestinationExtendedRequest(
221              final ExtendedRequest extendedRequest)
222         throws LDAPException
223  {
224    super(extendedRequest);
225
226    final ASN1OctetString value = extendedRequest.getValue();
227    if (value == null)
228    {
229      throw new LDAPException(ResultCode.DECODING_ERROR,
230           ERR_SET_NOTIFICATION_DEST_REQ_DECODE_NO_VALUE.get());
231    }
232
233    try
234    {
235      final ASN1Element[] elements =
236           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
237      managerID =
238           ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
239      destinationID =
240           ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();
241
242      final ASN1Element[] detailElements =
243           ASN1Sequence.decodeAsSequence(elements[2]).elements();
244      final ArrayList<ASN1OctetString> detailList =
245           new ArrayList<>(detailElements.length);
246      for (final ASN1Element e : detailElements)
247      {
248        detailList.add(ASN1OctetString.decodeAsOctetString(e));
249      }
250      destinationDetails = Collections.unmodifiableList(detailList);
251
252      SetNotificationDestinationChangeType ct =
253           SetNotificationDestinationChangeType.REPLACE;
254      for (int i=3; i < elements.length; i++)
255      {
256        final ASN1Element e = elements[i];
257        switch (e.getType())
258        {
259          case BER_TYPE_CHANGE_TYPE:
260            final int ctIntValue =
261                 ASN1Enumerated.decodeAsEnumerated(e).intValue();
262            ct = SetNotificationDestinationChangeType.valueOf(ctIntValue);
263            if (ct == null)
264            {
265              throw new LDAPException(ResultCode.DECODING_ERROR,
266                   ERR_SET_NOTIFICATION_DEST_REQ_INVALID_CT.get(ctIntValue));
267            }
268            break;
269
270          default:
271            throw new LDAPException(ResultCode.DECODING_ERROR,
272                 ERR_SET_NOTIFICATION_DEST_REQ_INVALID_ELEMENT_TYPE.get(
273                      StaticUtils.toHex(e.getType())));
274        }
275      }
276
277      changeType = ct;
278    }
279    catch (final LDAPException le)
280    {
281      Debug.debugException(le);
282      throw le;
283    }
284    catch (final Exception e)
285    {
286      Debug.debugException(e);
287      throw new LDAPException(ResultCode.DECODING_ERROR,
288           ERR_SET_NOTIFICATION_DEST_REQ_ERROR_DECODING_VALUE.get(
289                StaticUtils.getExceptionMessage(e)),
290           e);
291    }
292  }
293
294
295
296  /**
297   * Encodes the provided information into an ASN.1 octet string suitable for
298   * use as the value of this extended request.
299   *
300   * @param  managerID           The notification manager ID.  It must not be
301   *                             {@code null}.
302   * @param  destinationID       The notification destination ID.  It must not
303   *                             be {@code null}.
304   * @param  destinationDetails  The implementation-specific details for the
305   *                             notification destination.  At least one detail
306   *                             value must be provided.
307   * @param  changeType          The change type for the destination details.
308   *
309   * @return  The ASN.1 octet string containing the encoded value.
310   */
311  private static ASN1OctetString encodeValue(final String managerID,
312                      final String destinationID,
313                      final Collection<ASN1OctetString> destinationDetails,
314                      final SetNotificationDestinationChangeType changeType)
315  {
316    Validator.ensureNotNull(managerID);
317    Validator.ensureNotNull(destinationID);
318    Validator.ensureNotNull(destinationDetails);
319    Validator.ensureFalse(destinationDetails.isEmpty());
320
321    final ArrayList<ASN1Element> elements = new ArrayList<>(4);
322    elements.add(new ASN1OctetString(managerID));
323    elements.add(new ASN1OctetString(destinationID));
324    elements.add(new ASN1Sequence(
325         new ArrayList<ASN1Element>(destinationDetails)));
326
327    if ((changeType != null) &&
328        (changeType != SetNotificationDestinationChangeType.REPLACE))
329    {
330      elements.add(new ASN1Enumerated(BER_TYPE_CHANGE_TYPE,
331           changeType.intValue()));
332    }
333
334    return new ASN1OctetString(new ASN1Sequence(elements).encode());
335  }
336
337
338
339  /**
340   * Retrieves the notification manager ID.
341   *
342   * @return  The notification manager ID.
343   */
344  public String getManagerID()
345  {
346    return managerID;
347  }
348
349
350
351  /**
352   * Retrieves the notification destination ID.
353   *
354   * @return  The notification destination ID.
355   */
356  public String getDestinationID()
357  {
358    return destinationID;
359  }
360
361
362
363  /**
364   * Retrieves the implementation-specific details for the notification
365   * destination.
366   *
367   * @return  The implementation-specific details for the notification
368   *          destination.
369   */
370  public List<ASN1OctetString> getDestinationDetails()
371  {
372    return destinationDetails;
373  }
374
375
376
377  /**
378   * Retrieves the change type for the destination details.
379   *
380   * @return  The change type for the destination details.
381   */
382  public SetNotificationDestinationChangeType getChangeType()
383  {
384    return changeType;
385  }
386
387
388
389  /**
390   * {@inheritDoc}
391   */
392  @Override()
393  public SetNotificationDestinationExtendedRequest duplicate()
394  {
395    return duplicate(getControls());
396  }
397
398
399
400  /**
401   * {@inheritDoc}
402   */
403  @Override()
404  public SetNotificationDestinationExtendedRequest
405              duplicate(final Control[] controls)
406  {
407    final SetNotificationDestinationExtendedRequest r =
408         new SetNotificationDestinationExtendedRequest(managerID,
409              destinationID, destinationDetails, changeType, controls);
410    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
411    return r;
412  }
413
414
415
416  /**
417   * {@inheritDoc}
418   */
419  @Override()
420  public String getExtendedRequestName()
421  {
422    return INFO_EXTENDED_REQUEST_NAME_SET_NOTIFICATION_DEST.get();
423  }
424
425
426
427  /**
428   * {@inheritDoc}
429   */
430  @Override()
431  public void toString(final StringBuilder buffer)
432  {
433    buffer.append("SetNotificationDestinationExtendedRequest(managerID='");
434    buffer.append(managerID);
435    buffer.append("', destinationID='");
436    buffer.append(destinationID);
437    buffer.append("', destinationDetails=ASN1OctetString[");
438    buffer.append(destinationDetails.size());
439    buffer.append("], changeType=");
440    buffer.append(changeType.name());
441
442    final Control[] controls = getControls();
443    if (controls.length > 0)
444    {
445      buffer.append(", controls={");
446      for (int i=0; i < controls.length; i++)
447      {
448        if (i > 0)
449        {
450          buffer.append(", ");
451        }
452
453        buffer.append(controls[i]);
454      }
455      buffer.append('}');
456    }
457
458    buffer.append(')');
459  }
460}