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