001/* 002 * Copyright 2012-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.Iterator; 029import java.util.List; 030 031import com.unboundid.asn1.ASN1Element; 032import com.unboundid.asn1.ASN1OctetString; 033import com.unboundid.asn1.ASN1Sequence; 034import com.unboundid.ldap.sdk.Control; 035import com.unboundid.ldap.sdk.ExtendedResult; 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; 043 044import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 045 046 047 048/** 049 * This class provides an implementation of an extended result that can be used 050 * to provide information about the notification subscriptions defined in the 051 * target server. 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 OID for this result is 1.3.6.1.4.1.30221.2.6.41, and the value (if 064 * present) should have the following encoding: 065 * <BR><BR> 066 * <PRE> 067 * ListNotificationSubscriptionsResponse ::= SEQUENCE OF SEQUENCE { 068 * notificationDestinationID OCTET STRING, 069 * destinationDetails SEQUENCE OF OCTET STRING, 070 * subscriptions SEQUENCE OF SEQUENCE { 071 * subscriptionID OCTET STRING, 072 * subscriptionDetails SEQUENCE OF OCTET STRING } } 073 * </PRE> 074 */ 075@NotMutable() 076@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 077public final class ListNotificationSubscriptionsExtendedResult 078 extends ExtendedResult 079{ 080 /** 081 * The OID (1.3.6.1.4.1.30221.2.6.41) for the list notification subscriptions 082 * extended result. 083 */ 084 public static final String LIST_NOTIFICATION_SUBSCRIPTIONS_RESULT_OID = 085 "1.3.6.1.4.1.30221.2.6.41"; 086 087 088 089 /** 090 * The serial version UID for this serializable class. 091 */ 092 private static final long serialVersionUID = 8876370324325619149L; 093 094 095 096 // The notification destination details for this result. 097 private final List<NotificationDestinationDetails> destinations; 098 099 100 101 /** 102 * Creates a new list notification subscriptions extended result from the 103 * provided extended result. 104 * 105 * @param extendedResult The extended result to be decoded as a list 106 * notification subscriptions extended result. 107 * 108 * @throws LDAPException If a problem is encountered while attempting to 109 * decode the provided extended result as a 110 * multi-update result. 111 */ 112 public ListNotificationSubscriptionsExtendedResult( 113 final ExtendedResult extendedResult) 114 throws LDAPException 115 { 116 super(extendedResult); 117 118 final ASN1OctetString value = extendedResult.getValue(); 119 if (value == null) 120 { 121 destinations = Collections.emptyList(); 122 return; 123 } 124 125 try 126 { 127 final ASN1Element[] destsElements = 128 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 129 final ArrayList<NotificationDestinationDetails> destList = 130 new ArrayList<>(destsElements.length); 131 for (final ASN1Element destElement : destsElements) 132 { 133 final ASN1Element[] destElements = 134 ASN1Sequence.decodeAsSequence(destElement).elements(); 135 final String destID = 136 ASN1OctetString.decodeAsOctetString(destElements[0]).stringValue(); 137 138 final ASN1Element[] destDetailsElements = 139 ASN1Sequence.decodeAsSequence(destElements[1]).elements(); 140 final ArrayList<ASN1OctetString> destDetailsList = 141 new ArrayList<>(destDetailsElements.length); 142 for (final ASN1Element e : destDetailsElements) 143 { 144 destDetailsList.add(ASN1OctetString.decodeAsOctetString(e)); 145 } 146 147 final ASN1Element[] subElements = 148 ASN1Sequence.decodeAsSequence(destElements[2]).elements(); 149 final ArrayList<NotificationSubscriptionDetails> subscriptions = 150 new ArrayList<>(subElements.length); 151 for (final ASN1Element e : subElements) 152 { 153 final ASN1Element[] sElements = 154 ASN1Sequence.decodeAsSequence(e).elements(); 155 final String subID = 156 ASN1OctetString.decodeAsOctetString(sElements[0]).stringValue(); 157 158 final ASN1Element[] subDetailsElements = 159 ASN1Sequence.decodeAsSequence(sElements[1]).elements(); 160 final ArrayList<ASN1OctetString> subDetails = 161 new ArrayList<>(subDetailsElements.length); 162 for (final ASN1Element sde : subDetailsElements) 163 { 164 subDetails.add(ASN1OctetString.decodeAsOctetString(sde)); 165 } 166 subscriptions.add( 167 new NotificationSubscriptionDetails(subID, subDetails)); 168 } 169 170 destList.add(new NotificationDestinationDetails(destID, destDetailsList, 171 subscriptions)); 172 } 173 174 destinations = Collections.unmodifiableList(destList); 175 } 176 catch (final Exception e) 177 { 178 Debug.debugException(e); 179 throw new LDAPException(ResultCode.DECODING_ERROR, 180 ERR_LIST_NOTIFICATION_SUBS_RESULT_CANNOT_DECODE_VALUE.get( 181 StaticUtils.getExceptionMessage(e)), 182 e); 183 } 184 } 185 186 187 188 /** 189 * Creates a new list notification subscriptions extended request with the 190 * provided information. 191 * 192 * @param messageID The message ID for this extended result. 193 * @param resultCode The result code for this result. It must not be 194 * {@code null}. 195 * @param diagnosticMessage The diagnostic message to include in the result. 196 * It may be {@code null} if no diagnostic message 197 * should be included. 198 * @param matchedDN The matched DN to include in the result. It may 199 * be {@code null} if no matched DN should be 200 * included. 201 * @param referralURLs The set of referral URLs to include in the 202 * result. It may be {@code null} or empty if no 203 * referral URLs should be included. 204 * @param destinations The notification destination details for this 205 * result. It may be {@code null} or empty for a 206 * non-success result. 207 * @param controls The set of controls to include in the 208 * multi-update result. It may be {@code null} or 209 * empty if no controls should be included. 210 * 211 * @throws LDAPException If any of the results are for an inappropriate 212 * operation type. 213 */ 214 public ListNotificationSubscriptionsExtendedResult(final int messageID, 215 final ResultCode resultCode, final String diagnosticMessage, 216 final String matchedDN, final String[] referralURLs, 217 final Collection<NotificationDestinationDetails> destinations, 218 final Control... controls) 219 throws LDAPException 220 { 221 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs, 222 LIST_NOTIFICATION_SUBSCRIPTIONS_RESULT_OID, encodeValue(destinations), 223 controls); 224 225 if (destinations == null) 226 { 227 this.destinations = Collections.emptyList(); 228 } 229 else 230 { 231 this.destinations = 232 Collections.unmodifiableList(new ArrayList<>(destinations)); 233 } 234 } 235 236 237 238 /** 239 * Encodes the information from the provided set of results into a form 240 * suitable for use as the value of the extended result. 241 * 242 * @param destinations The notification destination details for the result. 243 * It may be {@code null} or empty for a non-success 244 * result. 245 * 246 * @return An ASN.1 element suitable for use as the value of the extended 247 * result. 248 */ 249 private static ASN1OctetString encodeValue( 250 final Collection<NotificationDestinationDetails> destinations) 251 { 252 if ((destinations == null) || destinations.isEmpty()) 253 { 254 return null; 255 } 256 257 final ArrayList<ASN1Element> elements = 258 new ArrayList<>(destinations.size()); 259 for (final NotificationDestinationDetails destDetails : destinations) 260 { 261 final ArrayList<ASN1Element> destElements = new ArrayList<>(3); 262 destElements.add(new ASN1OctetString(destDetails.getID())); 263 destElements.add(new ASN1Sequence(destDetails.getDetails())); 264 265 final ArrayList<ASN1Element> subElements = 266 new ArrayList<>(destDetails.getSubscriptions().size()); 267 for (final NotificationSubscriptionDetails subDetails : 268 destDetails.getSubscriptions()) 269 { 270 subElements.add(new ASN1Sequence( 271 new ASN1OctetString(subDetails.getID()), 272 new ASN1Sequence(subDetails.getDetails()))); 273 } 274 destElements.add(new ASN1Sequence(subElements)); 275 elements.add(new ASN1Sequence(destElements)); 276 } 277 278 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 279 } 280 281 282 283 /** 284 * Retrieves a list of the defined notification destinations and their 285 * associated subscriptions. 286 * 287 * @return A list of the defined notification destinations and their 288 * associated subscriptions. 289 */ 290 public List<NotificationDestinationDetails> getDestinations() 291 { 292 return destinations; 293 } 294 295 296 297 /** 298 * {@inheritDoc} 299 */ 300 @Override() 301 public String getExtendedResultName() 302 { 303 return INFO_EXTENDED_RESULT_NAME_LIST_NOTIFICATION_SUBS.get(); 304 } 305 306 307 308 /** 309 * Appends a string representation of this extended result to the provided 310 * buffer. 311 * 312 * @param buffer The buffer to which a string representation of this 313 * extended result will be appended. 314 */ 315 @Override() 316 public void toString(final StringBuilder buffer) 317 { 318 buffer.append("ListNotificationSubscriptionsExtendedResult(resultCode="); 319 buffer.append(getResultCode()); 320 321 final int messageID = getMessageID(); 322 if (messageID >= 0) 323 { 324 buffer.append(", messageID="); 325 buffer.append(messageID); 326 } 327 328 buffer.append(", notificationDestinations={"); 329 final Iterator<NotificationDestinationDetails> destIterator = 330 destinations.iterator(); 331 while (destIterator.hasNext()) 332 { 333 destIterator.next().toString(buffer); 334 if (destIterator.hasNext()) 335 { 336 buffer.append(", "); 337 } 338 } 339 buffer.append('}'); 340 341 final String diagnosticMessage = getDiagnosticMessage(); 342 if (diagnosticMessage != null) 343 { 344 buffer.append(", diagnosticMessage='"); 345 buffer.append(diagnosticMessage); 346 buffer.append('\''); 347 } 348 349 final String matchedDN = getMatchedDN(); 350 if (matchedDN != null) 351 { 352 buffer.append(", matchedDN='"); 353 buffer.append(matchedDN); 354 buffer.append('\''); 355 } 356 357 final String[] referralURLs = getReferralURLs(); 358 if (referralURLs.length > 0) 359 { 360 buffer.append(", referralURLs={"); 361 for (int i=0; i < referralURLs.length; i++) 362 { 363 if (i > 0) 364 { 365 buffer.append(", "); 366 } 367 368 buffer.append('\''); 369 buffer.append(referralURLs[i]); 370 buffer.append('\''); 371 } 372 buffer.append('}'); 373 } 374 375 final Control[] responseControls = getResponseControls(); 376 if (responseControls.length > 0) 377 { 378 buffer.append(", responseControls={"); 379 for (int i=0; i < responseControls.length; i++) 380 { 381 if (i > 0) 382 { 383 buffer.append(", "); 384 } 385 386 buffer.append(responseControls[i]); 387 } 388 buffer.append('}'); 389 } 390 391 buffer.append(')'); 392 } 393}