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