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: bommel $)
37 * @version $Revision: 1187700 $ $Date: 2011-10-22 07:19:37 -0500 (Sat, 22 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 }