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