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