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}