001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package com.sun.jsfcl.app;
043:
044: import java.util.Iterator;
045: import java.util.Map;
046: import javax.faces.context.FacesContext;
047: import javax.faces.component.UIViewRoot;
048: import javax.faces.event.PhaseEvent;
049: import javax.faces.event.PhaseId;
050: import javax.faces.lifecycle.Lifecycle;
051:
052: /**
053: * <p><strong>AbstractPageBean</strong> is the abstract base class for every
054: * page bean associated with a JSP page containing JavaServer Faces
055: * components. It extends {@link FacesBean}, so it inherits all of the
056: * default behavior found there.</p>
057: *
058: * <p>In addition to event handler methods that you create while building
059: * your application, the runtime environment will also call the following
060: * <em>lifecycle</em> related methods at appropriate points during the execution
061: * of your application:</p>
062: * <ul>
063: * <li><strong>init()</strong> - Called whenever you navigate to the
064: * corresponding JSP page, either directly (via a URL) or indirectly
065: * via page navigation from a different page. You can override this
066: * method to acquire any resources that will always be needed by this
067: * page.</li>
068: * <li><strong>preprocess()</strong> - If this request is a postback (i.e.
069: * your page is about to process an incoming form submit, this method
070: * will be called after the original component tree has been restored,
071: * but before any standard JavaServer Faces event processing is done
072: * (i.e. this is called before <em>Apply Request Values</em> phase of
073: * the request processing lifecycle). Override this method to acquire
074: * any resources that will be needed by event handlers (such as action
075: * methods, validator methods, or value change listener methods) that
076: * will be executed while executing the request processing lifecycle.</li>
077: * <li><strong>prerender()</strong> - If this page is the one that will be
078: * rendering the response, this method is called <em>after</em> any event
079: * processing, but before the actual rendering. Override this method to
080: * acquire resources that are only needed when a page is being rendered.
081: * </li>
082: * <li><strong>destroy()</strong> - Called unconditionally if
083: * <code>init()</code> was called, after completion of rendering by
084: * whichever page was actually rendered. Override this method to release
085: * any resources allocated in the <code>init()</code>,
086: * <code>preprocess()</code>, or <code>prerender()</code>
087: * methods (or in an event handler).</li>
088: * </ul>
089: */
090: public abstract class AbstractPageBean extends FacesBean {
091:
092: // ------------------------------------------------------ Instance Variables
093:
094: /**
095: * <p>The <code>FacesContext</code> instance for the request this
096: * <code>AbstractPageBean</code> is associated with.</p>
097: */
098: private FacesContext context = null;
099:
100: // ------------------------------------------------------------- Constructor
101:
102: /**
103: * <p>Register this bean as a <code>PhaseListener</code> so that it can
104: * participate in the request processing lifecycle of each request.</p>
105: */
106: public AbstractPageBean() {
107:
108: // Register to receive phase events ourselves
109: Lifecycle lifecycle = getLifecycle();
110: lifecycle.addPhaseListener(this );
111:
112: // Remember which FacesContext we are processing so that
113: // we can filter out irrelevant events later
114: context = FacesContext.getCurrentInstance();
115:
116: }
117:
118: // --------------------------------------------------- PhaseListener Methods
119:
120: /**
121: * <p>If this event is for the request associated with this
122: * page bean, call through to the appropriate "before" lifecycle
123: * method for this page bean, and notify interested session bean
124: * and application bean instances as well.</p>
125: *
126: * @param event <code>PhaseEvent</code> to be processed
127: */
128: public void beforePhase(PhaseEvent event) {
129:
130: // Does this event apply to this page bean instance?
131: if (context != FacesContext.getCurrentInstance()) {
132: return; // This is not our request
133: }
134:
135: // Call through to the appropriate handler on this page bean
136: super .beforePhase(event);
137:
138: // Call through to any session beans in our associated session
139: Map map = event.getFacesContext().getExternalContext()
140: .getSessionMap();
141: Iterator keys = map.keySet().iterator();
142: while (keys.hasNext()) {
143: String key = (String) keys.next();
144: Object value = map.get(key);
145: if (value instanceof AbstractSessionBean) {
146: ((AbstractSessionBean) value).beforePhase(event);
147: }
148: }
149:
150: // Call through to any application bean
151: map = event.getFacesContext().getExternalContext()
152: .getApplicationMap();
153: keys = map.keySet().iterator();
154: while (keys.hasNext()) {
155: String key = (String) keys.next();
156: Object value = map.get(key);
157: if (value instanceof AbstractApplicationBean) {
158: ((AbstractApplicationBean) value).beforePhase(event);
159: }
160: }
161:
162: }
163:
164: /**
165: * <p>If this event is for the request associated with this
166: * page bean, call through to the appropriate "after" lifecycle
167: * method for this page bean, and notify interested session bean
168: * and application bean instances as well. Then, if this is
169: * Render Response phase, deregister ourselves as a listener.</p>
170: *
171: * @param event <code>PhaseEvent</code> to be processed
172: */
173: public void afterPhase(PhaseEvent event) {
174:
175: // Does this event apply to this page bean instance?
176: if (context != FacesContext.getCurrentInstance()) {
177: return; // This is not our request
178: }
179:
180: // Call through to the appropriate handler on this page bean
181: super .afterPhase(event);
182:
183: // Call through to any session beans in our associated session
184: Map map = event.getFacesContext().getExternalContext()
185: .getSessionMap();
186: Iterator keys = map.keySet().iterator();
187: while (keys.hasNext()) {
188: String key = (String) keys.next();
189: Object value = map.get(key);
190: if (value instanceof AbstractSessionBean) {
191: ((AbstractSessionBean) value).afterPhase(event);
192: }
193: }
194:
195: // Call through to any application bean
196: map = event.getFacesContext().getExternalContext()
197: .getApplicationMap();
198: keys = map.keySet().iterator();
199: while (keys.hasNext()) {
200: String key = (String) keys.next();
201: Object value = map.get(key);
202: if (value instanceof AbstractApplicationBean) {
203: ((AbstractApplicationBean) value).afterPhase(event);
204: }
205: }
206:
207: // AFter render response phase, deregister ourselves as a listener
208: if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
209: getLifecycle().removePhaseListener(this );
210: context = null; // We do not need our reference any longer
211: }
212:
213: }
214:
215: // ------------------------------------------------------- Lifecycle Methods
216:
217: /**
218: * <p>Callback method that is called whenever a page is navigated to,
219: * either directly via a URL, or indirectly via page navigation.
220: * Override this method to acquire resources that will be needed
221: * for event handlers and lifecycle methods, whether or not this
222: * page is performing post back processing. Note that this method
223: * is called <strong>before</strong> the component tree has been
224: * restored, so you do not have access to any information from the
225: * JavaServer Faces components on this page.</p>
226: *
227: * <p>The default implementation does nothing.</p>
228: */
229: protected void init() {
230: ;
231: }
232:
233: /**
234: * <p>Callback method that is called after the component tree has been
235: * restored, but before any event processing takes place. This method
236: * will <strong>only</strong> be called on a "post back" request that
237: * is processing a form submit. Override this method to allocate
238: * resources that will be required in your event handlers.</p>
239: *
240: * <p>The default implementation does nothing.</p>
241: */
242: protected void preprocess() {
243: ;
244: }
245:
246: /**
247: * <p>Callback method that is called just before rendering takes place.
248: * This method will <strong>only</strong> be called for the page that
249: * will actually be rendered (and not, for example, on a page that
250: * handled a post back and then navigated to a different page). Override
251: * this method to allocate resources that will be required for rendering
252: * this page.</p>
253: *
254: * <p>The default implementation does nothing.</p>
255: */
256: protected void prerender() {
257: ;
258: }
259:
260: /**
261: * <p>Callback method that is called after rendering is completed for
262: * this request, if <code>init()</code> was called, regardless of whether
263: * or not this was the page that was actually rendered. Override this
264: * method to release resources acquired in the <code>init()</code>,
265: * <code>preprocess()</code>, or <code>prerender()</code> methods (or
266: * acquired during execution of an event handler).</p>
267: *
268: * <p>The default implementation does nothing.</p>
269: */
270: protected void destroy() {
271: ;
272: }
273:
274: // --------------------------------------------------------- Private Methods
275:
276: }
|