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 }