View Javadoc

1   /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  package org.springframework.security.ui.savedrequest;
17  
18  import org.springframework.security.util.PortResolver;
19  import org.springframework.security.util.UrlUtils;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.springframework.util.Assert;
23  
24  import javax.servlet.http.Cookie;
25  import javax.servlet.http.HttpServletRequest;
26  import java.util.ArrayList;
27  import java.util.Enumeration;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Locale;
31  import java.util.Map;
32  import java.util.TreeMap;
33  
34  
35  /**
36   * Represents central information from a <code>HttpServletRequest</code>.<p>This class is used by {@link
37   * org.springframework.security.ui.AbstractProcessingFilter} and {@link org.springframework.security.wrapper.SavedRequestAwareWrapper} to
38   * reproduce the request after successful authentication. An instance of this class is stored at the time of an
39   * authentication exception by {@link org.springframework.security.ui.ExceptionTranslationFilter}.</p>
40   * <p><em>IMPLEMENTATION NOTE</em>: It is assumed that this object is accessed only from the context of a single
41   * thread, so no synchronization around internal collection classes is performed.</p>
42   * <p>This class is based on code in Apache Tomcat.</p>
43   *
44   * @author Craig McClanahan
45   * @author Andrey Grebnev
46   * @author Ben Alex
47   * @version $Id: SavedRequest.java 2142 2007-09-21 18:18:21Z luke_t $
48   */
49  public class SavedRequest implements java.io.Serializable {
50      //~ Static fields/initializers =====================================================================================
51  
52      protected static final Log logger = LogFactory.getLog(SavedRequest.class);
53  
54      //~ Instance fields ================================================================================================
55  
56      private ArrayList cookies = new ArrayList();
57      private ArrayList locales = new ArrayList();
58      private Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER);
59      private Map parameters = new TreeMap(String.CASE_INSENSITIVE_ORDER);
60      private String contextPath;
61      private String method;
62      private String pathInfo;
63      private String queryString;
64      private String requestURI;
65      private String requestURL;
66      private String scheme;
67      private String serverName;
68      private String servletPath;
69      private int serverPort;
70  
71      //~ Constructors ===================================================================================================
72  
73      public SavedRequest(HttpServletRequest request, PortResolver portResolver) {
74          Assert.notNull(request, "Request required");
75          Assert.notNull(portResolver, "PortResolver required");
76  
77          // Cookies
78          Cookie[] cookies = request.getCookies();
79  
80          if (cookies != null) {
81              for (int i = 0; i < cookies.length; i++) {
82                  this.addCookie(cookies[i]);
83              }
84          }
85  
86          // Headers
87          Enumeration names = request.getHeaderNames();
88  
89          while (names.hasMoreElements()) {
90              String name = (String) names.nextElement();
91              Enumeration values = request.getHeaders(name);
92  
93              while (values.hasMoreElements()) {
94                  String value = (String) values.nextElement();
95                  this.addHeader(name, value);
96              }
97          }
98  
99          // Locales
100         Enumeration locales = request.getLocales();
101 
102         while (locales.hasMoreElements()) {
103             Locale locale = (Locale) locales.nextElement();
104             this.addLocale(locale);
105         }
106 
107         // Parameters
108         Map parameters = request.getParameterMap();
109         Iterator paramNames = parameters.keySet().iterator();
110 
111         while (paramNames.hasNext()) {
112             String paramName = (String) paramNames.next();
113             Object o = parameters.get(paramName);
114             if (o instanceof String[]) {
115                 String[] paramValues = (String[]) o;
116                 this.addParameter(paramName, paramValues);
117             } else {
118                 if (logger.isWarnEnabled()) {
119                     logger.warn("ServletRequest.getParameterMap() returned non-String array");
120                 }
121             }
122         }
123 
124         // Primitives
125         this.method = request.getMethod();
126         this.pathInfo = request.getPathInfo();
127         this.queryString = request.getQueryString();
128         this.requestURI = request.getRequestURI();
129         this.serverPort = portResolver.getServerPort(request);
130         this.requestURL = request.getRequestURL().toString();
131         this.scheme = request.getScheme();
132         this.serverName = request.getServerName();
133         this.contextPath = request.getContextPath();
134         this.servletPath = request.getServletPath();
135     }
136 
137     //~ Methods ========================================================================================================
138 
139     private void addCookie(Cookie cookie) {
140         cookies.add(new SavedCookie(cookie));
141     }
142 
143     private void addHeader(String name, String value) {
144         ArrayList values = (ArrayList) headers.get(name);
145 
146         if (values == null) {
147             values = new ArrayList();
148             headers.put(name, values);
149         }
150 
151         values.add(value);
152     }
153 
154     private void addLocale(Locale locale) {
155         locales.add(locale);
156     }
157 
158     private void addParameter(String name, String[] values) {
159         parameters.put(name, values);
160     }
161 
162     /**
163      * Determines if the current request matches the <code>SavedRequest</code>. All URL arguments are
164      * considered, but <em>not</em> method (POST/GET), cookies, locales, headers or parameters.
165      *
166      * @param request DOCUMENT ME!
167      * @param portResolver DOCUMENT ME!
168      * @return DOCUMENT ME!
169      */
170     public boolean doesRequestMatch(HttpServletRequest request, PortResolver portResolver) {
171         Assert.notNull(request, "Request required");
172         Assert.notNull(portResolver, "PortResolver required");
173 
174         if (!propertyEquals("pathInfo", this.pathInfo, request.getPathInfo())) {
175             return false;
176         }
177 
178         if (!propertyEquals("queryString", this.queryString, request.getQueryString())) {
179             return false;
180         }
181 
182         if (!propertyEquals("requestURI", this.requestURI, request.getRequestURI())) {
183             return false;
184         }
185 
186         if (!propertyEquals("serverPort", new Integer(this.serverPort), new Integer(portResolver.getServerPort(request))))
187         {
188             return false;
189         }
190 
191         if (!propertyEquals("requestURL", this.requestURL, request.getRequestURL().toString())) {
192             return false;
193         }
194 
195         if (!propertyEquals("scheme", this.scheme, request.getScheme())) {
196             return false;
197         }
198 
199         if (!propertyEquals("serverName", this.serverName, request.getServerName())) {
200             return false;
201         }
202 
203         if (!propertyEquals("contextPath", this.contextPath, request.getContextPath())) {
204             return false;
205         }
206 
207         if (!propertyEquals("servletPath", this.servletPath, request.getServletPath())) {
208             return false;
209         }
210 
211         return true;
212     }
213 
214     public String getContextPath() {
215         return contextPath;
216     }
217 
218     public List getCookies() {
219         List cookieList = new ArrayList(cookies.size());
220         for (Iterator iterator = cookies.iterator(); iterator.hasNext();) {
221             SavedCookie savedCookie = (SavedCookie) iterator.next();
222             cookieList.add(savedCookie.getCookie());
223         }
224         return cookieList;
225     }
226 
227     /**
228      * Indicates the URL that the user agent used for this request.
229      *
230      * @return the full URL of this request
231      */
232     public String getFullRequestUrl() {
233         return UrlUtils.getFullRequestUrl(this);
234     }
235 
236     public Iterator getHeaderNames() {
237         return (headers.keySet().iterator());
238     }
239 
240     public Iterator getHeaderValues(String name) {
241         ArrayList values = (ArrayList) headers.get(name);
242 
243         if (values == null) {
244             return ((new ArrayList()).iterator());
245         } else {
246             return (values.iterator());
247         }
248     }
249 
250     public Iterator getLocales() {
251         return (locales.iterator());
252     }
253 
254     public String getMethod() {
255         return (this.method);
256     }
257 
258     public Map getParameterMap() {
259         return parameters;
260     }
261 
262     public Iterator getParameterNames() {
263         return (parameters.keySet().iterator());
264     }
265 
266     public String[] getParameterValues(String name) {
267         return ((String[]) parameters.get(name));
268     }
269 
270     public String getPathInfo() {
271         return pathInfo;
272     }
273 
274     public String getQueryString() {
275         return (this.queryString);
276     }
277 
278     public String getRequestURI() {
279         return (this.requestURI);
280     }
281 
282     public String getRequestURL() {
283         return requestURL;
284     }
285 
286     /**
287      * Obtains the web application-specific fragment of the URL.
288      *
289      * @return the URL, excluding any server name, context path or servlet path
290      */
291     public String getRequestUrl() {
292         return UrlUtils.getRequestUrl(this);
293     }
294 
295     public String getScheme() {
296         return scheme;
297     }
298 
299     public String getServerName() {
300         return serverName;
301     }
302 
303     public int getServerPort() {
304         return serverPort;
305     }
306 
307     public String getServletPath() {
308         return servletPath;
309     }
310 
311     private boolean propertyEquals(String log, Object arg1, Object arg2) {
312         if ((arg1 == null) && (arg2 == null)) {
313             if (logger.isDebugEnabled()) {
314                 logger.debug(log + ": both null (property equals)");
315             }
316 
317             return true;
318         }
319 
320         if (((arg1 == null) && (arg2 != null)) || ((arg1 != null) && (arg2 == null))) {
321             if (logger.isDebugEnabled()) {
322                 logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)");
323             }
324 
325             return false;
326         }
327 
328         if (arg1.equals(arg2)) {
329             if (logger.isDebugEnabled()) {
330                 logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property equals)");
331             }
332 
333             return true;
334         } else {
335             if (logger.isDebugEnabled()) {
336                 logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)");
337             }
338 
339             return false;
340         }
341     }
342 
343     public String toString() {
344         return "SavedRequest[" + getFullRequestUrl() + "]";
345     }
346 }