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