View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.protocol;
29  
30  import java.util.HashMap;
31  import java.util.Map;
32  
33  import javax.net.ssl.SSLSession;
34  
35  import org.apache.hc.client5.http.HttpRoute;
36  import org.apache.hc.client5.http.RouteInfo;
37  import org.apache.hc.client5.http.auth.AuthCache;
38  import org.apache.hc.client5.http.auth.AuthExchange;
39  import org.apache.hc.client5.http.auth.AuthScheme;
40  import org.apache.hc.client5.http.auth.AuthSchemeFactory;
41  import org.apache.hc.client5.http.auth.CredentialsProvider;
42  import org.apache.hc.client5.http.config.RequestConfig;
43  import org.apache.hc.client5.http.cookie.CookieOrigin;
44  import org.apache.hc.client5.http.cookie.CookieSpec;
45  import org.apache.hc.client5.http.cookie.CookieSpecFactory;
46  import org.apache.hc.client5.http.cookie.CookieStore;
47  import org.apache.hc.core5.annotation.Internal;
48  import org.apache.hc.core5.http.EndpointDetails;
49  import org.apache.hc.core5.http.HttpHost;
50  import org.apache.hc.core5.http.HttpRequest;
51  import org.apache.hc.core5.http.HttpResponse;
52  import org.apache.hc.core5.http.ProtocolVersion;
53  import org.apache.hc.core5.http.config.Lookup;
54  import org.apache.hc.core5.http.protocol.HttpContext;
55  import org.apache.hc.core5.http.protocol.HttpCoreContext;
56  
57  /**
58   * Client execution {@link HttpContext}. This class can be re-used for
59   * multiple consecutive logically related request executions that represent
60   * a single communication session. This context may not be used concurrently.
61   * <p>
62   * IMPORTANT: This class is NOT thread-safe and MUST NOT be used concurrently by
63   * multiple message exchanges.
64   *
65   * @since 4.3
66   */
67  public class HttpClientContext extends HttpCoreContext {
68  
69      /**
70       * @deprecated Use getter methods
71       */
72      @Deprecated
73      public static final String HTTP_ROUTE   = "http.route";
74  
75      /**
76       * @deprecated Use getter methods
77       */
78      @Deprecated
79      public static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
80  
81      /**
82       * @deprecated Use getter methods
83       */
84      @Deprecated
85      public static final String COOKIESPEC_REGISTRY   = "http.cookiespec-registry";
86  
87      /**
88       * @deprecated Use getter methods
89       */
90      @Deprecated
91      public static final String COOKIE_SPEC           = "http.cookie-spec";
92  
93      /**
94       * @deprecated Use getter methods
95       */
96      @Deprecated
97      public static final String COOKIE_ORIGIN         = "http.cookie-origin";
98  
99      /**
100      * @deprecated Use getter methods
101      */
102     @Deprecated
103     public static final String COOKIE_STORE          = "http.cookie-store";
104 
105     /**
106      * @deprecated Use getter methods
107      */
108     @Deprecated
109     public static final String CREDS_PROVIDER        = "http.auth.credentials-provider";
110 
111     /**
112      * @deprecated Use getter methods
113      */
114     @Deprecated
115     public static final String AUTH_CACHE            = "http.auth.auth-cache";
116 
117     /**
118      * @deprecated Use getter methods
119      */
120     @Deprecated
121     public static final String AUTH_EXCHANGE_MAP     = "http.auth.exchanges";
122 
123     /**
124      * @deprecated Use getter methods
125      */
126     @Deprecated
127     public static final String USER_TOKEN            = "http.user-token";
128 
129     /**
130      * @deprecated Use getter methods
131      */
132     @Deprecated
133     public static final String AUTHSCHEME_REGISTRY   = "http.authscheme-registry";
134 
135     /**
136      * @deprecated Use getter methods
137      */
138     @Deprecated
139     public static final String REQUEST_CONFIG = "http.request-config";
140 
141     /**
142      * @deprecated Use getter methods
143      */
144     @Deprecated
145     public static final String EXCHANGE_ID = "http.exchange-id";
146 
147     /**
148      * @deprecated Use {@link #castOrCreate(HttpContext)}.
149      */
150     @Deprecated
151     public static HttpClientContext adapt(final HttpContext context) {
152         if (context == null) {
153             return new HttpClientContext();
154         }
155         if (context instanceof HttpClientContext) {
156             return (HttpClientContext) context;
157         }
158         return new HttpClientContext(context);
159     }
160 
161     /**
162      * Casts the given generic {@link HttpContext} as {@link HttpClientContext}.
163      *
164      * @since 5.4
165      */
166     public static HttpClientContext cast(final HttpContext context) {
167         if (context == null) {
168             return null;
169         }
170         if (context instanceof HttpClientContext) {
171             return (HttpClientContext) context;
172         } else {
173             return new Delegate(context);
174         }
175     }
176 
177     /**
178      * Casts the given generic {@link HttpContext} as {@link HttpClientContext} or
179      * creates new {@link HttpClientContext} if the given context is null.
180      *
181      * @since 5.4
182      */
183     public static HttpClientContext castOrCreate(final HttpContext context) {
184         return context != null ? cast(context) : create();
185     }
186 
187     public static HttpClientContext create() {
188         return new HttpClientContext();
189     }
190 
191     private HttpRoute route;
192     private RedirectLocations redirectLocations;
193     private CookieSpec cookieSpec;
194     private CookieOrigin cookieOrigin;
195     private Map<HttpHost, AuthExchange> authExchangeMap;
196     private String exchangeId;
197 
198     private Lookup<CookieSpecFactory> cookieSpecFactoryLookup;
199     private Lookup<AuthSchemeFactory> authSchemeFactoryLookup;
200     private CookieStore cookieStore;
201     private CredentialsProvider credentialsProvider;
202     private AuthCache authCache;
203     private Object userToken;
204     private RequestConfig requestConfig;
205 
206     public HttpClientContext(final HttpContext context) {
207         super(context);
208     }
209 
210     public HttpClientContext() {
211         super();
212     }
213 
214     /**
215      * Represents current route used to execute message exchanges.
216      * <p>
217      * This context attribute is expected to be populated by the protocol handler.
218      */
219     public RouteInfo getHttpRoute() {
220         return route;
221     }
222 
223     /**
224      * @since 5.4
225      */
226     @Internal
227     public void setRoute(final HttpRoute route) {
228         this.route = route;
229     }
230 
231     /**
232      * Represents a collection of all redirects executed in the context of request execution.
233      * <p>
234      * This context attribute is expected to be populated by the protocol handler.
235      */
236     public RedirectLocations getRedirectLocations() {
237         if (this.redirectLocations == null) {
238             this.redirectLocations = new RedirectLocations();
239         }
240         return this.redirectLocations;
241     }
242 
243     /**
244      * @since 5.4
245      */
246     @Internal
247     public void setRedirectLocations(final RedirectLocations redirectLocations) {
248         this.redirectLocations = redirectLocations;
249     }
250 
251     /**
252      * Represents a {@link CookieStore} used in the context of the request execution.
253      * <p>
254      * This context attribute can be set by the caller.
255      */
256     public CookieStore getCookieStore() {
257         return cookieStore;
258     }
259 
260     public void setCookieStore(final CookieStore cookieStore) {
261         this.cookieStore = cookieStore;
262     }
263 
264     /**
265      * Represents a {@link CookieSpec} chosen in the context of request execution.
266      * <p>
267      * This context attribute is expected to be populated by the protocol handler.
268      */
269     public CookieSpec getCookieSpec() {
270         return cookieSpec;
271     }
272 
273     /**
274      * @since 5.4
275      */
276     @Internal
277     public void setCookieSpec(final CookieSpec cookieSpec) {
278         this.cookieSpec = cookieSpec;
279     }
280 
281     /**
282      * Represents a {@link CookieOrigin} produced in the context of request execution.
283      * <p>
284      * This context attribute is expected to be populated by the protocol handler.
285      */
286     public CookieOrigin getCookieOrigin() {
287         return cookieOrigin;
288     }
289 
290     /**
291      * @since 5.4
292      */
293     @Internal
294     public void setCookieOrigin(final CookieOrigin cookieOrigin) {
295         this.cookieOrigin = cookieOrigin;
296     }
297 
298     /**
299      * Represents a {@link CookieSpecFactory} registry used in the context of the request execution.
300      * <p>
301      * This context attribute can be set by the caller.
302      */
303     public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
304         return cookieSpecFactoryLookup;
305     }
306 
307     public void setCookieSpecRegistry(final Lookup<CookieSpecFactory> lookup) {
308         this.cookieSpecFactoryLookup = lookup;
309     }
310 
311     /**
312      * Represents a {@link AuthSchemeFactory} registry used in the context of the request execution.
313      * <p>
314      * This context attribute can be set by the caller.
315      */
316     public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
317         return authSchemeFactoryLookup;
318     }
319 
320     public void setAuthSchemeRegistry(final Lookup<AuthSchemeFactory> lookup) {
321         this.authSchemeFactoryLookup = lookup;
322     }
323 
324     /**
325      * Represents a {@link CredentialsProvider} registry used in the context of the request execution.
326      * <p>
327      * This context attribute can be set by the caller.
328      */
329     public CredentialsProvider getCredentialsProvider() {
330         return credentialsProvider;
331     }
332 
333     public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
334         this.credentialsProvider = credentialsProvider;
335     }
336 
337     /**
338      * Represents a {@link AuthCache} used in the context of the request execution.
339      * <p>
340      * This context attribute can be set by the caller.
341      */
342     public AuthCache getAuthCache() {
343         return authCache;
344     }
345 
346     public void setAuthCache(final AuthCache authCache) {
347         this.authCache = authCache;
348     }
349 
350     /**
351      * Represents a map of {@link AuthExchange}s performed in the context of the request
352      * execution.
353      * <p>
354      * This context attribute is expected to be populated by the protocol handler.
355      *
356      * @since 5.0
357      */
358     public Map<HttpHost, AuthExchange> getAuthExchanges() {
359         if (authExchangeMap == null) {
360             authExchangeMap = new HashMap<>();
361         }
362         return authExchangeMap;
363     }
364 
365     /**
366      * @since 5.0
367      */
368     public AuthExchange getAuthExchange(final HttpHost host) {
369         return getAuthExchanges().computeIfAbsent(host, k -> new AuthExchange());
370     }
371 
372     /**
373      * @since 5.0
374      */
375     public void setAuthExchange(final HttpHost host, final AuthExchange authExchange) {
376         getAuthExchanges().put(host, authExchange);
377     }
378 
379     /**
380      * @since 5.0
381      */
382     public void resetAuthExchange(final HttpHost host, final AuthScheme authScheme) {
383         final AuthExchange authExchange = new AuthExchange();
384         authExchange.select(authScheme);
385         getAuthExchanges().put(host, authExchange);
386     }
387 
388     /**
389      * @deprecated Use {@link #getUserToken()}
390      */
391     @Deprecated
392     @SuppressWarnings("unchecked")
393     public <T> T getUserToken(final Class<T> clazz) {
394         return (T) getUserToken();
395     }
396 
397     /**
398      * Represents an arbitrary user token that identifies the user in the context
399      * of the request execution.
400      * <p>
401      * This context attribute can be set by the caller.
402      */
403     public Object getUserToken() {
404         return userToken;
405     }
406 
407     public void setUserToken(final Object userToken) {
408         this.userToken = userToken;
409     }
410 
411     /**
412      * Represents an {@link RequestConfig used} in the context of the request execution.
413      * <p>
414      * This context attribute can be set by the caller.
415      */
416     public RequestConfig getRequestConfig() {
417         return requestConfig;
418     }
419 
420     /**
421      * Returns {@link RequestConfig} set in the context or {@link RequestConfig#DEFAULT}
422      * if not explicitly set in the context.
423      *
424      * @since 5.4
425      */
426     public final RequestConfig getRequestConfigOrDefault() {
427         final RequestConfig requestConfig = getRequestConfig();
428         return requestConfig != null ? requestConfig : RequestConfig.DEFAULT;
429     }
430 
431     public void setRequestConfig(final RequestConfig requestConfig) {
432         this.requestConfig = requestConfig;
433     }
434 
435     /**
436      * Represents an identifier generated for the current message exchange executed
437      * in the given context.
438      * <p>
439      * This context attribute is expected to be populated by the protocol handler.
440      * @since 5.1
441      */
442     public String getExchangeId() {
443         return exchangeId;
444     }
445 
446     /**
447      * @since 5.1
448      */
449     public void setExchangeId(final String exchangeId) {
450         this.exchangeId = exchangeId;
451     }
452 
453     /**
454      * Internal adaptor class that delegates all its method calls to a plain {@link HttpContext}.
455      * To be removed in the future.
456      */
457     @SuppressWarnings("deprecation")
458     @Internal
459     static class Delegate extends HttpClientContext {
460 
461         private final HttpContext httpContext;
462 
463         Delegate(final HttpContext httpContext) {
464             super(null);
465             this.httpContext = httpContext;
466         }
467 
468         <T> T getAttr(final String id, final Class<T> clazz) {
469             final Object obj = httpContext.getAttribute(id);
470             if (obj == null) {
471                 return null;
472             }
473             return clazz.cast(obj);
474         }
475 
476         @Override
477         public RouteInfo getHttpRoute() {
478             return getAttr(HTTP_ROUTE, RouteInfo.class);
479         }
480 
481         @Override
482         public void setRoute(final HttpRoute route) {
483             httpContext.setAttribute(HTTP_ROUTE, route);
484         }
485 
486         @Override
487         public RedirectLocations getRedirectLocations() {
488             RedirectLocations redirectLocations = getAttr(REDIRECT_LOCATIONS, RedirectLocations.class);
489             if (redirectLocations == null) {
490                 redirectLocations = new RedirectLocations();
491                 httpContext.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
492             }
493             return redirectLocations;
494         }
495 
496         @Override
497         public void setRedirectLocations(final RedirectLocations redirectLocations) {
498             httpContext.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
499         }
500 
501         @Override
502         public CookieStore getCookieStore() {
503             return getAttr(COOKIE_STORE, CookieStore.class);
504         }
505 
506         @Override
507         public void setCookieStore(final CookieStore cookieStore) {
508             httpContext.setAttribute(COOKIE_STORE, cookieStore);
509         }
510 
511         @Override
512         public CookieSpec getCookieSpec() {
513             return getAttr(COOKIE_SPEC, CookieSpec.class);
514         }
515 
516         @Override
517         public void setCookieSpec(final CookieSpec cookieSpec) {
518             httpContext.setAttribute(COOKIE_SPEC, cookieSpec);
519         }
520 
521         @Override
522         public CookieOrigin getCookieOrigin() {
523             return getAttr(COOKIE_ORIGIN, CookieOrigin.class);
524         }
525 
526         @Override
527         public void setCookieOrigin(final CookieOrigin cookieOrigin) {
528             httpContext.setAttribute(COOKIE_ORIGIN, cookieOrigin);
529         }
530 
531         @Override
532         public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
533             return getAttr(COOKIESPEC_REGISTRY, Lookup.class);
534         }
535 
536         @Override
537         public void setCookieSpecRegistry(final Lookup<CookieSpecFactory> lookup) {
538             httpContext.setAttribute(COOKIESPEC_REGISTRY, lookup);
539         }
540 
541         @Override
542         public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
543             return getAttr(AUTHSCHEME_REGISTRY, Lookup.class);
544         }
545 
546         @Override
547         public void setAuthSchemeRegistry(final Lookup<AuthSchemeFactory> lookup) {
548             httpContext.setAttribute(AUTHSCHEME_REGISTRY, lookup);
549         }
550 
551         @Override
552         public CredentialsProvider getCredentialsProvider() {
553             return getAttr(CREDS_PROVIDER, CredentialsProvider.class);
554         }
555 
556         @Override
557         public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
558             httpContext.setAttribute(CREDS_PROVIDER, credentialsProvider);
559         }
560 
561         @Override
562         public AuthCache getAuthCache() {
563             return getAttr(AUTH_CACHE, AuthCache.class);
564         }
565 
566         @Override
567         public void setAuthCache(final AuthCache authCache) {
568             httpContext.setAttribute(AUTH_CACHE, authCache);
569         }
570 
571         @Override
572         public Map<HttpHost, AuthExchange> getAuthExchanges() {
573             Map<HttpHost, AuthExchange> map = getAttr(AUTH_EXCHANGE_MAP, Map.class);
574             if (map == null) {
575                 map = new HashMap<>();
576                 httpContext.setAttribute(AUTH_EXCHANGE_MAP, map);
577             }
578             return map;
579         }
580 
581         @Override
582         public Object getUserToken() {
583             return httpContext.getAttribute(USER_TOKEN);
584         }
585 
586         @Override
587         public void setUserToken(final Object userToken) {
588             httpContext.setAttribute(USER_TOKEN, userToken);
589         }
590 
591         @Override
592         public RequestConfig getRequestConfig() {
593             return getAttr(REQUEST_CONFIG, RequestConfig.class);
594         }
595 
596         @Override
597         public void setRequestConfig(final RequestConfig requestConfig) {
598             httpContext.setAttribute(REQUEST_CONFIG, requestConfig);
599         }
600 
601         @Override
602         public String getExchangeId() {
603             return getAttr(EXCHANGE_ID, String.class);
604         }
605 
606         @Override
607         public void setExchangeId(final String exchangeId) {
608             httpContext.setAttribute(EXCHANGE_ID, exchangeId);
609         }
610 
611         @Override
612         public HttpRequest getRequest() {
613             return getAttr(HttpCoreContext.HTTP_REQUEST, HttpRequest.class);
614         }
615 
616         @Override
617         public void setRequest(final HttpRequest request) {
618             httpContext.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
619         }
620 
621         @Override
622         public HttpResponse getResponse() {
623             return getAttr(HttpCoreContext.HTTP_RESPONSE, HttpResponse.class);
624         }
625 
626         @Override
627         public void setResponse(final HttpResponse response) {
628             httpContext.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
629         }
630 
631         @Override
632         public EndpointDetails getEndpointDetails() {
633             return getAttr(HttpCoreContext.CONNECTION_ENDPOINT, EndpointDetails.class);
634         }
635 
636         @Override
637         public void setEndpointDetails(final EndpointDetails endpointDetails) {
638             httpContext.setAttribute(CONNECTION_ENDPOINT, endpointDetails);
639         }
640 
641         @Override
642         public SSLSession getSSLSession() {
643             return getAttr(HttpCoreContext.SSL_SESSION, SSLSession.class);
644         }
645 
646         @Override
647         public void setSSLSession(final SSLSession sslSession) {
648             httpContext.setAttribute(HttpCoreContext.SSL_SESSION, sslSession);
649         }
650 
651         @Override
652         public ProtocolVersion getProtocolVersion() {
653             return httpContext.getProtocolVersion();
654         }
655 
656         @Override
657         public void setProtocolVersion(final ProtocolVersion version) {
658             httpContext.setProtocolVersion(version);
659         }
660 
661         @Override
662         public Object getAttribute(final String id) {
663             return httpContext.getAttribute(id);
664         }
665 
666         @Override
667         public Object setAttribute(final String id, final Object obj) {
668             return httpContext.setAttribute(id, obj);
669         }
670 
671         @Override
672         public Object removeAttribute(final String id) {
673             return httpContext.removeAttribute(id);
674         }
675 
676         @Override
677         public <T> T getAttribute(final String id, final Class<T> clazz) {
678             return getAttr(id, clazz);
679         }
680 
681         @Override
682         public String toString() {
683             return httpContext.toString();
684         }
685 
686     }
687 
688 }