001: /*
002: * ========================================================================
003: *
004: * Copyright 2001-2004 The Apache Software Foundation.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * ========================================================================
019: */
020: package org.apache.cactus.server;
021:
022: import java.io.BufferedReader;
023: import java.io.File;
024: import java.io.IOException;
025:
026: import java.security.Principal;
027:
028: import java.util.Enumeration;
029: import java.util.Locale;
030:
031: import javax.servlet.RequestDispatcher;
032: import javax.servlet.ServletInputStream;
033: import javax.servlet.http.Cookie;
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpSession;
036:
037: import org.apache.cactus.ServletURL;
038: import org.apache.commons.logging.Log;
039: import org.apache.commons.logging.LogFactory;
040:
041: /**
042: * Abstract wrapper around {@link HttpServletRequest}. This class provides
043: * a common implementation of the wrapper for the different Servlet APIs.
044: * This is an implementation that delegates all the call to the
045: * {@link HttpServletRequest} object passed in the constructor except for
046: * some overidden methods which are use to simulate a URL. This is to be able
047: * to simulate any URL that would have been used to call the test method : if
048: * this was not done, the URL that would be returned (by calling the
049: * {@link HttpServletRequest#getRequestURI()} method or others alike) would be
050: * the URL of the Cactus redirector servlet and not a URL that the test case
051: * want to simulate.
052: *
053: * @version $Id: AbstractHttpServletRequestWrapper.java 238993 2004-05-22 16:39:34Z vmassol $
054: */
055: public abstract class AbstractHttpServletRequestWrapper implements
056: HttpServletRequest {
057: /**
058: * The logger
059: */
060: private static final Log LOGGER = LogFactory
061: .getLog(AbstractHttpServletRequestWrapper.class);
062:
063: /**
064: * The real HTTP request
065: */
066: protected HttpServletRequest request;
067:
068: /**
069: * The URL to simulate
070: */
071: protected ServletURL url;
072:
073: /**
074: * Remote IP address to simulate (if any)
075: * @see #setRemoteIPAddress(String)
076: */
077: protected String remoteIPAddress;
078:
079: /**
080: * Remote Host name to simulate (if any)
081: * @see #setRemoteHostName(String)
082: */
083: protected String remoteHostName;
084:
085: /**
086: * Remote user to simulate (if any)
087: * @see #setRemoteUser(String)
088: */
089: protected String remoteUser;
090:
091: // New methods not in the interface --------------------------------------
092:
093: /**
094: * Construct an <code>HttpServletRequest</code> instance that delegates
095: * it's method calls to the request object passed as parameter and that
096: * uses the URL passed as parameter to simulate a URL from which the request
097: * would come from.
098: *
099: * @param theRequest the real HTTP request
100: * @param theURL the URL to simulate or <code>null</code> if none
101: */
102: public AbstractHttpServletRequestWrapper(
103: HttpServletRequest theRequest, ServletURL theURL) {
104: this .request = theRequest;
105: this .url = theURL;
106: }
107:
108: /**
109: * @return the original request object
110: */
111: public HttpServletRequest getOriginalRequest() {
112: return this .request;
113: }
114:
115: /**
116: * Simulates the remote IP address (ie the client IP address).
117: *
118: * @param theRemoteIPAddress the simulated IP address in string format.
119: * Exemple : "127.0.0.1"
120: */
121: public void setRemoteIPAddress(String theRemoteIPAddress) {
122: this .remoteIPAddress = theRemoteIPAddress;
123: }
124:
125: /**
126: * Simulates the remote host name(ie the client host name).
127: *
128: * @param theRemoteHostName the simulated host name in string format.
129: * Exemple : "atlantis"
130: */
131: public void setRemoteHostName(String theRemoteHostName) {
132: this .remoteHostName = theRemoteHostName;
133: }
134:
135: /**
136: * Sets the remote user name to simulate.
137: *
138: * @param theRemoteUser the simulated remote user name
139: */
140: public void setRemoteUser(String theRemoteUser) {
141: this .remoteUser = theRemoteUser;
142: }
143:
144: // Modified methods ------------------------------------------------------
145:
146: /**
147: * @return the context path from the simulated URL or the real context path
148: * if a simulation URL has not been defined. The real context path
149: * will be returned if the context path defined in the simulated
150: * URL has a null value.
151: */
152: public String getContextPath() {
153: String result = this .request.getContextPath();
154:
155: if ((this .url != null) && (this .url.getContextPath() != null)) {
156: result = this .url.getContextPath();
157: LOGGER.debug("Using simulated context : [" + result + "]");
158: }
159:
160: return result;
161: }
162:
163: /**
164: * @return the path info from the simulated URL or the real path info
165: * if a simulation URL has not been defined.
166: */
167: public String getPathInfo() {
168: String result;
169:
170: if (this .url != null) {
171: result = this .url.getPathInfo();
172: LOGGER.debug("Using simulated PathInfo : [" + result + "]");
173: } else {
174: result = this .request.getPathInfo();
175: }
176:
177: return result;
178: }
179:
180: /**
181: * @return the server name from the simulated URL or the real server name
182: * if a simulation URL has not been defined. If the server name
183: * defined in the simulation URL is null, return the real server
184: * name.
185: */
186: public String getServerName() {
187: String result = this .request.getServerName();
188:
189: if ((this .url != null) && (this .url.getHost() != null)) {
190: result = this .url.getHost();
191: LOGGER.debug("Using simulated server name : [" + result
192: + "]");
193: }
194:
195: return result;
196: }
197:
198: /**
199: * @return the server port number from the simulated URL or the real server
200: * port number if a simulation URL has not been defined. If no
201: * port is defined in the simulation URL, then port 80 is returned.
202: * If the server name has been defined with a null value in
203: * in the simulation URL, return the real server port.
204: */
205: public int getServerPort() {
206: int result = this .request.getServerPort();
207:
208: if ((this .url != null) && (this .url.getServerName() != null)) {
209: result = (this .url.getPort() == -1) ? 80 : this .url
210: .getPort();
211: LOGGER.debug("Using simulated server port : [" + result
212: + "]");
213: }
214:
215: return result;
216: }
217:
218: /**
219: * @return the URI from the simulated URL or the real URI
220: * if a simulation URL has not been defined.
221: */
222: public String getRequestURI() {
223: String result;
224:
225: if (this .url != null) {
226: result = getContextPath()
227: + ((getServletPath() == null) ? ""
228: : getServletPath())
229: + ((getPathInfo() == null) ? "" : getPathInfo());
230:
231: LOGGER.debug("Using simulated request URI : [" + result
232: + "]");
233: } else {
234: result = this .request.getRequestURI();
235: }
236:
237: return result;
238: }
239:
240: /**
241: * @return the servlet path from the simulated URL or the real servlet path
242: * if a simulation URL has not been defined. The real servlet path
243: * will be returned if the servlet path defined in the simulated
244: * URL has a null value.
245: */
246: public String getServletPath() {
247: String result = this .request.getServletPath();
248:
249: if ((this .url != null) && (this .url.getServletPath() != null)) {
250: result = this .url.getServletPath();
251: LOGGER.debug("Using simulated servlet path : [" + result
252: + "]");
253: }
254:
255: return result;
256: }
257:
258: /**
259: * @return any extra path information after the servlet name but
260: * before the query string, and translates it to a real path.
261: * Takes into account the simulated URL (if any).
262: */
263: public String getPathTranslated() {
264: String pathTranslated;
265:
266: if ((this .url != null) && (this .url.getPathInfo() != null)) {
267: String pathInfo = this .url.getPathInfo();
268:
269: // If getRealPath returns null then getPathTranslated should also
270: // return null (see section SRV.4.5 of the Servlet 2.3 spec).
271: if (this .request.getRealPath("/") == null) {
272: pathTranslated = null;
273: } else {
274: // Compute the translated path using the root real path
275: String newPathInfo = (pathInfo.startsWith("/") ? pathInfo
276: .substring(1)
277: : pathInfo);
278:
279: if (this .request.getRealPath("/").endsWith("/")) {
280: pathTranslated = this .request.getRealPath("/")
281: + newPathInfo.replace('/',
282: File.separatorChar);
283: } else {
284: pathTranslated = this .request.getRealPath("/")
285: + File.separatorChar
286: + newPathInfo.replace('/',
287: File.separatorChar);
288: }
289: }
290: } else {
291: pathTranslated = this .request.getPathTranslated();
292: }
293:
294: return pathTranslated;
295: }
296:
297: /**
298: * @return the query string from the simulated URL or the real query
299: * string if a simulation URL has not been defined.
300: */
301: public String getQueryString() {
302: String result;
303:
304: if (this .url != null) {
305: result = this .url.getQueryString();
306: LOGGER.debug("Using simulated query string : [" + result
307: + "]");
308: } else {
309: result = this .request.getQueryString();
310: }
311:
312: return result;
313: }
314:
315: /**
316: * @param thePath the path to the resource
317: * @return a wrapped request dispatcher instead of the real one, so that
318: * forward() and include() calls will use the wrapped dispatcher
319: * passing it the *original* request [this is needed for some
320: * servlet engine like Tomcat 3.x which do not support the new
321: * mechanism introduced by Servlet 2.3 Filters].
322: * @see HttpServletRequest#getRequestDispatcher(String)
323: */
324: public RequestDispatcher getRequestDispatcher(String thePath) {
325: // I hate it, but we have to write some logic here ! Ideally we
326: // shouldn't have to do this as it is supposed to be done by the servlet
327: // engine. However as we are simulating the request URL, we have to
328: // provide it ... This is where we can see the limitation of Cactus
329: // (it has to mock some parts of the servlet engine) !
330: if (thePath == null) {
331: return null;
332: }
333:
334: RequestDispatcher dispatcher = null;
335: String fullPath;
336:
337: // The spec says that the path can be relative, in which case it will
338: // be relative to the request. So for relative paths, we need to take
339: // into account the simulated URL (ServletURL).
340: if (thePath.startsWith("/")) {
341: fullPath = thePath;
342: } else {
343: String pI = getPathInfo();
344:
345: if (pI == null) {
346: fullPath = catPath(getServletPath(), thePath);
347: } else {
348: fullPath = catPath(getServletPath() + pI, thePath);
349: }
350:
351: if (fullPath == null) {
352: return null;
353: }
354: }
355:
356: LOGGER.debug("Computed full path : [" + fullPath + "]");
357:
358: dispatcher = new RequestDispatcherWrapper(this .request
359: .getRequestDispatcher(fullPath));
360:
361: return dispatcher;
362: }
363:
364: /**
365: * Will concatenate 2 paths, normalising it. For example :
366: * ( /a/b/c + d = /a/b/d, /a/b/c + ../d = /a/d ). Code borrowed from
367: * Tomcat 3.2.2 !
368: *
369: * @param theLookupPath the first part of the path
370: * @param thePath the part to add to the lookup path
371: * @return the concatenated thePath or null if an error occurs
372: */
373: private String catPath(String theLookupPath, String thePath) {
374: // Cut off the last slash and everything beyond
375: int index = theLookupPath.lastIndexOf("/");
376:
377: theLookupPath = theLookupPath.substring(0, index);
378:
379: // Deal with .. by chopping dirs off the lookup thePath
380: while (thePath.startsWith("../")) {
381: if (theLookupPath.length() > 0) {
382: index = theLookupPath.lastIndexOf("/");
383: theLookupPath = theLookupPath.substring(0, index);
384: } else {
385: // More ..'s than dirs, return null
386: return null;
387: }
388:
389: index = thePath.indexOf("../") + 3;
390: thePath = thePath.substring(index);
391: }
392:
393: return theLookupPath + "/" + thePath;
394: }
395:
396: /**
397: * @return the simulated remote IP address if any or the real one.
398: *
399: * @see HttpServletRequest#getRemoteAddr()
400: */
401: public String getRemoteAddr() {
402: String remoteIPAddress;
403:
404: if (this .remoteIPAddress != null) {
405: remoteIPAddress = this .remoteIPAddress;
406: } else {
407: remoteIPAddress = this .request.getRemoteAddr();
408: }
409:
410: return remoteIPAddress;
411: }
412:
413: /**
414: * @return the simulated remote host name if any or the real one.
415: *
416: * @see HttpServletRequest#getRemoteHost()
417: */
418: public String getRemoteHost() {
419: String remoteHostName;
420:
421: if (this .remoteHostName != null) {
422: remoteHostName = this .remoteHostName;
423: } else {
424: remoteHostName = this .request.getRemoteHost();
425: }
426:
427: return remoteHostName;
428: }
429:
430: /**
431: * @return the simulated remote user name if any or the real one.
432: *
433: * @see HttpServletRequest#getRemoteUser()
434: */
435: public String getRemoteUser() {
436: String remoteUser;
437:
438: if (this .remoteUser != null) {
439: remoteUser = this .remoteUser;
440: } else {
441: remoteUser = this .request.getRemoteUser();
442: }
443:
444: return remoteUser;
445: }
446:
447: // Not modified methods --------------------------------------------------
448:
449: /**
450: * @see HttpServletRequest#isRequestedSessionIdFromURL()
451: */
452: public boolean isRequestedSessionIdFromURL() {
453: return this .request.isRequestedSessionIdFromURL();
454: }
455:
456: /**
457: * @see HttpServletRequest#isRequestedSessionIdFromUrl()
458: */
459: public boolean isRequestedSessionIdFromUrl() {
460: return this .request.isRequestedSessionIdFromURL();
461: }
462:
463: /**
464: * @see HttpServletRequest#isUserInRole(String)
465: */
466: public boolean isUserInRole(String theRole) {
467: return this .request.isUserInRole(theRole);
468: }
469:
470: /**
471: * @see HttpServletRequest#isRequestedSessionIdValid()
472: */
473: public boolean isRequestedSessionIdValid() {
474: return this .request.isRequestedSessionIdValid();
475: }
476:
477: /**
478: * @see HttpServletRequest#isRequestedSessionIdFromCookie()
479: */
480: public boolean isRequestedSessionIdFromCookie() {
481: return this .request.isRequestedSessionIdFromCookie();
482: }
483:
484: /**
485: * @see HttpServletRequest#getLocales()
486: */
487: public Enumeration getLocales() {
488: return this .request.getLocales();
489: }
490:
491: /**
492: * @see HttpServletRequest#getHeader(String)
493: */
494: public String getHeader(String theName) {
495: return this .request.getHeader(theName);
496: }
497:
498: /**
499: * @see HttpServletRequest#getHeaders(String)
500: */
501: public Enumeration getHeaders(String theName) {
502: return this .request.getHeaders(theName);
503: }
504:
505: /**
506: * @see HttpServletRequest#getHeaderNames()
507: */
508: public Enumeration getHeaderNames() {
509: return this .request.getHeaderNames();
510: }
511:
512: /**
513: * @see HttpServletRequest#getScheme()
514: */
515: public String getScheme() {
516: return this .request.getScheme();
517: }
518:
519: /**
520: * @see HttpServletRequest#getAuthType()
521: */
522: public String getAuthType() {
523: return this .request.getAuthType();
524: }
525:
526: /**
527: * @see HttpServletRequest#getRealPath(String)
528: */
529: public String getRealPath(String thePath) {
530: return this .request.getRealPath(thePath);
531: }
532:
533: /**
534: * @see HttpServletRequest#getSession()
535: */
536: public HttpSession getSession() {
537: return this .request.getSession();
538: }
539:
540: /**
541: * @see HttpServletRequest#getSession(boolean)
542: */
543: public HttpSession getSession(boolean isCreate) {
544: return this .request.getSession(isCreate);
545: }
546:
547: /**
548: * @see HttpServletRequest#getReader()
549: */
550: public BufferedReader getReader() throws IOException {
551: return this .request.getReader();
552: }
553:
554: /**
555: * @see HttpServletRequest#getContentLength()
556: */
557: public int getContentLength() {
558: return this .request.getContentLength();
559: }
560:
561: /**
562: * @see HttpServletRequest#getParameterValues(String)
563: */
564: public String[] getParameterValues(String theName) {
565: return this .request.getParameterValues(theName);
566: }
567:
568: /**
569: * @see HttpServletRequest#getContentType()
570: */
571: public String getContentType() {
572: return this .request.getContentType();
573: }
574:
575: /**
576: * @see HttpServletRequest#getLocale()
577: */
578: public Locale getLocale() {
579: return this .request.getLocale();
580: }
581:
582: /**
583: * @see HttpServletRequest#removeAttribute(String)
584: */
585: public void removeAttribute(String theName) {
586: this .request.removeAttribute(theName);
587: }
588:
589: /**
590: * @see HttpServletRequest#getParameter(String)
591: */
592: public String getParameter(String theName) {
593: return this .request.getParameter(theName);
594: }
595:
596: /**
597: * @see HttpServletRequest#getInputStream()
598: */
599: public ServletInputStream getInputStream() throws IOException {
600: return this .request.getInputStream();
601: }
602:
603: /**
604: * @see HttpServletRequest#getUserPrincipal()
605: */
606: public Principal getUserPrincipal() {
607: return this .request.getUserPrincipal();
608: }
609:
610: /**
611: * @see HttpServletRequest#isSecure()
612: */
613: public boolean isSecure() {
614: return this .request.isSecure();
615: }
616:
617: /**
618: * @see HttpServletRequest#getCharacterEncoding()
619: */
620: public String getCharacterEncoding() {
621: return this .request.getCharacterEncoding();
622: }
623:
624: /**
625: * @see HttpServletRequest#getParameterNames()
626: */
627: public Enumeration getParameterNames() {
628: return this .request.getParameterNames();
629: }
630:
631: /**
632: * @see HttpServletRequest#getMethod()
633: */
634: public String getMethod() {
635: return this .request.getMethod();
636: }
637:
638: /**
639: * @see HttpServletRequest#setAttribute(String, Object)
640: */
641: public void setAttribute(String theName, Object theAttribute) {
642: this .request.setAttribute(theName, theAttribute);
643: }
644:
645: /**
646: * @see HttpServletRequest#getAttribute(String)
647: */
648: public Object getAttribute(String theName) {
649: return this .request.getAttribute(theName);
650: }
651:
652: /**
653: * @see HttpServletRequest#getIntHeader(String)
654: */
655: public int getIntHeader(String theName) {
656: return this .request.getIntHeader(theName);
657: }
658:
659: /**
660: * @see HttpServletRequest#getDateHeader(String)
661: */
662: public long getDateHeader(String theName) {
663: return this .request.getDateHeader(theName);
664: }
665:
666: /**
667: * @see HttpServletRequest#getAttributeNames()
668: */
669: public Enumeration getAttributeNames() {
670: return this .request.getAttributeNames();
671: }
672:
673: /**
674: * @see HttpServletRequest#getRequestedSessionId()
675: */
676: public String getRequestedSessionId() {
677: return this .request.getRequestedSessionId();
678: }
679:
680: /**
681: * @see HttpServletRequest#getCookies()
682: */
683: public Cookie[] getCookies() {
684: return this .request.getCookies();
685: }
686:
687: /**
688: * @see HttpServletRequest#getProtocol()
689: */
690: public String getProtocol() {
691: return this.request.getProtocol();
692: }
693: }
|