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 javax.faces.context;
20  
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  
26  import javax.el.ELContext;
27  import javax.faces.application.Application;
28  import javax.faces.application.FacesMessage;
29  import javax.faces.application.ProjectStage;
30  import javax.faces.component.UINamingContainer;
31  import javax.faces.component.UIViewRoot;
32  import javax.faces.event.PhaseId;
33  import javax.faces.render.RenderKit;
34  
35  /**
36   * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
37   */
38  public abstract class FacesContext
39  {
40      private static ThreadLocal<FacesContext> currentInstance = new ThreadLocal<FacesContext>();
41  
42      private static ThreadLocal<FacesContext> firstInstance = new ThreadLocal<FacesContext>();
43  
44      public abstract void addMessage(String clientId, FacesMessage message);
45  
46      public abstract Application getApplication();
47  
48      /**
49       * 
50       * @return
51       * 
52       * @since 2.0
53       */
54      public Map<Object, Object> getAttributes()
55      {
56          FacesContext ctx = firstInstance.get();
57          
58          if (ctx == null)
59          {
60              throw new UnsupportedOperationException();
61          }
62          
63          return ctx.getAttributes();
64      }
65  
66      public abstract Iterator<String> getClientIdsWithMessages();
67  
68      public static FacesContext getCurrentInstance()
69      {
70          return currentInstance.get();
71      }
72  
73      /**
74       * 
75       * @return
76       * 
77       * @since 2.0
78       */
79      public PhaseId getCurrentPhaseId()
80      {
81          FacesContext ctx = firstInstance.get();
82          
83          if (ctx == null)
84          {
85              throw new UnsupportedOperationException();
86          }
87          
88          return ctx.getCurrentPhaseId();
89      }
90      
91      /**
92       * Return the context within which all EL-expressions are evaluated.
93       * <p>
94       * A JSF implementation is expected to provide a full implementation of this class. However JSF also explicitly
95       * allows user code to apply the "decorator" pattern to this type, by overriding the FacesContextFactory class. In
96       * that pattern, the decorating class has a reference to an "underlying" implementation and forward calls to it,
97       * possibly after taking other related actions.
98       * <p>
99       * The decorator pattern does have difficulties with backwards-compatibility when new methods are added to the class
100      * being decorated, as with this method which was added in JSF1.2. Decorator classes that were written for JSF1.1
101      * will subclass this class, but will not override this method to pass the call on to the "underlying" instance.
102      * This base implementation therefore must do that for it.
103      * <p>
104      * Unfortunately the JSF designers stuffed up the design; this base class has no way of knowing what the
105      * "underlying" instance is! The current implementation here is therefore to delegate directly to the very
106      * <i>first</i> FacesContext instance registered within this request (via setCurrentInstance). This instance should
107      * be the "full" implementation provided by the JSF framework. The drawback is that when any decorator class is
108      * present which defaults to this base implementation, then any following decorator instances that do override this
109      * method do not get it invoked.
110      * <p>
111      * It is believed that the Sun JSF implementation (Mojarra) does something similar.
112      * 
113      * @since 1.2
114      */
115     public ELContext getELContext()
116     {
117         // Do NOT use getCurrentInstance here. For FacesContext decorators that
118         // register themselves as "the current instance" that will cause an
119         // infinite loop. For FacesContext decorators that do not register
120         // themselves as "the current instance", if they are themselves wrapped
121         // by a decorator that *does* register itself, then an infinite loop
122         // also occurs.
123         //
124         // As noted above, we really want to do something like
125         // ctx = getWrappedInstance();
126         // where the subclass can return the object it is delegating to.
127         // As there is no such method, however, the best we can do is pass the
128         // method call on to the first-registered FacesContext instance. That
129         // instance will never be "this", as the real original FacesContext
130         // object will provide a proper implementation of this method.
131         FacesContext ctx = firstInstance.get();
132 
133         if (ctx == null)
134         {
135             throw new NullPointerException(FacesContext.class.getName());
136         }
137 
138         ELContext elctx = ctx.getELContext();
139         if (elctx == null)
140         {
141             throw new UnsupportedOperationException();
142         }
143 
144         return elctx;
145     }
146 
147     /**
148      * 
149      * @return
150      * 
151      * @since 2.0
152      */
153     public ExceptionHandler getExceptionHandler()
154     {
155         FacesContext ctx = firstInstance.get();
156         
157         if (ctx == null)
158         {
159             throw new UnsupportedOperationException();
160         }
161         
162         return ctx.getExceptionHandler();
163     }
164 
165     public abstract ExternalContext getExternalContext();
166 
167     public abstract FacesMessage.Severity getMaximumSeverity();
168 
169     /**
170      * 
171      * @return
172      * 
173      * @since 2.0
174      */
175     public List<FacesMessage> getMessageList()
176     {
177         FacesContext ctx = firstInstance.get();
178         
179         if (ctx == null)
180         {
181             throw new UnsupportedOperationException();
182         }
183         
184         return ctx.getMessageList();
185     }
186     
187     /**
188      * 
189      * @param clientId
190      * @return
191      * 
192      * @since 2.0
193      */
194     public List<FacesMessage> getMessageList(String clientId)
195     {
196         FacesContext ctx = firstInstance.get();
197         
198         if (ctx == null)
199         {
200             throw new UnsupportedOperationException();
201         }
202         
203         return ctx.getMessageList(clientId);
204     }
205 
206     public abstract Iterator<FacesMessage> getMessages();
207 
208     public abstract Iterator<FacesMessage> getMessages(String clientId);
209 
210     /**
211      * <p>
212      * Return the PartialViewContext for this request. The PartialViewContext is used to control the processing of
213      * specified components during the execute portion of the request processing lifecycle (known as partial processing)
214      * and the rendering of specified components (known as partial rendering). This method must return a new
215      * PartialViewContext if one does not already exist.
216      * </p>
217      * 
218      * @return The PartialViewContext
219      * @throws IllegalStateException
220      *             if this method is called after this instance has been released
221      * 
222      * @since 2.0
223      */
224     public PartialViewContext getPartialViewContext()
225     {
226         FacesContext ctx = firstInstance.get();
227         
228         if (ctx == null)
229         {
230             throw new UnsupportedOperationException();
231         }
232         
233         return ctx.getPartialViewContext();
234     }
235 
236     public abstract RenderKit getRenderKit();
237 
238     public abstract boolean getRenderResponse();
239 
240     public abstract boolean getResponseComplete();
241 
242     public abstract ResponseStream getResponseStream();
243 
244     public abstract ResponseWriter getResponseWriter();
245     
246     /**
247      * 
248      * @return
249      * 
250      * @since 2.0
251      */
252     public boolean isValidationFailed()
253     {
254         FacesContext ctx = firstInstance.get();
255         
256         if (ctx == null)
257         {
258             throw new UnsupportedOperationException();
259         }
260         
261         return ctx.isValidationFailed();
262     }
263 
264     public abstract UIViewRoot getViewRoot();
265 
266     /**
267      * 
268      * @return
269      * 
270      * @since 2.0
271      */
272     public boolean isPostback()
273     {
274         FacesContext ctx = firstInstance.get();
275         
276         if (ctx == null)
277         {
278             throw new UnsupportedOperationException();
279         }
280         
281         return ctx.isPostback();
282     }
283     
284     /**
285      * 
286      * @return
287      * 
288      * @since 2.0
289      */
290     public boolean isProcessingEvents()
291     {
292         FacesContext ctx = firstInstance.get();
293         
294         if (ctx == null)
295         {
296             throw new UnsupportedOperationException();
297         }
298         
299         return ctx.isProcessingEvents();
300     }
301 
302     public abstract void release();
303 
304     public abstract void renderResponse();
305 
306     public abstract void responseComplete();
307 
308     protected static void setCurrentInstance(FacesContext context)
309     {
310         if (context == null)
311         {
312             currentInstance.remove();
313             firstInstance.remove();
314         }
315         else
316         {
317             currentInstance.set(context);
318 
319             if (firstInstance.get() == null)
320             {
321                 firstInstance.set(context);
322             }
323         }
324     }
325 
326     /**
327      * 
328      * @param currentPhaseId 
329      * @since 2.0
330      */
331     public void setCurrentPhaseId(PhaseId currentPhaseId)
332     {
333         FacesContext ctx = firstInstance.get();
334         
335         if (ctx == null)
336         {
337             throw new UnsupportedOperationException();
338         }
339         
340         ctx.setCurrentPhaseId(currentPhaseId);
341     }
342 
343     /**
344      * 
345      * @param exceptionHandler 
346      * @since 2.0
347      */
348     public void setExceptionHandler(ExceptionHandler exceptionHandler)
349     {
350         FacesContext ctx = firstInstance.get();
351         
352         if (ctx == null)
353         {
354             throw new UnsupportedOperationException();
355         }
356         
357         ctx.setExceptionHandler(exceptionHandler);
358     }
359     
360     /**
361      * 
362      * @param processingEvents
363      * @since 2.0
364      */
365     public void setProcessingEvents(boolean processingEvents)
366     {
367         FacesContext ctx = firstInstance.get();
368         
369         if (ctx == null)
370         {
371             throw new UnsupportedOperationException();
372         }
373         
374         ctx.setProcessingEvents(processingEvents);
375     }
376 
377     public abstract void setResponseStream(ResponseStream responseStream);
378 
379     public abstract void setResponseWriter(ResponseWriter responseWriter);
380 
381     public abstract void setViewRoot(UIViewRoot root);
382     
383     /**
384      * 
385      * 
386      * @since 2.0
387      */
388     public void validationFailed()
389     {
390         FacesContext ctx = firstInstance.get();
391         
392         if (ctx == null)
393         {
394             throw new UnsupportedOperationException();
395         }
396         
397         ctx.validationFailed();
398     }
399     
400     public boolean isProjectStage(ProjectStage stage)
401     {
402         if (stage == null)
403         {
404             throw new NullPointerException();
405         }
406         
407         if (stage.equals(getApplication().getProjectStage()))
408         {
409             return true;
410         }
411         return false;
412     }
413     
414     /**
415      * 
416      * @since 2.1
417      * @return
418      */
419     public boolean isReleased()
420     {
421         FacesContext ctx = firstInstance.get();
422         
423         if (ctx == null)
424         {
425             throw new UnsupportedOperationException();
426         }
427 
428         return ctx.isReleased();
429     }
430     
431     /**
432      * @since 2.2
433      * @return 
434      */
435     public List<String> getResourceLibraryContracts()
436     {
437         FacesContext ctx = firstInstance.get();
438         
439         if (ctx == null)
440         {
441             return Collections.emptyList();
442         }        
443         
444         return ctx.getResourceLibraryContracts();
445     }
446     
447     /**
448      * @since 2.2
449      * @param contracts 
450      */
451     public void setResourceLibraryContracts(List<String> contracts)
452     {
453         FacesContext ctx = firstInstance.get();
454         
455         if (ctx == null)
456         {
457             return;
458         }
459         ctx.setResourceLibraryContracts(contracts);
460     }
461     
462     /**
463      * @since 2.2
464      * @return 
465      */
466     public char getNamingContainerSeparatorChar()
467     {
468         FacesContext ctx = firstInstance.get();
469         
470         if (ctx == null)
471         {
472             return UINamingContainer.getSeparatorChar(this);
473         }
474         return ctx.getNamingContainerSeparatorChar();
475     }
476 }