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    }