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.Locale;
018    
019    import org.apache.tapestry.event.ChangeObserver;
020    import org.apache.tapestry.event.PageAttachListener;
021    import org.apache.tapestry.event.PageBeginRenderListener;
022    import org.apache.tapestry.event.PageDetachListener;
023    import org.apache.tapestry.event.PageEndRenderListener;
024    import org.apache.tapestry.event.PageValidateListener;
025    import org.apache.tapestry.services.ResponseBuilder;
026    import org.apache.tapestry.util.ContentType;
027    
028    /**
029     * A root level component responsible for generating an entire a page within the application.
030     * <p>
031     * Pages are created dynamically from thier class names (part of the
032     * {@link org.apache.tapestry.spec.IComponentSpecification}).
033     * 
034     * @see org.apache.tapestry.engine.IPageSource
035     * @see org.apache.tapestry.engine.IPageLoader
036     * @author Howard Lewis Ship
037     */
038    
039    public interface IPage extends IComponent
040    {
041        /**
042         * Invoked on a page when it is no longer needed by the engine, just before is is returned to
043         * the pool. The page is expected to null the engine, visit and changeObserver properties.
044         * <p>
045         * Classes should also reset any properties to default values (as if the instance was freshly
046         * instantiated).
047         * 
048         * @see org.apache.tapestry.engine.IPageSource#releasePage(IPage)
049         */
050    
051        void detach();
052    
053        /**
054         * Returns the {@link IEngine}that the page is currently attached to.
055         */
056    
057        IEngine getEngine();
058    
059        /**
060         * Returns the object (effectively, an {@link org.apache.tapestry.engine.IPageRecorder}) that
061         * is notified of any changes to persistant properties of the page.
062         */
063    
064        ChangeObserver getChangeObserver();
065    
066        /**
067         * Returns the <code>Locale</code> of the page. The locale may be used to determine what
068         * template is used by the page and the components contained by the page.
069         */
070    
071        Locale getLocale();
072    
073        /**
074         * Updates the page's locale. This is write-once, a subsequent attempt will throw an
075         * {@link ApplicationRuntimeException}.
076         */
077    
078        void setLocale(Locale value);
079    
080        /**
081         * Returns the fully qualified name of the page, including its namespace prefix, if any.
082         * 
083         * @since 2.3
084         */
085    
086        String getPageName();
087    
088        /**
089         * Sets the name of the page.
090         * 
091         * @param pageName
092         *            fully qualified page name (including namespace prefix, if any)
093         * @since 3.0
094         */
095    
096        void setPageName(String pageName);
097    
098        /**
099         * Returns a particular component from within the page. The path is a dotted name sequence
100         * identifying the component. It may be null in which case the page returns itself.
101         * 
102         * @exception ApplicationRuntimeException
103         *                runtime exception thrown if the path does not identify a component.
104         */
105    
106        IComponent getNestedComponent(String path);
107    
108        /**
109         * Attaches the page to the {@link IEngine engine}. This method is used when a pooled page is
110         * claimed for use with a particular engine; it will stay attached to the engine until the end
111         * of the current request cycle, then be returned to the pool.
112         * <p>
113         * This method will notify any {@link PageAttachListener}s.
114         * <p>
115         * This method is rarely overriden; to initialize page properties before a render, implement the
116         * {@link PageBeginRenderListener}interface.
117         */
118    
119        void attach(IEngine engine, IRequestCycle cycle);
120    
121        /**
122         * Used to explicitly fire {@link PageAttachListener}s for this page. This is used when a page
123         * is first loaded; The page loader attaches the newly created page <em>instance</em> before
124         * the rest of the page and components is loaded. In order to have meaningful event
125         * notifications when a page is first loaded (rather than pulled from the pool), it is necessary
126         * to fire page attach listeners at the end of the load.
127         * 
128         * @since 4.0
129         */
130    
131        void firePageAttached();
132    
133        /**
134         * Invoked to render the entire page. This should only be invoked by
135         * {@link IRequestCycle#renderPage(ResponseBuilder builder)}.
136         * <p>
137         * The page performs a render using the following steps:
138         * <ul>
139         * <li>Invokes
140         * {@link PageBeginRenderListener#pageBeginRender(org.apache.tapestry.event.PageEvent)}
141         * <li>Invokes {@link #beginResponse(IMarkupWriter, IRequestCycle)}
142         * <li>Invokes {@link IRequestCycle#commitPageChanges()}(if not rewinding)
143         * <li>Invokes {@link #render(IMarkupWriter, IRequestCycle)}
144         * <li>Invokes {@link PageEndRenderListener#pageEndRender(org.apache.tapestry.event.PageEvent)}
145         * (this occurs even if a previous step throws an exception).
146         * </ul>
147         */
148    
149        void renderPage(ResponseBuilder builder, IRequestCycle cycle);
150    
151        /**
152         * Invoked before a partial render of the page occurs (this happens when rewinding a
153         * {@link org.apache.tapestry.form.Form}within the page). The page is expected to fire
154         * appopriate events.
155         * 
156         * @since 2.2
157         */
158    
159        void beginPageRender();
160    
161        /**
162         * Invoked after a partial render of the page occurs (this happens when rewinding a
163         * {@link org.apache.tapestry.form.Form}within the page). The page is expected to fire
164         * appropriate events.
165         * 
166         * @since 2.2
167         */
168    
169        void endPageRender();
170    
171        void setChangeObserver(ChangeObserver value);
172    
173        /**
174         * Method invoked by the page, action and direct services to validate that the user is allowed
175         * to visit the page.
176         * <p>
177         * Most web applications have a concept of 'logging in' and pages that an anonymous (not logged
178         * in) user should not be able to visit directly. This method acts as the first line of defense
179         * against a malicous user hacking URLs.
180         * <p>
181         * Pages that should be protected will typically throw a {@linkPageRedirectException}, to
182         * redirect the user to an appropriate part of the system (such as, a login page).
183         * <p>
184         * Since 3.0, it is easiest to not override this method, but to implement the
185         * {@link PageValidateListener}interface instead.
186         */
187    
188        void validate(IRequestCycle cycle);
189    
190        /**
191         * Invoked to obtain the content type to be used for the response. The implementation of this
192         * method is the primary difference between an HTML page and an XML/WML/etc. page.
193         */
194    
195        ContentType getResponseContentType();
196    
197        /**
198         * Invoked just before rendering of the page is initiated. This gives the page a chance to
199         * perform any additional setup. One possible behavior is to set HTTP headers and cookies before
200         * any output is generated.
201         * <p>
202         * The timing of this explicitly <em>before</em>
203         * {@link org.apache.tapestry.engine.IPageRecorder page recorder}changes are committed.
204         * Rendering occurs <em>after</em> the recorders are committed, when it is too late to make
205         * changes to dynamic page properties.
206         */
207    
208        void beginResponse(IMarkupWriter writer, IRequestCycle cycle);
209    
210        /**
211         * Returns the current {@link IRequestCycle}. This is set when the page is loaded (or obtained
212         * from the pool) and attached to the {@link IEngine engine}.
213         */
214    
215        IRequestCycle getRequestCycle();
216    
217        /** @since 4.0 */
218        void addPageBeginRenderListener(PageBeginRenderListener listener);
219    
220        /** @since 4.0 */
221        void removePageBeginRenderListener(PageBeginRenderListener listener);
222    
223        /** @since 4.0 */
224    
225        void addPageEndRenderListener(PageEndRenderListener listener);
226    
227        /** @since 4.0 */
228    
229        void removePageEndRenderListener(PageEndRenderListener listener);
230    
231        /**
232         * @since 1.0.5
233         */
234    
235        void addPageDetachListener(PageDetachListener listener);
236    
237        /**
238         * @since 2.1
239         */
240    
241        void removePageDetachListener(PageDetachListener listener);
242    
243        /**
244         * @since 3.0
245         */
246    
247        void addPageValidateListener(PageValidateListener listener);
248    
249        /**
250         * @since 3.0
251         */
252    
253        void removePageValidateListener(PageValidateListener listener);
254    
255        /** @since 4.0 */
256    
257        void addPageAttachListener(PageAttachListener listener);
258    
259        /** @since 4.0 */
260    
261        void removePageAttachListener(PageAttachListener listener);
262    }