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