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 }