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         }
173         return new Delegate(context);
174     }
175 
176     /**
177      * Casts the given generic {@link HttpContext} as {@link HttpClientContext} or
178      * creates new {@link HttpClientContext} if the given context is null.
179      *
180      * @since 5.4
181      */
182     public static HttpClientContext castOrCreate(final HttpContext context) {
183         return context != null ? cast(context) : create();
184     }
185 
186     public static HttpClientContext create() {
187         return new HttpClientContext();
188     }
189 
190     private HttpRoute route;
191     private RedirectLocations redirectLocations;
192     private CookieSpec cookieSpec;
193     private CookieOrigin cookieOrigin;
194     private Map<HttpHost, AuthExchange> authExchangeMap;
195     private String exchangeId;
196 
197     private Lookup<CookieSpecFactory> cookieSpecFactoryLookup;
198     private Lookup<AuthSchemeFactory> authSchemeFactoryLookup;
199     private CookieStore cookieStore;
200     private CredentialsProvider credentialsProvider;
201     private AuthCache authCache;
202     private Object userToken;
203     private RequestConfig requestConfig;
204 
205     public HttpClientContext(final HttpContext context) {
206         super(context);
207     }
208 
209     public HttpClientContext() {
210         super();
211     }
212 
213     /**
214      * Represents current route used to execute message exchanges.
215      * <p>
216      * This context attribute is expected to be populated by the protocol handler.
217      */
218     public RouteInfo getHttpRoute() {
219         return route;
220     }
221 
222     /**
223      * @since 5.4
224      */
225     @Internal
226     public void setRoute(final HttpRoute route) {
227         this.route = route;
228     }
229 
230     /**
231      * Represents a collection of all redirects executed in the context of request execution.
232      * <p>
233      * This context attribute is expected to be populated by the protocol handler.
234      */
235     public RedirectLocations getRedirectLocations() {
236         if (this.redirectLocations == null) {
237             this.redirectLocations = new RedirectLocations();
238         }
239         return this.redirectLocations;
240     }
241 
242     /**
243      * @since 5.4
244      */
245     @Internal
246     public void setRedirectLocations(final RedirectLocations redirectLocations) {
247         this.redirectLocations = redirectLocations;
248     }
249 
250     /**
251      * Represents a {@link CookieStore} used in the context of the request execution.
252      * <p>
253      * This context attribute can be set by the caller.
254      */
255     public CookieStore getCookieStore() {
256         return cookieStore;
257     }
258 
259     public void setCookieStore(final CookieStore cookieStore) {
260         this.cookieStore = cookieStore;
261     }
262 
263     /**
264      * Represents a {@link CookieSpec} chosen in the context of request execution.
265      * <p>
266      * This context attribute is expected to be populated by the protocol handler.
267      */
268     public CookieSpec getCookieSpec() {
269         return cookieSpec;
270     }
271 
272     /**
273      * @since 5.4
274      */
275     @Internal
276     public void setCookieSpec(final CookieSpec cookieSpec) {
277         this.cookieSpec = cookieSpec;
278     }
279 
280     /**
281      * Represents a {@link CookieOrigin} produced in the context of request execution.
282      * <p>
283      * This context attribute is expected to be populated by the protocol handler.
284      */
285     public CookieOrigin getCookieOrigin() {
286         return cookieOrigin;
287     }
288 
289     /**
290      * @since 5.4
291      */
292     @Internal
293     public void setCookieOrigin(final CookieOrigin cookieOrigin) {
294         this.cookieOrigin = cookieOrigin;
295     }
296 
297     /**
298      * Represents a {@link CookieSpecFactory} registry used in the context of the request execution.
299      * <p>
300      * This context attribute can be set by the caller.
301      */
302     public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
303         return cookieSpecFactoryLookup;
304     }
305 
306     public void setCookieSpecRegistry(final Lookup<CookieSpecFactory> lookup) {
307         this.cookieSpecFactoryLookup = lookup;
308     }
309 
310     /**
311      * Represents a {@link AuthSchemeFactory} registry used in the context of the request execution.
312      * <p>
313      * This context attribute can be set by the caller.
314      */
315     public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
316         return authSchemeFactoryLookup;
317     }
318 
319     public void setAuthSchemeRegistry(final Lookup<AuthSchemeFactory> lookup) {
320         this.authSchemeFactoryLookup = lookup;
321     }
322 
323     /**
324      * Represents a {@link CredentialsProvider} registry used in the context of the request execution.
325      * <p>
326      * This context attribute can be set by the caller.
327      */
328     public CredentialsProvider getCredentialsProvider() {
329         return credentialsProvider;
330     }
331 
332     public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
333         this.credentialsProvider = credentialsProvider;
334     }
335 
336     /**
337      * Represents a {@link AuthCache} used in the context of the request execution.
338      * <p>
339      * This context attribute can be set by the caller.
340      */
341     public AuthCache getAuthCache() {
342         return authCache;
343     }
344 
345     public void setAuthCache(final AuthCache authCache) {
346         this.authCache = authCache;
347     }
348 
349     /**
350      * Represents a map of {@link AuthExchange}s performed in the context of the request
351      * execution.
352      * <p>
353      * This context attribute is expected to be populated by the protocol handler.
354      *
355      * @since 5.0
356      */
357     public Map<HttpHost, AuthExchange> getAuthExchanges() {
358         if (authExchangeMap == null) {
359             authExchangeMap = new HashMap<>();
360         }
361         return authExchangeMap;
362     }
363 
364     /**
365      * @since 5.0
366      */
367     public AuthExchange getAuthExchange(final HttpHost host) {
368         return getAuthExchanges().computeIfAbsent(host, k -> new AuthExchange());
369     }
370 
371     /**
372      * @since 5.0
373      */
374     public void setAuthExchange(final HttpHost host, final AuthExchange authExchange) {
375         getAuthExchanges().put(host, authExchange);
376     }
377 
378     /**
379      * @since 5.0
380      */
381     public void resetAuthExchange(final HttpHost host, final AuthScheme authScheme) {
382         final AuthExchange authExchange = new AuthExchange();
383         authExchange.select(authScheme);
384         getAuthExchanges().put(host, authExchange);
385     }
386 
387     /**
388      * @deprecated Use {@link #getUserToken()}
389      */
390     @Deprecated
391     @SuppressWarnings("unchecked")
392     public <T> T getUserToken(final Class<T> clazz) {
393         return (T) getUserToken();
394     }
395 
396     /**
397      * Represents an arbitrary user token that identifies the user in the context
398      * of the request execution.
399      * <p>
400      * This context attribute can be set by the caller.
401      */
402     public Object getUserToken() {
403         return userToken;
404     }
405 
406     public void setUserToken(final Object userToken) {
407         this.userToken = userToken;
408     }
409 
410     /**
411      * Represents an {@link RequestConfig used} in the context of the request execution.
412      * <p>
413      * This context attribute can be set by the caller.
414      */
415     public RequestConfig getRequestConfig() {
416         return requestConfig;
417     }
418 
419     /**
420      * Returns {@link RequestConfig} set in the context or {@link RequestConfig#DEFAULT}
421      * if not explicitly set in the context.
422      *
423      * @since 5.4
424      */
425     public final RequestConfig getRequestConfigOrDefault() {
426         final RequestConfig requestConfig = getRequestConfig();
427         return requestConfig != null ? requestConfig : RequestConfig.DEFAULT;
428     }
429 
430     public void setRequestConfig(final RequestConfig requestConfig) {
431         this.requestConfig = requestConfig;
432     }
433 
434     /**
435      * Represents an identifier generated for the current message exchange executed
436      * in the given context.
437      * <p>
438      * This context attribute is expected to be populated by the protocol handler.
439      * @since 5.1
440      */
441     public String getExchangeId() {
442         return exchangeId;
443     }
444 
445     /**
446      * @since 5.1
447      */
448     public void setExchangeId(final String exchangeId) {
449         this.exchangeId = exchangeId;
450     }
451 
452     /**
453      * Internal adaptor class that delegates all its method calls to a plain {@link HttpContext}.
454      * To be removed in the future.
455      */
456     @SuppressWarnings("deprecation")
457     @Internal
458     static class Delegate extends HttpClientContext {
459 
460         private final HttpContext httpContext;
461 
462         Delegate(final HttpContext httpContext) {
463             super(null);
464             this.httpContext = httpContext;
465         }
466 
467         <T> T getAttr(final String id, final Class<T> clazz) {
468             final Object obj = httpContext.getAttribute(id);
469             if (obj == null) {
470                 return null;
471             }
472             return clazz.cast(obj);
473         }
474 
475         @Override
476         public RouteInfo getHttpRoute() {
477             return getAttr(HTTP_ROUTE, RouteInfo.class);
478         }
479 
480         @Override
481         public void setRoute(final HttpRoute route) {
482             httpContext.setAttribute(HTTP_ROUTE, route);
483         }
484 
485         @Override
486         public RedirectLocations getRedirectLocations() {
487             RedirectLocations redirectLocations = getAttr(REDIRECT_LOCATIONS, RedirectLocations.class);
488             if (redirectLocations == null) {
489                 redirectLocations = new RedirectLocations();
490                 httpContext.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
491             }
492             return redirectLocations;
493         }
494 
495         @Override
496         public void setRedirectLocations(final RedirectLocations redirectLocations) {
497             httpContext.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
498         }
499 
500         @Override
501         public CookieStore getCookieStore() {
502             return getAttr(COOKIE_STORE, CookieStore.class);
503         }
504 
505         @Override
506         public void setCookieStore(final CookieStore cookieStore) {
507             httpContext.setAttribute(COOKIE_STORE, cookieStore);
508         }
509 
510         @Override
511         public CookieSpec getCookieSpec() {
512             return getAttr(COOKIE_SPEC, CookieSpec.class);
513         }
514 
515         @Override
516         public void setCookieSpec(final CookieSpec cookieSpec) {
517             httpContext.setAttribute(COOKIE_SPEC, cookieSpec);
518         }
519 
520         @Override
521         public CookieOrigin getCookieOrigin() {
522             return getAttr(COOKIE_ORIGIN, CookieOrigin.class);
523         }
524 
525         @Override
526         public void setCookieOrigin(final CookieOrigin cookieOrigin) {
527             httpContext.setAttribute(COOKIE_ORIGIN, cookieOrigin);
528         }
529 
530         @Override
531         public Lookup<CookieSpecFactory> getCookieSpecRegistry() {
532             return getAttr(COOKIESPEC_REGISTRY, Lookup.class);
533         }
534 
535         @Override
536         public void setCookieSpecRegistry(final Lookup<CookieSpecFactory> lookup) {
537             httpContext.setAttribute(COOKIESPEC_REGISTRY, lookup);
538         }
539 
540         @Override
541         public Lookup<AuthSchemeFactory> getAuthSchemeRegistry() {
542             return getAttr(AUTHSCHEME_REGISTRY, Lookup.class);
543         }
544 
545         @Override
546         public void setAuthSchemeRegistry(final Lookup<AuthSchemeFactory> lookup) {
547             httpContext.setAttribute(AUTHSCHEME_REGISTRY, lookup);
548         }
549 
550         @Override
551         public CredentialsProvider getCredentialsProvider() {
552             return getAttr(CREDS_PROVIDER, CredentialsProvider.class);
553         }
554 
555         @Override
556         public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
557             httpContext.setAttribute(CREDS_PROVIDER, credentialsProvider);
558         }
559 
560         @Override
561         public AuthCache getAuthCache() {
562             return getAttr(AUTH_CACHE, AuthCache.class);
563         }
564 
565         @Override
566         public void setAuthCache(final AuthCache authCache) {
567             httpContext.setAttribute(AUTH_CACHE, authCache);
568         }
569 
570         @Override
571         public Map<HttpHost, AuthExchange> getAuthExchanges() {
572             Map<HttpHost, AuthExchange> map = getAttr(AUTH_EXCHANGE_MAP, Map.class);
573             if (map == null) {
574                 map = new HashMap<>();
575                 httpContext.setAttribute(AUTH_EXCHANGE_MAP, map);
576             }
577             return map;
578         }
579 
580         @Override
581         public Object getUserToken() {
582             return httpContext.getAttribute(USER_TOKEN);
583         }
584 
585         @Override
586         public void setUserToken(final Object userToken) {
587             httpContext.setAttribute(USER_TOKEN, userToken);
588         }
589 
590         @Override
591         public RequestConfig getRequestConfig() {
592             return getAttr(REQUEST_CONFIG, RequestConfig.class);
593         }
594 
595         @Override
596         public void setRequestConfig(final RequestConfig requestConfig) {
597             httpContext.setAttribute(REQUEST_CONFIG, requestConfig);
598         }
599 
600         @Override
601         public String getExchangeId() {
602             return getAttr(EXCHANGE_ID, String.class);
603         }
604 
605         @Override
606         public void setExchangeId(final String exchangeId) {
607             httpContext.setAttribute(EXCHANGE_ID, exchangeId);
608         }
609 
610         @Override
611         public HttpRequest getRequest() {
612             return getAttr(HttpCoreContext.HTTP_REQUEST, HttpRequest.class);
613         }
614 
615         @Override
616         public void setRequest(final HttpRequest request) {
617             httpContext.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
618         }
619 
620         @Override
621         public HttpResponse getResponse() {
622             return getAttr(HttpCoreContext.HTTP_RESPONSE, HttpResponse.class);
623         }
624 
625         @Override
626         public void setResponse(final HttpResponse response) {
627             httpContext.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
628         }
629 
630         @Override
631         public EndpointDetails getEndpointDetails() {
632             return getAttr(HttpCoreContext.CONNECTION_ENDPOINT, EndpointDetails.class);
633         }
634 
635         @Override
636         public void setEndpointDetails(final EndpointDetails endpointDetails) {
637             httpContext.setAttribute(CONNECTION_ENDPOINT, endpointDetails);
638         }
639 
640         @Override
641         public SSLSession getSSLSession() {
642             return getAttr(HttpCoreContext.SSL_SESSION, SSLSession.class);
643         }
644 
645         @Override
646         public void setSSLSession(final SSLSession sslSession) {
647             httpContext.setAttribute(HttpCoreContext.SSL_SESSION, sslSession);
648         }
649 
650         @Override
651         public ProtocolVersion getProtocolVersion() {
652             return httpContext.getProtocolVersion();
653         }
654 
655         @Override
656         public void setProtocolVersion(final ProtocolVersion version) {
657             httpContext.setProtocolVersion(version);
658         }
659 
660         @Override
661         public Object getAttribute(final String id) {
662             return httpContext.getAttribute(id);
663         }
664 
665         @Override
666         public Object setAttribute(final String id, final Object obj) {
667             return httpContext.setAttribute(id, obj);
668         }
669 
670         @Override
671         public Object removeAttribute(final String id) {
672             return httpContext.removeAttribute(id);
673         }
674 
675         @Override
676         public <T> T getAttribute(final String id, final Class<T> clazz) {
677             return getAttr(id, clazz);
678         }
679 
680         @Override
681         public String toString() {
682             return httpContext.toString();
683         }
684 
685     }
686 
687 }