Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/myfaces/lifecycle/LifecycleImpl.java


1   /*
2    * Copyright 2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.myfaces.lifecycle;
17  
18  import org.apache.myfaces.util.DebugUtils;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  import javax.faces.FacesException;
24  import javax.faces.application.Application;
25  import javax.faces.application.ViewHandler;
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.UIInput;
28  import javax.faces.component.UIViewRoot;
29  import javax.faces.context.ExternalContext;
30  import javax.faces.context.FacesContext;
31  import javax.faces.el.ValueBinding;
32  import javax.faces.event.PhaseEvent;
33  import javax.faces.event.PhaseId;
34  import javax.faces.event.PhaseListener;
35  import javax.faces.lifecycle.Lifecycle;
36  import java.io.IOException;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.Iterator;
40  import java.util.List;
41  import javax.portlet.PortletRequest;
42  import org.apache.myfaces.portlet.MyFacesGenericPortlet;
43  import org.apache.myfaces.portlet.PortletUtil;
44  
45  /**
46   * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2
47   * @author Manfred Geiler (latest modification by $Author: bdudney $)
48   * @version $Revision: 294841 $ $Date: 2005-10-04 13:13:34 -0400 (Tue, 04 Oct 2005) $
49   */
50  public class LifecycleImpl
51          extends Lifecycle
52  {
53      private static final Log log = LogFactory.getLog(LifecycleImpl.class);
54  
55      private List _phaseListenerList = new ArrayList();
56      private PhaseListener[] _phaseListenerArray = null;
57  
58      public LifecycleImpl()
59      {
60          // hide from public access
61      }
62  
63      public void execute(FacesContext facesContext)
64          throws FacesException
65      {
66          if (restoreView(facesContext))
67          {
68              return;
69          }
70  
71          if (applyRequestValues(facesContext))
72          {
73              return;
74          }
75  
76          if (processValidations(facesContext))
77          {
78              return;
79          }
80  
81          if (updateModelValues(facesContext))
82          {
83              return;
84          }
85  
86          if (invokeApplication(facesContext))
87          {
88              return;
89          }
90      }
91  
92  
93      // Phases
94  
95      /**
96       * Restore View (JSF.2.2.1)
97       * @return true, if immediate rendering should occur
98       */
99      private boolean restoreView(FacesContext facesContext)
100         throws FacesException
101     {
102         boolean skipFurtherProcessing = false;
103         if (log.isTraceEnabled()) log.trace("entering restoreView in " + LifecycleImpl.class.getName());
104 
105         informPhaseListenersBefore(facesContext, PhaseId.RESTORE_VIEW);
106 
107         if(isResponseComplete(facesContext, "restoreView", true))
108         {
109             // have to skips this phase
110             return true;
111         }
112         if (shouldRenderResponse(facesContext, "restoreView", true)) 
113         {
114       skipFurtherProcessing = true;
115     }
116 
117         // Derive view identifier
118         String viewId = deriveViewId(facesContext);
119 
120         Application application = facesContext.getApplication();
121         ViewHandler viewHandler = application.getViewHandler();
122 
123         //boolean viewCreated = false;
124         UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
125         if (viewRoot == null)
126         {
127             viewRoot = viewHandler.createView(facesContext, viewId);
128             viewRoot.setViewId(viewId);
129             facesContext.renderResponse();
130             //viewCreated = true;
131         }
132 
133         facesContext.setViewRoot(viewRoot);
134 
135         /* This section has been disabled because it causes some bug.
136          * Be careful if you need to re-enable it.
137          * Furthermore, for an unknown reason, it seems that by default
138          * it is executed (i.e. log.isTraceEnabled() is true).
139          * Bug example :
140          * This traceView causes DebugUtil.printComponent to print all the attributes
141          * of the view components.
142          * And if you have a data table within an aliasBean, this causes the data table
143          * to initialize it's value attribute while the alias isn't set.
144          * So, the value initializes with an UIData.EMPTY_DATA_MODEL, and not with the aliased one.
145          * But as it's initialized, it will not try to get the value from the ValueBinding next
146          * time it needs to.
147          * I expect this to cause more similar bugs.
148          * TODO : Completely remove or be SURE by default it's not executed, and it has no more side-effects.
149 
150         if (log.isTraceEnabled())
151         {
152             //Note: DebugUtils Logger must also be in trace level
153             DebugUtils.traceView(viewCreated ? "Newly created view" : "Restored view");
154         }*/
155 
156         if (facesContext.getExternalContext().getRequestParameterMap().isEmpty())
157         {
158             //no POST or query parameters --> set render response flag
159             facesContext.renderResponse();
160         }
161 
162         recursivelyHandleComponentReferencesAndSetValid(facesContext, viewRoot);
163 
164         informPhaseListenersAfter(facesContext, PhaseId.RESTORE_VIEW);
165 
166         if (isResponseComplete(facesContext, "restoreView", false)
167         || shouldRenderResponse(facesContext, "restoreView", false))
168         {
169             // since this phase is completed we don't need to return right away even if the response is completed
170             skipFurtherProcessing = true;
171         }
172 
173         if (!skipFurtherProcessing && log.isTraceEnabled()) log.trace("exiting restoreView in " + LifecycleImpl.class.getName());
174         return skipFurtherProcessing;
175     }
176 
177 
178     /**
179      * Apply Request Values (JSF.2.2.2)
180      * @return true, if response is complete
181      */
182     private boolean applyRequestValues(FacesContext facesContext)
183         throws FacesException
184     {
185         boolean skipFurtherProcessing = false;
186         if (log.isTraceEnabled()) log.trace("entering applyRequestValues in " + LifecycleImpl.class.getName());
187 
188         informPhaseListenersBefore(facesContext, PhaseId.APPLY_REQUEST_VALUES);
189 
190         if(isResponseComplete(facesContext, "applyRequestValues", true))
191         {
192             // have to return right away
193             return true;
194         }
195         if(shouldRenderResponse(facesContext, "applyRequestValues", true))
196         {
197             skipFurtherProcessing = true;
198         }
199 
200         facesContext.getViewRoot().processDecodes(facesContext);
201 
202         informPhaseListenersAfter(facesContext, PhaseId.APPLY_REQUEST_VALUES);
203 
204 
205         if (isResponseComplete(facesContext, "applyRequestValues", false)
206         || shouldRenderResponse(facesContext, "applyRequestValues", false))
207         {
208             // since this phase is completed we don't need to return right away even if the response is completed
209             skipFurtherProcessing = true;
210         }
211 
212         if (!skipFurtherProcessing && log.isTraceEnabled())
213       log.trace("exiting applyRequestValues in "
214           + LifecycleImpl.class.getName());
215         return skipFurtherProcessing;
216     }
217 
218 
219     /**
220      * Process Validations (JSF.2.2.3)
221      * @return true, if response is complete
222      */
223     private boolean processValidations(FacesContext facesContext) throws FacesException
224     {
225         boolean skipFurtherProcessing = false;
226         if (log.isTraceEnabled()) log.trace("entering processValidations in " + LifecycleImpl.class.getName());
227 
228         informPhaseListenersBefore(facesContext, PhaseId.PROCESS_VALIDATIONS);
229 
230         if(isResponseComplete(facesContext, "processValidations", true))
231         {
232             // have to return right away
233             return true;
234         }
235         if(shouldRenderResponse(facesContext, "processValidations", true))
236         {
237             skipFurtherProcessing = true;
238         }
239 
240         facesContext.getViewRoot().processValidators(facesContext);
241 
242         informPhaseListenersAfter(facesContext, PhaseId.PROCESS_VALIDATIONS);
243 
244     if (isResponseComplete(facesContext, "processValidations", false)
245         || shouldRenderResponse(facesContext, "processValidations", false))
246         {
247             // since this phase is completed we don't need to return right away even if the response is completed
248             skipFurtherProcessing = true;
249         }
250 
251         if (!skipFurtherProcessing && log.isTraceEnabled()) log.trace("exiting processValidations in " + LifecycleImpl.class.getName());
252         return skipFurtherProcessing;
253     }
254 
255 
256     /**
257      * Update Model Values (JSF.2.2.4)
258      * @return true, if response is complete
259      */
260     private boolean updateModelValues(FacesContext facesContext) throws FacesException
261     {
262       boolean skipFurtherProcessing = false;
263         if (log.isTraceEnabled()) log.trace("entering updateModelValues in " + LifecycleImpl.class.getName());
264 
265         informPhaseListenersBefore(facesContext, PhaseId.UPDATE_MODEL_VALUES);
266 
267         if(isResponseComplete(facesContext, "updateModelValues", true))
268         {
269             // have to return right away
270             return true;
271         }
272         if(shouldRenderResponse(facesContext, "updateModelValues", true))
273         {
274             skipFurtherProcessing = true;
275         }
276 
277         facesContext.getViewRoot().processUpdates(facesContext);
278 
279         informPhaseListenersAfter(facesContext, PhaseId.UPDATE_MODEL_VALUES);
280 
281     if (isResponseComplete(facesContext, "updateModelValues", false)
282         || shouldRenderResponse(facesContext, "updateModelValues", false))
283         {
284             // since this phase is completed we don't need to return right away even if the response is completed
285             skipFurtherProcessing = true;
286         }
287 
288         if (!skipFurtherProcessing && log.isTraceEnabled()) log.trace("exiting updateModelValues in " + LifecycleImpl.class.getName());
289 
290         return skipFurtherProcessing;
291     }
292 
293 
294     /**
295      * Invoke Application (JSF.2.2.5)
296      * @return true, if response is complete
297      */
298     private boolean invokeApplication(FacesContext facesContext)
299         throws FacesException
300     {
301       boolean skipFurtherProcessing = false;
302         if (log.isTraceEnabled()) log.trace("entering invokeApplication in " + LifecycleImpl.class.getName());
303 
304         informPhaseListenersBefore(facesContext, PhaseId.INVOKE_APPLICATION);
305 
306         if(isResponseComplete(facesContext, "invokeApplication", true))
307         {
308             // have to return right away
309             return true;
310         }
311         if(shouldRenderResponse(facesContext, "invokeApplication", true))
312         {
313             skipFurtherProcessing = true;
314         }
315 
316         facesContext.getViewRoot().processApplication(facesContext);
317 
318         informPhaseListenersAfter(facesContext, PhaseId.INVOKE_APPLICATION);
319 
320     if (isResponseComplete(facesContext, "invokeApplication", false)
321         || shouldRenderResponse(facesContext, "invokeApplication", false))
322         {
323             // since this phase is completed we don't need to return right away even if the response is completed
324             skipFurtherProcessing = true;
325         }
326 
327         if (!skipFurtherProcessing && log.isTraceEnabled()) log.trace("exiting invokeApplication in " + LifecycleImpl.class.getName());
328 
329         return skipFurtherProcessing;
330     }
331 
332 
333     public void render(FacesContext facesContext) throws FacesException
334     {
335         // if the response is complete we should not be invoking the phase listeners
336         if(isResponseComplete(facesContext, "render", true))
337         {
338             return;
339         }
340         if (log.isTraceEnabled()) log.trace("entering renderResponse in " + LifecycleImpl.class.getName());
341 
342         informPhaseListenersBefore(facesContext, PhaseId.RENDER_RESPONSE);
343         // also possible that one of the listeners completed the response
344         if(isResponseComplete(facesContext, "render", true))
345         {
346             return;
347         }
348         Application application = facesContext.getApplication();
349         ViewHandler viewHandler = application.getViewHandler();
350         try
351         {
352             viewHandler.renderView(facesContext, facesContext.getViewRoot());
353         }
354         catch (IOException e)
355         {
356             throw new FacesException(e.getMessage(), e);
357         }
358 
359         informPhaseListenersAfter(facesContext, PhaseId.RENDER_RESPONSE);
360         if (log.isTraceEnabled())
361         {
362             //Note: DebugUtils Logger must also be in trace level
363             DebugUtils.traceView("View after rendering");
364         }
365 
366         if (log.isTraceEnabled()) log.trace("exiting renderResponse in " + LifecycleImpl.class.getName());
367     }
368 
369 
370     private boolean isResponseComplete(FacesContext facesContext, String phase, boolean before) {
371         boolean flag = false;
372         if (facesContext.getResponseComplete())
373         {
374             if (log.isDebugEnabled())
375         log.debug("exiting from lifecycle.execute in " + phase
376             + " because getResponseComplete is true from one of the " +
377             (before ? "before" : "after") + " listeners");
378             flag = true;
379         }
380         return flag;
381     }
382 
383     private boolean shouldRenderResponse(FacesContext facesContext, String phase, boolean before) {
384         boolean flag = false;
385         if (facesContext.getRenderResponse())
386         {
387             if (log.isDebugEnabled())
388         log.debug("exiting from lifecycle.execute in " + phase
389             + " because getRenderResponse is true from one of the " + 
390             (before ? "before" : "after") + " listeners");
391             flag = true;
392         }
393         return flag;
394   }
395 
396     private static String deriveViewId(FacesContext facesContext)
397     {
398         ExternalContext externalContext = facesContext.getExternalContext();
399 
400         if (PortletUtil.isPortletRequest(facesContext))
401         {
402             PortletRequest request = (PortletRequest)externalContext.getRequest();
403             return request.getParameter(MyFacesGenericPortlet.VIEW_ID);
404         }
405 
406         String viewId = externalContext.getRequestPathInfo();  //getPathInfo
407         if (viewId == null)
408         {
409             //No extra path info found, so it is propably extension mapping
410             viewId = externalContext.getRequestServletPath();  //getServletPath
411             DebugUtils.assertError(viewId != null,
412                                    log, "RequestServletPath is null, cannot determine viewId of current page.");
413             //TODO: JSF Spec 2.2.1 - what do they mean by "if the default ViewHandler implementation is used..." ?
414             String defaultSuffix = externalContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
415             String suffix = defaultSuffix != null ? defaultSuffix : ViewHandler.DEFAULT_SUFFIX;
416             DebugUtils.assertError(suffix.charAt(0) == '.',
417                                    log, "Default suffix must start with a dot!");
418 
419             int dot = viewId.lastIndexOf('.');
420             if (dot == -1)
421             {
422                 log.error("Assumed extension mapping, but there is no extension in " + viewId);
423             }
424             else
425             {
426                 viewId = viewId.substring(0, dot) + suffix;
427             }
428         }
429 
430         return viewId;
431     }
432 
433 
434     private static void recursivelyHandleComponentReferencesAndSetValid(FacesContext facesContext,
435                                                                         UIComponent root)
436     {
437         for (Iterator it = root.getFacetsAndChildren(); it.hasNext(); )
438         {
439             UIComponent component = (UIComponent)it.next();
440 
441             ValueBinding binding = component.getValueBinding("binding");    //TODO: constant
442             if (binding != null && !binding.isReadOnly(facesContext))
443             {
444                 binding.setValue(facesContext, component);
445             }
446 
447             if (component instanceof UIInput)
448             {
449                 ((UIInput)component).setValid(true);
450             }
451 
452             recursivelyHandleComponentReferencesAndSetValid(facesContext, component);
453         }
454     }
455 
456     public void addPhaseListener(PhaseListener phaseListener)
457     {
458         if(phaseListener == null)
459         {
460             throw new NullPointerException("PhaseListener must not be null.");
461         }
462         if (_phaseListenerList == null)
463         {
464             _phaseListenerList = new ArrayList();
465             if (_phaseListenerArray != null)
466             {
467                 _phaseListenerList.addAll(Arrays.asList(_phaseListenerArray));
468                 _phaseListenerArray = null;
469             }
470         }
471         _phaseListenerList.add(phaseListener);
472     }
473 
474     public void removePhaseListener(PhaseListener phaseListener)
475     {
476         if(phaseListener == null)
477         {
478             throw new NullPointerException("PhaseListener must not be null.");
479         }
480         if (_phaseListenerList == null)
481         {
482             _phaseListenerList = new ArrayList();
483             if (_phaseListenerArray != null)
484             {
485                 _phaseListenerList.addAll(Arrays.asList(_phaseListenerArray));
486                 _phaseListenerArray = null;
487             }
488         }
489         _phaseListenerList.remove(phaseListener);
490     }
491 
492     public PhaseListener[] getPhaseListeners()
493     {
494         if (_phaseListenerArray == null)
495         {
496             if (_phaseListenerList == null)
497             {
498                 _phaseListenerArray = new PhaseListener[0];
499             }
500             else
501             {
502                 _phaseListenerArray = (PhaseListener[])_phaseListenerList.toArray(new PhaseListener[_phaseListenerList.size()]);
503                 _phaseListenerList = null;
504             }
505         }
506         return _phaseListenerArray;
507     }
508 
509 
510     private void informPhaseListenersBefore(FacesContext facesContext, PhaseId phaseId)
511     {
512         PhaseListener[] phaseListeners = getPhaseListeners();
513         for (int i = 0; i < phaseListeners.length; i++)
514         {
515             PhaseListener phaseListener = phaseListeners[i];
516             int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
517             if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() ||
518                 listenerPhaseId == phaseId.getOrdinal())
519             {
520                 phaseListener.beforePhase(new PhaseEvent(facesContext, phaseId, this));
521             }
522         }
523 
524     }
525 
526     private void informPhaseListenersAfter(FacesContext facesContext, PhaseId phaseId)
527     {
528         PhaseListener[] phaseListeners = getPhaseListeners();
529         for (int i = 0; i < phaseListeners.length; i++)
530         {
531             PhaseListener phaseListener = phaseListeners[i];
532             int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
533             if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() ||
534                 listenerPhaseId == phaseId.getOrdinal())
535             {
536                 phaseListener.afterPhase(new PhaseEvent(facesContext, phaseId, this));
537             }
538         }
539 
540     }
541 
542 }