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