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  package org.apache.myfaces.context.servlet;
20  
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.LinkedHashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import javax.faces.FactoryFinder;
30  import javax.faces.application.ApplicationFactory;
31  import javax.faces.application.FacesMessage;
32  import javax.faces.context.ExternalContext;
33  import javax.faces.context.FacesContext;
34  import javax.faces.context.PartialViewContext;
35  import javax.faces.context.PartialViewContextFactory;
36  import javax.faces.context.ResponseStream;
37  import javax.faces.context.ResponseWriter;
38  import javax.faces.event.PhaseId;
39  import javax.faces.render.RenderKit;
40  import javax.faces.render.RenderKitFactory;
41  import javax.servlet.ServletContext;
42  import javax.servlet.ServletRequest;
43  import javax.servlet.ServletResponse;
44  
45  import org.apache.myfaces.context.ReleaseableExternalContext;
46  import org.apache.myfaces.context.ReleaseableFacesContextFactory;
47  import org.apache.myfaces.shared.util.NullIterator;
48  
49  /**
50   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
51   * @author Anton Koinov
52   * @version $Revision: 1364593 $ $Date: 2012-07-23 07:07:46 -0500 (Mon, 23 Jul 2012) $
53   */
54  public class FacesContextImpl extends FacesContextImplBase
55  {
56  
57      private static final String METHOD_RESPONSEWRITER = "responseWriter";
58      static final String RE_SPLITTER = "[\\s\\t\\r\\n]*\\,[\\s\\t\\r\\n]*";
59      
60      // ~ Instance fields ----------------------------------------------------------------------------
61      
62      private Map<String, List<FacesMessage>> _messages = null;
63      private List<FacesMessage> _orderedMessages = null;
64      private PhaseId _currentPhaseId;
65      private ResponseStream _responseStream = null;
66      private ResponseWriter _responseWriter = null;
67      private FacesMessage.Severity _maximumSeverity = null;
68      private boolean _renderResponse = false;
69      private boolean _responseComplete = false;
70      private boolean _validationFailed = false;
71      private PartialViewContext _partialViewContext = null;
72      private ReleaseableFacesContextFactory _facesContextFactory = null;
73      
74      private PartialViewContextFactory _partialViewContextFactory = null;
75      private RenderKitFactory _renderKitFactory = null;
76  
77      // ~ Constructors -------------------------------------------------------------------------------
78      
79      /**
80       * Creates a FacesContextImpl with a ServletExternalContextImpl.
81       */
82      public FacesContextImpl(final ServletContext servletContext, final ServletRequest servletRequest,
83                              final ServletResponse servletResponse)
84      {
85          this(new ServletExternalContextImpl(servletContext, servletRequest, servletResponse));
86      }
87      
88      /**
89       * Private constructor used in internal construtor chain.
90       * @param externalContext
91       */
92      private FacesContextImpl(ServletExternalContextImpl externalContext)
93      {
94          this(externalContext, externalContext, null);
95      }
96      
97      /**
98       * Creates a FacesContextImpl with the given ExternalContext,
99       * ReleaseableExternalContext and ReleaseableFacesContextFactory.
100      * @param externalContext
101      * @param defaultExternalContext
102      * @param facesContextFactory
103      */
104     public FacesContextImpl(final ExternalContext externalContext,
105             final ReleaseableExternalContext defaultExternalContext , 
106             final ReleaseableFacesContextFactory facesContextFactory)
107     {
108         // setCurrentInstance is called in constructor of super class
109         super(externalContext, defaultExternalContext);
110         
111         _facesContextFactory = facesContextFactory;
112     }
113     
114     public FacesContextImpl(final ExternalContext externalContext,
115             final ReleaseableExternalContext defaultExternalContext , 
116             final ReleaseableFacesContextFactory facesContextFactory,
117             final ApplicationFactory applicationFactory,
118             final RenderKitFactory renderKitFactory,
119             final PartialViewContextFactory partialViewContextFactory)
120     {
121         // setCurrentInstance is called in constructor of super class
122         super(externalContext, defaultExternalContext, applicationFactory, 
123                 renderKitFactory);
124         
125         _facesContextFactory = facesContextFactory;
126         _renderKitFactory = renderKitFactory;
127         _partialViewContextFactory = partialViewContextFactory;
128     }
129 
130     // ~ Methods ------------------------------------------------------------------------------------
131     
132     @Override
133     public final void release()
134     {
135         assertNotReleased();
136 
137         _messages = null;
138         _orderedMessages = null;
139         _currentPhaseId = null;
140         _responseStream = null;
141         _responseWriter = null;
142         _maximumSeverity = null;
143         _partialViewContext = null;
144         _renderKitFactory = null;
145         _partialViewContextFactory = null;
146 
147         if (_facesContextFactory != null)
148         {
149             _facesContextFactory.release();
150             _facesContextFactory = null;
151         }
152 
153         // release FacesContextImplBase (sets current instance to null)
154         super.release();
155     }
156     
157     @Override
158     public final FacesMessage.Severity getMaximumSeverity()
159     {
160         assertNotReleased();
161 
162         return _maximumSeverity;
163     }
164     
165     @Override
166     public final void addMessage(final String clientId, final FacesMessage message)
167     {
168         assertNotReleased();
169 
170         if (message == null)
171         {
172             throw new NullPointerException("message");
173         }
174 
175         if (_messages == null)
176         {
177             _messages = new LinkedHashMap<String, List<FacesMessage>>();
178             _orderedMessages = new ArrayList<FacesMessage>();
179         }
180         
181         List<FacesMessage> lst = _messages.get(clientId); 
182         if (lst == null)
183         {
184             lst = new ArrayList<FacesMessage>();
185             _messages.put(clientId, lst);
186         }
187         
188         lst.add(message);
189         _orderedMessages.add (message);
190         
191         FacesMessage.Severity serSeverity = message.getSeverity();
192         if (serSeverity != null)
193         {
194             if (_maximumSeverity == null)
195             {
196                 _maximumSeverity = serSeverity;
197             }
198             else if (serSeverity.compareTo(_maximumSeverity) > 0)
199             {
200                 _maximumSeverity = serSeverity;
201             }
202         }
203     }
204 
205     @Override
206     public List<FacesMessage> getMessageList()
207     {
208         assertNotReleased();
209         
210         if (_messages == null)
211         {
212             return Collections.unmodifiableList(Collections.<FacesMessage>emptyList());
213         }
214         
215         return Collections.unmodifiableList(_orderedMessages);
216     }
217 
218     @Override
219     public List<FacesMessage> getMessageList(String clientId)
220     {
221         assertNotReleased();
222         
223         if (_messages == null || !_messages.containsKey(clientId))
224         {
225             return Collections.unmodifiableList(Collections.<FacesMessage>emptyList());
226         }
227         
228         return _messages.get(clientId);
229     }
230 
231     @Override
232     public final Iterator<FacesMessage> getMessages()
233     {
234         assertNotReleased();
235 
236         if (_messages == null)
237         {
238             return NullIterator.instance();
239         }
240         
241         return _orderedMessages.iterator();
242     }
243 
244     @Override
245     public final Iterator<FacesMessage> getMessages(final String clientId)
246     {
247 
248         assertNotReleased();
249 
250         if (_messages == null || !_messages.containsKey(clientId))
251         {
252             return NullIterator.instance();
253         }
254         
255         return _messages.get(clientId).iterator();        
256     }
257     
258     @Override
259     public final Iterator<String> getClientIdsWithMessages()
260     {
261         assertNotReleased();
262 
263         if (_messages == null || _messages.isEmpty())
264         {
265             return NullIterator.instance();
266         }
267         
268         return _messages.keySet().iterator();
269     }
270     
271     @Override
272     public PhaseId getCurrentPhaseId()
273     {
274         assertNotReleased();
275 
276         return _currentPhaseId;
277     }
278     
279     @Override
280     public void setCurrentPhaseId(PhaseId currentPhaseId)
281     {
282         assertNotReleased();
283 
284         _currentPhaseId = currentPhaseId;
285     }
286     
287     @Override
288     public PartialViewContext getPartialViewContext()
289     {
290         assertNotReleased();
291 
292         if (_partialViewContext == null)
293         {
294             //Get through factory finder
295             if (_partialViewContextFactory == null)
296             {
297                 _partialViewContextFactory = (PartialViewContextFactory)
298                     FactoryFinder.getFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY);
299             }
300             // Put actual facesContext as param, not this - this can be wrapped
301             _partialViewContext = _partialViewContextFactory.getPartialViewContext(FacesContext.getCurrentInstance());
302         }
303         return _partialViewContext;
304     }
305 
306     @Override
307     public final boolean getRenderResponse()
308     {
309         assertNotReleased();
310 
311         return _renderResponse;
312     }
313     
314     @Override
315     public final void renderResponse()
316     {
317         assertNotReleased();
318 
319         _renderResponse = true;
320     }
321 
322     @Override
323     public final boolean getResponseComplete()
324     {
325         assertNotReleased();
326 
327         return _responseComplete;
328     }
329     
330     @Override
331     public final void responseComplete()
332     {
333         assertNotReleased();
334 
335         _responseComplete = true;
336     }
337 
338     @Override
339     public final void setResponseStream(final ResponseStream responseStream)
340     {
341         assertNotReleased();
342 
343         if (responseStream == null)
344         {
345             throw new NullPointerException("responseStream");
346         }
347         _responseStream = responseStream;
348     }
349 
350     @Override
351     public final ResponseStream getResponseStream()
352     {
353         assertNotReleased();
354 
355         return _responseStream;
356     }
357 
358     @Override
359     public final void setResponseWriter(final ResponseWriter responseWriter)
360     {
361         assertNotReleased();
362 
363         if (responseWriter == null)
364         {
365             throw new NullPointerException(METHOD_RESPONSEWRITER);
366         }
367         _responseWriter = responseWriter;
368     }
369 
370     @Override
371     public final ResponseWriter getResponseWriter()
372     {
373         assertNotReleased();
374 
375         return _responseWriter;
376     }
377 
378     @Override
379     public boolean isPostback()
380     {
381         assertNotReleased();
382 
383         RenderKit renderKit = getRenderKit();
384         FacesContext facesContext = FacesContext.getCurrentInstance();
385         if (renderKit == null)
386         {
387             // NullPointerException with StateManager, because
388             // to restore state it first restore structure,
389             // then fill it and in the middle of the two previous
390             // process there is many calls from _ComponentChildrenList.childAdded
391             // to facesContext.isPostback, and getViewRoot is null.
392             // 
393             // Setting a "phantom" UIViewRoot calling facesContext.setViewRoot(viewRoot)
394             // to avoid it is bad, because this is work of RestoreViewExecutor,
395             // and theorically ViewHandler.restoreView must return an UIViewRoot
396             // instance.
397             //
398             // The problem with this is if the user changes the renderkit directly
399             // using f:view renderKitId param, the ResponseStateManager returned
400             // will be the one tied to faces-config selected RenderKit. But the usual 
401             // method to check if a request is a postback, is always detect the param
402             // javax.faces.ViewState, so there is no problem after all.
403             String renderKitId = facesContext.getApplication().getViewHandler().calculateRenderKitId(facesContext);
404             if (_renderKitFactory == null)
405             {
406                 _renderKitFactory = (RenderKitFactory) 
407                     FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
408             }
409             renderKit = _renderKitFactory.getRenderKit(facesContext, renderKitId);
410         }
411         return renderKit.getResponseStateManager().isPostback(facesContext);
412     }
413 
414     @Override
415     public void validationFailed()
416     {
417         assertNotReleased();
418         
419         _validationFailed=true;
420     }
421 
422     @Override
423     public boolean isValidationFailed()
424     {
425         assertNotReleased();
426         
427         return _validationFailed;
428     }
429     
430 }