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