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}