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.LDAPException; 030 import com.unboundid.ldap.sdk.ResultCode; 031 import com.unboundid.util.NotMutable; 032 import com.unboundid.util.ThreadSafety; 033 import com.unboundid.util.ThreadSafetyLevel; 034 035 import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 036 037 038 039 /** 040 * <BLOCKQUOTE> 041 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID 042 * LDAP SDK for Java. It is not available for use in applications that 043 * include only the Standard Edition of the LDAP SDK, and is not supported for 044 * use in conjunction with non-UnboundID products. 045 * </BLOCKQUOTE> 046 * This class defines an intermediate client request control, which can be used 047 * to provide a server with information about the client and any downstream 048 * clients that it may have. It can be used to help trace operations from the 049 * client to the directory server, potentially through any intermediate hops 050 * (like proxy servers) that may also support the intermediate client controls. 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 * IntermediateClientRequest ::= SEQUENCE { 058 * downstreamRequest [0] IntermediateClientRequest OPTIONAL, 059 * downstreamClientAddress [1] OCTET STRING OPTIONAL, 060 * downstreamClientSecure [2] BOOLEAN DEFAULT FALSE, 061 * clientIdentity [3] authzId OPTIONAL, 062 * clientName [4] OCTET STRING OPTIONAL, 063 * clientSessionID [5] OCTET STRING OPTIONAL, 064 * clientRequestID [6] OCTET STRING OPTIONAL, 065 * ... } 066 * </PRE> 067 * <H2>Example</H2> 068 * The following example demonstrates the use of the intermediate client 069 * controls to perform a search operation in the directory server. The request 070 * will be from an application named "my client" with a session ID of 071 * "session123" and a request ID of "request456": 072 * <PRE> 073 * SearchRequest searchRequest = new SearchRequest("dc=example,dc=com", 074 * SearchScope.SUB, Filter.createEqualityFilter("uid", "john.doe")); 075 * searchRequest.addControl(new IntermediateClientRequestControl(null, null, 076 * null, null, "my client", "session123", "request456")); 077 * SearchResult searchResult = connection.search(searchRequest); 078 * 079 * IntermediateClientResponseControl c = 080 * IntermediateClientResponseControl.get(searchResult); 081 * if (c != null) 082 * { 083 * // There was an intermediate client response control. 084 * IntermediateClientResponseValue responseValue = c.getResponseValue(); 085 * } 086 * </PRE> 087 */ 088 @NotMutable() 089 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 090 public final class IntermediateClientRequestControl 091 extends Control 092 { 093 /** 094 * The OID (1.3.6.1.4.1.30221.2.5.2) for the intermediate client request 095 * control. 096 */ 097 public static final String INTERMEDIATE_CLIENT_REQUEST_OID = 098 "1.3.6.1.4.1.30221.2.5.2"; 099 100 101 102 /** 103 * The serial version UID for this serializable class. 104 */ 105 private static final long serialVersionUID = 4883725840393001578L; 106 107 108 109 // The value for this intermediate client request control. 110 private final IntermediateClientRequestValue value; 111 112 113 114 /** 115 * Creates a new intermediate client request control with the provided 116 * information. It will be marked critical. 117 * 118 * @param downstreamRequest A wrapped intermediate client request from 119 * a downstream client. It may be 120 * {@code null} if there is no downstream 121 * request. 122 * @param downstreamClientAddress The IP address or resolvable name of the 123 * downstream client system. It may be 124 * {@code null} if there is no downstream 125 * client or its address is not available. 126 * @param downstreamClientSecure Indicates whether communication with the 127 * downstream client is secure. It may be 128 * {@code null} if there is no downstream 129 * client or it is not known whether the 130 * communication is secure. 131 * @param clientIdentity The requested client authorization 132 * identity. It may be {@code null} if there 133 * is no requested authorization identity. 134 * @param clientName An identifier string that summarizes the 135 * client application that created this 136 * intermediate client request. It may be 137 * {@code null} if that information is not 138 * available. 139 * @param clientSessionID A string that may be used to identify the 140 * session in the client application. It may 141 * be {@code null} if there is no available 142 * session identifier. 143 * @param clientRequestID A string that may be used to identify the 144 * request in the client application. It may 145 * be {@code null} if there is no available 146 * request identifier. 147 */ 148 public IntermediateClientRequestControl( 149 final IntermediateClientRequestValue downstreamRequest, 150 final String downstreamClientAddress, 151 final Boolean downstreamClientSecure, final String clientIdentity, 152 final String clientName, final String clientSessionID, 153 final String clientRequestID) 154 { 155 this(true, 156 new IntermediateClientRequestValue(downstreamRequest, 157 downstreamClientAddress, downstreamClientSecure, 158 clientIdentity, clientName, clientSessionID, 159 clientRequestID)); 160 } 161 162 163 164 /** 165 * Creates a new intermediate client request control with the provided value. 166 * It will be marked critical. 167 * 168 * @param value The value to use for this intermediate client request 169 * control. It must not be {@code null}. 170 */ 171 public IntermediateClientRequestControl( 172 final IntermediateClientRequestValue value) 173 { 174 this(true, value); 175 } 176 177 178 179 /** 180 * Creates a new intermediate client request control with the provided value. 181 * 182 * @param isCritical Indicates whether the control should be marked 183 * critical. 184 * @param value The value to use for this intermediate client request 185 * control. It must not be {@code null}. 186 */ 187 public IntermediateClientRequestControl(final boolean isCritical, 188 final IntermediateClientRequestValue value) 189 { 190 super(INTERMEDIATE_CLIENT_REQUEST_OID, isCritical, 191 new ASN1OctetString(value.encode().encode())); 192 193 this.value = value; 194 } 195 196 197 198 /** 199 * Creates a new intermediate client request control which is decoded from the 200 * provided generic control. 201 * 202 * @param control The generic control to be decoded as an intermediate 203 * client request control. 204 * 205 * @throws LDAPException If the provided control cannot be decoded as an 206 * intermediate client request control. 207 */ 208 public IntermediateClientRequestControl(final Control control) 209 throws LDAPException 210 { 211 super(control); 212 213 final ASN1OctetString controlValue = control.getValue(); 214 if (controlValue == null) 215 { 216 throw new LDAPException(ResultCode.DECODING_ERROR, 217 ERR_ICREQ_CONTROL_NO_VALUE.get()); 218 } 219 220 final ASN1Sequence valueSequence; 221 try 222 { 223 final ASN1Element valueElement = 224 ASN1Element.decode(controlValue.getValue()); 225 valueSequence = ASN1Sequence.decodeAsSequence(valueElement); 226 } 227 catch (Exception e) 228 { 229 throw new LDAPException(ResultCode.DECODING_ERROR, 230 ERR_ICREQ_CONTROL_VALUE_NOT_SEQUENCE.get(e), e); 231 } 232 233 value = IntermediateClientRequestValue.decode(valueSequence); 234 } 235 236 237 238 /** 239 * Retrieves the value for this intermediate client request. 240 * 241 * @return The value for this intermediate client request. 242 */ 243 public IntermediateClientRequestValue getRequestValue() 244 { 245 return value; 246 } 247 248 249 250 /** 251 * Retrieves the wrapped request from a downstream client, if available. 252 * 253 * @return The wrapped request from a downstream client, or {@code null} if 254 * there is none. 255 */ 256 public IntermediateClientRequestValue getDownstreamRequest() 257 { 258 return value.getDownstreamRequest(); 259 } 260 261 262 263 /** 264 * Retrieves the requested client authorization identity, if available. 265 * 266 * @return The requested client authorization identity, or {@code null} if 267 * there is none. 268 */ 269 public String getClientIdentity() 270 { 271 return value.getClientIdentity(); 272 } 273 274 275 276 /** 277 * Retrieves the IP address or resolvable name of the downstream client 278 * system, if available. 279 * 280 * @return The IP address or resolvable name of the downstream client system, 281 * or {@code null} if there is no downstream client or its address is 282 * not available. 283 */ 284 public String getDownstreamClientAddress() 285 { 286 return value.getDownstreamClientAddress(); 287 } 288 289 290 291 /** 292 * Indicates whether the communication with the communication with the 293 * downstream client is secure (i.e., whether communication between the 294 * client application and the downstream client is safe from interpretation or 295 * undetectable alteration by a third party observer or interceptor). 296 * 297 * 298 * @return {@code Boolean.TRUE} if communication with the downstream client 299 * is secure, {@code Boolean.FALSE} if it is not secure, or 300 * {@code null} if there is no downstream client or it is not known 301 * whether the communication is secure. 302 */ 303 public Boolean downstreamClientSecure() 304 { 305 return value.downstreamClientSecure(); 306 } 307 308 309 310 /** 311 * Retrieves a string that identifies the client application that created this 312 * intermediate client request value. 313 * 314 * @return A string that may be used to identify the client application that 315 * created this intermediate client request value. 316 */ 317 public String getClientName() 318 { 319 return value.getClientName(); 320 } 321 322 323 324 /** 325 * Retrieves a string that may be used to identify the session in the client 326 * application. 327 * 328 * @return A string that may be used to identify the session in the client 329 * application, or {@code null} if there is none. 330 */ 331 public String getClientSessionID() 332 { 333 return value.getClientSessionID(); 334 } 335 336 337 338 /** 339 * Retrieves a string that may be used to identify the request in the client 340 * application. 341 * 342 * @return A string that may be used to identify the request in the client 343 * application, or {@code null} if there is none. 344 */ 345 public String getClientRequestID() 346 { 347 return value.getClientRequestID(); 348 } 349 350 351 352 /** 353 * {@inheritDoc} 354 */ 355 @Override() 356 public String getControlName() 357 { 358 return INFO_CONTROL_NAME_INTERMEDIATE_CLIENT_REQUEST.get(); 359 } 360 361 362 363 /** 364 * {@inheritDoc} 365 */ 366 @Override() 367 public void toString(final StringBuilder buffer) 368 { 369 buffer.append("IntermediateClientRequestControl(isCritical="); 370 buffer.append(isCritical()); 371 buffer.append(", value="); 372 value.toString(buffer); 373 buffer.append(')'); 374 } 375 }