• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2010 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.servlet;
18 
19 import com.google.common.collect.Maps;
20 import com.google.inject.OutOfScopeException;
21 
22 import java.io.IOException;
23 import java.util.Map;
24 
25 import javax.servlet.ServletInputStream;
26 import javax.servlet.http.Cookie;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletRequestWrapper;
29 import javax.servlet.http.HttpSession;
30 
31 /**
32  * A wrapper for requests that makes requests immutable, taking a snapshot
33  * of the original request.
34  *
35  * @author dhanji@gmail.com (Dhanji R. Prasanna)
36  */
37 class ContinuingHttpServletRequest extends HttpServletRequestWrapper {
38 
39   // We clear out the attributes as they are mutable and not thread-safe.
40   private final Map<String, Object> attributes = Maps.newHashMap();
41   private final Cookie[] cookies;
42 
ContinuingHttpServletRequest(HttpServletRequest request)43   public ContinuingHttpServletRequest(HttpServletRequest request) {
44     super(request);
45 
46     Cookie[] originalCookies = request.getCookies();
47     if (originalCookies != null) {
48       int numberOfCookies = originalCookies.length;
49       cookies = new Cookie[numberOfCookies];
50       for (int i = 0; i < numberOfCookies; i++) {
51         Cookie originalCookie = originalCookies[i];
52 
53         // Snapshot each cookie + freeze.
54         // No snapshot is required if this is a snapshot of a snapshot(!)
55         if (originalCookie instanceof ImmutableCookie) {
56           cookies[i] = originalCookie;
57         } else {
58           cookies[i] = new ImmutableCookie(originalCookie);
59         }
60       }
61     } else {
62       cookies = null;
63     }
64   }
65 
getSession()66   @Override public HttpSession getSession() {
67     throw new OutOfScopeException("Cannot access the session in a continued request");
68   }
69 
getSession(boolean create)70   @Override public HttpSession getSession(boolean create) {
71     throw new UnsupportedOperationException("Cannot access the session in a continued request");
72   }
73 
getInputStream()74   @Override public ServletInputStream getInputStream() throws IOException {
75     throw new UnsupportedOperationException("Cannot access raw request on a continued request");
76   }
77 
setAttribute(String name, Object o)78   @Override public void setAttribute(String name, Object o) {
79     attributes.put(name, o);
80   }
81 
removeAttribute(String name)82   @Override public void removeAttribute(String name) {
83     attributes.remove(name);
84   }
85 
getAttribute(String name)86   @Override public Object getAttribute(String name) {
87     return attributes.get(name);
88   }
89 
getCookies()90   @Override public Cookie[] getCookies() {
91     // NOTE(dhanji): Cookies themselves are mutable. However a ContinuingHttpServletRequest
92     // snapshots the original set of cookies it received and imprisons them in immutable
93     // form. Unfortunately, the cookie array itself is mutable and there is no way for us
94     // to avoid this. At worst, however, mutation effects are restricted within the scope
95     // of a single request. Continued requests are not affected after snapshot time.
96     return cookies;
97   }
98 
99   private static final class ImmutableCookie extends Cookie {
ImmutableCookie(Cookie original)100     public ImmutableCookie(Cookie original) {
101       super(original.getName(), original.getValue());
102 
103       super.setMaxAge(original.getMaxAge());
104       super.setPath(original.getPath());
105       super.setComment(original.getComment());
106       super.setSecure(original.getSecure());
107       super.setValue(original.getValue());
108       super.setVersion(original.getVersion());
109 
110       if (original.getDomain() != null) {
111         super.setDomain(original.getDomain());
112       }
113     }
114 
setComment(String purpose)115     @Override public void setComment(String purpose) {
116       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
117     }
118 
setDomain(String pattern)119     @Override public void setDomain(String pattern) {
120       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
121     }
122 
setMaxAge(int expiry)123     @Override public void setMaxAge(int expiry) {
124       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
125     }
126 
setPath(String uri)127     @Override public void setPath(String uri) {
128       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
129     }
130 
setSecure(boolean flag)131     @Override public void setSecure(boolean flag) {
132       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
133     }
134 
setValue(String newValue)135     @Override public void setValue(String newValue) {
136       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
137     }
138 
setVersion(int v)139     @Override public void setVersion(int v) {
140       throw new UnsupportedOperationException("Cannot modify cookies on a continued request");
141     }
142   }
143 }
144