001 /*
002 * Copyright 2014-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.controls;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.Collection;
028 import java.util.Collections;
029 import java.util.Iterator;
030 import java.util.LinkedHashSet;
031 import java.util.List;
032 import java.util.Set;
033
034 import com.unboundid.asn1.ASN1Element;
035 import com.unboundid.asn1.ASN1OctetString;
036 import com.unboundid.asn1.ASN1Sequence;
037 import com.unboundid.asn1.ASN1Set;
038 import com.unboundid.ldap.sdk.Control;
039 import com.unboundid.ldap.sdk.DecodeableControl;
040 import com.unboundid.ldap.sdk.ExtendedResult;
041 import com.unboundid.ldap.sdk.LDAPException;
042 import com.unboundid.ldap.sdk.LDAPResult;
043 import com.unboundid.ldap.sdk.ResultCode;
044 import com.unboundid.ldap.sdk.SearchResultEntry;
045 import com.unboundid.util.Debug;
046 import com.unboundid.util.NotMutable;
047 import com.unboundid.util.StaticUtils;
048 import com.unboundid.util.ThreadSafety;
049 import com.unboundid.util.ThreadSafetyLevel;
050 import com.unboundid.util.Validator;
051
052 import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
053
054
055
056 /**
057 * <BLOCKQUOTE>
058 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID
059 * LDAP SDK for Java. It is not available for use in applications that
060 * include only the Standard Edition of the LDAP SDK, and is not supported for
061 * use in conjunction with non-UnboundID products.
062 * </BLOCKQUOTE>
063 * This class provides a response control that may be used to provide the
064 * backend set ID(s) for any relevant backend sets accessed during the course
065 * of processing an operation. It may be returned in response to a request
066 * containing either the get backend set ID request control or the route to
067 * backend set request control. For add, simple bind, compare, delete,
068 * modify, and modify DN operations, the LDAP result message for the operation
069 * may contain zero or one get backend set ID response control. For extended
070 * operations, the extended result message may contain zero, one, or multiple
071 * get backend set ID response controls. For search operations, each search
072 * result entry may contain zero or one get backend set ID response control,
073 * while the search result done message will not contain any such control. See
074 * the {@link GetBackendSetIDRequestControl} class documentation for a more
075 * complete description of the usage for these controls.
076 * <BR><BR>
077 * The get backend set ID response control has an OID of
078 * "1.3.6.1.4.1.30221.2.5.34", a criticality of false, and a value with the
079 * following encoding:
080 * <PRE>
081 * GET_BACKEND_SET_ID_RESPONSE_VALUE ::= SEQUENCE {
082 * entryBalancingRequestProcessorID OCTET STRING,
083 * backendSetIDs SET SIZE (1..MAX) OF OCTET STRING,
084 * ... }
085 * </PRE>
086 *
087 * @see GetBackendSetIDRequestControl
088 * @see RouteToBackendSetRequestControl
089 */
090 @NotMutable()
091 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
092 public final class GetBackendSetIDResponseControl
093 extends Control
094 implements DecodeableControl
095 {
096 /**
097 * The OID (1.3.6.1.4.1.30221.2.5.34) for the get backend set ID response
098 * control.
099 */
100 public static final String GET_BACKEND_SET_ID_RESPONSE_OID =
101 "1.3.6.1.4.1.30221.2.5.34";
102
103
104
105 /**
106 * The serial version UID for this serializable class.
107 */
108 private static final long serialVersionUID = 117359364981309726L;
109
110
111
112 // The backend set IDs for backend sets used during processing.
113 private final Set<String> backendSetIDs;
114
115 // The identifier for the entry-balancing request processor with which the
116 // backend set IDs are associated.
117 private final String entryBalancingRequestProcessorID;
118
119
120
121 /**
122 * Creates a new empty control instance that is intended to be used only for
123 * decoding controls via the {@code DecodeableControl} interface.
124 */
125 GetBackendSetIDResponseControl()
126 {
127 entryBalancingRequestProcessorID = null;
128 backendSetIDs = null;
129 }
130
131
132
133 /**
134 * Creates a new get backend set ID response control with the provided
135 * information.
136 *
137 * @param entryBalancingRequestProcessorID The identifier for the
138 * entry-balancing request processor
139 * with which the backend set IDs
140 * are associated. It must not be
141 * {@code null}.
142 * @param backendSetID The backend set ID for the
143 * backend set used during
144 * processing. It must not be
145 * {@code null}.
146 */
147 public GetBackendSetIDResponseControl(
148 final String entryBalancingRequestProcessorID,
149 final String backendSetID)
150 {
151 this(entryBalancingRequestProcessorID, Arrays.asList(backendSetID));
152 }
153
154
155
156 /**
157 * Creates a new get backend set ID response control with the provided
158 * information.
159 *
160 * @param entryBalancingRequestProcessorID The identifier for the
161 * entry-balancing request processor
162 * with which the backend set IDs
163 * are associated. It must not be
164 * {@code null}.
165 * @param backendSetIDs The backend set IDs for backend
166 * sets used during processing. It
167 * must not be {@code null} or
168 * empty.
169 */
170 public GetBackendSetIDResponseControl(
171 final String entryBalancingRequestProcessorID,
172 final Collection<String> backendSetIDs)
173 {
174 super(GET_BACKEND_SET_ID_RESPONSE_OID, false,
175 encodeValue(entryBalancingRequestProcessorID, backendSetIDs));
176
177 this.entryBalancingRequestProcessorID = entryBalancingRequestProcessorID;
178 this.backendSetIDs =
179 Collections.unmodifiableSet(new LinkedHashSet<String>(backendSetIDs));
180 }
181
182
183
184 /**
185 * Creates a new get backend set ID response control decoded from the given
186 * generic control contents.
187 *
188 * @param oid The OID for the control.
189 * @param isCritical Indicates whether this control should be marked
190 * critical.
191 * @param value The encoded value for the control.
192 *
193 * @throws LDAPException If a problem occurs while attempting to decode the
194 * generic control as a get backend set ID response
195 * control.
196 */
197 public GetBackendSetIDResponseControl(final String oid,
198 final boolean isCritical,
199 final ASN1OctetString value)
200 throws LDAPException
201 {
202 super(oid, isCritical, value);
203
204 if (value == null)
205 {
206 throw new LDAPException(ResultCode.DECODING_ERROR,
207 ERR_GET_BACKEND_SET_ID_RESPONSE_MISSING_VALUE.get());
208 }
209
210 try
211 {
212 final ASN1Element[] elements =
213 ASN1Sequence.decodeAsSequence(value.getValue()).elements();
214 entryBalancingRequestProcessorID =
215 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
216
217 final ASN1Element[] backendSetIDElements =
218 ASN1Set.decodeAsSet(elements[1]).elements();
219 final LinkedHashSet<String> setIDs =
220 new LinkedHashSet<String>(backendSetIDElements.length);
221 for (final ASN1Element e : backendSetIDElements)
222 {
223 setIDs.add(ASN1OctetString.decodeAsOctetString(e).stringValue());
224 }
225 backendSetIDs = Collections.unmodifiableSet(setIDs);
226 }
227 catch (final Exception e)
228 {
229 Debug.debugException(e);
230 throw new LDAPException(ResultCode.DECODING_ERROR,
231 ERR_GET_BACKEND_SET_ID_RESPONSE_CANNOT_DECODE.get(
232 StaticUtils.getExceptionMessage(e)),
233 e);
234 }
235 }
236
237
238
239 /**
240 * Encodes the provided information into an octet string suitable for use as
241 * the value of this control.
242 *
243 * @param entryBalancingRequestProcessorID The identifier for the
244 * entry-balancing request processor
245 * with which the backend set IDs
246 * are associated. It must not be
247 * {@code null}.
248 * @param backendSetIDs The backend set IDs for backend
249 * sets used during processing. It
250 * must not be {@code null} or
251 * empty.
252 *
253 * @return The encoded representation of the control value.
254 */
255 private static ASN1OctetString encodeValue(
256 final String entryBalancingRequestProcessorID,
257 final Collection<String> backendSetIDs)
258 {
259 Validator.ensureNotNull(entryBalancingRequestProcessorID);
260 Validator.ensureNotNull(backendSetIDs);
261 Validator.ensureFalse(backendSetIDs.isEmpty());
262
263 final ArrayList<ASN1Element> backendSetIDElements =
264 new ArrayList<ASN1Element>(backendSetIDs.size());
265 for (final String s : backendSetIDs)
266 {
267 backendSetIDElements.add(new ASN1OctetString(s));
268 }
269
270 final ASN1Sequence valueSequence = new ASN1Sequence(
271 new ASN1OctetString(entryBalancingRequestProcessorID),
272 new ASN1Set(backendSetIDElements));
273 return new ASN1OctetString(valueSequence.encode());
274 }
275
276
277
278 /**
279 * {@inheritDoc}
280 */
281 public GetBackendSetIDResponseControl decodeControl(final String oid,
282 final boolean isCritical,
283 final ASN1OctetString value)
284 throws LDAPException
285 {
286 return new GetBackendSetIDResponseControl(oid, isCritical, value);
287 }
288
289
290
291 /**
292 * Retrieves the identifier for the entry-balancing request processor with
293 * which the backend sets IDs are associated.
294 *
295 * @return The identifier for the entry-balancing request processor with
296 * which the backend set IDs are associated.
297 */
298 public String getEntryBalancingRequestProcessorID()
299 {
300 return entryBalancingRequestProcessorID;
301 }
302
303
304
305 /**
306 * Retrieves the backend set IDs for the backend sets used during processing.
307 *
308 * @return The backend set IDs for the backend sets used during processing.
309 */
310 public Set<String> getBackendSetIDs()
311 {
312 return backendSetIDs;
313 }
314
315
316
317 /**
318 * Extracts a get backend set ID response control from the provided result.
319 *
320 * @param result The result from which to retrieve the get backend set ID
321 * response control.
322 *
323 * @return The get backend set ID response control contained in the provided
324 * result, or {@code null} if the result did not contain a get
325 * backend set ID response control.
326 *
327 * @throws LDAPException If a problem is encountered while attempting to
328 * decode the get backend set ID response control
329 * contained in the provided result.
330 */
331 public static GetBackendSetIDResponseControl get(final LDAPResult result)
332 throws LDAPException
333 {
334 final Control c =
335 result.getResponseControl(GET_BACKEND_SET_ID_RESPONSE_OID);
336 if (c == null)
337 {
338 return null;
339 }
340
341 if (c instanceof GetBackendSetIDResponseControl)
342 {
343 return (GetBackendSetIDResponseControl) c;
344 }
345 else
346 {
347 return new GetBackendSetIDResponseControl(c.getOID(), c.isCritical(),
348 c.getValue());
349 }
350 }
351
352
353
354 /**
355 * Extracts a get backend set ID response control from the provided search
356 * result entry.
357 *
358 * @param entry The entry from which to retrieve the get backend set ID
359 * response control.
360 *
361 * @return The get backend set ID response control contained in the provided
362 * entry, or {@code null} if the entry did not contain a get backend
363 * set ID response control.
364 *
365 * @throws LDAPException If a problem is encountered while attempting to
366 * decode the get backend set ID response control
367 * contained in the provided result.
368 */
369 public static GetBackendSetIDResponseControl
370 get(final SearchResultEntry entry)
371 throws LDAPException
372 {
373 final Control c = entry.getControl(GET_BACKEND_SET_ID_RESPONSE_OID);
374 if (c == null)
375 {
376 return null;
377 }
378
379 if (c instanceof GetBackendSetIDResponseControl)
380 {
381 return (GetBackendSetIDResponseControl) c;
382 }
383 else
384 {
385 return new GetBackendSetIDResponseControl(c.getOID(), c.isCritical(),
386 c.getValue());
387 }
388 }
389
390
391
392 /**
393 * Extracts any get backend set ID response controls from the provided
394 * extended result.
395 *
396 * @param result The extended result from which to retrieve the get backend
397 * set ID response control(s).
398 *
399 * @return A list of get backend set ID response controls contained in the
400 * provided extended result, or an empty list if the result did not
401 * contain a get any backend set ID response controls.
402 *
403 * @throws LDAPException If a problem is encountered while attempting to
404 * decode the any backend set ID response control
405 * contained in the provided result.
406 */
407 public static List<GetBackendSetIDResponseControl>
408 get(final ExtendedResult result)
409 throws LDAPException
410 {
411 final Control[] controls = result.getResponseControls();
412 if (controls.length == 0)
413 {
414 return Collections.emptyList();
415 }
416
417 final ArrayList<GetBackendSetIDResponseControl> decodedControls =
418 new ArrayList<GetBackendSetIDResponseControl>(controls.length);
419 for (final Control c : controls)
420 {
421 if (c instanceof GetBackendSetIDResponseControl)
422 {
423 decodedControls.add((GetBackendSetIDResponseControl) c);
424 }
425 else if (c.getOID().equals(GET_BACKEND_SET_ID_RESPONSE_OID))
426 {
427 decodedControls.add(new GetBackendSetIDResponseControl(c.getOID(),
428 c.isCritical(), c.getValue()));
429 }
430 }
431
432 return Collections.unmodifiableList(decodedControls);
433 }
434
435
436
437 /**
438 * {@inheritDoc}
439 */
440 @Override()
441 public String getControlName()
442 {
443 return INFO_CONTROL_NAME_GET_BACKEND_SET_ID_RESPONSE.get();
444 }
445
446
447
448 /**
449 * {@inheritDoc}
450 */
451 @Override()
452 public void toString(final StringBuilder buffer)
453 {
454 buffer.append("GetBackendSetIDResponseControl(" +
455 "entryBalancingRequestProcessorID='");
456 buffer.append(entryBalancingRequestProcessorID);
457 buffer.append("', backendSetIDs={");
458
459 final Iterator<String> iterator = backendSetIDs.iterator();
460 while (iterator.hasNext())
461 {
462 buffer.append('\'');
463 buffer.append(iterator.next());
464 buffer.append('\'');
465
466 if (iterator.hasNext())
467 {
468 buffer.append(", ");
469 }
470 }
471
472 buffer.append("})");
473 }
474 }