001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.server.webapp;
031:
032: import com.caucho.i18n.CharacterEncoding;
033: import com.caucho.log.Log;
034: import com.caucho.server.connection.CauchoRequest;
035: import com.caucho.server.connection.CauchoResponse;
036: import com.caucho.server.connection.Form;
037: import com.caucho.server.connection.RequestAdapter;
038: import com.caucho.server.connection.ServletInputStreamImpl;
039: import com.caucho.server.dispatch.Invocation;
040: import com.caucho.server.session.SessionImpl;
041: import com.caucho.server.session.SessionManager;
042: import com.caucho.util.Alarm;
043: import com.caucho.util.CharBuffer;
044: import com.caucho.util.FreeList;
045: import com.caucho.util.HashMapImpl;
046: import com.caucho.vfs.BufferedReaderAdapter;
047: import com.caucho.vfs.Encoding;
048: import com.caucho.vfs.ReadStream;
049:
050: import javax.servlet.RequestDispatcher;
051: import javax.servlet.ServletException;
052: import javax.servlet.ServletInputStream;
053: import javax.servlet.http.HttpServletRequest;
054: import javax.servlet.http.HttpServletResponse;
055: import javax.servlet.http.HttpSession;
056: import java.io.BufferedReader;
057: import java.io.IOException;
058: import java.util.*;
059: import java.util.logging.*;
060:
061: /**
062: * sub-request for a include() page
063: */
064: class DispatchRequest extends RequestAdapter {
065: protected static final Logger log = Logger
066: .getLogger(DispatchRequest.class.getName());
067:
068: private static final FreeList<DispatchRequest> _freeList = new FreeList<DispatchRequest>(
069: 32);
070:
071: private WebApp _webApp;
072: private WebApp _oldWebApp;
073: private Invocation _invocation;
074: private Form _formParser;
075: private HashMapImpl<String, String[]> _form;
076: protected ReadStream _readStream;
077: protected ServletInputStreamImpl _is;
078: // Reader for post contents
079: private BufferedReaderAdapter _bufferedReader;
080: private String _method;
081: private String _uri;
082: private String _servletPath;
083: private String _pathInfo;
084: private String _queryString;
085: private String _addedQuery;
086: private SessionImpl _session;
087:
088: private String _pageUri;
089: private String _pageContextPath;
090: private String _pageServletPath;
091: private String _pagePathInfo;
092: private String _pageQueryString;
093:
094: protected DispatchRequest() {
095: }
096:
097: /**
098: * Creates a dispatch request.
099: */
100: public static DispatchRequest createDispatch() {
101: DispatchRequest req = _freeList.allocate();
102: if (req == null)
103: req = new DispatchRequest();
104:
105: return req;
106: }
107:
108: void init(Invocation invocation, WebApp webApp, WebApp oldWebApp,
109: HttpServletRequest request, HttpServletResponse response,
110: String method, String uri, String servletPath,
111: String pathInfo, String queryString, String addedQuery)
112: throws ServletException {
113: super .init(request, response, webApp);
114:
115: _invocation = invocation;
116: _webApp = webApp;
117: _oldWebApp = oldWebApp;
118:
119: _form = null;
120:
121: _readStream = null;
122: _is = null;
123:
124: _bufferedReader = null;
125:
126: _method = method;
127: _uri = uri;
128: _servletPath = servletPath;
129: _pathInfo = pathInfo;
130: _queryString = queryString;
131: _addedQuery = addedQuery;
132:
133: _pageUri = null;
134: _pageContextPath = null;
135: _pageServletPath = null;
136: _pagePathInfo = null;
137: _pageQueryString = null;
138:
139: _session = null;
140: }
141:
142: void setStream(ReadStream readStream) {
143: _readStream = readStream;
144: }
145:
146: public WebApp getWebApp() {
147: return _webApp;
148: }
149:
150: public String getMethod() {
151: return _method;
152: }
153:
154: public String getRequestURI() {
155: return _uri;
156: }
157:
158: /**
159: * Returns the URL for the request
160: */
161: public StringBuffer getRequestURL() {
162: StringBuffer sb = new StringBuffer();
163:
164: sb.append(getScheme());
165: sb.append("://");
166: sb.append(getServerName());
167: if (getServerPort() > 0 && getServerPort() != 80
168: && getServerPort() != 443) {
169: sb.append(":");
170: sb.append(getServerPort());
171: }
172: sb.append(getRequestURI());
173:
174: return sb;
175: }
176:
177: void setPageURI(String uri) {
178: _pageUri = uri;
179: }
180:
181: public String getPageURI() {
182: return _pageUri;
183: }
184:
185: /**
186: * Returns the servlet context prefix of the webApp.
187: */
188: public String getContextPath() {
189: if (_webApp != null)
190: return _webApp.getContextPath();
191: else
192: return "/";
193: }
194:
195: /**
196: * Sets the servlet context prefix of page.
197: */
198: void setPageContextPath(String contextPath) {
199: _pageContextPath = contextPath;
200: }
201:
202: /**
203: * Gets the servlet context prefix of page.
204: */
205: public String getPageContextPath() {
206: return _pageContextPath;
207: }
208:
209: public String getServletPath() {
210: return _servletPath;
211: }
212:
213: public String getPageServletPath() {
214: return _pageServletPath;
215: }
216:
217: void setPageServletPath(String servletPath) {
218: _pageServletPath = servletPath;
219: }
220:
221: public String getPathInfo() {
222: return _pathInfo;
223: }
224:
225: public String getPagePathInfo() {
226: return _pagePathInfo;
227: }
228:
229: void setPagePathInfo(String pathInfo) {
230: _pagePathInfo = pathInfo;
231: }
232:
233: public String getQueryString() {
234: return _queryString;
235: }
236:
237: void setPageQueryString(String queryString) {
238: _pageQueryString = queryString;
239: }
240:
241: public String getPageQueryString() {
242: return _pageQueryString;
243: }
244:
245: public Map getParameterMap() {
246: if (_form == null)
247: _form = parseQuery();
248:
249: return _form;
250: }
251:
252: public Enumeration getParameterNames() {
253: if (_form == null)
254: _form = parseQuery();
255:
256: return Collections.enumeration(_form.keySet());
257: }
258:
259: public String[] getParameterValues(String name) {
260: if (_form == null)
261: _form = parseQuery();
262:
263: return _form.get(name);
264: }
265:
266: public String getParameter(String name) {
267: String[] values = getParameterValues(name);
268: if (values == null || values.length == 0)
269: return null;
270:
271: return values[0];
272: }
273:
274: private HashMapImpl<String, String[]> parseQuery() {
275: HashMapImpl<String, String[]> table = new HashMapImpl<String, String[]>();
276:
277: String defaultEncoding = CharacterEncoding.getLocalEncoding();
278: String charEncoding = getCharacterEncoding();
279: if (charEncoding == null)
280: charEncoding = defaultEncoding;
281: String javaEncoding = Encoding.getJavaName(charEncoding);
282:
283: if (_addedQuery != null) {
284: try {
285: if (_formParser == null)
286: _formParser = new Form();
287: _formParser.parseQueryString(table, _addedQuery,
288: javaEncoding, false);
289: } catch (Exception e) {
290: }
291: }
292:
293: Enumeration en = super .getParameterNames();
294: while (en.hasMoreElements()) {
295: String key = (String) en.nextElement();
296: String[] oldValues = (String[]) super
297: .getParameterValues(key);
298: String[] newValues = (String[]) table.get(key);
299:
300: if (oldValues == null) {
301: } else if (newValues == null)
302: table.put(key, oldValues);
303: else {
304: String[] next = new String[oldValues.length
305: + newValues.length];
306: System.arraycopy(newValues, 0, next, 0,
307: newValues.length);
308: System.arraycopy(oldValues, 0, next, newValues.length,
309: oldValues.length);
310: table.put(key, next);
311: }
312: }
313:
314: return table;
315: }
316:
317: public String getRealPath(String path) {
318: return _webApp.getRealPath(path);
319: }
320:
321: public String getPathTranslated() {
322: if (_pathInfo != null)
323: return getRealPath(_pathInfo);
324: else
325: return null;
326: }
327:
328: public RequestDispatcher getRequestDispatcher(String path) {
329: if (path.startsWith("/"))
330: return _webApp.getRequestDispatcher(path);
331: else
332: return _webApp.getRequestDispatcher(getPwd() + path);
333: }
334:
335: public String getPwd() {
336: CharBuffer cb = CharBuffer.allocate();
337:
338: String servletPath = getPageServletPath();
339: if (servletPath != null)
340: cb.append(servletPath);
341: String pathInfo = getPagePathInfo();
342: if (pathInfo != null)
343: cb.append(pathInfo);
344:
345: int p = cb.lastIndexOf('/');
346: if (p >= 0)
347: cb.setLength(p);
348: cb.append('/');
349:
350: return cb.close();
351: }
352:
353: public ReadStream getStream() throws IOException {
354: if (_readStream == null
355: && getRequest() instanceof CauchoRequest)
356: return ((CauchoRequest) getRequest()).getStream();
357: else
358: return _readStream;
359: }
360:
361: public ServletInputStream getInputStream() throws IOException {
362: if (_readStream == null)
363: return super .getInputStream();
364:
365: if (_is == null)
366: _is = new ServletInputStreamImpl();
367: _is.init(_readStream);
368:
369: return _is;
370: }
371:
372: public BufferedReader getReader() throws IOException {
373: if (_readStream == null)
374: return super .getReader();
375:
376: if (_bufferedReader == null)
377: _bufferedReader = new BufferedReaderAdapter(getStream());
378:
379: // bufferedReader is just an adapter to get the signature right.
380: _bufferedReader.init(getStream());
381:
382: return _bufferedReader;
383: }
384:
385: /**
386: * Returns the current session.
387: *
388: * @param create true if a new session should be created
389: *
390: * @return the current session
391: */
392: @Override
393: public HttpSession getSession(boolean create) {
394: SessionManager manager = null;
395:
396: if (_webApp != null)
397: manager = _webApp.getSessionManager();
398:
399: if (manager != null)
400: setVaryCookie(manager.getCookieName());
401:
402: if (_session != null && _session.isValid()) {
403: setHasCookie();
404:
405: return _session;
406: }
407:
408: if (_webApp == _oldWebApp) {
409: HttpSession hSession = super .getSession(create);
410: if (hSession != null)
411: setHasCookie();
412:
413: return hSession;
414: } else {
415: SessionImpl oldSession = _session;
416: _session = createSession(create, oldSession != null);
417: }
418:
419: if (_session != null)
420: setHasCookie();
421:
422: return _session;
423: }
424:
425: /**
426: * Returns the current session.
427: *
428: * XXX: duplicated in AbstractHttpRequest
429: *
430: * @param create true if a new session should be created
431: *
432: * @return the current session
433: */
434: private SessionImpl createSession(boolean create,
435: boolean hasOldSession) {
436: SessionManager manager = getSessionManager();
437:
438: String id = getRequestedSessionId();
439:
440: long now = Alarm.getCurrentTime();
441:
442: SessionImpl session;
443:
444: if (id != null && id.length() > 6) {
445: session = manager.getSession(id, now, create,
446: isRequestedSessionIdFromCookie());
447: if (session == null) {
448: } else if (session.isValid()) {
449: if (session != null)
450: setHasCookie();
451: if (!session.getId().equals(id)
452: && manager.enableSessionCookies()) {
453: HttpServletResponse response = getResponse();
454:
455: if (response instanceof CauchoResponse)
456: ((CauchoResponse) getResponse())
457: .setSessionId(session.getId());
458: }
459:
460: return session;
461: }
462: } else
463: id = null;
464:
465: if (!create)
466: return null;
467:
468: // Must accept old ids because different webApps in the same
469: // server must share the same cookie
470: //
471: // But, if the session group doesn't match, then create a new
472: // session.
473:
474: session = manager.createSession(id, now, this ,
475: isRequestedSessionIdFromCookie());
476:
477: if (session != null)
478: setHasCookie();
479:
480: if (session.getId().equals(id))
481: return session;
482:
483: if (manager.enableSessionCookies()) {
484: HttpServletResponse response = getResponse();
485:
486: if (response instanceof CauchoResponse)
487: ((CauchoResponse) getResponse()).setSessionId(session
488: .getId());
489: }
490:
491: return session;
492: }
493:
494: public boolean authenticate() throws ServletException, IOException {
495: if (!(getRequest() instanceof CauchoRequest))
496: return false;
497: else
498: return ((CauchoRequest) getRequest()).authenticate();
499: }
500:
501: /**
502: * Returns true if the user represented by the current request
503: * plays the named role.
504: *
505: * @param role the named role to test.
506: * @return true if the user plays the role.
507: */
508: public boolean isUserInRole(String role) {
509: HashMap<String, String> roleMap = _invocation
510: .getSecurityRoleMap();
511:
512: if (roleMap != null) {
513: String linkRole = roleMap.get(role);
514:
515: if (linkRole != null)
516: role = linkRole;
517: }
518:
519: return super .isUserInRole(role);
520: }
521:
522: /**
523: * Cleans up at the end of the request
524: */
525: public void finish() throws IOException {
526: SessionImpl session = _session;
527: _session = null;
528:
529: if (session != null)
530: session.finish();
531: }
532:
533: /**
534: * Frees the request.
535: */
536: public static void free(DispatchRequest req) {
537: req.free();
538:
539: _freeList.free(req);
540: }
541:
542: /**
543: * Clears variables.
544: */
545: protected void free() {
546: super .free();
547:
548: _session = null;
549: _webApp = null;
550: _oldWebApp = null;
551: _readStream = null;
552:
553: if (_is != null)
554: _is.free();
555: }
556:
557: public String toString() {
558: return "DispatchRequest[" + getRequest() + "]";
559: }
560: }
|