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    }