KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icesoft > faces > webapp > xmlhttp > PersistentFacesState


1 /*
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * "The contents of this file are subject to the Mozilla Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
11  * License for the specific language governing rights and limitations under
12  * the License.
13  *
14  * The Original Code is ICEfaces 1.5 open source software code, released
15  * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
16  * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
17  * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
18  *
19  * Contributor(s): _____________________.
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
23  * License), in which case the provisions of the LGPL License are
24  * applicable instead of those above. If you wish to allow use of your
25  * version of this file only under the terms of the LGPL License and not to
26  * allow others to use your version of this file under the MPL, indicate
27  * your decision by deleting the provisions above and replace them with
28  * the notice and other provisions required by the LGPL License. If you do
29  * not delete the provisions above, a recipient may use your version of
30  * this file under either the MPL or the LGPL License."
31  *
32  */

33
34 package com.icesoft.faces.webapp.xmlhttp;
35
36 import com.icesoft.faces.context.BridgeFacesContext;
37 import com.icesoft.faces.context.ViewListener;
38 import com.icesoft.faces.webapp.http.common.Configuration;
39 import com.icesoft.faces.webapp.parser.ImplementationUtil;
40
41 import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
42 import edu.emory.mathcs.backport.java.util.concurrent.Executors;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45
46 import javax.faces.FactoryFinder;
47 import javax.faces.context.ExternalContext;
48 import javax.faces.context.FacesContext;
49 import javax.faces.lifecycle.Lifecycle;
50 import javax.faces.lifecycle.LifecycleFactory;
51 import java.io.Serializable JavaDoc;
52 import java.util.Collection JavaDoc;
53 import java.util.Map JavaDoc;
54
55 /**
56  * The {@link PersistentFacesState} class allows an application to initiate
57  * rendering asynchronously and independently of user interaction.
58  * <p/>
59  * Typical use is to obtain a {@link PersistentFacesState} instance in a managed
60  * bean constructor and then use that instance for any relevant rendering
61  * requests.
62  * <p/>
63  * Applications should obtain the <code>PersistentFacesState</code> instance
64  * using the public static getInstance() method. The recommended approach is to
65  * call this method from a mangaged-bean constructor and use the instance
66  * obtained for any {@link #render} requests.
67  */

