1   /*
2    * Copyright 2002-2004 the original author or authors.
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 org.huihoo.jfox.soaf.util.filter;
18  
19  import java.io.BufferedReader;
20  import java.io.ByteArrayInputStream;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.io.Reader;
24  import java.io.Serializable;
25  import java.io.UnsupportedEncodingException;
26  import java.lang.reflect.Array;
27  import java.security.Principal;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.Date;
31  import java.util.Enumeration;
32  import java.util.HashSet;
33  import java.util.Hashtable;
34  import java.util.Iterator;
35  import java.util.LinkedList;
36  import java.util.List;
37  import java.util.Locale;
38  import java.util.Map;
39  import java.util.Set;
40  import java.util.Vector;
41  
42  import javax.servlet.RequestDispatcher;
43  import javax.servlet.ServletContext;
44  import javax.servlet.ServletInputStream;
45  import javax.servlet.http.Cookie;
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpSession;
48  
49  /***
50   * Mock implementation of the HttpServletRequest interface.
51   * <p>
52   * Used for testing the web framework; also useful for testing application
53   * controllers.
54   * 
55   * @author Rod Johnson
56   * @author Juergen Hoeller
57   * @since 1.0.2
58   */
59  public class MockHttpServletRequest implements HttpServletRequest, Serializable {
60  
61      public static final String DEFAULT_PROTOCOL = "http";
62  
63      public static final String DEFAULT_SERVER_ADDR = "127.0.0.1";
64  
65      public static final String DEFAULT_SERVER_NAME = "localhost";
66  
67      public static final int DEFAULT_SERVER_PORT = 80;
68  
69      public static final String DEFAULT_REMOTE_ADDR = "127.0.0.1";
70  
71      public static final String DEFAULT_REMOTE_HOST = "localhost";
72  
73      //---------------------------------------------------------------------
74      // ServletRequest properties
75      //---------------------------------------------------------------------
76  
77      private final Hashtable attributes = new Hashtable();
78  
79      private String characterEncoding;
80  
81      private byte[] content;
82  
83      private String contentType;
84  
85      private final Map parameters = new Hashtable();
86  
87      private String protocol = DEFAULT_PROTOCOL;
88  
89      private String scheme = DEFAULT_PROTOCOL;
90  
91      private String serverName = DEFAULT_SERVER_NAME;
92  
93      private int serverPort = DEFAULT_SERVER_PORT;
94  
95      private String remoteAddr = DEFAULT_REMOTE_ADDR;
96  
97      private String remoteHost = DEFAULT_REMOTE_HOST;
98  
99      /*** List of locales in descending order */
100     private final Vector locales = new Vector();
101 
102     private boolean secure = false;
103 
104     private final ServletContext servletContext;
105 
106     private int remotePort = DEFAULT_SERVER_PORT;
107 
108     private String localName = DEFAULT_SERVER_NAME;
109 
110     private String localAddr = DEFAULT_SERVER_ADDR;
111 
112     private int localPort = DEFAULT_SERVER_PORT;
113 
114     //---------------------------------------------------------------------
115     // HttpServletRequest properties
116     //---------------------------------------------------------------------
117 
118     private String authType;
119 
120     private Cookie[] cookies;
121 
122     private final Hashtable headers = new Hashtable();
123 
124     private String method;
125 
126     private String pathInfo;
127 
128     private String contextPath = "";
129 
130     private String queryString;
131 
132     private String remoteUser;
133 
134     private final Set userRoles = new HashSet();
135 
136     private Principal userPrincipal;
137 
138     private String requestURI = "";
139 
140     private String servletPath = "";
141 
142     private HttpSession session;
143 
144     private boolean requestedSessionIdValid = true;
145 
146     private boolean requestedSessionIdFromCookie = true;
147 
148     private boolean requestedSessionIdFromURL = false;
149 
150     //---------------------------------------------------------------------
151     // Constructors
152     //---------------------------------------------------------------------
153 
154     /***
155      * Create a new MockHttpServletRequest.
156      * 
157      * @param servletContext the ServletContext that the request runs in
158      */
159     public MockHttpServletRequest(ServletContext servletContext) {
160         this.locales.add(Locale.ENGLISH);
161         this.servletContext = servletContext;
162     }
163 
164     /***
165      * Create a new MockHttpServletRequest.
166      * 
167      * @param servletContext the ServletContext that the request runs in
168      * @param method the request method
169      * @param requestURI the request URI
170      * @see #setMethod
171      * @see #setRequestURI
172      */
173     public MockHttpServletRequest(ServletContext servletContext, String method,
174             String requestURI) {
175         this(servletContext);
176         this.method = method;
177         this.requestURI = requestURI;
178     }
179 
180     /***
181      * Create a new MockHttpServletRequest with a MockServletContext.
182      * 
183      * @see MockServletContext
184      */
185     public MockHttpServletRequest() {
186         this(new MockServletContext());
187     }
188 
189     /***
190      * Create a new MockHttpServletRequest with a MockServletContext.
191      * 
192      * @param method the request method
193      * @param requestURI the request URI
194      * @see #setMethod
195      * @see #setRequestURI
196      * @see MockServletContext
197      */
198     public MockHttpServletRequest(String method, String requestURI) {
199         this(new MockServletContext(), method, requestURI);
200     }
201 
202     //---------------------------------------------------------------------
203     // ServletRequest interface
204     //---------------------------------------------------------------------
205 
206     public Object getAttribute(String name) {
207         return this.attributes.get(name);
208     }
209 
210     public Enumeration getAttributeNames() {
211         return this.attributes.keys();
212     }
213 
214     public String getCharacterEncoding() {
215         return characterEncoding;
216     }
217 
218     public void setCharacterEncoding(String characterEncoding) {
219         this.characterEncoding = characterEncoding;
220     }
221 
222     public void setContent(byte[] content) {
223         this.content = content;
224     }
225 
226     public int getContentLength() {
227         return (this.content != null ? content.length : -1);
228     }
229 
230     public void setContentType(String contentType) {
231         this.contentType = contentType;
232     }
233 
234     public String getContentType() {
235         return contentType;
236     }
237 
238     public ServletInputStream getInputStream() {
239         if (this.content != null) {
240             return new MockServletInputStream(new ByteArrayInputStream(
241                     this.content));
242         } else {
243             return null;
244         }
245     }
246 
247     /***
248      * Add a single value for an HTTP parameter.
249      * <p>
250      * If there are already one or more values registered for the given
251      * parameter name, the given value will be added to the end of the list.
252      */
253     public void addParameter(String name, String value) {
254         addParameter(name, new String[] { value });
255     }
256 
257     /***
258      * Add an array of values for an HTTP parameter.
259      * <p>
260      * If there are already one or more values registered for the given
261      * parameter name, the given values will be added to the end of the list.
262      */
263     public void addParameter(String name, String[] values) {
264         String[] oldArr = (String[]) this.parameters.get(name);
265         if (oldArr != null) {
266             String[] newArr = new String[oldArr.length + values.length];
267             System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);
268             System.arraycopy(values, 0, newArr, oldArr.length, values.length);
269             this.parameters.put(name, newArr);
270         } else {
271             this.parameters.put(name, values);
272         }
273     }
274 
275     public String getParameter(String name) {
276         String[] arr = (String[]) this.parameters.get(name);
277         return (arr != null && arr.length > 0 ? arr[0] : null);
278     }
279 
280     public Enumeration getParameterNames() {
281         return Collections.enumeration(this.parameters.keySet());
282     }
283 
284     public String[] getParameterValues(String name) {
285         return (String[]) this.parameters.get(name);
286     }
287 
288     public Map getParameterMap() {
289         return Collections.unmodifiableMap(this.parameters);
290     }
291 
292     public void setProtocol(String protocol) {
293         this.protocol = protocol;
294     }
295 
296     public String getProtocol() {
297         return protocol;
298     }
299 
300     public void setScheme(String scheme) {
301         this.scheme = scheme;
302     }
303 
304     public String getScheme() {
305         return scheme;
306     }
307 
308     public void setServerName(String serverName) {
309         this.serverName = serverName;
310     }
311 
312     public String getServerName() {
313         return serverName;
314     }
315 
316     public void setServerPort(int serverPort) {
317         this.serverPort = serverPort;
318     }
319 
320     public int getServerPort() {
321         return serverPort;
322     }
323 
324     public BufferedReader getReader() throws UnsupportedEncodingException {
325         if (this.content != null) {
326             InputStream sourceStream = new ByteArrayInputStream(this.content);
327             Reader sourceReader = (this.characterEncoding != null) ? new InputStreamReader(
328                     sourceStream, this.characterEncoding)
329                     : new InputStreamReader(sourceStream);
330             return new BufferedReader(sourceReader);
331         } else {
332             return null;
333         }
334     }
335 
336     public void setRemoteAddr(String remoteAddr) {
337         this.remoteAddr = remoteAddr;
338     }
339 
340     public String getRemoteAddr() {
341         return remoteAddr;
342     }
343 
344     public void setRemoteHost(String remoteHost) {
345         this.remoteHost = remoteHost;
346     }
347 
348     public String getRemoteHost() {
349         return remoteHost;
350     }
351 
352     public void setAttribute(String name, Object value) {
353         if (value != null) {
354             this.attributes.put(name, value);
355         } else {
356             this.attributes.remove(name);
357         }
358     }
359 
360     public void removeAttribute(String name) {
361         this.attributes.remove(name);
362     }
363 
364     /***
365      * Add a new preferred locale, before any existing locales.
366      */
367     public void addPreferredLocale(Locale locale) {
368         this.locales.add(0, locale);
369     }
370 
371     public Locale getLocale() {
372         return (Locale) this.locales.get(0);
373     }
374 
375     public Enumeration getLocales() {
376         return this.locales.elements();
377     }
378 
379     public void setSecure(boolean secure) {
380         this.secure = secure;
381     }
382 
383     public boolean isSecure() {
384         return secure;
385     }
386 
387     public RequestDispatcher getRequestDispatcher(String path) {
388         return new MockRequestDispatcher(path);
389     }
390 
391     public String getRealPath(String path) {
392         return this.servletContext.getRealPath(path);
393     }
394 
395     public void setRemotePort(int remotePort) {
396         this.remotePort = remotePort;
397     }
398 
399     public int getRemotePort() {
400         return remotePort;
401     }
402 
403     public void setLocalName(String localName) {
404         this.localName = localName;
405     }
406 
407     public String getLocalName() {
408         return localName;
409     }
410 
411     public void setLocalAddr(String localAddr) {
412         this.localAddr = localAddr;
413     }
414 
415     public String getLocalAddr() {
416         return localAddr;
417     }
418 
419     public void setLocalPort(int localPort) {
420         this.localPort = localPort;
421     }
422 
423     public int getLocalPort() {
424         return localPort;
425     }
426 
427     //---------------------------------------------------------------------
428     // HttpServletRequest interface
429     //---------------------------------------------------------------------
430 
431     public void setAuthType(String authType) {
432         this.authType = authType;
433     }
434 
435     public String getAuthType() {
436         return authType;
437     }
438 
439     public void setCookies(Cookie[] cookies) {
440         this.cookies = cookies;
441     }
442 
443     public Cookie[] getCookies() {
444         return cookies;
445     }
446 
447     /***
448      * Add a header entry for the given name.
449      * <p>
450      * If there was no entry for that header name before, the value will be used
451      * as-is. In case of an existing entry, a String array will be created,
452      * adding the given value (more specifically, its toString representation)
453      * as further element.
454      * <p>
455      * Multiple values can only be stored as list of Strings, following the
456      * Servlet spec (see <code>getHeaders</code> accessor). As alternative to
457      * repeated <code>addHeader</code> calls for individual elements, you can
458      * use a single call with an entire array or Collection of values as
459      * parameter.
460      * 
461      * @see #getHeaderNames
462      * @see #getHeader
463      * @see #getHeaders
464      * @see #getDateHeader
465      * @see #getIntHeader
466      */
467     public void addHeader(String name, Object value) {
468         Object oldValue = this.headers.get(name);
469         if (oldValue instanceof List) {
470             List list = (List) oldValue;
471             addHeaderValue(list, value);
472         } else if (oldValue != null) {
473             List list = new LinkedList();
474             list.add(oldValue);
475             addHeaderValue(list, value);
476             this.headers.put(name, list);
477         } else if (value instanceof Collection || value.getClass().isArray()) {
478             List list = new LinkedList();
479             addHeaderValue(list, value);
480             this.headers.put(name, list);
481         } else {
482             this.headers.put(name, value);
483         }
484     }
485 
486     private void addHeaderValue(List list, Object value) {
487         if (value instanceof Collection) {
488             Collection valueColl = (Collection) value;
489             for (Iterator it = valueColl.iterator(); it.hasNext();) {
490                 Object element = it.next();
491                 list.add(element.toString());
492             }
493         } else if (value.getClass().isArray()) {
494             int length = Array.getLength(value);
495             for (int i = 0; i < length; i++) {
496                 Object element = Array.get(value, i);
497                 list.add(element.toString());
498             }
499         } else {
500             list.add(value);
501         }
502     }
503 
504     public long getDateHeader(String name) {
505         Object value = this.headers.get(name);
506         if (value instanceof Date) {
507             return ((Date) value).getTime();
508         } else if (value instanceof Number) {
509             return ((Number) value).longValue();
510         } else if (value != null) {
511             throw new IllegalArgumentException("Value for header '" + name
512                     + "' is neither a Date nor a Number: " + value);
513         } else {
514             return -1L;
515         }
516     }
517 
518     public String getHeader(String name) {
519         Object value = this.headers.get(name);
520         if (value instanceof List) {
521             return "";
522         } else if (value != null) {
523             return value.toString();
524         } else {
525             return null;
526         }
527     }
528 
529     public Enumeration getHeaders(String name) {
530         Object value = this.headers.get(name);
531         if (value instanceof List) {
532             return Collections.enumeration((List) value);
533         } else if (value != null) {
534             Vector vector = new Vector(1);
535             vector.add(value.toString());
536             return vector.elements();
537         } else {
538             return Collections.enumeration(Collections.EMPTY_SET);
539         }
540     }
541 
542     public Enumeration getHeaderNames() {
543         return this.headers.keys();
544     }
545 
546     public int getIntHeader(String name) {
547         Object value = this.headers.get(name);
548         if (value instanceof Number) {
549             return ((Number) value).intValue();
550         } else if (value != null) {
551             throw new NumberFormatException("Value for header '" + name
552                     + "' is not a Number: " + value);
553         } else {
554             return -1;
555         }
556     }
557 
558     public void setMethod(String method) {
559         this.method = method;
560     }
561 
562     public String getMethod() {
563         return method;
564     }
565 
566     public void setPathInfo(String pathInfo) {
567         this.pathInfo = pathInfo;
568     }
569 
570     public String getPathInfo() {
571         return pathInfo;
572     }
573 
574     public String getPathTranslated() {
575         return (this.pathInfo != null ? getRealPath(this.pathInfo) : null);
576     }
577 
578     public void setContextPath(String contextPath) {
579         this.contextPath = contextPath;
580     }
581 
582     public String getContextPath() {
583         return contextPath;
584     }
585 
586     public void setQueryString(String queryString) {
587         this.queryString = queryString;
588     }
589 
590     public String getQueryString() {
591         return queryString;
592     }
593 
594     public void setRemoteUser(String remoteUser) {
595         this.remoteUser = remoteUser;
596     }
597 
598     public String getRemoteUser() {
599         return remoteUser;
600     }
601 
602     /***
603      * @deprecated in favor of addUserRole
604      * @see #addUserRole
605      */
606     public void addRole(String role) {
607         addUserRole(role);
608     }
609 
610     public void addUserRole(String role) {
611         this.userRoles.add(role);
612     }
613 
614     public boolean isUserInRole(String role) {
615         return this.userRoles.contains(role);
616     }
617 
618     public void setUserPrincipal(Principal userPrincipal) {
619         this.userPrincipal = userPrincipal;
620     }
621 
622     public Principal getUserPrincipal() {
623         return userPrincipal;
624     }
625 
626     public String getRequestedSessionId() {
627         HttpSession session = this.getSession();
628         return (session != null ? session.getId() : null);
629     }
630 
631     public void setRequestURI(String requestURI) {
632         this.requestURI = requestURI;
633     }
634 
635     public String getRequestURI() {
636         return requestURI;
637     }
638 
639     public StringBuffer getRequestURL() {
640         StringBuffer url = new StringBuffer(this.scheme);
641         url.append("://").append(this.serverName).append(':').append(
642                 this.serverPort);
643         url.append(getRequestURI());
644         return url;
645     }
646 
647     public void setServletPath(String servletPath) {
648         this.servletPath = servletPath;
649     }
650 
651     public String getServletPath() {
652         return servletPath;
653     }
654 
655     public void setSession(HttpSession session) {
656         this.session = session;
657         if (session instanceof MockHttpSession) {
658             MockHttpSession mockSession = ((MockHttpSession) session);
659             mockSession.access();
660         }
661     }
662 
663     public HttpSession getSession(boolean create) {
664         // reset session if invalidated
665         if (this.session instanceof MockHttpSession
666                 && ((MockHttpSession) this.session).isInvalid()) {
667             this.session = null;
668         }
669         // create new session if necessary
670         if (this.session == null && create) {
671             this.session = new MockHttpSession(this.servletContext);
672         }
673         return this.session;
674     }
675 
676     public HttpSession getSession() {
677         return getSession(true);
678     }
679 
680     public void setRequestedSessionIdValid(boolean requestedSessionIdValid) {
681         this.requestedSessionIdValid = requestedSessionIdValid;
682     }
683 
684     public boolean isRequestedSessionIdValid() {
685         return this.requestedSessionIdValid;
686     }
687 
688     public void setRequestedSessionIdFromCookie(
689             boolean requestedSessionIdFromCookie) {
690         this.requestedSessionIdFromCookie = requestedSessionIdFromCookie;
691     }
692 
693     public boolean isRequestedSessionIdFromCookie() {
694         return this.requestedSessionIdFromCookie;
695     }
696 
697     public void setRequestedSessionIdFromURL(boolean requestedSessionIdFromURL) {
698         this.requestedSessionIdFromURL = requestedSessionIdFromURL;
699     }
700 
701     public boolean isRequestedSessionIdFromURL() {
702         return this.requestedSessionIdFromURL;
703     }
704 
705     public boolean isRequestedSessionIdFromUrl() {
706         return isRequestedSessionIdFromURL();
707     }
708 
709 }