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