View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.lifecycle;
21  
22  import org.apache.myfaces.tobago.util.DebugUtils;
23  import org.apache.myfaces.tobago.util.RequestUtils;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import javax.faces.FacesException;
28  import javax.faces.context.FacesContext;
29  import javax.faces.event.PhaseId;
30  import javax.faces.event.PhaseListener;
31  import javax.faces.lifecycle.Lifecycle;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  /**
36   * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2
37   *
38   * Not longer needed.
39   *
40   * @deprecated since Tobago 2.0.0
41   */
42  @Deprecated
43  public class TobagoLifecycle extends Lifecycle {
44  
45    private static final Logger LOG = LoggerFactory.getLogger(TobagoLifecycle.class);
46  
47    public static final String VIEW_ROOT_KEY = TobagoLifecycle.class.getName() + ".VIEW_ROOT_KEY";
48    public static final String FACES_MESSAGES_KEY = TobagoLifecycle.class.getName() + ".FACES_MESSAGES_KEY";
49  
50    private PhaseExecutor[] lifecycleExecutors;
51    private PhaseExecutor renderExecutor;
52  
53    private final List<PhaseListener> phaseListenerList = new ArrayList<PhaseListener>();
54  
55    /**
56     * Lazy cache for returning phaseListenerList as an Array.
57     */
58    private PhaseListener[] phaseListenerArray = null;
59  
60    public TobagoLifecycle() {
61      // hide from public access
62      lifecycleExecutors = new PhaseExecutor[]{
63          new RestoreViewExecutor(),
64          new ApplyRequestValuesExecutor(),
65          new ProcessValidationsExecutor(),
66          new UpdateModelValuesExecutor(),
67          new InvokeApplicationExecutor()
68      };
69  
70      renderExecutor = new RenderResponseExecutor();
71    }
72  
73    public void execute(final FacesContext context) throws FacesException {
74  
75      final PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, context, getPhaseListeners());
76  
77      // At very first ensure the requestEncoding, this MUST done before
78      // accessing request parameters, which can occur in custom phaseListeners.
79      RequestUtils.ensureEncoding(context);
80  
81      for (final PhaseExecutor executor : lifecycleExecutors) {
82        if (executePhase(context, executor, phaseListenerMgr)) {
83          return;
84        }
85      }
86    }
87  
88    private boolean executePhase(
89        final FacesContext facesContext, final PhaseExecutor executor, final PhaseListenerManager phaseListenerMgr)
90        throws FacesException {
91  
92      boolean skipFurtherProcessing = false;
93      if (LOG.isTraceEnabled()) {
94        LOG.trace("entering " + executor.getPhase() + " in " + TobagoLifecycle.class.getName());
95      }
96  
97      try {
98        phaseListenerMgr.informPhaseListenersBefore(executor.getPhase());
99  
100       if (isResponseComplete(facesContext, executor.getPhase(), true)) {
101         // have to return right away
102         return true;
103       }
104       if (shouldRenderResponse(facesContext, executor.getPhase(), true)) {
105         skipFurtherProcessing = true;
106       }
107 
108       if (executor.execute(facesContext)) {
109         return true;
110       }
111     } finally {
112       phaseListenerMgr.informPhaseListenersAfter(executor.getPhase());
113     }
114 
115 
116     if (isResponseComplete(facesContext, executor.getPhase(), false)
117         || shouldRenderResponse(facesContext, executor.getPhase(), false)) {
118       // since this phase is completed we don't need to return right away even if the response is completed
119       skipFurtherProcessing = true;
120     }
121 
122     if (!skipFurtherProcessing && LOG.isTraceEnabled()) {
123       LOG.trace("exiting " + executor.getPhase() + " in " + TobagoLifecycle.class.getName());
124     }
125 
126     return skipFurtherProcessing;
127   }
128 
129   public void render(final FacesContext facesContext) throws FacesException {
130     // if the response is complete we should not be invoking the phase listeners
131     if (isResponseComplete(facesContext, renderExecutor.getPhase(), true)) {
132       return;
133     }
134     if (LOG.isTraceEnabled()) {
135       LOG.trace("entering " + renderExecutor.getPhase() + " in " + TobagoLifecycle.class.getName());
136     }
137 
138     final PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext, getPhaseListeners());
139 
140     try {
141       phaseListenerMgr.informPhaseListenersBefore(renderExecutor.getPhase());
142       // also possible that one of the listeners completed the response
143       if (isResponseComplete(facesContext, renderExecutor.getPhase(), true)) {
144         return;
145       }
146       renderExecutor.execute(facesContext);
147     } finally {
148       phaseListenerMgr.informPhaseListenersAfter(renderExecutor.getPhase());
149     }
150 
151     if (LOG.isTraceEnabled()) {
152       LOG.trace(DebugUtils.toString(facesContext.getViewRoot(), 0));
153       LOG.trace("exiting " + renderExecutor.getPhase() + " in " + TobagoLifecycle.class.getName());
154     }
155 
156   }
157 
158   private boolean isResponseComplete(final FacesContext facesContext, final PhaseId phase, final boolean before) {
159     boolean flag = false;
160     if (facesContext.getResponseComplete()) {
161       if (LOG.isDebugEnabled()) {
162         LOG.debug("exiting from lifecycle.execute in " + phase
163             + " because getResponseComplete is true from one of the "
164             + (before ? "before" : "after") + " listeners");
165       }
166       flag = true;
167     }
168     return flag;
169   }
170 
171   private boolean shouldRenderResponse(final FacesContext facesContext, final PhaseId phase, final boolean before) {
172     boolean flag = false;
173     if (facesContext.getRenderResponse()) {
174       if (LOG.isDebugEnabled()) {
175         LOG.debug("exiting from lifecycle.execute in " + phase
176             + " because getRenderResponse is true from one of the "
177             + (before ? "before" : "after") + " listeners");
178       }
179       flag = true;
180     }
181     return flag;
182   }
183 
184   public void addPhaseListener(final PhaseListener phaseListener) {
185     if (phaseListener == null) {
186       throw new NullPointerException("PhaseListener must not be null.");
187     }
188     synchronized (phaseListenerList) {
189       phaseListenerList.add(phaseListener);
190       phaseListenerArray = null; // reset lazy cache array
191     }
192   }
193 
194   public void removePhaseListener(final PhaseListener phaseListener) {
195     if (phaseListener == null) {
196       throw new NullPointerException("PhaseListener must not be null.");
197     }
198     synchronized (phaseListenerList) {
199       phaseListenerList.remove(phaseListener);
200       phaseListenerArray = null; // reset lazy cache array
201     }
202   }
203 
204   public PhaseListener[] getPhaseListeners() {
205     synchronized (phaseListenerList) {
206       // (re)build lazy cache array if necessary
207       if (phaseListenerArray == null) {
208         phaseListenerArray = phaseListenerList.toArray(new PhaseListener[phaseListenerList.size()]);
209       }
210       return phaseListenerArray;
211     }
212   }
213 }