68 public class PersistentFacesState implements Serializable JavaDoc {
69     private static final Log log = LogFactory.getLog(PersistentFacesState.class);
70     private static ExecutorService executorService = Executors.newSingleThreadExecutor();
71     private static InheritableThreadLocal JavaDoc localInstance = new InheritableThreadLocal JavaDoc();
72     private BridgeFacesContext facesContext;
73     private Lifecycle lifecycle;
74
75     private ClassLoader JavaDoc renderableClassLoader = null;
76     private boolean synchronousMode;
77     private Collection JavaDoc viewListeners;
78
79     public PersistentFacesState(BridgeFacesContext facesContext, Collection JavaDoc viewListeners, Configuration configuration) {
80         //JIRA case ICE-1365
81
//Save a reference to the web app classloader so that server-side
82
//render requests work regardless of how they are originated.
83
renderableClassLoader = Thread.currentThread().getContextClassLoader();
84
85         this.facesContext = facesContext;
86         this.viewListeners = viewListeners;
87         this.synchronousMode = configuration.getAttributeAsBoolean("synchronousUpdate", false);
88         LifecycleFactory factory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
89         this.lifecycle = factory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
90         this.setCurrentInstance();
91     }
92
93     public void setCurrentInstance() {
94         localInstance.set(this);
95     }
96
97     /**
98      * Obtain the <code>PersistentFacesState</code> instance appropriate for the
99      * current context. This is managed through InheritableThreadLocal
100      * variables. The recommended approach is to call this method from a
101      * mangaged-bean constructor and use the instance obtained for any {@link
102      * #render} requests.
103      *
104      * @return the PersistentFacesState appropriate for the calling Thread
105      */

106     public static PersistentFacesState getInstance() {
107         return (PersistentFacesState) localInstance.get();
108     }
109
110     /**
111      * Obtain the {@link PersistentFacesState} instance keyed by viewNumber from
112      * the specified sessionMap. This API is not intended for application use.
113      *
114      * @param sessionMap session-scope parameters
115      * @return the PersistentFacesState
116      * @deprecated
117      */

118     public static PersistentFacesState getInstance(Map JavaDoc sessionMap) {
119         return getInstance();
120     }
121
122     /**
123      * Return the FacesContext associated with this instance.
124      *
125      * @return the FacesContext for this instance
126      */

127     public FacesContext getFacesContext() {
128         return facesContext;
129     }
130
131     //todo: try to remove this method in the future
132
public void setFacesContext(BridgeFacesContext facesContext) {
133         this.facesContext = facesContext;
134     }
135
136     /**
137      * Render the view associated with this <code>PersistentFacesState</code>.
138      * The user's browser will be immediately updated with any changes.
139      */

140     public void render() throws RenderingException {
141         warn();
142         facesContext.setCurrentInstance();
143         facesContext.setFocusId("");
144         synchronized (facesContext) {
145             try {
146                 lifecycle.render(facesContext);
147                 facesContext.release();
148             } catch (IllegalStateException JavaDoc e) {
149                 if (log.isDebugEnabled()) {
150                     log.debug("fatal render failure for viewNumber "
151                             + facesContext.getViewNumber(), e);
152                 }
153                 throw new FatalRenderingException(
154                         "fatal render failure for viewNumber "
155                                 + facesContext.getViewNumber(), e);
156             } catch (Exception JavaDoc e) {
157                 if (log.isDebugEnabled()) {
158                     log.debug("transient render failure for viewNumber "
159                             + facesContext.getViewNumber(), e);
160                 }
161                 throw new TransientRenderingException(
162                         "transient render failure for viewNumber "
163                                 + facesContext.getViewNumber(), e);
164             }
165         }
166     }
167
168     /**
169      * Render the view associated with this <code>PersistentFacesState</code>.
170      * This takes place on a separate thread to guard against potential deadlock
171      * from calling {@link #render} during view rendering.
172      */

173     public void renderLater() {
174         warn();
175         executorService.execute(new RenderRunner());
176     }
177
178     public void renderLater(long miliseconds) {
179         warn();
180         executorService.execute(new RenderRunner(miliseconds));
181     }
182
183     /**
184      * Redirect browser to a different URI. The user's browser will be
185      * immediately redirected without any user interaction required.
186      *
187      * @param uri the relative or absolute URI.
188      */

189     public void redirectTo(String JavaDoc uri) {
190         warn();
191         try {
192             facesContext.setCurrentInstance();
193             ExternalContext externalContext = facesContext.getExternalContext();
194             externalContext.redirect(uri);
195         } catch (Exception JavaDoc e) {
196             throw new RuntimeException JavaDoc(e);
197         }
198     }
199
200     /**
201      * Redirect browser to a different page. The redirect page is selected based
202      * on the navigation rule. The user's browser will be immediately redirected
203      * without any user interaction required.
204      *
205      * @param outcome the 'from-outcome' field in the navigation rule.
206      */

207     public void navigateTo(String JavaDoc outcome) {
208         warn();
209         try {
210             facesContext.setCurrentInstance();
211             facesContext.getApplication().getNavigationHandler()
212                     .handleNavigation(facesContext,
213                             facesContext.getViewRoot().getViewId(),
214                             outcome);
215         } catch (Exception JavaDoc e) {
216             throw new RuntimeException JavaDoc(e);
217         }
218     }
219
220     /**
221      * Threads that used to server request/response cycles in an application
222      * server are generally pulled from a pool. Just before the thread is done
223      * completing the cycle, we should clear any local instance variables to
224      * ensure that they are not hanging on to any session references, otherwise
225      * the session and their resources are not released.
226      */

227     public void release() {
228         localInstance.set(null);
229     }
230
231     /**
232      * Execute the view associated with this <code>PersistentFacesState</code>.
233      * This is typically followed immediatly by a call to
234      * {@link PersistentFacesState#render}.
235      */

236     public void execute() throws RenderingException {
237         facesContext.setCurrentInstance();
238         synchronized (facesContext) {
239             try {
240                 if (ImplementationUtil.isJSF12()){
241                 //facesContext.renderResponse() skips phase listeners
242
//in JSF 1.2, so do a full execute with no stale input
243
//instead
244
facesContext.getExternalContext()
245                         .getRequestParameterMap().clear();
246                 }
247                 else {
248                     facesContext.renderResponse();
249                 }
250                 lifecycle.execute(facesContext);
251             } catch (IllegalStateException JavaDoc e) {
252                 if (log.isDebugEnabled()) {
253                     log.debug("fatal render failure for viewNumber "
254                             + facesContext.getViewNumber(), e);
255                 }
256                 throw new FatalRenderingException(
257                         "fatal render failure for viewNumber "
258                                 + facesContext.getViewNumber(), e);
259             } catch (Exception JavaDoc e) {
260                 if (log.isDebugEnabled()) {
261                     log.debug("transient render failure for viewNumber "
262                             + facesContext.getViewNumber(), e);
263                 }
264                 throw new TransientRenderingException(
265                         "transient render failure for viewNumber "
266                                 + facesContext.getViewNumber(), e);
267             }
268         }
269     }
270
271
272     public ClassLoader JavaDoc getRenderableClassLoader() {
273         return renderableClassLoader;
274     }
275
276     public void addViewListener(ViewListener listener) {
277         viewListeners.add(listener);
278     }
279
280     private class RenderRunner implements Runnable JavaDoc {
281         private long delay = 0;
282
283         public RenderRunner() {
284         }
285
286         public RenderRunner(long miliseconds) {
287             delay = miliseconds;
288         }
289
290         /**
291          * <p>Not for application use. Entry point for {@link
292          * PersistentFacesState#renderLater}.</p>
293          */

294         public void run() {
295             try {
296                 Thread.sleep(delay);
297                 // JIRA #1377 Call execute before render.
298
execute();
299                 render();
300             } catch (RenderingException e) {
301                 if (log.isDebugEnabled()) {
302                     log.debug("renderLater failed ", e);
303                 }
304             } catch (InterruptedException JavaDoc e) {
305                 //ignore
306
}
307         }
308     }
309
310     private void warn() {
311         if (synchronousMode) {
312             log.warn("Running in 'synchronous mode'. The page updates were queued but not sent.");
313         }
314     }
315 }
316
317
318
319
320
321
322
Popular Tags