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.core5.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.core5.annotation.Internal;
36  import org.apache.hc.core5.http.EndpointDetails;
37  import org.apache.hc.core5.http.HttpRequest;
38  import org.apache.hc.core5.http.HttpResponse;
39  import org.apache.hc.core5.http.HttpVersion;
40  import org.apache.hc.core5.http.ProtocolVersion;
41  import org.apache.hc.core5.util.Args;
42  
43  /**
44   * Core execution {@link HttpContext}.
45   * <p>
46   * IMPORTANT: This class is NOT thread-safe and MUST NOT be used concurrently by
47   * multiple message exchanges.
48   *
49   * @since 4.3
50   */
51  public class HttpCoreContext implements HttpContext {
52  
53      /**
54       * @deprecated Use getter methods
55       */
56      @Deprecated
57      public static final String CONNECTION_ENDPOINT  = HttpContext.RESERVED_PREFIX + "connection-endpoint";
58  
59      /**
60       * @deprecated Use getter methods
61       */
62      @Deprecated
63      public static final String SSL_SESSION = HttpContext.RESERVED_PREFIX + "ssl-session";
64  
65      /**
66       * @deprecated Use getter methods
67       */
68      @Deprecated
69      public static final String HTTP_REQUEST     = HttpContext.RESERVED_PREFIX + "request";
70  
71      /**
72       * @deprecated Use getter methods
73       */
74      @Deprecated
75      public static final String HTTP_RESPONSE    = HttpContext.RESERVED_PREFIX + "response";
76  
77      public static HttpCoreContext create() {
78          return new HttpCoreContext();
79      }
80  
81      /**
82       * @deprecated Use {@link #cast(HttpContext)}.
83       */
84      @Deprecated
85      public static HttpCoreContext adapt(final HttpContext context) {
86          if (context == null) {
87              return new HttpCoreContext();
88          }
89          if (context instanceof HttpCoreContext) {
90              return (HttpCoreContext) context;
91          }
92          return new HttpCoreContext(context);
93      }
94  
95      /**
96       * Casts the given generic {@link HttpContext} as {@link HttpCoreContext}.
97       *
98       * @since 5.3
99       */
100     public static HttpCoreContext cast(final HttpContext context) {
101         if (context == null) {
102             return null;
103         }
104         if (context instanceof HttpCoreContext) {
105             return (HttpCoreContext) context;
106         } else {
107             return new Delegate(context);
108         }
109     }
110 
111     /**
112      * Casts the given generic {@link HttpContext} as {@link HttpCoreContext} or
113      * creates new {@link HttpCoreContext} if the given context is null.
114      *
115      * @since 5.4
116      */
117     public static HttpCoreContext castOrCreate(final HttpContext context) {
118         return context != null ? cast(context) : create();
119     }
120 
121     private final HttpContext parentContext;
122     private Map<String, Object> map;
123     private ProtocolVersion version;
124     private HttpRequest request;
125     private HttpResponse response;
126     private EndpointDetails endpointDetails;
127     private SSLSession sslSession;
128 
129     public HttpCoreContext(final HttpContext parentContext) {
130         super();
131         this.parentContext = parentContext;
132     }
133 
134     public HttpCoreContext() {
135         super();
136         this.parentContext = null;
137     }
138 
139     /**
140      * Represents the protocol version used by the message exchange.
141      * <p>
142      * This context attribute is expected to be populated by the protocol handler
143      * in the course of request execution.
144      *
145      * @since 5.0
146      */
147     @Override
148     public ProtocolVersion getProtocolVersion() {
149         return this.version != null ? this.version : HttpVersion.HTTP_1_1;
150     }
151 
152     /**
153      * @since 5.0
154      */
155     @Override
156     public void setProtocolVersion(final ProtocolVersion version) {
157         this.version = version;
158     }
159 
160     @Override
161     public Object getAttribute(final String id) {
162         Object o = map != null ? map.get(id) : null;
163         if (o == null && parentContext != null) {
164             o = parentContext.getAttribute(id);
165         }
166         return o;
167     }
168 
169     @Override
170     public Object setAttribute(final String id, final Object obj) {
171         if (map == null) {
172             map = new HashMap<>();
173         }
174         return map.put(id, obj);
175     }
176 
177     @Override
178     public Object removeAttribute(final String id) {
179         if (map != null) {
180             return map.remove(id);
181         } else {
182             return null;
183         }
184     }
185 
186     public <T> T getAttribute(final String id, final Class<T> clazz) {
187         Args.notNull(clazz, "Attribute class");
188         final Object obj = getAttribute(id);
189         if (obj == null) {
190             return null;
191         }
192         return clazz.cast(obj);
193     }
194 
195     /**
196      * Represents current request message head.
197      * <p>
198      * This context attribute is expected to be populated by the protocol handler
199      * in the course of request execution.
200      */
201     public HttpRequest getRequest() {
202         return request;
203     }
204 
205     /**
206      * @since 5.3
207      */
208     @Internal
209     public void setRequest(final HttpRequest request) {
210         this.request = request;
211     }
212 
213     /**
214      * Represents current response message head.
215      * <p>
216      * This context attribute is expected to be populated by the protocol handler
217      * in the course of request execution.
218      */
219     public HttpResponse getResponse() {
220         return response;
221     }
222 
223     /**
224      * @since 5.3
225      */
226     @Internal
227     public void setResponse(final HttpResponse response) {
228         this.response = response;
229     }
230 
231     /**
232      * Represents current connection endpoint details.
233      * <p>
234      * This context attribute is expected to be populated by the protocol handler
235      * in the course of request execution.
236      * @since 5.0
237      */
238     public EndpointDetails getEndpointDetails() {
239         return endpointDetails;
240     }
241 
242     /**
243      * @since 5.3
244      */
245     @Internal
246     public void setEndpointDetails(final EndpointDetails endpointDetails) {
247         this.endpointDetails = endpointDetails;
248     }
249 
250     /**
251      * Represents current TLS session details.
252      * <p>
253      * This context attribute is expected to be populated by the protocol handler
254      * in the course of request execution.
255      * @since 5.0
256      */
257     public SSLSession getSSLSession() {
258         return sslSession;
259     }
260 
261     /**
262      * @since 5.3
263      */
264     @Internal
265     public void setSSLSession(final SSLSession sslSession) {
266         this.sslSession = sslSession;
267     }
268 
269     /**
270      * Internal adaptor class that delegates all its method calls to a plain {@link HttpContext}.
271      * To be removed in the future.
272      */
273     @SuppressWarnings("deprecation")
274     @Internal
275     static class Delegate extends HttpCoreContext {
276 
277         private final HttpContext httpContext;
278 
279         Delegate(final HttpContext httpContext) {
280             super(null);
281             this.httpContext = httpContext;
282         }
283 
284         <T> T getAttr(final String id, final Class<T> clazz) {
285             final Object obj = httpContext.getAttribute(id);
286             if (obj == null) {
287                 return null;
288             }
289             return clazz.cast(obj);
290         }
291 
292         @Override
293         public HttpRequest getRequest() {
294             return getAttr(HTTP_REQUEST, HttpRequest.class);
295         }
296 
297         @Override
298         public void setRequest(final HttpRequest request) {
299             httpContext.setAttribute(HTTP_REQUEST, request);
300         }
301 
302         @Override
303         public HttpResponse getResponse() {
304             return getAttr(HTTP_RESPONSE, HttpResponse.class);
305         }
306 
307         @Override
308         public void setResponse(final HttpResponse response) {
309             httpContext.setAttribute(HTTP_RESPONSE, response);
310         }
311 
312         @Override
313         public EndpointDetails getEndpointDetails() {
314             return getAttr(CONNECTION_ENDPOINT, EndpointDetails.class);
315         }
316 
317         @Override
318         public void setEndpointDetails(final EndpointDetails endpointDetails) {
319             httpContext.setAttribute(CONNECTION_ENDPOINT, endpointDetails);
320         }
321 
322         @Override
323         public SSLSession getSSLSession() {
324             return getAttr(SSL_SESSION, SSLSession.class);
325         }
326 
327         @Override
328         public void setSSLSession(final SSLSession sslSession) {
329             httpContext.setAttribute(SSL_SESSION, sslSession);
330         }
331 
332         @Override
333         public ProtocolVersion getProtocolVersion() {
334             return httpContext.getProtocolVersion();
335         }
336 
337         @Override
338         public void setProtocolVersion(final ProtocolVersion version) {
339             httpContext.setProtocolVersion(version);
340         }
341 
342         @Override
343         public Object getAttribute(final String id) {
344             return httpContext.getAttribute(id);
345         }
346 
347         @Override
348         public Object setAttribute(final String id, final Object obj) {
349             return httpContext.setAttribute(id, obj);
350         }
351 
352         @Override
353         public Object removeAttribute(final String id) {
354             return httpContext.removeAttribute(id);
355         }
356 
357         @Override
358         public <T> T getAttribute(final String id, final Class<T> clazz) {
359             return getAttr(id, clazz);
360         }
361 
362         @Override
363         public String toString() {
364             return httpContext.toString();
365         }
366 
367     }
368 
369     @Override
370     public String toString() {
371         return "HttpCoreContext{" +
372                 "version=" + version +
373                 ", request=" + request +
374                 ", response=" + response +
375                 ", endpointDetails=" + endpointDetails +
376                 ", sslSession=" + sslSession +
377                 '}';
378     }
379 
380 }