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