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