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 }