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