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