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