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