001: /*
002: * $Id: WebRequestCycle.java 5766 2006-05-19 09:55:48 +0000 (Fri, 19 May 2006)
003: * joco01 $ $Revision: 462049 $ $Date: 2006-05-19 09:55:48 +0000 (Fri, 19 May
004: * 2006) $
005: *
006: * ==============================================================================
007: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
008: * use this file except in compliance with the License. You may obtain a copy of
009: * the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
015: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
016: * License for the specific language governing permissions and limitations under
017: * the License.
018: */
019: package wicket.protocol.http;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: import wicket.AbortException;
025: import wicket.IRedirectListener;
026: import wicket.MetaDataKey;
027: import wicket.Page;
028: import wicket.RequestCycle;
029: import wicket.Response;
030: import wicket.RestartResponseAtInterceptPageException;
031: import wicket.Session;
032: import wicket.markup.html.pages.BrowserInfoPage;
033: import wicket.protocol.http.request.WebClientInfo;
034: import wicket.request.ClientInfo;
035: import wicket.request.IRequestCycleProcessor;
036: import wicket.settings.IRequestCycleSettings;
037:
038: /**
039: * RequestCycle implementation for HTTP protocol. Holds the application,
040: * session, request and response objects for a given HTTP request. Contains
041: * methods (urlFor*) which yield a URL for bookmarkable pages as well as
042: * non-bookmarkable component interfaces. The protected handleRender method is
043: * the internal entrypoint which takes care of the details of rendering a
044: * response to an HTTP request.
045: *
046: * @see RequestCycle
047: * @author Jonathan Locke
048: * @author Johan Compagner
049: * @author Gili Tzabari
050: * @author Eelco Hillenius
051: */
052: public class WebRequestCycle extends RequestCycle {
053: /** Logging object */
054: private static final Log log = LogFactory
055: .getLog(WebRequestCycle.class);
056:
057: private static final MetaDataKey BROWSER_WAS_POLLED_KEY = new MetaDataKey(
058: Boolean.class) {
059: private static final long serialVersionUID = 1L;
060: };
061:
062: /**
063: * Constructor which simply passes arguments to superclass for storage
064: * there.
065: *
066: * @param session
067: * The session
068: * @param request
069: * The request
070: * @param response
071: * The response
072: */
073: public WebRequestCycle(final WebSession session,
074: final WebRequest request, final Response response) {
075: super (session, request, response);
076: }
077:
078: /**
079: * By default returns the WebApplication's default request cycle processor.
080: * Typically, you don't override this method but instead override
081: * {@link WebApplication#getRequestCycleProcessor()}.
082: * <p>
083: * <strong>if you decide to override this method to provide a custom
084: * processor per request cycle, any mounts done via WebApplication will not
085: * work and and {@link #onRuntimeException(Page, RuntimeException)} is not
086: * called unless you deliberately put effort in it to make it work.</strong>
087: * </p>
088: *
089: * @see wicket.RequestCycle#getProcessor()
090: */
091: public IRequestCycleProcessor getProcessor() {
092: return ((WebApplication) getApplication())
093: .getRequestCycleProcessor();
094: }
095:
096: /**
097: * @return Request as a WebRequest
098: */
099: public WebRequest getWebRequest() {
100: return (WebRequest) request;
101: }
102:
103: /**
104: * @return Response as a WebResponse
105: */
106: public WebResponse getWebResponse() {
107: return (WebResponse) response;
108: }
109:
110: /**
111: * @return Session as a WebSession
112: */
113: public WebSession getWebSession() {
114: return (WebSession) session;
115: }
116:
117: /**
118: * Redirects browser to the given page. NOTE: Usually, you should never call
119: * this method directly, but work with setResponsePage instead. This method
120: * is part of Wicket's internal behavior and should only be used when you
121: * want to circumvent the normal framework behavior and issue the redirect
122: * directly.
123: *
124: * @param page
125: * The page to redirect to
126: */
127: public final void redirectTo(final Page page) {
128: String redirectUrl = null;
129:
130: // Check if use serverside response for client side redirects
131: IRequestCycleSettings settings = application
132: .getRequestCycleSettings();
133: if ((settings.getRenderStrategy() == IRequestCycleSettings.REDIRECT_TO_BUFFER)
134: && (application instanceof WebApplication)) {
135: // remember the current response
136: final WebResponse currentResponse = getWebResponse();
137: try {
138: // create the redirect response.
139: final BufferedHttpServletResponse servletResponse = new BufferedHttpServletResponse(
140: currentResponse.getHttpServletResponse());
141: final WebResponse redirectResponse = new WebResponse(
142: servletResponse) {
143: public CharSequence encodeURL(CharSequence url) {
144: return currentResponse.encodeURL(url);
145: }
146: };
147: redirectResponse.setCharacterEncoding(currentResponse
148: .getCharacterEncoding());
149:
150: // redirect the response to the buffer
151: setResponse(redirectResponse);
152:
153: // render the page into the buffer
154: page.renderPage();
155:
156: // re-assign the original response
157: setResponse(currentResponse);
158:
159: final String responseRedirect = servletResponse
160: .getRedirectUrl();
161: if (responseRedirect != null) {
162: // if the redirectResponse has another redirect url set
163: // then the rendering of this page caused a redirect to
164: // something else.
165: // set this redirect then.
166: redirectUrl = responseRedirect;
167: } else if (servletResponse.getContentLength() > 0) {
168: // call filter() so that any filters can process the
169: // response
170: servletResponse.filter(currentResponse);
171:
172: // Set the final character encoding before calling close
173: servletResponse
174: .setCharacterEncoding(currentResponse
175: .getCharacterEncoding());
176: // close it so that the reponse is fixed and encoded from
177: // here on.
178: servletResponse.close();
179:
180: redirectUrl = page.urlFor(
181: IRedirectListener.INTERFACE).toString();
182: int index = redirectUrl.indexOf("?");
183: String sessionId = getWebRequest()
184: .getHttpServletRequest().getSession(true)
185: .getId();
186: ((WebApplication) application).addBufferedResponse(
187: sessionId,
188: redirectUrl.substring(index + 1),
189: servletResponse);
190: }
191: } catch (RuntimeException ex) {
192: // re-assign the original response
193: setResponse(currentResponse);
194: if (ex instanceof AbortException)
195: throw ex;
196: log.error(ex.getMessage(), ex);
197: IRequestCycleProcessor processor = getProcessor();
198: processor.respond(ex, this );
199: return;
200: }
201: } else {
202: redirectUrl = page.urlFor(IRedirectListener.INTERFACE)
203: .toString();
204:
205: // Redirect page can touch its models already (via for example the
206: // constructors)
207: page.internalDetach();
208: }
209:
210: if (redirectUrl == null) {
211: redirectUrl = page.urlFor(IRedirectListener.INTERFACE)
212: .toString();
213: }
214:
215: // Always touch the page again so that a redirect listener makes a page
216: // statefull and adds it to the pagemap
217: session.touch(page);
218:
219: // Redirect to the url for the page
220: response.redirect(redirectUrl);
221: }
222:
223: /**
224: * @see wicket.RequestCycle#newClientInfo()
225: */
226: protected ClientInfo newClientInfo() {
227: if (getApplication().getRequestCycleSettings()
228: .getGatherExtendedBrowserInfo()) {
229: Session session = getSession();
230: if (session.getMetaData(BROWSER_WAS_POLLED_KEY) == null) {
231: // we haven't done the redirect yet; record that we will be
232: // doing that now and redirect
233: session.setMetaData(BROWSER_WAS_POLLED_KEY,
234: Boolean.TRUE);
235: throw new RestartResponseAtInterceptPageException(
236: new BrowserInfoPage(getRequest().getURL()));
237: }
238: // if we get here, the redirect already has been done; clear
239: // the meta data entry; we don't need it any longer is the client
240: // info object will be cached too
241: session.setMetaData(BROWSER_WAS_POLLED_KEY, (Boolean) null);
242: }
243: return new WebClientInfo(this );
244: }
245:
246: /**
247: * If it's an ajax request we always redirects.
248: *
249: * @see wicket.RequestCycle#getRedirect()
250: */
251: public final boolean getRedirect() {
252: if (getWebRequest().isAjax()) {
253: return true;
254: } else {
255: return super.getRedirect();
256: }
257: }
258: }
|