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  
23  import javax.el.ELContext;
24  import javax.faces.application.FacesMessage;
25  
26  /**
27   * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
28   *
29   * @author Manfred Geiler (latest modification by $Author: skitching $)
30   * @version $Revision: 676298 $ $Date: 2008-07-13 05:31:48 -0500 (Sun, 13 Jul 2008) $
31   */
32  public abstract class FacesContext
33  {
34      /**
35       * Return the context within which all EL-expressions are evaluated.
36       * <p>
37       * A JSF implementation is expected to provide a full implementation of this
38       * class. However JSF also explicitly allows user code to apply the "decorator"
39       * pattern to this type, by overriding the FacesContextFactory class. In that
40       * pattern, the decorating class has a reference to an "underlying" implementation
41       * and forward calls to it, possibly after taking other related actions.
42       * <p>
43       * The decorator pattern does have difficulties with backwards-compatibility when
44       * new methods are added to the class being decorated, as with this method which
45       * was added in JSF1.2. Decorator classes that were written for JSF1.1 will subclass
46       * this class, but will not override this method to pass the call on to the 
47       * "underlying" instance. This base implementation therefore must do that for it.
48       * <p>
49       * Unfortunately the JSF designers stuffed up the design; this base class has no way
50       * of knowing what the "underlying" instance is! The current implementation here
51       * is therefore to delegate directly to the very <i>first</i> FacesContext instance
52       * registered within this request (via setCurrentInstance). This instance should
53       * be the "full" implementation provided by the JSF framework. The drawback is that
54       * when any decorator class is present which defaults to this base implementation,
55       * then any following decorator instances that do override this method do not get
56       * it invoked.
57       * <p>
58       * It is believed that the Sun JSF implementation (Mojarra) does something similar.
59       * 
60       * @since 1.2
61       */
62      public ELContext getELContext()
63      {
64          // Do NOT use getCurrentInstance here. For FacesContext decorators that
65          // register themselves as "the current instance" that will cause an
66          // infinite loop. For FacesContext decorators that do not register
67          // themselves as "the current instance", if they are themselves wrapped
68          // by a decorator that *does* register itself, then an infinite loop
69          // also occurs.
70          //
71          // As noted above, we really want to do something like
72          //   ctx = getWrappedInstance();
73          // where the subclass can return the object it is delegating to. 
74          // As there is no such method, however, the best we can do is pass the
75          // method call on to the first-registered FacesContext instance. That
76          // instance will never be "this", as the real original FacesContext
77          // object will provide a proper implementation of this method.
78          FacesContext ctx = _firstInstance.get();
79  
80          if (ctx == null)
81          {
82              throw new NullPointerException(FacesContext.class.getName());
83          }
84  
85          ELContext elctx = ctx.getELContext();
86  
87          if (elctx == null)
88          {
89              throw new UnsupportedOperationException();
90          }
91  
92          return elctx;
93      }
94      
95      public abstract javax.faces.application.Application getApplication();
96  
97      public abstract Iterator<String> getClientIdsWithMessages();
98  
99      public abstract javax.faces.context.ExternalContext getExternalContext();
100 
101     public abstract FacesMessage.Severity getMaximumSeverity();
102 
103     public abstract Iterator<FacesMessage> getMessages();
104 
105     public abstract Iterator<FacesMessage> getMessages(String clientId);
106 
107     public abstract javax.faces.render.RenderKit getRenderKit();
108 
109     public abstract boolean getRenderResponse();
110 
111     public abstract boolean getResponseComplete();
112 
113     public abstract javax.faces.context.ResponseStream getResponseStream();
114 
115     public abstract void setResponseStream(javax.faces.context.ResponseStream responseStream);
116 
117     public abstract javax.faces.context.ResponseWriter getResponseWriter();
118 
119     public abstract void setResponseWriter(javax.faces.context.ResponseWriter responseWriter);
120 
121     public abstract javax.faces.component.UIViewRoot getViewRoot();
122 
123     public abstract void setViewRoot(javax.faces.component.UIViewRoot root);
124 
125     public abstract void addMessage(String clientId,
126                                     javax.faces.application.FacesMessage message);
127 
128     public abstract void release();
129 
130     public abstract void renderResponse();
131 
132     public abstract void responseComplete();
133 
134     private static ThreadLocal<FacesContext> _currentInstance = new ThreadLocal<FacesContext>()
135     {
136         protected FacesContext initialValue()
137         {
138             return null;
139         }
140     };
141 
142     private static ThreadLocal<FacesContext> _firstInstance = new ThreadLocal<FacesContext>()
143     {
144         protected FacesContext initialValue()
145         {
146             return null;
147         }
148     };
149 
150     public static FacesContext getCurrentInstance()
151     {
152         return _currentInstance.get();
153     }
154 
155     protected static void setCurrentInstance(javax.faces.context.FacesContext context)
156     {
157         if (context == null)
158         {
159             _currentInstance.remove();
160             _firstInstance.remove();
161         }
162         else
163         {
164             _currentInstance.set(context);
165             
166             if (_firstInstance.get() == null)
167             {
168                 _firstInstance.set(context);
169             }
170         }
171     }
172 }