1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.lifecycle;
20
21 import java.util.List;
22 import java.util.concurrent.CopyOnWriteArrayList;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25
26 import javax.faces.FacesException;
27 import javax.faces.FactoryFinder;
28 import javax.faces.application.ProjectStage;
29 import javax.faces.context.FacesContext;
30 import javax.faces.context.Flash;
31 import javax.faces.event.ExceptionQueuedEvent;
32 import javax.faces.event.ExceptionQueuedEventContext;
33 import javax.faces.event.PhaseId;
34 import javax.faces.event.PhaseListener;
35 import javax.faces.lifecycle.ClientWindow;
36 import javax.faces.lifecycle.ClientWindowFactory;
37 import javax.faces.lifecycle.Lifecycle;
38
39 import org.apache.myfaces.config.FacesConfigurator;
40 import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
41 import org.apache.myfaces.util.DebugUtils;
42
43
44
45
46
47
48
49
50 public class LifecycleImpl extends Lifecycle
51 {
52
53 private static final Logger log = Logger.getLogger(LifecycleImpl.class.getName());
54
55
56
57
58
59 public static final String FIRST_REQUEST_PROCESSED_PARAM = "org.apache.myfaces.lifecycle.first.request.processed";
60
61 private final PhaseExecutor[] lifecycleExecutors;
62 private final PhaseExecutor renderExecutor;
63
64
65
66
67
68
69
70
71
72
73
74
75
76 private final List<PhaseListener> _phaseListenerList
77 = new CopyOnWriteArrayList<PhaseListener>();
78
79
80
81
82
83
84
85
86
87 private volatile boolean _firstRequestProcessed = false;
88
89
90
91
92
93
94
95 private ClientWindowFactory clientWindowFactory;
96
97 public LifecycleImpl()
98 {
99
100 lifecycleExecutors = new PhaseExecutor[] { new RestoreViewExecutor(), new ApplyRequestValuesExecutor(),
101 new ProcessValidationsExecutor(), new UpdateModelValuesExecutor(), new InvokeApplicationExecutor() };
102
103 renderExecutor = new RenderResponseExecutor();
104 clientWindowFactory = (ClientWindowFactory) FactoryFinder.getFactory(FactoryFinder.CLIENT_WINDOW_FACTORY);
105 }
106
107 @Override
108 public void attachWindow(FacesContext facesContext)
109 {
110 ClientWindow clientWindow = facesContext.getExternalContext().getClientWindow();
111 if (clientWindow == null)
112 {
113 clientWindow = getClientWindowFactory().getClientWindow(facesContext);
114 }
115 if (clientWindow != null)
116 {
117 clientWindow.decode(facesContext);
118 facesContext.getExternalContext().setClientWindow(clientWindow);
119 }
120 }
121
122 protected ClientWindowFactory getClientWindowFactory()
123 {
124 return clientWindowFactory;
125 }
126
127 @Override
128 public void execute(FacesContext facesContext) throws FacesException
129 {
130
131
132
133
134 if(!facesContext.isProjectStage(ProjectStage.Production))
135 {
136 WebXml.update(facesContext.getExternalContext());
137 new FacesConfigurator(facesContext.getExternalContext()).update();
138 }
139
140 PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext, getPhaseListeners());
141 for (PhaseExecutor executor : lifecycleExecutors)
142 {
143 if (executePhase(facesContext, executor, phaseListenerMgr))
144 {
145 return;
146 }
147 }
148
149
150
151
152
153
154 }
155
156 private boolean executePhase(FacesContext context, PhaseExecutor executor, PhaseListenerManager phaseListenerMgr)
157 throws FacesException
158 {
159 boolean skipFurtherProcessing = false;
160
161 if (log.isLoggable(Level.FINEST))
162 {
163 log.finest("entering " + executor.getPhase() + " in " + LifecycleImpl.class.getName());
164 }
165
166 PhaseId currentPhaseId = executor.getPhase();
167 Flash flash = context.getExternalContext().getFlash();
168
169 try
170 {
171
172
173
174
175
176
177 context.setCurrentPhaseId(currentPhaseId);
178
179 flash.doPrePhaseActions(context);
180
181
182 executor.doPrePhaseActions(context);
183
184 phaseListenerMgr.informPhaseListenersBefore(currentPhaseId);
185
186 if (isResponseComplete(context, currentPhaseId, true))
187 {
188
189 return true;
190 }
191 if (shouldRenderResponse(context, currentPhaseId, true))
192 {
193 skipFurtherProcessing = true;
194 }
195
196 if (executor.execute(context))
197 {
198 return true;
199 }
200 }
201
202 catch (Throwable e)
203 {
204
205
206 publishException (e, currentPhaseId, context);
207 }
208
209 finally
210 {
211 phaseListenerMgr.informPhaseListenersAfter(currentPhaseId);
212
213 flash.doPostPhaseActions(context);
214
215 }
216
217 context.getExceptionHandler().handle();
218
219 if (isResponseComplete(context, currentPhaseId, false) || shouldRenderResponse(context, currentPhaseId, false))
220 {
221
222 skipFurtherProcessing = true;
223 }
224
225 if (!skipFurtherProcessing && log.isLoggable(Level.FINEST))
226 {
227 log.finest("exiting " + executor.getPhase() + " in " + LifecycleImpl.class.getName());
228 }
229
230 return skipFurtherProcessing;
231 }
232
233 @Override
234 public void render(FacesContext facesContext) throws FacesException
235 {
236
237
238
239 if (isResponseComplete(facesContext, renderExecutor.getPhase(), true))
240 {
241 return;
242 }
243 if (log.isLoggable(Level.FINEST))
244 {
245 log.finest("entering " + renderExecutor.getPhase() + " in " + LifecycleImpl.class.getName());
246 }
247
248 PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext, getPhaseListeners());
249 Flash flash = facesContext.getExternalContext().getFlash();
250
251 try
252 {
253 facesContext.setCurrentPhaseId(renderExecutor.getPhase());
254
255 flash.doPrePhaseActions(facesContext);
256
257
258 renderExecutor.doPrePhaseActions(facesContext);
259
260 phaseListenerMgr.informPhaseListenersBefore(renderExecutor.getPhase());
261
262 if (isResponseComplete(facesContext, renderExecutor.getPhase(), true))
263 {
264 return;
265 }
266
267 renderExecutor.execute(facesContext);
268 }
269
270 catch (Throwable e)
271 {
272
273
274 publishException (e, renderExecutor.getPhase(), facesContext);
275 }
276
277 finally
278 {
279 phaseListenerMgr.informPhaseListenersAfter(renderExecutor.getPhase());
280 flash.doPostPhaseActions(facesContext);
281
282
283
284 requestProcessed(facesContext);
285 }
286
287 facesContext.getExceptionHandler().handle();
288
289 if (log.isLoggable(Level.FINEST))
290 {
291
292 DebugUtils.traceView("View after rendering");
293 }
294
295 if (log.isLoggable(Level.FINEST))
296 {
297 log.finest("exiting " + renderExecutor.getPhase() + " in " + LifecycleImpl.class.getName());
298 }
299
300
301
302
303
304
305 }
306
307 private boolean isResponseComplete(FacesContext facesContext, PhaseId phase, boolean before)
308 {
309 boolean flag = false;
310 if (facesContext.getResponseComplete())
311 {
312 if (log.isLoggable(Level.FINE))
313 {
314 log.fine("exiting from lifecycle.execute in " + phase
315 + " because getResponseComplete is true from one of the " + (before ? "before" : "after")
316 + " listeners");
317 }
318 flag = true;
319 }
320 return flag;
321 }
322
323 private boolean shouldRenderResponse(FacesContext facesContext, PhaseId phase, boolean before)
324 {
325 boolean flag = false;
326 if (facesContext.getRenderResponse())
327 {
328 if (log.isLoggable(Level.FINE))
329 {
330 log.fine("exiting from lifecycle.execute in " + phase
331 + " because getRenderResponse is true from one of the " + (before ? "before" : "after")
332 + " listeners");
333 }
334 flag = true;
335 }
336 return flag;
337 }
338
339 @Override
340 public void addPhaseListener(PhaseListener phaseListener)
341 {
342 if (phaseListener == null)
343 {
344 throw new NullPointerException("PhaseListener must not be null.");
345 }
346
347
348 _phaseListenerList.add(phaseListener);
349
350
351 }
352
353 @Override
354 public void removePhaseListener(PhaseListener phaseListener)
355 {
356 if (phaseListener == null)
357 {
358 throw new NullPointerException("PhaseListener must not be null.");
359 }
360
361
362 _phaseListenerList.remove(phaseListener);
363
364
365 }
366
367 @Override
368 public PhaseListener[] getPhaseListeners()
369 {
370
371
372
373
374
375
376
377
378
379 return _phaseListenerList.toArray(new PhaseListener[_phaseListenerList.size()]);
380 }
381
382 private void publishException (Throwable e, PhaseId phaseId, FacesContext facesContext)
383 {
384 ExceptionQueuedEventContext context = new ExceptionQueuedEventContext (facesContext, e, null, phaseId);
385
386 facesContext.getApplication().publishEvent (facesContext, ExceptionQueuedEvent.class, context);
387 }
388
389
390
391
392
393
394
395
396 private void requestProcessed(FacesContext facesContext)
397 {
398 if(!_firstRequestProcessed)
399 {
400
401
402
403
404
405 facesContext.getExternalContext().getApplicationMap()
406 .put(FIRST_REQUEST_PROCESSED_PARAM, Boolean.TRUE);
407
408 _firstRequestProcessed = true;
409 }
410 }
411 }