001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry;
016    
017    import org.apache.tapestry.engine.IEngineService;
018    import org.apache.tapestry.engine.IMonitor;
019    import org.apache.tapestry.request.RequestContext;
020    import org.apache.tapestry.services.Infrastructure;
021    
022    /**
023     * Controller object that manages a single request cycle. A request cycle is one 'hit' on the web
024     * server. In the case of a Tapestry application, this will involve:
025     * <ul>
026     * <li>Responding to the URL by finding an {@link IEngineService}object
027     * <li>Determining the result page
028     * <li>Renderring the result page
029     * <li>Releasing any resources
030     * </ul>
031     * <p>
032     * Mixed in with this is:
033     * <ul>
034     * <li>Exception handling
035     * <li>Loading of pages and templates from resources
036     * <li>Tracking changes to page properties, and restoring pages to prior states
037     * <li>Pooling of page objects
038     * </ul>
039     * <p>
040     * A request cycle is broken up into two phases. The <em>rewind</em> phase is optional, as it tied
041     * to {@link org.apache.tapestry.link.ActionLink}or {@link org.apache.tapestry.form.Form}
042     * components. In the rewind phase, a previous page render is redone (discarding output) until a
043     * specific component of the page is reached. This rewinding ensures that the page is restored to
044     * the exact state it had when the URL for the request cycle was generated, taking into account the
045     * dynamic nature of the page ({@link org.apache.tapestry.components.Foreach},
046     * {@link org.apache.tapestry.components.Conditional}, etc.). Once this component is reached, it
047     * can notify its {@link IActionListener}. The listener has the ability to update the state of any
048     * pages and select a new result page.
049     * <p>
050     * Following the rewind phase is the <em>render</em> phase. During the render phase, a page is
051     * actually rendered and output sent to the client web browser.
052     * 
053     * @author Howard Lewis Ship
054     */
055    
056    public interface IRequestCycle
057    {
058        /**
059         * Invoked after the request cycle is no longer needed, to release any resources it may have.
060         * This includes releasing any loaded pages back to the page source.
061         */
062    
063        public void cleanup();
064    
065        /**
066         * Passes the String through
067         * {@link javax.servlet.http.HttpServletResponse#encodeURL(java.lang.String)}, which ensures
068         * that the session id is encoded in the URL (if necessary).
069         */
070    
071        public String encodeURL(String URL);
072    
073        /**
074         * Returns the engine which is processing this request cycle.
075         */
076    
077        public IEngine getEngine();
078    
079        /**
080         * Retrieves a previously stored attribute, returning null if not found. Attributes allow
081         * components to locate each other; primarily they allow a wrapped component to locate a
082         * component which wraps it. Attributes are cleared at the end of the render (or rewind).
083         */
084    
085        public Object getAttribute(String name);
086    
087        public IMonitor getMonitor();
088    
089        /**
090         * Returns the next action id. ActionLink ids are used to identify different actions on a page
091         * (URLs that are related to dynamic page state).
092         * 
093         * @deprecated To be removed in release 4.1 with no replacement.
094         * @see #getUniqueId(String)
095         */
096    
097        public String getNextActionId();
098    
099        /**
100         * Identifies the active page, the page which will ultimately render the response.
101         */
102    
103        public IPage getPage();
104    
105        /**
106         * Returns the page with the given name. If the page has been previously loaded in the current
107         * request cycle, that page is returned. Otherwise, the engine's page loader is used to load the
108         * page.
109         * 
110         * @throws PageNotFoundException
111         *             if the page does not exist.
112         * @see org.apache.tapestry.engine.IPageSource#getPage(IRequestCycle, String, IMonitor)
113         */
114    
115        public IPage getPage(String name);
116    
117        /**
118         * Returns true if the context is being used to rewind a prior state of the page. This is only
119         * true when there is a target action id.
120         */
121    
122        public boolean isRewinding();
123    
124        /**
125         * Checks to see if the current action id matches the target action id. Returns true only if
126         * they match. Returns false if there is no target action id (that is, during page rendering).
127         * <p>
128         * If theres a match on action id, then the component is compared against the target component.
129         * If there's a mismatch then a {@link StaleLinkException}is thrown.
130         */
131    
132        public boolean isRewound(IComponent component) throws StaleLinkException;
133    
134        /**
135         * Removes a previously stored attribute, if one with the given name exists.
136         */
137    
138        public void removeAttribute(String name);
139    
140        /**
141         * Renders the given page. Applications should always use this method to render the page, rather
142         * than directly invoking {@link IPage#render(IMarkupWriter, IRequestCycle)}since the request
143         * cycle must perform some setup before rendering.
144         */
145    
146        public void renderPage(IMarkupWriter writer);
147    
148        /**
149         * Rewinds a page and executes some form of action when the component with the specified action
150         * id is reached.
151         * 
152         * @see IAction
153         * @see org.apache.tapestry.link.ActionLink
154         * @deprecated To be removed in 4.1 with no replacement.
155         */
156    
157        public void rewindPage(String targetActionId, IComponent targetComponent);
158    
159        /**
160         * Allows a temporary object to be stored in the request cycle, which allows otherwise unrelated
161         * objects to communicate. This is similar to <code>HttpServletRequest.setAttribute()</code>,
162         * except that values can be changed and removed as well.
163         * <p>
164         * This is used by components to locate each other. A component, such as
165         * {@link org.apache.tapestry.html.Body}, will write itself under a well-known name into the
166         * request cycle, and components it wraps can locate it by that name.
167         * <p>
168         * Attributes are cleared at the end of each render or rewind phase.
169         */
170    
171        public void setAttribute(String name, Object value);
172    
173        /**
174         * Invoked just before rendering the response page to get all
175         * {@link org.apache.tapestry.engine.IPageRecorder page recorders}touched in this request cycle
176         * to commit their changes (save them to persistant storage).
177         * 
178         * @see org.apache.tapestry.engine.IPageRecorder#commit()
179         */
180    
181        public void commitPageChanges();
182    
183        /**
184         * Returns the service which initiated this request cycle.
185         * 
186         * @since 1.0.1
187         */
188    
189        public IEngineService getService();
190    
191        /**
192         * Used by {@link IForm forms}to perform a <em>partial</em> rewind so as to respond to the
193         * form submission (using the direct service).
194         * <p>
195         * Note: the targetActionId parameter was removed in release 4.0.
196         * 
197         * @since 1.0.2
198         */
199    
200        public void rewindForm(IForm form);
201    
202        /**
203         * Much like {@link #forgetPage(String)}, but the page stays active and can even record
204         * changes, until the end of the request cycle, at which point it is discarded (and any recorded
205         * changes are lost). This is used in certain rare cases where a page has persistent state but
206         * is being renderred "for the last time".
207         * 
208         * @since 2.0.2
209         * @deprecated To be removed in 4.1. Use {@link #forgetPage(String)}.
210         */
211    
212        public void discardPage(String name);
213    
214        /**
215         * Invoked by a {@link IEngineService service} to store an array of application-specific
216         * parameters. These can later be retrieved (typically, by an application-specific listener
217         * method) by invoking {@link #getServiceParameters()}.
218         * <p>
219         * Through release 2.1, parameters was of type String[]. This is an incompatible change in 2.2.
220         * 
221         * @see org.apache.tapestry.engine.DirectService
222         * @since 2.0.3
223         * @deprecated To be removed in 4.1. Use {@link #setListenerParameters(Object[])}instead.
224         */
225    
226        public void setServiceParameters(Object[] parameters);
227    
228        /**
229         * Invoked by a {@link IEngineService service} to store an array of application-specific
230         * parameters. These can later be retrieved (typically, by an application-specific listener
231         * method) by invoking {@link #getListenerParameters()}.
232         * 
233         * @see org.apache.tapestry.engine.DirectService
234         * @since 4.0
235         */
236        public void setListenerParameters(Object[] parameters);
237    
238        /**
239         * Returns parameters previously stored by {@link #setServiceParameters(Object[])}.
240         * <p>
241         * Through release 2.1, the return type was String[]. This is an incompatible change in 2.2.
242         * 
243         * @since 2.0.3
244         * @deprecated To be removed in 4.1. Use {@link #getListenerParameters()}instead.
245         */
246    
247        public Object[] getServiceParameters();
248    
249        /**
250         * Returns parameters previously stored by {@link #setListenerParameters(Object[])}.
251         * 
252         * @since 4.0
253         */
254    
255        public Object[] getListenerParameters();
256    
257        /**
258         * A convienience for invoking {@link #activate(IPage)}. Invokes {@link #getPage(String)}to
259         * get an instance of the named page.
260         * 
261         * @since 3.0
262         */
263    
264        public void activate(String name);
265    
266        /**
267         * Sets the active page for the request. The active page is the page which will ultimately
268         * render the response. The activate page is typically set by the {@link IEngineService service}.
269         * Frequently, the active page is changed (from a listener method) to choose an alternate page
270         * to render the response).
271         * <p>
272         * {@link IPage#validate(IRequestCycle)}is invoked on the page to be activated.
273         * {@link PageRedirectException}is caught and the page specified in the exception will be the
274         * active page instead (that is, a page may "pass the baton" to another page using the
275         * exception). The new page is also validated. This continues until a page does not throw
276         * {@link PageRedirectException}.
277         * <p>
278         * Validation loops can occur, where page A redirects to page B and then page B redirects back
279         * to page A (possibly with intermediate steps). This is detected and results in an
280         * {@link ApplicationRuntimeException}.
281         * 
282         * @since 3.0
283         */
284        public void activate(IPage page);
285    
286        /**
287         * Returns a query parameter value, or null if not provided in the request. If multiple values
288         * are provided, returns the first value.
289         * 
290         * @since 4.0
291         */
292        public String getParameter(String name);
293    
294        /**
295         * Returns all query parameter values for the given name. Returns null if no values were
296         * provided.
297         * 
298         * @since 4.0
299         */
300        public String[] getParameters(String name);
301    
302        /**
303         * Converts a partial URL into an absolute URL. Prefixes the provided URL with servlet context
304         * path (if any), then expands it to a full URL by prepending with the scheme, server and port
305         * (determined from the current {@link org.apache.tapestry.web.WebRequest request}.
306         * 
307         * @since 4.0
308         */
309    
310        public String getAbsoluteURL(String partialURL);
311    
312        /**
313         * Forgets any stored changes to the specified page. If the page has already been loaded (and
314         * rolled back) then the loaded page instance is not affected; if the page is only loaded
315         * subsequently, the page instance will not see any persisted property changes.
316         * 
317         * @since 4.0
318         */
319    
320        public void forgetPage(String name);
321    
322        /**
323         * Returns the central {@link org.apache.tapestry.services.Infrastructure} object used to
324         * manage the processing of the request.
325         * 
326         * @since 4.0
327         */
328    
329        public Infrastructure getInfrastructure();
330    
331        /**
332         * Returns the {@link RequestContext}. This is provided to ease the upgrade from Tapestry 3.0.
333         * 
334         * @deprecated To be removed in 4.1.
335         */
336    
337        public RequestContext getRequestContext();
338    
339        /**
340         * Returns the provided string, possibly modified (with an appended suffix) to make it unique.
341         * 
342         * @param baseId
343         *            the base id from which to generate the unique string.
344         * @return baseId, or baseId with a suffix appended (if the method has been previously invoked
345         *         with the same baseId).
346         */
347    
348        public String getUniqueId(String baseId);
349    
350        /**
351         * Sends a redirect to the client web browser. This is currently a convinience for constructing
352         * and throwing a {@link RedirectException}, but may change in a later release.
353         * 
354         * @since 4.0
355         * @throws RedirectException
356         */
357    
358        public void sendRedirect(String URL);
359    }