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 }