11848a29d323bd4d47581ae92b7551f4f236a3883dhanji/** 21848a29d323bd4d47581ae92b7551f4f236a3883dhanji * Copyright (C) 2010 Google Inc. 31848a29d323bd4d47581ae92b7551f4f236a3883dhanji * 41848a29d323bd4d47581ae92b7551f4f236a3883dhanji * Licensed under the Apache License, Version 2.0 (the "License"); 51848a29d323bd4d47581ae92b7551f4f236a3883dhanji * you may not use this file except in compliance with the License. 61848a29d323bd4d47581ae92b7551f4f236a3883dhanji * You may obtain a copy of the License at 71848a29d323bd4d47581ae92b7551f4f236a3883dhanji * 81848a29d323bd4d47581ae92b7551f4f236a3883dhanji * http://www.apache.org/licenses/LICENSE-2.0 91848a29d323bd4d47581ae92b7551f4f236a3883dhanji * 101848a29d323bd4d47581ae92b7551f4f236a3883dhanji * Unless required by applicable law or agreed to in writing, software 111848a29d323bd4d47581ae92b7551f4f236a3883dhanji * distributed under the License is distributed on an "AS IS" BASIS, 121848a29d323bd4d47581ae92b7551f4f236a3883dhanji * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131848a29d323bd4d47581ae92b7551f4f236a3883dhanji * See the License for the specific language governing permissions and 141848a29d323bd4d47581ae92b7551f4f236a3883dhanji * limitations under the License. 151848a29d323bd4d47581ae92b7551f4f236a3883dhanji */ 161848a29d323bd4d47581ae92b7551f4f236a3883dhanji 171848a29d323bd4d47581ae92b7551f4f236a3883dhanjipackage com.google.inject.servlet; 181848a29d323bd4d47581ae92b7551f4f236a3883dhanji 19d9c913acca55023ef5d76a32c3d4a51ee6b420cbsberlinimport com.google.common.collect.Maps; 20b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.inject.OutOfScopeException; 21b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 221848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport java.io.IOException; 231848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport java.util.Map; 24b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 251848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport javax.servlet.ServletInputStream; 261848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport javax.servlet.http.Cookie; 271848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport javax.servlet.http.HttpServletRequest; 281848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport javax.servlet.http.HttpServletRequestWrapper; 291848a29d323bd4d47581ae92b7551f4f236a3883dhanjiimport javax.servlet.http.HttpSession; 301848a29d323bd4d47581ae92b7551f4f236a3883dhanji 311848a29d323bd4d47581ae92b7551f4f236a3883dhanji/** 321848a29d323bd4d47581ae92b7551f4f236a3883dhanji * A wrapper for requests that makes requests immutable, taking a snapshot 331848a29d323bd4d47581ae92b7551f4f236a3883dhanji * of the original request. 341848a29d323bd4d47581ae92b7551f4f236a3883dhanji * 351848a29d323bd4d47581ae92b7551f4f236a3883dhanji * @author dhanji@gmail.com (Dhanji R. Prasanna) 361848a29d323bd4d47581ae92b7551f4f236a3883dhanji */ 371848a29d323bd4d47581ae92b7551f4f236a3883dhanjiclass ContinuingHttpServletRequest extends HttpServletRequestWrapper { 381848a29d323bd4d47581ae92b7551f4f236a3883dhanji 391848a29d323bd4d47581ae92b7551f4f236a3883dhanji // We clear out the attributes as they are mutable and not thread-safe. 401848a29d323bd4d47581ae92b7551f4f236a3883dhanji private final Map<String, Object> attributes = Maps.newHashMap(); 413b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna private final Cookie[] cookies; 421848a29d323bd4d47581ae92b7551f4f236a3883dhanji 431848a29d323bd4d47581ae92b7551f4f236a3883dhanji public ContinuingHttpServletRequest(HttpServletRequest request) { 441848a29d323bd4d47581ae92b7551f4f236a3883dhanji super(request); 453b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 463b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna Cookie[] originalCookies = request.getCookies(); 473b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna if (originalCookies != null) { 483b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna int numberOfCookies = originalCookies.length; 493b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna cookies = new Cookie[numberOfCookies]; 503b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna for (int i = 0; i < numberOfCookies; i++) { 513b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna Cookie originalCookie = originalCookies[i]; 523b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 533b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // Snapshot each cookie + freeze. 543b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // No snapshot is required if this is a snapshot of a snapshot(!) 553b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna if (originalCookie instanceof ImmutableCookie) { 563b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna cookies[i] = originalCookie; 573b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } else { 583b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna cookies[i] = new ImmutableCookie(originalCookie); 593b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 603b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 613b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } else { 623b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna cookies = null; 633b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 641848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 651848a29d323bd4d47581ae92b7551f4f236a3883dhanji 661848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public HttpSession getSession() { 671848a29d323bd4d47581ae92b7551f4f236a3883dhanji throw new OutOfScopeException("Cannot access the session in a continued request"); 681848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 691848a29d323bd4d47581ae92b7551f4f236a3883dhanji 701848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public HttpSession getSession(boolean create) { 711848a29d323bd4d47581ae92b7551f4f236a3883dhanji throw new UnsupportedOperationException("Cannot access the session in a continued request"); 721848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 731848a29d323bd4d47581ae92b7551f4f236a3883dhanji 741848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public ServletInputStream getInputStream() throws IOException { 751848a29d323bd4d47581ae92b7551f4f236a3883dhanji throw new UnsupportedOperationException("Cannot access raw request on a continued request"); 761848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 771848a29d323bd4d47581ae92b7551f4f236a3883dhanji 781848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public void setAttribute(String name, Object o) { 791848a29d323bd4d47581ae92b7551f4f236a3883dhanji attributes.put(name, o); 801848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 811848a29d323bd4d47581ae92b7551f4f236a3883dhanji 821848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public void removeAttribute(String name) { 831848a29d323bd4d47581ae92b7551f4f236a3883dhanji attributes.remove(name); 841848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 851848a29d323bd4d47581ae92b7551f4f236a3883dhanji 861848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public Object getAttribute(String name) { 871848a29d323bd4d47581ae92b7551f4f236a3883dhanji return attributes.get(name); 881848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 891848a29d323bd4d47581ae92b7551f4f236a3883dhanji 901848a29d323bd4d47581ae92b7551f4f236a3883dhanji @Override public Cookie[] getCookies() { 913b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // NOTE(dhanji): Cookies themselves are mutable. However a ContinuingHttpServletRequest 923b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // snapshots the original set of cookies it received and imprisons them in immutable 933b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // form. Unfortunately, the cookie array itself is mutable and there is no way for us 943b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // to avoid this. At worst, however, mutation effects are restricted within the scope 953b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna // of a single request. Continued requests are not affected after snapshot time. 963b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna return cookies; 973b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 983b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 993b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna private static final class ImmutableCookie extends Cookie { 1003b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna public ImmutableCookie(Cookie original) { 1013b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super(original.getName(), original.getValue()); 1023b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1033b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setMaxAge(original.getMaxAge()); 1043b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setPath(original.getPath()); 1053b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setComment(original.getComment()); 1063b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setSecure(original.getSecure()); 1073b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setValue(original.getValue()); 1083b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setVersion(original.getVersion()); 1093b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1103b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna if (original.getDomain() != null) { 1113b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna super.setDomain(original.getDomain()); 1123b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1133b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1143b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1153b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setComment(String purpose) { 1163b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 1173b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1183b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1193b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setDomain(String pattern) { 1203b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 1213b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1223b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1233b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setMaxAge(int expiry) { 1243b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 1253b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1263b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1273b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setPath(String uri) { 1283b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 1293b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1303b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1313b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setSecure(boolean flag) { 1323b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 1333b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1343b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1353b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setValue(String newValue) { 1363b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 1373b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna } 1383b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna 1393b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna @Override public void setVersion(int v) { 1403b02622e856e845f9bc5353a494b5ccc75dec40cDhanji R. Prasanna throw new UnsupportedOperationException("Cannot modify cookies on a continued request"); 141882330dad166a44b2498c7c13dcab61d853cecddChristian Edward Gruber } 1421848a29d323bd4d47581ae92b7551f4f236a3883dhanji } 1431848a29d323bd4d47581ae92b7551f4f236a3883dhanji} 144