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.application;
20
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.ResourceBundle;
27
28 import javax.el.ELContextListener;
29 import javax.el.ELException;
30 import javax.el.ELResolver;
31 import javax.el.ExpressionFactory;
32 import javax.el.ValueExpression;
33 import javax.faces.FacesException;
34 import javax.faces.component.ActionSource;
35 import javax.faces.component.ActionSource2;
36 import javax.faces.component.UIComponent;
37 import javax.faces.context.ExternalContext;
38 import javax.faces.component.UIViewRoot;
39 import javax.faces.component.behavior.Behavior;
40 import javax.faces.context.FacesContext;
41 import javax.faces.convert.Converter;
42 import javax.faces.el.MethodBinding;
43 import javax.faces.el.PropertyResolver;
44 import javax.faces.el.ReferenceSyntaxException;
45 import javax.faces.el.ValueBinding;
46 import javax.faces.el.VariableResolver;
47 import javax.faces.event.AbortProcessingException;
48 import javax.faces.event.ActionListener;
49 import javax.faces.event.SystemEvent;
50 import javax.faces.event.SystemEventListener;
51 import javax.faces.event.SystemEventListenerHolder;
52 import javax.faces.validator.Validator;
53
54 /**
55 * <p>
56 * Application represents a per-web-application singleton object where applications based on JavaServer Faces (or
57 * implementations wishing to provide extended functionality) can register application-wide singletons that provide
58 * functionality required by JavaServer Faces. Default implementations of each object are provided for cases where the
59 * application does not choose to customize the behavior.
60 * </p>
61 *
62 * <p>
63 * The instance of {@link Application} is created by calling the <code>getApplication()</code> method of
64 * {@link ApplicationFactory}. Because this instance is shared, it must be implemented in a thread-safe manner.
65 * </p>
66 *
67 * Holds webapp-wide resources for a JSF application. There is a single one of these for a web application, accessable
68 * via
69 *
70 * <pre>
71 * FacesContext.getCurrentInstance().getApplication()
72 * </pre>
73 *
74 * In particular, this provides a factory for UIComponent objects. It also provides convenience methods for creating
75 * ValueBinding objects.
76 *
77 * See Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
78 *
79 * @author Manfred Geiler (latest modification by $Author: bommel $)
80 * @author Stan Silvert
81 * @version $Revision: 1187700 $ $Date: 2011-10-22 07:19:37 -0500 (Sat, 22 Oct 2011) $
82 */
83 @SuppressWarnings("deprecation")
84 public abstract class Application
85 {
86
87 /**
88 * Retrieve the current Myfaces Application Instance, lookup
89 * on the application map. All methods introduced on jsf 1.2
90 * for Application interface should thrown by default
91 * UnsupportedOperationException, but the ri scan and find the
92 * original Application impl, and redirect the call to that
93 * method instead throwing it, allowing application implementations
94 * created before jsf 1.2 continue working.
95 *
96 * Note: every method, which uses getMyfacesApplicationInstance() to
97 * delegate itself to the current ApplicationImpl MUST be
98 * overriden by the current ApplicationImpl to prevent infinite loops.
99 */
100 private Application getMyfacesApplicationInstance()
101 {
102 FacesContext facesContext = FacesContext.getCurrentInstance();
103 if (facesContext != null)
104 {
105 ExternalContext externalContext = facesContext.getExternalContext();
106 if (externalContext != null)
107 {
108 return (Application) externalContext.getApplicationMap().get("org.apache.myfaces.application.ApplicationImpl");
109 }
110 }
111 return null;
112 }
113
114 private Application getMyfacesApplicationInstance(FacesContext facesContext)
115 {
116 if (facesContext != null)
117 {
118 ExternalContext externalContext = facesContext.getExternalContext();
119 if (externalContext != null)
120 {
121 return (Application) externalContext.getApplicationMap().get("org.apache.myfaces.application.ApplicationImpl");
122 }
123 }
124 return null;
125 }
126
127 // The concrete methods throwing UnsupportedOperationExceptiom were added for JSF 1.2.
128 // They supply default to allows old Application implementations to still work.
129
130 /**
131 * @since 2.0
132 *
133 * FIXME: Notify EG, this should not be abstract and throw UnsupportedOperationException
134 */
135 public void addBehavior(String behaviorId, String behaviorClass)
136 {
137 Application application = getMyfacesApplicationInstance();
138 if (application != null)
139 {
140 application.addBehavior(behaviorId, behaviorClass);
141 return;
142 }
143 throw new UnsupportedOperationException();
144 }
145
146 /**
147 * Define a new mapping from a logical "component type" to an actual java class name. This controls what type is
148 * created when method createComponent of this class is called.
149 * <p>
150 * Param componentClass must be the fully-qualified class name of some class extending the UIComponent class. The
151 * class must have a default constructor, as instances of it will be created using Class.newInstance.
152 * <p>
153 * It is permitted to override a previously defined mapping, ie to call this method multiple times with the same
154 * componentType string. The createComponent method will simply use the last defined mapping.
155 */
156 /**
157 * Register a new mapping of component type to the name of the corresponding {@link UIComponent} class. This allows
158 * subsequent calls to <code>createComponent()</code> to serve as a factory for {@link UIComponent} instances.
159 *
160 * @param componentType
161 * - The component type to be registered
162 * @param componentClass
163 * - The fully qualified class name of the corresponding {@link UIComponent} implementation
164 *
165 * @throws NullPointerException
166 * if <code>componentType</code> or <code>componentClass</code> is <code>null</code>
167 */
168 public abstract void addComponent(String componentType, String componentClass);
169
170 /**
171 * Register a new converter class that is capable of performing conversions for the specified target class.
172 *
173 * @param targetClass
174 * - The class for which this converter is registered
175 * @param converterClass
176 * - The fully qualified class name of the corresponding {@link Converter} implementation
177 *
178 * @throws NullPointerException
179 * if <code>targetClass</code> or <code>converterClass</code> is <code>null</code>
180 */
181 public abstract void addConverter(Class<?> targetClass, String converterClass);
182
183 /**
184 * Register a new mapping of converter id to the name of the corresponding {@link Converter} class. This allows
185 * subsequent calls to createConverter() to serve as a factory for {@link Converter} instances.
186 *
187 * @param componentType
188 * - The component type to be registered
189 * @param componentClass
190 * - The fully qualified class name of the corresponding {@link UIComponent} implementation
191 *
192 * @throws NullPointerException
193 * if <code>componentType</code> or <code>componentClass</code> is <code>null</code>
194 */
195 public abstract void addConverter(String converterId, String converterClass);
196
197 /**
198 *
199 * @param validatorId
200 *
201 * @since 2.0
202 */
203 public void addDefaultValidatorId(String validatorId)
204 {
205 }
206
207 /**
208 * <p>
209 * Provide a way for Faces applications to register an <code>ELContextListener</code> that will be notified on
210 * creation of <code>ELContext</code> instances.
211 * <p>
212 *
213 * <p>
214 * An implementation is provided that throws <code>UnsupportedOperationException</code> so that users that decorate
215 * the <code>Application</code> continue to work.
216 * </p>
217 *
218 * @since 1.2
219 */
220 public void addELContextListener(ELContextListener listener)
221 {
222 Application application = getMyfacesApplicationInstance();
223 if (application != null)
224 {
225 application.addELContextListener(listener);
226 return;
227 }
228 throw new UnsupportedOperationException();
229 }
230
231 /**
232 * <p>
233 * Cause an the argument <code>resolver</code> to be added to the resolver chain as specified in section 5.5.1 of
234 * the JavaServer Faces Specification.
235 * </p>
236 *
237 * <p>
238 * It is not possible to remove an <code>ELResolver</code> registered with this method, once it has been registered.
239 * </p>
240 *
241 * <p>
242 * It is illegal to register an ELResolver after the application has received any requests from the client. If an
243 * attempt is made to register a listener after that time, an IllegalStateException must be thrown. This restriction
244 * is in place to allow the JSP container to optimize for the common case where no additional
245 * <code>ELResolvers</code> are in the chain, aside from the standard ones. It is permissible to add
246 * <code>ELResolvers</code> before or after initialization to a CompositeELResolver that is already in the chain.
247 * <p>
248 *
249 * <p>
250 * The default implementation throws <code>UnsupportedOperationException</code> and is provided for the sole purpose
251 * of not breaking existing applications that extend {@link Application}.
252 * </p>
253 *
254 * @since 1.2
255 */
256 public void addELResolver(ELResolver resolver)
257 {
258 // The following concrete methods were added for JSF 1.2. They supply default
259 // implementations that throw UnsupportedOperationException.
260 // This allows old Application implementations to still work.
261 Application application = getMyfacesApplicationInstance();
262 if (application != null)
263 {
264 application.addELResolver(resolver);
265 return;
266 }
267 throw new UnsupportedOperationException();
268 }
269
270 /**
271 *Register a new mapping of validator id to the name of the corresponding <code>Validator</code> class. This allows
272 * subsequent calls to <code>createValidator()</code> to serve as a factory for <code>Validator</code> instances.
273 *
274 *@param <code>validatorId</code> - The validator id to be registered
275 *@param <code>validatorClass</code> - The fully qualified class name of the corresponding Validator implementation
276 *
277 *@throws NullPointerException
278 * if <code>validatorId</code> or <code>validatorClass</code> is <code>null</code>
279 */
280 public abstract void addValidator(String validatorId, String validatorClass);
281
282 /**
283 *
284 * @param behaviorId
285 * @return
286 * @throws FacesException
287 * @since 2.0
288 *
289 * FIXME: Notify EG, this should not be abstract and throw UnsupportedOperationException
290 */
291 public Behavior createBehavior(String behaviorId) throws FacesException
292 {
293 Application application = getMyfacesApplicationInstance();
294 if (application != null)
295 {
296 return application.createBehavior(behaviorId);
297 }
298 throw new UnsupportedOperationException();
299 }
300
301 /**
302 * ???
303 *
304 * @param context
305 * @param componentResource
306 * @return
307 *
308 * @since 2.0
309 */
310 public UIComponent createComponent(FacesContext context, Resource componentResource)
311 {
312 Application application = getMyfacesApplicationInstance(context);
313 if (application != null)
314 {
315 return application.createComponent(context, componentResource);
316 }
317 throw new UnsupportedOperationException();
318 }
319
320 /**
321 *
322 * @param context
323 * @param componentType
324 * @param rendererType
325 * @return
326 *
327 * @since 2.0
328 */
329 public UIComponent createComponent(FacesContext context, String componentType, String rendererType)
330 {
331 Application application = getMyfacesApplicationInstance(context);
332 if (application != null)
333 {
334 return application.createComponent(context, componentType, rendererType);
335 }
336 throw new UnsupportedOperationException();
337 }
338
339 /**
340 * <p>
341 * Create a new UIComponent subclass, using the mappings defined by previous calls to the addComponent method of
342 * this class.
343 * </p>
344 *
345 * @throws FacesException
346 * if there is no mapping defined for the specified componentType, or if an instance of the specified
347 * type could not be created for any reason.
348 */
349 public abstract UIComponent createComponent(String componentType) throws FacesException;
350
351 /**
352 * <p>
353 * Create an object which has an associating "binding" expression tying the component to a user property.
354 * </p>
355 *
356 * <p>
357 * First the specified value-binding is evaluated; if it returns a non-null value then the component
358 * "already exists" and so the resulting value is simply returned.
359 * </p>
360 *
361 * <p>
362 * Otherwise a new UIComponent instance is created using the specified componentType, and the new object stored via
363 * the provided value-binding before being returned.
364 * </p>
365 *
366 * @deprecated
367 */
368 public abstract UIComponent createComponent(ValueBinding componentBinding, FacesContext context,
369 String componentType) throws FacesException;
370
371 /**
372 * <p>
373 * Call the <code>getValue()</code> method on the specified <code>ValueExpression</code>. If it returns a
374 * <code>{@link UIComponent}</code> instance, return it as the value of this method. If it does not, instantiate a
375 * new <code>{@linkUIComponent}</code> instance of the specified component type, pass the new component to the
376 * <code>setValue()</code> method of the specified <code>ValueExpression</code>, and return it.
377 * </p>
378 *
379 * @param componentExpression
380 * - <code>ValueExpression</code> representing a component value expression (typically specified by the
381 * <code>component</code> attribute of a custom tag)
382 * @param context
383 * - {@link FacesContext} for the current request
384 * @param componentType
385 * - Component type to create if the ValueExpression does not return a component instance
386 *
387 * @throws FacesException
388 * if a <code>{@link UIComponent}</code> cannot be created
389 * @throws NullPointerException
390 * if any parameter is null
391 * <p>
392 * A default implementation is provided that throws <code>UnsupportedOperationException</code> so that
393 * users that decorate <code>Application</code> can continue to function
394 * </p>
395 *
396 * @since 1.2
397 */
398 public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType)
399 throws FacesException
400 {
401 Application application = getMyfacesApplicationInstance(context);
402 if (application != null)
403 {
404 return application.createComponent(componentExpression, context, componentType);
405 }
406 throw new UnsupportedOperationException();
407 }
408
409 /**
410 *
411 * @param componentExpression
412 * @param context
413 * @param componentType
414 * @param rendererType
415 * @return
416 *
417 * @since 2.0
418 */
419 public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType,
420 String rendererType)
421 {
422 Application application = getMyfacesApplicationInstance(context);
423 if (application != null)
424 {
425 return application.createComponent(componentExpression, context,
426 componentType, rendererType);
427 }
428 throw new UnsupportedOperationException();
429 }
430
431 /**
432 * <p>
433 * Instantiate and return a new <code>{@link Converter}</code> instance of the class that has registered itself as
434 * capable of performing conversions for objects of the specified type. If no such <code>{@link Converter}</code>
435 * class can be identified, return null.
436 * </p>
437 *
438 * <p>
439 * To locate an appropriate <code>{@link Converter}</code> class, the following algorithm is performed, stopping as
440 * soon as an appropriate <code>{@link Converter}</code> class is found: Locate a <code>{@link Converter}</code>
441 * registered for the target class itself. <Locate a <code>{@link Converter}</code> registered for interfaces that
442 * are implemented by the target class (directly or indirectly). Locate a <code>{@link Converter}</code> registered
443 * for the superclass (if any) of the target class, recursively working up the inheritance hierarchy.
444 * </p>
445 *
446 * <p>
447 * If the <code>{@link Converter}</code> has a single argument constructor that accepts a Class, instantiate the
448 * <code>{@link Converter}</code> using that constructor, passing the argument <code>{@link targetClass}</code> as
449 * the sole argument. Otherwise, simply use the zero-argument constructor.
450 *
451 * @param targetClass
452 * - Target class for which to return a <code>{@link Converter}</code>
453 *
454 * @throws FacesException
455 * if the <code>{@link Converter}</code> cannot be created
456 * @throws NullPointerException
457 * if <code>targetClass</code> is <code>null</code>
458 *
459 */
460 public abstract Converter createConverter(Class<?> targetClass);
461
462 /**
463 * Instantiate and return a new <code>{@link Converter}</code> instance of the class specified by a previous call to
464 * <code>addConverter()</code> for the specified converter id. If there is no such registration for this converter
465 * id, return <code>null</code>.
466 *
467 * @param converterId
468 * - The converter id for which to create and return a new <code>{@link Converter}</code> instance
469 *
470 * @throws FacesException
471 * if the <code>{@link Converter}</code> cannot be created
472 * @throws NullPointerException
473 * if converterId is <code>null</code>
474 */
475 public abstract Converter createConverter(String converterId);
476
477 /**
478 * Create an object which can be used to invoke an arbitrary method via an EL expression at a later time. This is
479 * similar to createValueBinding except that it can invoke an arbitrary method (with parameters) rather than just
480 * get/set a javabean property.
481 * <p>
482 * This is used to invoke ActionListener method, and ValueChangeListener methods.
483 *
484 * @deprecated
485 */
486 public abstract MethodBinding createMethodBinding(String ref, Class<?>[] params) throws ReferenceSyntaxException;
487
488 /**
489 * Instantiate and return a new <code>{@link Validator}</code> instance of the class specified by a previous call to
490 * <code>addValidator()</code> for the specified validator id.
491 *
492 * @param <code>validatorId</code>- The <code>{@link Validator}</code> id for which to create and return a new
493 * Validator instance
494 *
495 * @throws FacesException
496 * if a <code>{@link Validator}/<code> of the specified id cannot be created
497 * @throws NullPointerException
498 * if validatorId is <code>null</code>
499 */
500 public abstract Validator createValidator(String validatorId) throws FacesException;
501
502 /**
503 * <p>
504 * Create an object which can be used to invoke an arbitrary method via an EL expression at a later time. This is
505 * similar to createValueBinding except that it can invoke an arbitrary method (with parameters) rather than just
506 * get/set a javabean property.
507 * </p>
508 * This is used to invoke ActionListener method, and ValueChangeListener methods.
509 *
510 * @deprecated
511 */
512 public abstract ValueBinding createValueBinding(String ref) throws ReferenceSyntaxException;
513
514 /**
515 * <p>
516 * Get a value by evaluating an expression.
517 * </p>
518 *
519 * <p>
520 * Call <code>{@link getExpressionFactory()}</code> then call
521 * <code>ExpressionFactory.createValueExpression(javax.el.ELContext, java.lang.String, java.lang.Class)</code>
522 * passing the argument <code>expression</code> and <code>expectedType</code>. Call
523 * <code>{@link FacesContext#getELContext()}</code> and pass it to
524 * <code>ValueExpression.getValue(javax.el.ELContext)</code>, returning the result.
525 * </p>
526 *
527 * <p>
528 * An implementation is provided that throws <code>UnsupportedOperationException</code> so that users that decorate
529 * the <code>Application</code> continue to work.
530 * <p>
531 *
532 * @throws javax.el.ELException
533 */
534 public <T> T evaluateExpressionGet(FacesContext context, String expression, Class<? extends T> expectedType)
535 throws ELException
536 {
537 Application application = getMyfacesApplicationInstance(context);
538 if (application != null)
539 {
540 return application.evaluateExpressionGet(context, expression, expectedType);
541 }
542 throw new UnsupportedOperationException();
543 }
544
545 /**
546 * <p>
547 * Return the default <code>ActionListener</code> to be registered for all <code>ActionSource<3code> components
548 * in this appication. If not explicitly set, a default implementation must be provided that performs the
549 * following functions:
550 * </p>
551 * <ul>
552 * <li>The <code>processAction()</code> method must first call <code>FacesContext.renderResponse()</code>in order to
553 * bypass any intervening lifecycle phases, once the method returns.</li>
554 *
555 * <li>The <code>processAction()</code> method must next determine the logical outcome of this event, as follows:</li>
556 *
557 * <ul>
558 * <li>If the originating component has a non-<code>null action</code> property, retrieve the <code>
559 * MethodBinding<code> from the property, and call <code>invoke()</code>
560 * on it. Convert the returned value (if any) to a String, and use it as the logical outcome.</li>
561 * <li>Otherwise, the logical outcome is null.</li>
562 * </ul>
563 * </ul>
564 * <ul>
565 * <li>The <code>processAction()</code> method must finally retrieve the <code>NavigationHandler<3code> instance
566 * for this application and call <code>NavigationHandler.handleNavigation(javax.faces.context.FacesContext,
567 * java.lang.String, java.lang.String)</code> passing:</li>
568 * <ul>
569 * <li>the {@link FacesContext} for the current request</li>
570 * <li>If there is a <code>MethodBinding</code> instance for the <code>action</code> property of this component, the
571 * result of calling {@link MethodBinding.getExpressionString()} on it, null otherwise</li>
572 * <li>the logical outcome as determined above</li>
573 * <ul>
574 * </ul>
575 * <p>
576 * Note that the specification for the default <code>ActionListener</code> contiues to call for the use of a
577 * deprecated property (<code>action</code>) and class (<code>MethodBinding</code>). Unfortunately, this is
578 * necessary because the default ActionListener must continue to work with components that do not implement
579 * {@link ActionSource2}, and only implement {@link ActionSource}.
580 */
581 public abstract ActionListener getActionListener();
582
583 /**
584 *
585 * @return
586 *
587 * @since 2.0
588 *
589 * FIXME: Notify EG, this should not be abstract and throw UnsupportedOperationException
590 */
591 public Iterator<String> getBehaviorIds()
592 {
593 Application application = getMyfacesApplicationInstance();
594 if (application != null)
595 {
596 return application.getBehaviorIds();
597 }
598 // It is better to return an empty iterator,
599 // to keep compatiblity with previous jsf 2.0 Application
600 // instances
601 return Collections.EMPTY_LIST.iterator();
602 }
603
604 /**
605 * Return an <code>Iterator</code> over the set of currently defined component types for this
606 * <code>Application</code>.
607 */
608 public abstract Iterator<String> getComponentTypes();
609
610 /**
611 * Return an <code>Iterator</code> over the set of currently registered converter ids for this
612 * <code>Application</code>
613 *
614 * @return
615 */
616 public abstract Iterator<String> getConverterIds();
617
618 /**
619 *Return an <code>Iterator</code> over the set of <code>Class</code> instances for which <code>{@link Converter}
620 * </code> <code>classes</code>have been explicitly registered.
621 *
622 * @return
623 */
624 public abstract Iterator<Class<?>> getConverterTypes();
625
626 /**
627 *Return the default <code>Locale</code> for this application. If not explicitly set, <code>null</code> is
628 * returned.
629 *
630 * @return
631 */
632 public abstract Locale getDefaultLocale();
633
634 /**
635 * Return the <code>renderKitId</code> to be used for rendering this application. If not explicitly set,
636 * <code>null</code> is returned.
637 *
638 * @return
639 */
640 public abstract String getDefaultRenderKitId();
641
642 /**
643 *
644 * @return
645 *
646 * @since 2.0
647 */
648 public Map<String, String> getDefaultValidatorInfo()
649 {
650 Application application = getMyfacesApplicationInstance();
651 if (application != null)
652 {
653 return application.getDefaultValidatorInfo();
654 }
655 throw new UnsupportedOperationException();
656 }
657
658 /**
659 * <p>
660 * If no calls have been made to <code>addELContextListener(javax.el.ELContextListener)</code>, this method must
661 * return an empty array
662 * <p>
663 * .
664 *
665 * <p>
666 * Otherwise, return an array representing the list of listeners added by calls to
667 * <code>addELContextListener(javax.el.ELContextListener)</code>.
668 * <p>
669 *
670 * <p>
671 * An <code>implementation</code> is provided that throws UnsupportedOperationException so that users that decorate
672 * the <code>Application</code> continue to work.
673 * </p>
674 *
675 * @since 1.2
676 */
677 public ELContextListener[] getELContextListeners()
678 {
679 Application application = getMyfacesApplicationInstance();
680 if (application != null)
681 {
682 return application.getELContextListeners();
683 }
684 throw new UnsupportedOperationException();
685 }
686
687 /**
688 * <ul>
689 * Return the singleton <code>ELResolver</code> instance to be used for all EL resolution. This is actually an
690 * instance of <code>CompositeELResolver</code> that must contain the following ELResolver instances in the
691 * following order:
692 * <li><code>ELResolver</code> instances declared using the <el-resolver> element in the application configuration
693 * resources.</li>
694 *
695 * <li>An <code> implementation</code> that wraps the head of the legacy VariableResolver chain, as per section
696 * <code> VariableResolver ChainWrapper</code> in Chapter 5 in the spec document.</li>
697 *
698 * <li>An <code>implementation</code> that wraps the head of the legacy PropertyResolver chain, as per section
699 * <code>PropertyResolver ChainWrapper</code> in Chapter 5 in the spec document.</li>
700 *
701 * <li>Any <code>ELResolver</code> instances added by calls to
702 * <code>{@link #addELResolver(javax.el.ELResolver)}</code>.</li>
703 *
704 * <li>The default implementation throws <code>UnsupportedOperationException</code> and is provided for the sole
705 * purpose of not breaking existing applications that extend <code>{@link Application}</code>.</li>
706 * <ul>
707 *
708 * @since 1.2
709 */
710 public ELResolver getELResolver()
711 {
712 Application application = getMyfacesApplicationInstance();
713 if (application != null)
714 {
715 return application.getELResolver();
716 }
717 throw new UnsupportedOperationException();
718 }
719
720 /**
721 * <p>
722 * Return the <code>ExpressionFactory</code> instance for this application. This instance is used by the convenience
723 * method <code>{@link #evaluateExpressionGet(javax.faces.context.FacesContext, java.lang.String, java.lang.Class)}.
724 * </p>
725 *
726 * <p>
727 * The implementation must return the <code>ExpressionFactory</code> from the JSP container by calling <code>
728 * JspFactory.getDefaultFactory().getJspApplicationContext(servletContext).getExpressionFactory()</code>.
729 * </p>
730 *
731 * <p>
732 * An implementation is provided that throws <code>UnsupportedOperationException</code> so that users that decorate
733 * the <code>Application</code> continue to work.
734 * </p>
735 *
736 * @since 1.2
737 */
738 public ExpressionFactory getExpressionFactory()
739 {
740 Application application = getMyfacesApplicationInstance();
741 if (application != null)
742 {
743 return application.getExpressionFactory();
744 }
745 throw new UnsupportedOperationException();
746 }
747
748 /**
749 * Return the fully qualified class name of the <code>ResourceBundle</code> to be used for JavaServer Faces messages
750 * for this application. If not explicitly set, <code>null</code> is returned.
751 */
752 public abstract String getMessageBundle();
753
754 /**
755 *Return the <code>{@link NavigationHandler}</code> instance that will be passed the outcome returned by any
756 * invoked application action for this web application. If not explicitly set, a default implementation must be
757 * provided that performs the functions described in the <code>{@link NavigationHandler}</code> class description.
758 */
759 public abstract NavigationHandler getNavigationHandler();
760
761 /**
762 * <p>
763 * Return the project stage for the currently running application instance. The default value is <code>
764 * {@link ProjectStage#Production}</code>
765 * </p>
766 *
767 * <p>
768 * The implementation of this method must perform the following algorithm or an equivalent with the same end result
769 * to determine the value to return.
770 * </p>
771 *
772 * <ul>
773 * <li>If the value has already been determined by a previous call to this method, simply return that value.</li>
774 * <li>Look for a <code>JNDI</code> environment entry under the key given by the value of
775 * <code>{@link ProjectStage#PROJECT_STAGE_JNDI_NAME}</code> (return type of java.lang.String). If found, continue
776 * with the algorithm below, otherwise, look for an entry in the <code>initParamMap</code> of the
777 * <code>ExternalContext</code> from the current <code>FacesContext</code> with the key
778 * <code>{@link ProjectStage#PROJECT_STAGE_PARAM_NAME}</code></li>
779 * <li>If a value is found found, see if an enum constant can be obtained by calling
780 * <code>ProjectStage.valueOf()</code>, passing the value from the <code>initParamMap</code>. If this succeeds
781 * without exception, save the value and return it.</li>
782 * <li>If not found, or any of the previous attempts to discover the enum constant value have failed, log a
783 * descriptive error message, assign the value as <code>ProjectStage.Production</code> and return it.</li>
784 * <ul>
785 *
786 * @since 2.0
787 */
788 public ProjectStage getProjectStage()
789 {
790 Application application = getMyfacesApplicationInstance();
791 if (application != null)
792 {
793 return application.getProjectStage();
794 }
795 throw new UnsupportedOperationException();
796 }
797
798 /**
799 * Get the object used by the VariableResolver to read and write named properties on java beans, Arrays, Lists and
800 * Maps. This object is used by the ValueBinding implementation, and during the process of configuring
801 * "managed bean" properties.
802 *
803 * @deprecated
804 */
805 public abstract PropertyResolver getPropertyResolver();
806
807 /**
808 * <p>
809 * Find a <code>ResourceBundle</code> as defined in the application configuration resources under the specified
810 * name. If a <code>ResourceBundle</code> was defined for the name, return an instance that uses the locale of the
811 * current <code>{@link UIViewRoot}</code>.
812 * </p>
813 *
814 * <p>
815 * The default implementation throws <code>UnsupportedOperationException</code> and is provided for the sole purpose
816 * of not breaking existing applications that extend this class.
817 * </p>
818 *
819 * @return <code>ResourceBundle</code> for the current UIViewRoot, otherwise null
820 *
821 * @throws FacesException
822 * if a bundle was defined, but not resolvable
823 * @throws NullPointerException
824 * if ctx == null || name == null
825 */
826 public ResourceBundle getResourceBundle(FacesContext ctx, String name) throws FacesException, NullPointerException
827 {
828 Application application = getMyfacesApplicationInstance(ctx);
829 if (application != null)
830 {
831 return application.getResourceBundle(ctx, name);
832 }
833 throw new UnsupportedOperationException();
834 }
835
836 /**
837 * <p>
838 * Return the singleton, stateless, thread-safe <code>{@link ResourceHandler}</code> for this application. The JSF
839 * implementation must support the following techniques for declaring an alternate implementation of <code>
840 * ResourceHandler</code>.
841 * </p>
842 *
843 * <ul>
844 * <li>The <code>ResourceHandler</code> implementation is declared in the application configuration resources by
845 * giving the fully qualified class name as the value of the <code><resource-handler></code> element within the
846 * <code>application</code> element.</li>
847 * <li>RELEASE_PENDING(edburns) It can also be declared via an annotation as specified in [287-ConfigAnnotations].</li>
848 * </ul>
849 *
850 * <p>
851 * In all of the above cases, the runtime must employ the decorator pattern as for every other pluggable artifact in
852 * JSF.
853 * </p>
854 *
855 * @since 2.0
856 */
857 public ResourceHandler getResourceHandler()
858 {
859 Application application = getMyfacesApplicationInstance();
860 if (application != null)
861 {
862 return application.getResourceHandler();
863 }
864 throw new UnsupportedOperationException();
865 }
866
867 /**
868 * Return the <code>StateManager</code> instance that will be utilized during the Restore View and Render Response
869 * phases of the request processing lifecycle. If not explicitly set, a default implementation must be provided that
870 * performs the functions described in the <code>StateManager</code> description in the JavaServer Faces
871 * Specification.
872 */
873 public abstract StateManager getStateManager();
874
875 /**
876 * Return an <code>Iterator</code> over the supported <code>Locales</code> for this appication.
877 */
878 public abstract Iterator<Locale> getSupportedLocales();
879
880 /**
881 *Return an <code>Iterator</code> over the set of currently registered validator ids for this
882 * <code>Application</code>.
883 */
884 public abstract Iterator<String> getValidatorIds();
885
886 /**
887 * Get the object used to resolve expressions of form "#{...}".
888 *
889 * @deprecated
890 */
891 public abstract VariableResolver getVariableResolver();
892
893 /**
894 * Set the <code>{@link ViewHandler}</code> instance that will be utilized during the
895 * <code> Restore View and Render Response</code> phases of the request processing lifecycle.
896 *
897 * @return
898 */
899 public abstract ViewHandler getViewHandler();
900
901 /**
902 *
903 * @param facesContext
904 * @param systemEventClass
905 * @param sourceBaseType
906 * @param source
907 *
908 * @since 2.0
909 */
910 public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Class<?> sourceBaseType, Object source)
911 {
912 Application application = getMyfacesApplicationInstance(facesContext);
913 if (application != null)
914 {
915 application.publishEvent(facesContext, systemEventClass, sourceBaseType, source);
916 return;
917 }
918 throw new UnsupportedOperationException();
919 }
920
921 /**
922 * <p>
923 * If there are one or more listeners for events of the type represented by <code>systemEventClass</code>, call
924 * those listeners,passing source as the <code>source</code> of the event. The implementation should be as fast as
925 * possible in determining whether or not a listener for the given <code>systemEventClass</code> and
926 * <code>source</code> has been installed, and should return immediately once such a determination has been made.
927 * The implementation of <code>publishEvent</code> must honor the requirements stated in
928 * <code>{@link subscribeToEvent(java.lang.Class, java.lang.Class,
929 * javax.faces.event.SystemEventListener)}</code>
930 * <p>
931 * <p>
932 * The default implementation must implement an algorithm semantically equivalent to the following to locate
933 * listener instances and to invoke them.
934 * <p>
935 * <ul>
936 * <li>If the <code>source</code> argument implements <code>{@link SystemEventListenerHolder}</code>, call
937 * <code>{@link SystemEventListenerHolder.getListenersForEventClass(java.lang.Class)}</code> on it, passing the
938 * <code>systemEventClass</code> argument. If the list is not empty, perform algorithm
939 * <code>traverseListenerList</code> on the list.</li>
940 *
941 * <li>If any <code>Application</code> level listeners have been installed by previous calls to </code>{@link
942 * subscribeToEvent(java.lang.Class, java.lang.Class, SystemEventListener)}</code>, perform algorithm
943 * <code>traverseListenerList</code> on the list.</li>
944 *
945 * <li>If any <code>Application</code> level listeners have been installed by previous calls to
946 * <code>{@link subscribeToEvent(java.lang.Class, SystemEventListener)}</code>, perform algorithm
947 * <code>traverseListenerList</code> on the list.</li>
948 * </ul>
949 *
950 * <p>
951 * If the act of invoking the <code>processListener</code> method causes an </code>{@link AbortProcessingException}
952 * </code> to be thrown, processing of the listeners must be aborted.
953 * </p>
954 *
955 * <p>
956 * Algorithm <code>traverseListenerList</code>: For each listener in the list,
957 * <p>
958 *
959 * <ul>
960 * <li>Call
961 * <code>{@link SystemEventListener.isListenerForSource(java.lang.Object)}<code>, passing the <code>source</code>
962 * argument. If this returns <code>false</code>, take no action on the listener.</li>
963 *
964 * <li>Otherwise, if the event to be passed to the listener instances has not yet been constructed, construct the
965 * event, passing <code>source</code> as the argument to the one-argument constructor that takes an
966 * <code>Object</code>. This same event instance must be passed to all listener instances.</li>
967 *
968 * <li>Call
969 * <code>{@link SystemEvent.isAppropriateListener(javax.faces.event.FacesListener)}<code>, passing the listener
970 * instance as the argument. If this returns <code>false</code>, take no action on the listener.</li>
971 *
972 * <li>Call <code>{@link SystemEvent.processListener(javax.faces.event.FacesListener)}</code>, passing the listener
973 * instance.</li>
974 *
975 * @param systemEventClass
976 * - The Class of event that is being published. Must be non-null.
977 *
978 * @param source
979 * - The <code>source</code> for the event of type systemEventClass. Must be non- <code>null</code>, and
980 * must implement <code>{@link SystemEventListenerHolder}</code>.
981 *
982 * @since 2.0
983 */
984 public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Object source)
985 {
986 Application application = getMyfacesApplicationInstance(facesContext);
987 if (application != null)
988 {
989 application.publishEvent(facesContext, systemEventClass, source);
990 return;
991 }
992 throw new UnsupportedOperationException();
993 }
994
995 /**
996 * <p>
997 * Remove the argument <code>listener</code> from the list of <code>ELContextListeners</code>. If <code>listener
998 * </code> is null, no exception is thrown and no action is performed. If <code>listener</code> is not in the list,
999 * no exception is thrown and no action is performed.
1000 * <p>
1001 *
1002 * <p>
1003 * An implementation is provided that throws <code>UnsupportedOperationException</code> so that users that decorate
1004 * the <code>Application</code> continue to work.
1005 *
1006 * @param listener
1007 */
1008 public void removeELContextListener(ELContextListener listener)
1009 {
1010 Application application = getMyfacesApplicationInstance();
1011 if (application != null)
1012 {
1013 application.removeELContextListener(listener);
1014 return;
1015 }
1016 throw new UnsupportedOperationException();
1017 }
1018
1019 /**
1020 * Set the default <code>{@link ActionListener}</code> to be registered for all <code>{@link ActionSource}</code>
1021 * components.
1022 *
1023 * @param listener
1024 * - The new default <code>{@link ActionListener}</code>
1025 *
1026 * @throws NullPointerException
1027 * if listener is null
1028 */
1029 public abstract void setActionListener(ActionListener listener);
1030
1031 /**
1032 * Set the default <code>Locale</code> for this application.
1033 *
1034 * @param locale
1035 * - The new default <code>Locale</code>
1036 *
1037 * @throws NullPointerException
1038 * if listener is null
1039 */
1040 public abstract void setDefaultLocale(Locale locale);
1041
1042 /**
1043 * Return the <code>renderKitId</code> to be used for rendering this application. If not explicitly set, <code>null
1044 * </code> is returned.
1045 *
1046 * @param renderKitId
1047 */
1048 public abstract void setDefaultRenderKitId(String renderKitId);
1049
1050 /**
1051 * Set the fully qualified class name of the <code>ResourceBundle </code> to be used for JavaServer Faces messages
1052 * for this application. See the JavaDocs for the <code>java.util.ResourceBundle </code> class for more information
1053 * about the syntax for resource bundle names.
1054 *
1055 * @param bundle
1056 * - Base name of the resource bundle to be used
1057 *
1058 * @throws NullPointerException
1059 * if bundle is null
1060 */
1061 public abstract void setMessageBundle(String bundle);
1062
1063 /**
1064 * Set the {@link NavigationHandler} instance that will be passed the outcome returned by any invoked application
1065 * action for this web application.
1066 *
1067 * @param handler
1068 * - The new NavigationHandler instance
1069 */
1070 public abstract void setNavigationHandler(NavigationHandler handler);
1071
1072 /**
1073 * The recommended way to affect the execution of the EL is to provide an <el-resolver> element at the right place
1074 * in the application configuration resources which will be considered in the normal course of expression
1075 * evaluation. This method now will cause the argument resolver to be wrapped inside an implementation of ELResolver
1076 * and exposed to the EL resolution system as if the user had called addELResolver(javax.el.ELResolver).
1077 *
1078 * @deprecated
1079 */
1080 public abstract void setPropertyResolver(PropertyResolver resolver);
1081
1082 /**
1083 *
1084 * @param resourceHandler
1085 *
1086 * @since 2.0
1087 */
1088 public void setResourceHandler(ResourceHandler resourceHandler)
1089 {
1090 Application application = getMyfacesApplicationInstance();
1091 if (application != null)
1092 {
1093 application.setResourceHandler(resourceHandler);
1094 return;
1095 }
1096 throw new UnsupportedOperationException();
1097 }
1098
1099 /**
1100 *Set the {@link StateManager} instance that will be utilized during the <code>Restore View and Render Response
1101 * </code> phases of the request processing lifecycle.
1102 *
1103 * @param <code>manager</code> - The new {@link StateManager}instance
1104 *
1105 * @throws IllegalStateException
1106 * if this method is called after at least one request has been processed by the <code>Lifecycle</code>
1107 * instance for this application.
1108 * @throws NullPointerException
1109 * if manager is <code>null</code>
1110 */
1111 public abstract void setStateManager(StateManager manager);
1112
1113 /**
1114 * Set the <code>Locale</code> instances representing the supported <code>Locales</code> for this application.
1115 *
1116 * @param <code>Locale</code>- The set of supported <code>Locales</code> for this application
1117 *
1118 * @throws NullPointerException
1119 * if the argument newLocales is <code>null</code>.
1120 *
1121 */
1122 public abstract void setSupportedLocales(Collection<Locale> locales);
1123
1124 /**
1125 * The recommended way to affect the execution of the EL is to provide an <el-resolver> element at the right place
1126 * in the application configuration resources which will be considered in the normal course of expression
1127 * evaluation. This method now will cause the argument resolver to be wrapped inside an implementation of ELResolver
1128 * and exposed to the EL resolution system as if the user had called addELResolver(javax.el.ELResolver).
1129 *
1130 * @deprecated
1131 */
1132 public abstract void setVariableResolver(VariableResolver resolver);
1133
1134 /**
1135 * Set the {@link ViewHandler} instance that will be utilized during the <code>Restore View and Render Response
1136 * </code> phases of the request processing lifecycle.
1137 *
1138 * @param handler
1139 * - The new {@link ViewHandler} instance
1140 *
1141 * @throws IllegalStateException
1142 * if this method is called after at least one request has been processed by the <code>Lifecycle</code>
1143 * instance for this application.
1144 * @throws NullPointerException
1145 * if <code>handler</code> is <code>null</code>
1146 */
1147 public abstract void setViewHandler(ViewHandler handler);
1148
1149 /**
1150 *
1151 * @param systemEventClass
1152 * @param sourceClass
1153 * @param listener
1154 *
1155 * @since 2.0
1156 */
1157 public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
1158 SystemEventListener listener)
1159 {
1160 Application application = getMyfacesApplicationInstance();
1161 if (application != null)
1162 {
1163 application.subscribeToEvent(systemEventClass, sourceClass, listener);
1164 return;
1165 }
1166 throw new UnsupportedOperationException();
1167 }
1168
1169 /**
1170 *
1171 * @param systemEventClass
1172 * @param listener
1173 *
1174 * @since 2.0
1175 */
1176 public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener)
1177 {
1178 Application application = getMyfacesApplicationInstance();
1179 if (application != null)
1180 {
1181 application.subscribeToEvent(systemEventClass, listener);
1182 return;
1183 }
1184 subscribeToEvent(systemEventClass, null, listener);
1185 }
1186
1187 /**
1188 *
1189 * @param systemEventClass
1190 * @param sourceClass
1191 * @param listener
1192 *
1193 * @since 2.0
1194 */
1195 public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
1196 SystemEventListener listener)
1197 {
1198 Application application = getMyfacesApplicationInstance();
1199 if (application != null)
1200 {
1201 application.unsubscribeFromEvent(systemEventClass, sourceClass, listener);
1202 return;
1203 }
1204 throw new UnsupportedOperationException();
1205 }
1206
1207 /**
1208 *
1209 * @param systemEventClass
1210 * @param listener
1211 *
1212 * @since 2.0
1213 */
1214 public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener)
1215 {
1216 Application application = getMyfacesApplicationInstance();
1217 if (application != null)
1218 {
1219 application.unsubscribeFromEvent(systemEventClass, listener);
1220 return;
1221 }
1222 unsubscribeFromEvent(systemEventClass, null, listener);
1223 }
1224 }