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