001 /* 002 * Copyright 2008-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 com.unboundid.asn1.ASN1Element; 026 import com.unboundid.asn1.ASN1OctetString; 027 import com.unboundid.asn1.ASN1Sequence; 028 import com.unboundid.ldap.sdk.Control; 029 import com.unboundid.ldap.sdk.DecodeableControl; 030 import com.unboundid.ldap.sdk.LDAPException; 031 import com.unboundid.ldap.sdk.LDAPResult; 032 import com.unboundid.ldap.sdk.ResultCode; 033 import com.unboundid.util.NotMutable; 034 import com.unboundid.util.ThreadSafety; 035 import com.unboundid.util.ThreadSafetyLevel; 036 037 import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 038 039 040 041 /** 042 * <BLOCKQUOTE> 043 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID 044 * LDAP SDK for Java. It is not available for use in applications that 045 * include only the Standard Edition of the LDAP SDK, and is not supported for 046 * use in conjunction with non-UnboundID products. 047 * </BLOCKQUOTE> 048 * This class defines an intermediate client response control, which can be used 049 * to provide a server with information about the client and any downstream 050 * clients that it may have. 051 * <BR><BR> 052 * This control is not based on any public standard. It was originally 053 * developed for use with the UnboundID Directory Server. The value of this 054 * control uses the following encoding: 055 * <BR><BR> 056 * <PRE> 057 * IntermediateClientResponse ::= SEQUENCE { 058 * upstreamResponse [0] IntermediateClientResponse OPTIONAL, 059 * upstreamServerAddress [1] OCTET STRING OPTIONAL, 060 * upstreamServerSecure [3] BOOLEAN DEFAULT FALSE, 061 * serverName [4] OCTET STRING OPTIONAL, 062 * serverSessionID [5] OCTET STRING OPTIONAL, 063 * serverResponseID [6] OCTET STRING OPTIONAL, 064 * ... } 065 * </PRE> 066 * See the documentation in the {@link IntermediateClientRequestControl} class 067 * for an example of using the intermediate client request and response 068 * controls. 069 */ 070 @NotMutable() 071 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 072 public final class IntermediateClientResponseControl 073 extends Control 074 implements DecodeableControl 075 { 076 /** 077 * The OID (1.3.6.1.4.1.30221.2.5.2) for the intermediate client response 078 * control. 079 */ 080 public static final String INTERMEDIATE_CLIENT_RESPONSE_OID = 081 "1.3.6.1.4.1.30221.2.5.2"; 082 083 084 085 /** 086 * The serial version UID for this serializable class. 087 */ 088 private static final long serialVersionUID = 7476073413872875835L; 089 090 091 092 // The value for this intermediate client response control. 093 private final IntermediateClientResponseValue value; 094 095 096 097 /** 098 * Creates a new empty control instance that is intended to be used only for 099 * decoding controls via the {@code DecodeableControl} interface. 100 */ 101 IntermediateClientResponseControl() 102 { 103 value = null; 104 } 105 106 107 108 /** 109 * Creates a new intermediate client response control with the provided 110 * information. It will not be marked critical. 111 * 112 * @param upstreamResponse A wrapped intermediate client response from 113 * an upstream server. It may be {@code null} 114 * if there is no wrapped upstream response. 115 * @param upstreamServerAddress The IP address or resolvable name of the 116 * upstream server system. It may be 117 * {@code null} if there is no upstream server 118 * or its address is not available. 119 * @param upstreamServerSecure Indicates whether communication with the 120 * upstream server is secure. It may be 121 * {@code null} if there is no upstream server 122 * or it is not known whether the communication 123 * is secure. 124 * @param serverName An identifier string that summarizes the 125 * server application that created this 126 * intermediate client response. It may be 127 * {@code null} if that information is not 128 * available. 129 * @param serverSessionID A string that may be used to identify the 130 * session in the server application. It may 131 * be {@code null} if there is no available 132 * session identifier. 133 * @param serverResponseID A string that may be used to identify the 134 * response in the server application. It may 135 * be {@code null} if there is no available 136 * response identifier. 137 */ 138 public IntermediateClientResponseControl( 139 final IntermediateClientResponseValue upstreamResponse, 140 final String upstreamServerAddress, 141 final Boolean upstreamServerSecure, final String serverName, 142 final String serverSessionID, final String serverResponseID) 143 { 144 this(false, 145 new IntermediateClientResponseValue(upstreamResponse, 146 upstreamServerAddress, upstreamServerSecure, serverName, 147 serverSessionID, serverResponseID)); 148 } 149 150 151 152 /** 153 * Creates a new intermediate client response control with the provided 154 * information. 155 * 156 * @param oid The OID for the control. 157 * @param isCritical Indicates whether the control should be marked 158 * critical. 159 * @param value The encoded value for the control. This may be 160 * {@code null} if no value was provided. 161 * 162 * @throws LDAPException If the provided control cannot be decoded as an 163 * intermediate client response control. 164 */ 165 public IntermediateClientResponseControl(final String oid, 166 final boolean isCritical, 167 final ASN1OctetString value) 168 throws LDAPException 169 { 170 super(oid, isCritical, value); 171 172 if (value == null) 173 { 174 throw new LDAPException(ResultCode.DECODING_ERROR, 175 ERR_ICRESP_CONTROL_NO_VALUE.get()); 176 } 177 178 final ASN1Sequence valueSequence; 179 try 180 { 181 final ASN1Element valueElement = ASN1Element.decode(value.getValue()); 182 valueSequence = ASN1Sequence.decodeAsSequence(valueElement); 183 } 184 catch(Exception e) 185 { 186 throw new LDAPException(ResultCode.DECODING_ERROR, 187 ERR_ICRESP_CONTROL_VALUE_NOT_SEQUENCE.get( 188 String.valueOf(e)), e); 189 } 190 191 this.value = IntermediateClientResponseValue.decode(valueSequence); 192 } 193 194 195 196 /** 197 * Creates a new intermediate client response control with the provided value. 198 * It will be marked critical. 199 * 200 * @param value The value to use for this intermediate client response 201 * control. It must not be {@code null}. 202 */ 203 public IntermediateClientResponseControl( 204 final IntermediateClientResponseValue value) 205 { 206 this(false, value); 207 } 208 209 210 211 /** 212 * Creates a new intermediate client response control with the provided value. 213 * 214 * @param isCritical Indicates whether the control should be marked 215 * critical. 216 * @param value The value to use for this intermediate client response 217 * control. It must not be {@code null}. 218 */ 219 public IntermediateClientResponseControl(final boolean isCritical, 220 final IntermediateClientResponseValue value) 221 { 222 super(INTERMEDIATE_CLIENT_RESPONSE_OID, isCritical, 223 new ASN1OctetString(value.encode().encode())); 224 225 this.value = value; 226 } 227 228 229 230 /** 231 * {@inheritDoc} 232 */ 233 public IntermediateClientResponseControl decodeControl(final String oid, 234 final boolean isCritical, final ASN1OctetString value) 235 throws LDAPException 236 { 237 return new IntermediateClientResponseControl(oid, isCritical, value); 238 } 239 240 241 242 /** 243 * Extracts an intermediate client response control from the provided result. 244 * 245 * @param result The result from which to retrieve the intermediate client 246 * response control. 247 * 248 * @return The intermediate client response control contained in the provided 249 * result, or {@code null} if the result did not contain an 250 * intermediate client response control. 251 * 252 * @throws LDAPException If a problem is encountered while attempting to 253 * decode the intermediate client response control 254 * contained in the provided result. 255 */ 256 public static IntermediateClientResponseControl get(final LDAPResult result) 257 throws LDAPException 258 { 259 final Control c = 260 result.getResponseControl(INTERMEDIATE_CLIENT_RESPONSE_OID); 261 if (c == null) 262 { 263 return null; 264 } 265 266 if (c instanceof IntermediateClientResponseControl) 267 { 268 return (IntermediateClientResponseControl) c; 269 } 270 else 271 { 272 return new IntermediateClientResponseControl(c.getOID(), c.isCritical(), 273 c.getValue()); 274 } 275 } 276 277 278 279 /** 280 * Retrieves the value for this intermediate client response. 281 * 282 * @return The value for this intermediate client response. 283 */ 284 public IntermediateClientResponseValue getResponseValue() 285 { 286 return value; 287 } 288 289 290 291 /** 292 * Retrieves the wrapped response from an upstream server, if available. 293 * 294 * @return The wrapped response from an upstream server, or {@code null} if 295 * there is none. 296 */ 297 public IntermediateClientResponseValue getUpstreamResponse() 298 { 299 return value.getUpstreamResponse(); 300 } 301 302 303 304 /** 305 * Retrieves the IP address or resolvable name of the upstream server system, 306 * if available. 307 * 308 * @return The IP address or resolvable name of the upstream server system, 309 * {@code null} if there is no upstream server or its address is not 310 * available. 311 */ 312 public String getUpstreamServerAddress() 313 { 314 return value.getUpstreamServerAddress(); 315 } 316 317 318 319 /** 320 * Indicates whether the communication with the communication with the 321 * upstream server is secure (i.e., whether communication between the 322 * server application and the upstream server is safe from interpretation or 323 * undetectable alteration by a third party observer or interceptor). 324 * 325 * 326 * @return {@code Boolean.TRUE} if communication with the upstream server is 327 * secure, {@code Boolean.FALSE} if it is not secure, or 328 * {@code null} if there is no upstream server or it is not known 329 * whether the communication is secure. 330 */ 331 public Boolean upstreamServerSecure() 332 { 333 return value.upstreamServerSecure(); 334 } 335 336 337 338 /** 339 * Retrieves a string that identifies the server application that created this 340 * intermediate client response value. 341 * 342 * @return A string that may be used to identify the server application that 343 * created this intermediate client response value. 344 */ 345 public String getServerName() 346 { 347 return value.getServerName(); 348 } 349 350 351 352 /** 353 * Retrieves a string that may be used to identify the session in the server 354 * application. 355 * 356 * @return A string that may be used to identify the session in the server 357 * application, or {@code null} if there is none. 358 */ 359 public String getServerSessionID() 360 { 361 return value.getServerSessionID(); 362 } 363 364 365 366 /** 367 * Retrieves a string that may be used to identify the response in the server 368 * application. 369 * 370 * @return A string that may be used to identify the response in the server 371 * application, or {@code null} if there is none. 372 */ 373 public String getServerResponseID() 374 { 375 return value.getServerResponseID(); 376 } 377 378 379 380 /** 381 * {@inheritDoc} 382 */ 383 @Override() 384 public String getControlName() 385 { 386 return INFO_CONTROL_NAME_INTERMEDIATE_CLIENT_RESPONSE.get(); 387 } 388 389 390 391 /** 392 * {@inheritDoc} 393 */ 394 @Override() 395 public void toString(final StringBuilder buffer) 396 { 397 buffer.append("IntermediateClientResponseControl(isCritical="); 398 buffer.append(isCritical()); 399 buffer.append(", value="); 400 value.toString(buffer); 401 buffer.append(')'); 402 } 403 }