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