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 java.util.Iterator;
018
019 import org.apache.tapestry.engine.IEngineService;
020 import org.apache.tapestry.services.Infrastructure;
021 import org.apache.tapestry.services.ResponseBuilder;
022
023 /**
024 * Controller object that manages a single request cycle. A request cycle is one 'hit' on the web
025 * server. In the case of a Tapestry application, this will involve:
026 * <ul>
027 * <li>Responding to the URL by finding an {@link IEngineService}object
028 * <li>Determining the result page
029 * <li>Renderring the result page
030 * <li>Releasing any resources
031 * </ul>
032 * <p>
033 * Mixed in with this is:
034 * <ul>
035 * <li>Exception handling
036 * <li>Loading of pages and templates from resources
037 * <li>Tracking changes to page properties, and restoring pages to prior states
038 * <li>Pooling of page objects
039 * </ul>
040 *
041 * <p>
042 * A request cycle is broken up into two phases. The <em>rewind</em> phase is optional, as it tied
043 * to {@link org.apache.tapestry.link.ActionLink}or {@link org.apache.tapestry.form.Form}
044 * components. In the rewind phase, a previous page render is redone (discarding output) until a
045 * specific component of the page is reached. This rewinding ensures that the page is restored to
046 * the exact state it had when the URL for the request cycle was generated, taking into account the
047 * dynamic nature of the page ({@link org.apache.tapestry.components.Foreach},
048 * {@link org.apache.tapestry.components.Conditional}, etc.). Once this component is reached, it
049 * can notify its {@link IActionListener}. The listener has the ability to update the state of any
050 * pages and select a new result page.
051 * </p>
052 *
053 * <p>
054 * Following the rewind phase is the <em>render</em> phase. During the render phase, a page is
055 * actually rendered and output sent to the client web browser.
056 * </p>
057 * @author Howard Lewis Ship
058 */
059
060 public interface IRequestCycle
061 {
062 /**
063 * Invoked after the request cycle is no longer needed, to release any resources it may have.
064 * This includes releasing any loaded pages back to the page source.
065 */
066
067 void cleanup();
068
069 /**
070 * Passes the String through
071 * {@link javax.servlet.http.HttpServletResponse#encodeURL(java.lang.String)}, which ensures
072 * that the session id is encoded in the URL (if necessary).
073 */
074
075 String encodeURL(String URL);
076
077 /**
078 * Returns the engine which is processing this request cycle.
079 */
080
081 IEngine getEngine();
082
083 /**
084 * Retrieves a previously stored attribute, returning null if not found. Attributes allow
085 * components to locate each other; primarily they allow a wrapped component to locate a
086 * component which wraps it. Attributes are cleared at the end of the render (or rewind).
087 */
088
089 Object getAttribute(String name);
090
091 /**
092 * Identifies the active page, the page which will ultimately render the response.
093 */
094
095 IPage getPage();
096
097 /**
098 * Returns the page with the given name. If the page has been previously loaded in the current
099 * request cycle, that page is returned. Otherwise, the engine's page loader is used to load the
100 * page.
101 *
102 * @throws PageNotFoundException
103 * if the page does not exist.
104 * @see org.apache.tapestry.engine.IPageSource#getPage(IRequestCycle, String, IMonitor)
105 */
106
107 IPage getPage(String name);
108
109 /**
110 * Returns true if the context is being used to rewind a prior state of the page. This is only
111 * true when there is a target action id.
112 */
113
114 boolean isRewinding();
115
116 /**
117 * Checks to see if the current action id matches the target action id. Returns true only if
118 * they match. Returns false if there is no target action id (that is, during page rendering).
119 * <p>
120 * If theres a match on action id, then the component is compared against the target component.
121 * If there's a mismatch then a {@link StaleLinkException}is thrown.
122 */
123
124 boolean isRewound(IComponent component);
125
126 /**
127 * Sets the {@link ResponseBuilder} to use for this response, don't
128 * try setting this unless you're very sure you know what you are doing as
129 * this isn't the only way that it is used. (ie replacing this builder won't
130 * necessarily override another builder being used already)
131 *
132 * @param builder The response builder that may be used by components
133 * to help with delegate/sub component rendering.
134 */
135 void setResponseBuilder(ResponseBuilder builder);
136
137 /**
138 * Entry point for getting the response builder used to build
139 * this response.
140 * @return The response builder used for this response.
141 */
142 ResponseBuilder getResponseBuilder();
143
144 /**
145 * Tests if the render component chain is empty, meaning no components have
146 * been loaded onto the stack yet.
147 *
148 * @return True, if the current stack is empty.
149 */
150 boolean renderStackEmpty();
151
152 /**
153 * Looks at the object at the top of the render stack without removing
154 * the {@link IRender} from the stack.
155 *
156 * @return The last (parent) item added to the current render stack.
157 */
158 IRender renderStackPeek();
159
160 /**
161 * Removes the {@link IRender} at the top of the stack, if any.
162 *
163 * @return The removed {@link IRender}, if any.
164 */
165 IRender renderStackPop();
166
167 /**
168 * Pushes the specified render onto the current render stack.
169 *
170 * @param render The {@link IRender} object being pushed.
171 * @return The added {@link IRender}.
172 */
173 IRender renderStackPush(IRender render);
174
175 /**
176 * Returns the 1-based position where an object is on this stack. If the object
177 * o occurs as an item in this stack, this method returns the distance from the
178 * top of the stack of the occurrence nearest the top of the stack; the topmost
179 * item on the stack is considered to be at distance 1. The equals method is used
180 * to compare o to the items in this stack.
181 *
182 * @param render The {@link IRender} being searched for.
183 *
184 * @return the 1-based position from the top of the stack where the object is
185 * located; the return value -1 indicates that the object is not on the stack.
186 */
187 int renderStackSearch(IRender render);
188
189 /**
190 * Creates a traversable iterator for moving through the stack.
191 *
192 * @return An iterator over the current stack.
193 */
194 Iterator renderStackIterator();
195
196 /**
197 * Removes a previously stored attribute, if one with the given name exists.
198 */
199
200 void removeAttribute(String name);
201
202 /**
203 * Renders the given page. Applications should always use this method to render the page, rather
204 * than directly invoking {@link IPage#render(IMarkupWriter, IRequestCycle)}since the request
205 * cycle must perform some setup before rendering.
206 */
207
208 void renderPage(ResponseBuilder builder);
209
210 /**
211 * Allows a temporary object to be stored in the request cycle, which allows otherwise unrelated
212 * objects to communicate. This is similar to <code>HttpServletRequest.setAttribute()</code>,
213 * except that values can be changed and removed as well.
214 * <p>
215 * This is used by components to locate each other. A component, such as
216 * {@link org.apache.tapestry.html.Body}, will write itself under a well-known name into the
217 * request cycle, and components it wraps can locate it by that name.
218 * <p>
219 * Attributes are cleared at the end of each render or rewind phase.
220 */
221
222 void setAttribute(String name, Object value);
223
224 /**
225 * Invoked just before rendering the response page to get all
226 * {@link org.apache.tapestry.engine.IPageRecorder page recorders}touched in this request cycle
227 * to commit their changes (save them to persistant storage).
228 *
229 * @see org.apache.tapestry.engine.IPageRecorder#commit()
230 */
231
232 void commitPageChanges();
233
234 /**
235 * Returns the service which initiated this request cycle.
236 *
237 * @since 1.0.1
238 */
239
240 IEngineService getService();
241
242 /**
243 * Used by {@link IForm forms}to perform a <em>partial</em> rewind so as to respond to the
244 * form submission (using the direct service).
245 * <p>
246 * Note: the targetActionId parameter was removed in release 4.0.
247 *
248 * @since 1.0.2
249 */
250
251 void rewindForm(IForm form);
252
253 /**
254 * Invoked by a {@link IEngineService service} to store an array of application-specific
255 * parameters. These can later be retrieved (typically, by an application-specific listener
256 * method) by invoking {@link #getListenerParameters()}.
257 *
258 * @see org.apache.tapestry.engine.DirectService
259 * @since 4.0
260 */
261 void setListenerParameters(Object[] parameters);
262
263 /**
264 * Returns parameters previously stored by {@link #setListenerParameters(Object[])}.
265 *
266 * @since 4.0
267 */
268
269 Object[] getListenerParameters();
270
271 /**
272 * A convienience for invoking {@link #activate(IPage)}. Invokes {@link #getPage(String)}to
273 * get an instance of the named page.
274 *
275 * @since 3.0
276 */
277
278 void activate(String name);
279
280 /**
281 * Sets the active page for the request. The active page is the page which will ultimately
282 * render the response. The activate page is typically set by the {@link IEngineService service}.
283 * Frequently, the active page is changed (from a listener method) to choose an alternate page
284 * to render the response).
285 * <p>
286 * {@link IPage#validate(IRequestCycle)}is invoked on the page to be activated.
287 * {@link PageRedirectException}is caught and the page specified in the exception will be the
288 * active page instead (that is, a page may "pass the baton" to another page using the
289 * exception). The new page is also validated. This continues until a page does not throw
290 * {@link PageRedirectException}.
291 * <p>
292 * Validation loops can occur, where page A redirects to page B and then page B redirects back
293 * to page A (possibly with intermediate steps). This is detected and results in an
294 * {@link ApplicationRuntimeException}.
295 *
296 * @since 3.0
297 */
298 void activate(IPage page);
299
300 /**
301 * Returns a query parameter value, or null if not provided in the request. If multiple values
302 * are provided, returns the first value.
303 *
304 * @since 4.0
305 */
306 String getParameter(String name);
307
308 /**
309 * Returns all query parameter values for the given name. Returns null if no values were
310 * provided.
311 *
312 * @since 4.0
313 */
314 String[] getParameters(String name);
315
316 /**
317 * Converts a partial URL into an absolute URL. Prefixes the provided URL with servlet context
318 * path (if any), then expands it to a full URL by prepending with the scheme, server and port
319 * (determined from the current {@link org.apache.tapestry.web.WebRequest request}.
320 *
321 * @since 4.0
322 */
323
324 String getAbsoluteURL(String partialURL);
325
326 /**
327 * Forgets any stored changes to the specified page. If the page has already been loaded (and
328 * rolled back) then the loaded page instance is not affected; if the page is only loaded
329 * subsequently, the page instance will not see any persisted property changes.
330 *
331 * @since 4.0
332 */
333
334 void forgetPage(String name);
335
336 /**
337 * Returns the central {@link org.apache.tapestry.services.Infrastructure} object used to
338 * manage the processing of the request.
339 *
340 * @since 4.0
341 */
342
343 Infrastructure getInfrastructure();
344
345 /**
346 * Returns the provided string, possibly modified (with an appended suffix) to make it unique.
347 *
348 * @param baseId
349 * the base id from which to generate the unique string.
350 * @return baseId, or baseId with a suffix appended (if the method has been previously invoked
351 * with the same baseId).
352 */
353
354 String getUniqueId(String baseId);
355
356 /**
357 * Sends a redirect to the client web browser. This is currently a convinience for constructing
358 * and throwing a {@link RedirectException}, but may change in a later release.
359 *
360 * @since 4.0
361 * @throws RedirectException
362 */
363
364 void sendRedirect(String URL);
365 }