001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.impl;
017:
018: import java.io.IOException;
019: import java.io.StringWriter;
020:
021: import javax.servlet.ServletConfig;
022: import javax.servlet.ServletContext;
023: import javax.servlet.ServletException;
024: import javax.servlet.http.HttpServletRequest;
025: import javax.servlet.http.HttpServletResponse;
026: import javax.servlet.http.HttpSession;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.directwebremoting.Container;
031: import org.directwebremoting.ScriptSession;
032: import org.directwebremoting.WebContext;
033: import org.directwebremoting.extend.EnginePrivate;
034: import org.directwebremoting.extend.RealScriptSession;
035: import org.directwebremoting.extend.RealWebContext;
036: import org.directwebremoting.extend.ScriptSessionManager;
037: import org.directwebremoting.util.IdGenerator;
038: import org.directwebremoting.util.SwallowingHttpServletResponse;
039:
040: /**
041: * A default implementation of WebContext.
042: * @author Joe Walker [joe at getahead dot ltd dot uk]
043: */
044: public class DefaultWebContext extends DefaultServerContext implements
045: RealWebContext {
046: /**
047: * Create a new DefaultWebContext
048: * @param request The incoming http request
049: * @param response The outgoing http reply
050: * @param config The servlet configuration
051: * @param context The servlet context
052: * @param container The IoC container
053: * @see org.directwebremoting.WebContextFactory.WebContextBuilder#set(HttpServletRequest, HttpServletResponse, ServletConfig, ServletContext, Container)
054: */
055: public DefaultWebContext(HttpServletRequest request,
056: HttpServletResponse response, ServletConfig config,
057: ServletContext context, Container container) {
058: super (config, context, container);
059:
060: this .request = request;
061: this .response = response;
062:
063: Object value = container
064: .getBean("avoidConnectionLimitWithWindowName");
065: if (value != null) {
066: avoidConnectionLimitWithWindowName = Boolean
067: .parseBoolean(value.toString());
068: }
069: }
070:
071: /* (non-Javadoc)
072: * @see org.directwebremoting.extend.RealWebContext#checkPageInformation(java.lang.String, java.lang.String, java.lang.String)
073: */
074: public void checkPageInformation(String sentPage,
075: String sentScriptId, String windowName) {
076: ScriptSessionManager scriptSessionManager = getScriptSessionManager();
077:
078: // Get the httpSessionId if it exists, but don't create one if it doesn't
079: String httpSessionId = null;
080: HttpSession httpSession = request.getSession(false);
081: if (httpSession != null) {
082: httpSessionId = httpSession.getId();
083: }
084:
085: // Check validity to the script session id. It could be invalid due to
086: // to a server re-start, a timeout, a back-button, just because the user
087: // is new to this page, or because someone is hacking
088: RealScriptSession scriptSession = scriptSessionManager
089: .getScriptSession(sentScriptId, sentPage, httpSessionId);
090: if (scriptSession == null) {
091: // Force creation of a new script session
092: scriptSession = scriptSessionManager.createScriptSession(
093: sentPage, httpSessionId);
094: String newSessionId = scriptSession.getId();
095:
096: // Inject a (new) script session id into the page
097: EnginePrivate.remoteHandleNewScriptSession(scriptSession,
098: newSessionId);
099:
100: // Use the new script session id not the one passed in
101: log.debug("ScriptSession re-sync: " + sentScriptId
102: + " has become " + newSessionId);
103: this .scriptSessionId = newSessionId;
104: this .page = sentPage;
105: } else {
106: // This could be called from a poll or an rpc call, so this is a
107: // good place to update the session access time
108: scriptSession.updateLastAccessedTime();
109:
110: String storedPage = scriptSession.getPage();
111: if (!storedPage.equals(sentPage)) {
112: log.error("Invalid Page: Passed page=" + sentPage
113: + ", but page in script session=" + storedPage);
114: throw new SecurityException("Invalid Page");
115: }
116:
117: // The passed script session id passed the test, use it
118: this .scriptSessionId = sentScriptId;
119: this .page = sentPage;
120: }
121:
122: if (avoidConnectionLimitWithWindowName) {
123: if (windowName == null || windowName.equals("")) {
124: windowName = "DWR-" + generator.generateId(16);
125: EnginePrivate.remoteHandleNewWindowName(scriptSession,
126: windowName);
127: }
128: scriptSession.setWindowName(windowName);
129: }
130: }
131:
132: /* (non-Javadoc)
133: * @see org.directwebremoting.WebContext#getCurrentPage()
134: */
135: public String getCurrentPage() {
136: return page;
137: }
138:
139: /* (non-Javadoc)
140: * @see org.directwebremoting.WebContext#getScriptSession()
141: */
142: public ScriptSession getScriptSession() {
143: ScriptSessionManager manager = getScriptSessionManager();
144:
145: RealScriptSession scriptSession = manager.getScriptSession(
146: scriptSessionId, null, null);
147: if (scriptSession == null) {
148: throw new SecurityException(
149: "Expected script session to exist");
150: }
151:
152: return scriptSession;
153: }
154:
155: /* (non-Javadoc)
156: * @see org.directwebremoting.WebContext#getSession()
157: */
158: public HttpSession getSession() {
159: return request.getSession();
160: }
161:
162: /* (non-Javadoc)
163: * @see org.directwebremoting.WebContext#getSession(boolean)
164: */
165: public HttpSession getSession(boolean create) {
166: return request.getSession(create);
167: }
168:
169: /* (non-Javadoc)
170: * @see org.directwebremoting.WebContext#getHttpServletRequest()
171: */
172: public HttpServletRequest getHttpServletRequest() {
173: return request;
174: }
175:
176: /* (non-Javadoc)
177: * @see org.directwebremoting.WebContext#getHttpServletResponse()
178: */
179: public HttpServletResponse getHttpServletResponse() {
180: return response;
181: }
182:
183: /* (non-Javadoc)
184: * @see org.directwebremoting.WebContext#forwardToString(java.lang.String)
185: */
186: public String forwardToString(String url) throws ServletException,
187: IOException {
188: StringWriter sout = new StringWriter();
189: StringBuffer buffer = sout.getBuffer();
190:
191: HttpServletResponse realResponse = getHttpServletResponse();
192: HttpServletResponse fakeResponse = new SwallowingHttpServletResponse(
193: realResponse, sout, realResponse.getCharacterEncoding());
194:
195: HttpServletRequest realRequest = getHttpServletRequest();
196: realRequest
197: .setAttribute(WebContext.ATTRIBUTE_DWR, Boolean.TRUE);
198:
199: getServletContext().getRequestDispatcher(url).forward(
200: realRequest, fakeResponse);
201:
202: return buffer.toString();
203: }
204:
205: /**
206: * We can turn connection limit avoidance off
207: */
208: private boolean avoidConnectionLimitWithWindowName = true;
209:
210: /**
211: * If a window does not have a name, we give it one so we can avoid the
212: * 2 connection limit
213: */
214: private static IdGenerator generator = new IdGenerator();
215:
216: /**
217: * The unique ID (like a session ID) assigned to the current page
218: */
219: private String scriptSessionId = null;
220:
221: /**
222: * The URL of the current page
223: */
224: private String page = null;
225:
226: /**
227: * The HttpServletRequest associated with the current request
228: */
229: private HttpServletRequest request = null;
230:
231: /**
232: * The HttpServletResponse associated with the current request
233: */
234: private HttpServletResponse response = null;
235:
236: /**
237: * The log stream
238: */
239: private static final Log log = LogFactory
240: .getLog(DefaultWebContext.class);
241: }
|