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