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      * @return
329      * 
330      * @since 2.0
331      */
332     public void setCurrentPhaseId(PhaseId currentPhaseId)
333     {
334         FacesContext ctx = firstInstance.get();
335         
336         if (ctx == null)
337         {
338             throw new UnsupportedOperationException();
339         }
340         
341         ctx.setCurrentPhaseId(currentPhaseId);
342     }
343 
344     /**
345      * 
346      * @return
347      * 
348      * @since 2.0
349      */
350     public void setExceptionHandler(ExceptionHandler exceptionHandler)
351     {
352         FacesContext ctx = firstInstance.get();
353         
354         if (ctx == null)
355         {
356             throw new UnsupportedOperationException();
357         }
358         
359         ctx.setExceptionHandler(exceptionHandler);
360     }
361     
362     /**
363      * 
364      * @param processingEvents
365      * 
366      * @since 2.0
367      */
368     public void setProcessingEvents(boolean processingEvents)
369     {
370         FacesContext ctx = firstInstance.get();
371         
372         if (ctx == null)
373         {
374             throw new UnsupportedOperationException();
375         }
376         
377         ctx.setProcessingEvents(processingEvents);
378     }
379 
380     public abstract void setResponseStream(ResponseStream responseStream);
381 
382     public abstract void setResponseWriter(ResponseWriter responseWriter);
383 
384     public abstract void setViewRoot(UIViewRoot root);
385     
386     /**
387      * 
388      * 
389      * @since 2.0
390      */
391     public void validationFailed()
392     {
393         FacesContext ctx = firstInstance.get();
394         
395         if (ctx == null)
396         {
397             throw new UnsupportedOperationException();
398         }
399         
400         ctx.validationFailed();
401     }
402     
403     public boolean isProjectStage(ProjectStage stage)
404     {
405         if (stage == null)
406         {
407             throw new NullPointerException();
408         }
409         
410         if (stage.equals(getApplication().getProjectStage()))
411         {
412             return true;
413         }
414         return false;
415     }
416     
417     /**
418      * 
419      * @since 2.1
420      * @return
421      */
422     public boolean isReleased()
423     {
424         FacesContext ctx = firstInstance.get();
425         
426         if (ctx == null)
427         {
428             throw new UnsupportedOperationException();
429         }
430 
431         return ctx.isReleased();
432     }
433     
434     /**
435      * @since 2.2
436      * @return 
437      */
438     public List<String> getResourceLibraryContracts()
439     {
440         FacesContext ctx = firstInstance.get();
441         
442         if (ctx == null)
443         {
444             return Collections.emptyList();
445         }        
446         
447         return ctx.getResourceLibraryContracts();
448     }
449     
450     /**
451      * @since 2.2
452      * @param contracts 
453      */
454     public void setResourceLibraryContracts(List<String> contracts)
455     {
456         FacesContext ctx = firstInstance.get();
457         
458         if (ctx == null)
459         {
460             return;
461         }
462         ctx.setResourceLibraryContracts(contracts);
463     }
464     
465     /**
466      * @since 2.2
467      * @return 
468      */
469     public char getNamingContainerSeparatorChar()
470     {
471         FacesContext ctx = firstInstance.get();
472         
473         if (ctx == null)
474         {
475             return UINamingContainer.getSeparatorChar(this);
476         }
477         return ctx.getNamingContainerSeparatorChar();
478     }
479 }