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