Save This Page
Home » mojarra-1.2_09-b02-FCS-source » javax.faces.application » [javadoc | source]
    1   /*
    2    * $Id: Application.java,v 1.50 2007/04/27 22:00:02 ofung Exp $
    3    */
    4   
    5   /*
    6    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    7    * 
    8    * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    9    * 
   10    * The contents of this file are subject to the terms of either the GNU
   11    * General Public License Version 2 only ("GPL") or the Common Development
   12    * and Distribution License("CDDL") (collectively, the "License").  You
   13    * may not use this file except in compliance with the License. You can obtain
   14    * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   15    * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   16    * language governing permissions and limitations under the License.
   17    * 
   18    * When distributing the software, include this License Header Notice in each
   19    * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   20    * Sun designates this particular file as subject to the "Classpath" exception
   21    * as provided by Sun in the GPL Version 2 section of the License file that
   22    * accompanied this code.  If applicable, add the following below the License
   23    * Header, with the fields enclosed by brackets [] replaced by your own
   24    * identifying information: "Portions Copyrighted [year]
   25    * [name of copyright owner]"
   26    * 
   27    * Contributor(s):
   28    * 
   29    * If you wish your version of this file to be governed by only the CDDL or
   30    * only the GPL Version 2, indicate your decision by adding "[Contributor]
   31    * elects to include this software in this distribution under the [CDDL or GPL
   32    * Version 2] license."  If you don't indicate a single choice of license, a
   33    * recipient has the option to distribute your version of this file under
   34    * either the CDDL, the GPL Version 2 or to extend the choice of license to
   35    * its licensees as provided above.  However, if you add GPL Version 2 code
   36    * and therefore, elected the GPL Version 2 license, then the option applies
   37    * only if the new code is made subject to such option by the copyright
   38    * holder.
   39    */
   40   
   41   package javax.faces.application;
   42   
   43   
   44   import java.util.Iterator;
   45   import java.util.Collection;
   46   import java.util.Locale;
   47   import java.util.ResourceBundle;
   48   
   49   import javax.faces.FacesException;
   50   import javax.faces.component.UIComponent;
   51   import javax.faces.context.FacesContext;
   52   import javax.faces.context.ExternalContext;
   53   import javax.faces.convert.Converter;
   54   import javax.faces.el.MethodBinding;
   55   import javax.faces.el.PropertyResolver;
   56   import javax.faces.el.ReferenceSyntaxException;
   57   import javax.faces.el.ValueBinding;
   58   import javax.faces.el.VariableResolver;
   59   import javax.faces.event.ActionListener;
   60   import javax.faces.validator.Validator;
   61   
   62   import javax.el.ELContextListener;
   63   import javax.el.ExpressionFactory;
   64   import javax.el.ValueExpression;
   65   import javax.el.ELException;
   66   import javax.el.ELResolver;
   67   
   68   
   69   
   70   /**
   71    * <p><strong>Application</strong> represents a per-web-application
   72    * singleton object where applications based on JavaServer Faces (or
   73    * implementations wishing to provide extended functionality) can
   74    * register application-wide singletons that provide functionality
   75    * required by JavaServer Faces.  Default implementations of each
   76    * object are provided for cases where the application does not choose
   77    * to customize the behavior.</p>
   78    *
   79    * <p>The instance of {@link Application} is created by calling the
   80    * <code>getApplication()</code> method of {@link ApplicationFactory}.
   81    * Because this instance is shared, it must be implemented in a
   82    * thread-safe manner.</p>
   83    *
   84    * <p>The application also acts as a factory for several types of
   85    * Objects specified in the Faces Configuration file.  Please see {@link
   86    * Application#createComponent}, {@link Application#createConverter},
   87    * and {@link Application#createValidator}. </p>
   88    */
   89   
   90   public abstract class Application {
   91   
   92   
   93       // ------------------------------------------------------------- Properties
   94   
   95   
   96       /**
   97        * <p>Return the default {@link ActionListener} to be registered for
   98        * all {@link javax.faces.component.ActionSource} components in this
   99        * appication.  If not explicitly set, a default implementation must
  100        * be provided that performs the
  101        *
  102        * following functions:</p>
  103        * <ul>
  104        * <li>The <code>processAction()</code> method must first call
  105        *     <code>FacesContext.renderResponse()</code> in order to bypass
  106        *     any intervening lifecycle phases, once the method returns.</li>
  107        * <li>The <code>processAction()</code> method must next determine
  108        *     the logical outcome of this event, as follows:
  109        *     <ul>
  110        *     <li>If the originating component has a non-<code>null</code>
  111        *     <code>action</code> property, retrieve the {@link
  112        *     MethodBinding} from the property, and call
  113        *     <code>invoke()</code> on it.  Convert the returned value (if
  114        *     any) to a String, and use it as the logical outcome.</li>
  115   
  116        *     <li>Otherwise, the logical outcome is <code>null</code>.</li>
  117        *     </ul></li>
  118   
  119        * <li>The <code>processAction()</code> method must finally retrieve
  120        *     the <code>NavigationHandler</code> instance for this
  121        *     application and call {@link
  122        *     NavigationHandler#handleNavigation} passing: 
  123        *
  124        *     <ul>
  125   
  126        *     <li>the {@link FacesContext} for the current request</li>
  127   
  128        *     <li>If there is a <code>MethodBinding</code> instance for the
  129        *     <code>action</code> property of this component, the result of
  130        *     calling {@link MethodBinding#getExpressionString} on it, null
  131        *     otherwise</li>
  132        *
  133        *     <li>the logical outcome as determined above</li>
  134        *
  135        *     </ul>
  136        *
  137        *     </li>
  138        * </ul>
  139        *
  140        * <p>Note that the specification for the default
  141        * <code>ActionListener</code> contiues to call for the use of a
  142        * <strong>deprecated</strong> property (<code>action</code>) and
  143        * class (<code>MethodBinding</code>).  Unfortunately, this is
  144        * necessary because the default <code>ActionListener</code> must
  145        * continue to work with components that do not implement {@link
  146        * javax.faces.component.ActionSource2}, and only implement {@link
  147        * javax.faces.component.ActionSource}.</p>
  148        */
  149       public abstract ActionListener getActionListener();
  150   
  151   
  152       /**
  153        * <p>Set the default {@link ActionListener} to be registered for all
  154        * {@link javax.faces.component.ActionSource} components.</p>
  155        * </p>
  156        *
  157        * @param listener The new default {@link ActionListener}
  158        *
  159        * @throws NullPointerException if <code>listener</code>
  160        *  is <code>null</code>
  161        */
  162       public abstract void setActionListener(ActionListener listener);
  163   
  164   
  165       /**
  166        * <p>Return the default <code>Locale</code> for this application.  If
  167        * not explicitly set, <code>null</code> is returned.</p>
  168        */ 
  169       public abstract Locale getDefaultLocale();
  170   
  171   
  172       /**
  173        * <p>Set the default <code>Locale</code> for this application.</p>
  174        *
  175        * @param locale The new default <code>Locale</code>
  176        *
  177        * @throws NullPointerException if <code>locale</code>
  178        *  is <code>null</code>
  179        */
  180       public abstract void setDefaultLocale(Locale locale);
  181   
  182   
  183       /**
  184        * <p>Return the <code>renderKitId</code> to be used for rendering
  185        * this application.  If not explicitly set, <code>null</code> is
  186        * returned.</p>
  187        */
  188       public abstract String getDefaultRenderKitId();
  189   
  190   
  191       /**
  192        * <p>Set the <code>renderKitId</code> to be used to render this
  193        * application.  Unless the client has provided a custom {@link ViewHandler}
  194        * that supports the use of multiple {@link javax.faces.render.RenderKit}
  195        * instances in the same application, this method must only be called at
  196        * application startup, before any Faces requests have been processed.
  197        * This is a limitation of the current Specification, and may be lifted in
  198        * a future release.</p>
  199        */
  200       public abstract void setDefaultRenderKitId(String renderKitId);
  201   	
  202   
  203   
  204       /**
  205        * <p>Return the fully qualified class name of the
  206        * <code>ResourceBundle</code> to be used for JavaServer Faces messages
  207        * for this application.  If not explicitly set, <code>null</code>
  208        * is returned.</p>
  209        */
  210       public abstract String getMessageBundle();
  211   
  212   
  213       /**
  214        * <p>Set the fully qualified class name of the <code>ResourceBundle</code>
  215        * to be used for JavaServer Faces messages for this application.  See the
  216        * JavaDocs for the <code>java.util.ResourceBundle</code> class for more
  217        * information about the syntax for resource bundle names.</p>
  218        *
  219        * @param bundle Base name of the resource bundle to be used
  220        *
  221        * @throws NullPointerException if <code>bundle</code>
  222        *  is <code>null</code>
  223        */
  224       public abstract void setMessageBundle(String bundle);
  225   
  226   
  227       /**
  228        * <p>Return the {@link NavigationHandler} instance that will be passed
  229        * the outcome returned by any invoked application action for this
  230        * web application.  If not explicitly set, a default implementation
  231        * must be provided that performs the functions described in the
  232        * {@link NavigationHandler} class description.</p>
  233        */
  234       public abstract NavigationHandler getNavigationHandler();
  235   
  236   
  237       /**
  238        * <p>Set the {@link NavigationHandler} instance that will be passed
  239        * the outcome returned by any invoked application action for this
  240        * web application.</p>
  241        *
  242        * @param handler The new {@link NavigationHandler} instance
  243        *
  244        * @throws NullPointerException if <code>handler</code>
  245        *  is <code>null</code>
  246        */
  247       public abstract void setNavigationHandler(NavigationHandler handler);
  248   
  249       
  250   
  251   
  252       /**
  253        * <p>Return a {@link PropertyResolver} instance that wraps the
  254        * {@link ELResolver} instance that Faces provides to the unified EL
  255        * for the resolution of expressions that appear programmatically in
  256        * an application.</p>
  257        *
  258        * <p>Note that this no longer returns the default
  259        * <code>PropertyResolver</code> since that class is now a no-op
  260        * that aids in allowing custom <code>PropertyResolver</code>s to
  261        * affect the EL resolution process.</p>
  262        *
  263        * @deprecated This has been replaced by {@link #getELResolver}.  
  264        */
  265       public abstract PropertyResolver getPropertyResolver();
  266   
  267   
  268       /**
  269        * <p>Set the {@link PropertyResolver} instance that will be utilized
  270        * to resolve method and value bindings.</p>
  271        *
  272        * <p>This method is now deprecated but the implementation must
  273        * cause the argument to be set as the head of the legacy
  274        * <code>PropertyResolver</code> chain, replacing any existing value
  275        * that was set from the application configuration resources.</p>
  276        *
  277        *  <p>It is illegal to call this method after
  278        * the application has received any requests from the client.  If an
  279        * attempt is made to register a listener after that time it must have
  280        * no effect. </p>
  281        *
  282        * @param resolver The new {@link PropertyResolver} instance
  283        *
  284        * @throws NullPointerException if <code>resolver</code>
  285        *  is <code>null</code>
  286        *
  287        * @deprecated The recommended way to affect the execution of the EL
  288        * is to provide an <code>&lt;el-resolver&gt;</code> element at the
  289        * right place in the application configuration resources which will
  290        * be considered in the normal course of expression evaluation.
  291        * This method now will cause the argument <code>resolver</code> to
  292        * be wrapped inside an implementation of {@link ELResolver} and
  293        * exposed to the EL resolution system as if the user had called
  294        * {@link #addELResolver}.
  295        *
  296        * @throws IllegalStateException if called after the first
  297        * request to the {@link javax.faces.webapp.FacesServlet} has been
  298        * serviced.
  299        */
  300       public abstract void setPropertyResolver(PropertyResolver resolver);
  301       
  302       /**
  303        * <p>Find a <code>ResourceBundle</code> as defined in the
  304        * application configuration resources under the specified name.  If
  305        * a <code>ResourceBundle</code> was defined for the name, return an
  306        * instance that uses the locale of the current {@link
  307        * javax.faces.component.UIViewRoot}.</p>
  308        *
  309        * <p>The default implementation throws 
  310        * <code>UnsupportedOperationException</code> and is provided
  311        * for the sole purpose of not breaking existing applications that extend
  312        * this class.</p>
  313        *
  314        * @return <code>ResourceBundle</code> for the current UIViewRoot,
  315        * otherwise null
  316        *
  317        * @throws FacesException if a bundle was defined, but not resolvable
  318        *
  319        * @throws NullPointerException if ctx == null || name == null
  320        *
  321        * @since 1.2
  322        */
  323       
  324       public ResourceBundle getResourceBundle(FacesContext ctx, String name) {
  325           Application app = getRIApplicationImpl(ctx);
  326           if (app != null) {
  327               //noinspection TailRecursion
  328               return app.getResourceBundle(ctx, name);
  329           }
  330           
  331           throw new UnsupportedOperationException();
  332       }
  333       
  334   
  335   
  336       /**
  337        * <p>Return the {@link VariableResolver} that wraps the {@link
  338        * ELResolver} instance that Faces provides to the unified EL for
  339        * the resolution of expressions that appear programmatically in an
  340        * application.  The implementation of the
  341        * <code>VariableResolver</code>must pass <code>null</code> as the
  342        * base argument for any methods invoked on the underlying
  343        * <code>ELResolver</code>.</p>
  344        *
  345        * <p>Note that this method no longer returns the default
  346        * <code>VariableResolver</code>, since that class now is a no-op
  347        * that aids in allowing custom <code>VariableResolver</code>s to
  348        * affect the EL resolution process.</p>
  349        *
  350        * @deprecated This has been replaced by {@link #getELResolver}.  
  351        */
  352       public abstract VariableResolver getVariableResolver();
  353   
  354   
  355       /**
  356        * <p>Set the {@link VariableResolver} instance that will be consulted
  357        * to resolve method and value bindings.</p>
  358        *
  359        * <p>This method is now deprecated but the implementation must
  360        * cause the argument to be set as the head of the legacy
  361        * <code>VariableResolver</code> chain, replacing any existing value
  362        * that was set from the application configuration resources.</p>
  363        *
  364        *  <p>It is illegal to call this method after
  365        * the application has received any requests from the client.  If an
  366        * attempt is made to register a listener after that time it must have 
  367        * no effect.</p>
  368        *
  369        * @param resolver The new {@link VariableResolver} instance
  370        *
  371        * @throws NullPointerException if <code>resolver</code>
  372        *  is <code>null</code>
  373        *
  374        * @deprecated The recommended way to affect the execution of the EL
  375        * is to provide an <code>&lt;el-resolver&gt;</code> element at the
  376        *
  377        * right place in the application configuration resources which will
  378        * be considered in the normal course of expression evaluation.
  379        * This method now will cause the argument <code>resolver</code> to
  380        * be wrapped inside an implementation of {@link ELResolver} and
  381        * exposed to the EL resolution system as if the user had called
  382        * {@link #addELResolver}.
  383        *
  384        * @throws IllegalStateException if called after the first
  385        * request to the {@link javax.faces.webapp.FacesServlet} has been
  386        * serviced.
  387        */
  388       public abstract void setVariableResolver(VariableResolver resolver);
  389   
  390       /**
  391        * <p>Cause an the argument <code>resolver</code> to be added to the
  392        * resolver chain as specified in section 5.5.1 of the JavaServer
  393        * Faces Specification.</p>
  394        *
  395        * <p>It is not possible to remove an <code>ELResolver</code>
  396        * registered with this method, once it has been registered.</p>
  397        *
  398        *  <p>It is illegal to register an <code>ELResolver</code> after
  399        * the application has received any requests from the client.  If an
  400        * attempt is made to register a listener after that time, an
  401        * <code>IllegalStateException</code> must be thrown. This restriction is
  402        * in place to allow the JSP container to optimize for the common
  403        * case where no additional <code>ELResolver</code>s are in the
  404        * chain, aside from the standard ones. It is permissible to add
  405        * <code>ELResolver</code>s before or after initialization to a
  406        * <code>CompositeELResolver</code> that is already in the
  407        * chain.</p>
  408        *
  409        * <p>The default implementation throws 
  410        * <code>UnsupportedOperationException</code> and is provided
  411        * for the sole purpose of not breaking existing applications that extend
  412        * {@link Application}.</p>
  413        *
  414        * @since 1.2
  415        */
  416   
  417       public void addELResolver(ELResolver resolver) {
  418           Application app = getRIApplicationImpl();
  419           if (app != null) {
  420               app.addELResolver(resolver);
  421           } else {
  422               throw new UnsupportedOperationException();
  423           }
  424       }
  425   
  426       /**
  427        * <p>Return the singleton {@link ELResolver} instance to be used
  428        * for all EL resolution.  This is actually an instance of {@link
  429        * javax.el.CompositeELResolver} that must contain the following
  430        * <code>ELResolver</code> instances in the following order:</p>
  431        *
  432        * 	<ol>
  433        *
  434        *	  <li><p><code>ELResolver</code> instances declared using the
  435        *	  &lt;el-resolver&gt; element in the application configuration
  436        *	  resources.  </p></li>
  437        *
  438        *	  <li><p>An <code>implementation</code> that wraps the head of
  439        *	  the legacy <code>VariableResolver</code> chain, as per section
  440        *	  <i>VariableResolver ChainWrapper</i> in Chapter 5 in the spec
  441        *	  document.</p></li>
  442        *
  443        *	  <li><p>An <code>implementation</code> that wraps the head of
  444        *	  the legacy <code>PropertyResolver</code> chain, as per section
  445        *	  <i>PropertyResolver ChainWrapper</i> in Chapter 5 in the spec
  446        *	  document.</p></li>
  447        *
  448        *	  <li><p>Any <code>ELResolver</code> instances added by calls to
  449        *	  {@link #addELResolver}.</p></li>
  450        *
  451        *	</ol>
  452        *
  453        * <p>The default implementation throws <code>UnsupportedOperationException</code>
  454        * and is provided for the sole purpose of not breaking existing applications 
  455        * that extend {@link Application}.</p>
  456        *
  457        * @since 1.2
  458        */
  459   
  460       public ELResolver getELResolver() {
  461           Application app = getRIApplicationImpl();
  462           if (app != null) {
  463               //noinspection TailRecursion
  464               return app.getELResolver();
  465           }
  466           throw new UnsupportedOperationException();
  467       }
  468   
  469   
  470       /**
  471        * <p>Return the {@link ViewHandler} instance that will be utilized
  472        * during the <em>Restore View</em> and <em>Render Response</em>
  473        * phases of the request processing lifecycle.  If not explicitly set,
  474        * a default implementation must be provided that performs the functions
  475        * described in the {@link ViewHandler} description in the
  476        * JavaServer Faces Specification.</p>
  477        */
  478       public abstract ViewHandler getViewHandler();
  479   
  480   
  481       /**
  482        * <p>Set the {@link ViewHandler} instance that will be utilized
  483        * during the <em>Restore View</em> and <em>Render Response</em>
  484        * phases of the request processing lifecycle.</p>
  485        *
  486        * @param handler The new {@link ViewHandler} instance
  487        *
  488        * @throws IllegalStateException if this method is called after
  489        * at least one request has been processed by the
  490        * <code>Lifecycle</code> instance for this application.
  491        * @throws NullPointerException if <code>handler</code>
  492        *  is <code>null</code>
  493        */
  494       public abstract void setViewHandler(ViewHandler handler);
  495   
  496   
  497   
  498       /**
  499        * <p>Return the {@link StateManager} instance that will be utilized
  500        * during the <em>Restore View</em> and <em>Render Response</em>
  501        * phases of the request processing lifecycle.  If not explicitly set,
  502        * a default implementation must be provided that performs the functions
  503        * described in the {@link StateManager} description
  504        * in the JavaServer Faces Specification.</p>
  505        */
  506       public abstract StateManager getStateManager();
  507   
  508   
  509       /**
  510        * <p>Set the {@link StateManager} instance that will be utilized
  511        * during the <em>Restore View</em> and <em>Render Response</em>
  512        * phases of the request processing lifecycle.</p>
  513        *
  514        * @param manager The new {@link StateManager} instance
  515        *
  516        * @throws IllegalStateException if this method is called after
  517        * at least one request has been processed by the
  518        * <code>Lifecycle</code> instance for this application.
  519        * @throws NullPointerException if <code>manager</code>
  520        *  is <code>null</code>
  521        */
  522       public abstract void setStateManager(StateManager manager);
  523   
  524   
  525       // ------------------------------------------------------- Object Factories
  526   
  527   
  528       /**
  529        * <p>Register a new mapping of component type to the name of the
  530        * corresponding {@link UIComponent} class.  This allows subsequent calls
  531        * to <code>createComponent()</code> to serve as a factory for
  532        * {@link UIComponent} instances.</p>
  533        *
  534        * @param componentType The component type to be registered
  535        * @param componentClass The fully qualified class name of the
  536        *  corresponding {@link UIComponent} implementation
  537        *
  538        * @throws NullPointerException if <code>componentType</code> or
  539        *  <code>componentClass</code> is <code>null</code>
  540        */
  541       public abstract void addComponent(String componentType,
  542                                         String componentClass);
  543   
  544   
  545       /**
  546        * <p>Instantiate and return a new {@link UIComponent} instance of the
  547        * class specified by a previous call to <code>addComponent()</code> for
  548        * the specified component type.</p>
  549        *
  550        * @param componentType The component type for which to create and
  551        *  return a new {@link UIComponent} instance
  552        *
  553        * @throws FacesException if a {@link UIComponent} of the
  554        *  specified type cannot be created
  555        * @throws NullPointerException if <code>componentType</code>
  556        *  is <code>null</code>
  557        */ 
  558       public abstract UIComponent createComponent(String componentType)
  559           throws FacesException;
  560   
  561   
  562       /**
  563        * <p>Wrap the argument <code>componentBinding</code> in an
  564        * implementation of {@link ValueExpression} and call through to
  565        * {@link
  566        * #createComponent(javax.el.ValueExpression,javax.faces.context.FacesContext,java.lang.String)}.</p>
  567        *
  568        * @param componentBinding {@link ValueBinding} representing a
  569        * component value binding expression (typically specified by the
  570        * <code>component</code> attribute of a custom tag)
  571        * @param context {@link FacesContext} for the current request
  572        * @param componentType Component type to create if the {@link ValueBinding}
  573        *  does not return a component instance
  574        *
  575        * @throws FacesException if a {@link UIComponent} cannot be created
  576        * @throws NullPointerException if any parameter is <code>null</code>
  577        *
  578        *
  579        * @deprecated This has been replaced by {@link
  580        * #createComponent(javax.el.ValueExpression,javax.faces.context.FacesContext,java.lang.String)}.
  581        */
  582       public abstract UIComponent createComponent(ValueBinding componentBinding,
  583                                                   FacesContext context,
  584                                                   String componentType)
  585   	throws FacesException;
  586   
  587       /**
  588        * <p>Call the <code>getValue()</code> method on the specified
  589        * {@link ValueExpression}.  If it returns a {@link
  590        * UIComponent} instance, return it as the value of this method.  If
  591        * it does not, instantiate a new {@link UIComponent} instance of
  592        * the specified component type, pass the new component to the
  593        * <code>setValue()</code> method of the specified {@link
  594        * ValueExpression}, and return it.</p>
  595        *
  596        * @param componentExpression {@link ValueExpression} representing a
  597        * component value expression (typically specified by the
  598        * <code>component</code> attribute of a custom tag)
  599        * @param context {@link FacesContext} for the current request
  600        * @param componentType Component type to create if the {@link
  601        * ValueExpression} does not return a component instance
  602        *
  603        * @throws FacesException if a {@link UIComponent} cannot be created
  604        * @throws NullPointerException if any parameter is <code>null</code>
  605        *
  606        * <p>A default implementation is provided that throws 
  607        * <code>UnsupportedOperationException</code> so that users
  608        * that decorate <code>Application</code> can continue to function</p>.
  609        * 
  610        * @since 1.2
  611        */
  612       public UIComponent createComponent(ValueExpression componentExpression,
  613                                          FacesContext context,
  614                                          String componentType)
  615   	throws FacesException {
  616           if (null == componentExpression || null == context ||
  617               null == componentType) {
  618           	// PENDING - i18n
  619               StringBuilder builder = new StringBuilder(64);
  620               builder.append("null parameters - ");
  621               builder.append("componentExpression: ").append(componentExpression);
  622               builder.append(", context: ").append(context);
  623               builder.append(", componentType: ").append(componentType);
  624               throw new NullPointerException(builder.toString());
  625           }
  626   
  627           Object result;
  628           boolean createOne = false;
  629   
  630           try {
  631               if (null != (result = 
  632                   componentExpression.getValue(context.getELContext()))) {
  633                   // if the result is not an instance of UIComponent
  634                   createOne = (!(result instanceof UIComponent));
  635                   // we have to create one.
  636               }
  637               if (null == result || createOne) {
  638                   result = this.createComponent(componentType);
  639                   componentExpression.setValue((context.getELContext()), result);
  640               }
  641           } catch (ELException elex) {
  642               throw new FacesException(elex);
  643           }
  644   
  645           return (UIComponent) result;    
  646       }
  647   
  648   
  649       /**
  650        * <p>Return an <code>Iterator</code> over the set of currently defined
  651        * component types for this <code>Application</code>.</p>
  652        */
  653       public abstract Iterator<String> getComponentTypes();
  654   
  655   
  656       /**
  657        * <p>Register a new mapping of converter id to the name of the
  658        * corresponding {@link Converter} class.  This allows subsequent calls
  659        * to <code>createConverter()</code> to serve as a factory for
  660        * {@link Converter} instances.</p>
  661        *
  662        * @param converterId The converter id to be registered
  663        * @param converterClass The fully qualified class name of the
  664        *  corresponding {@link Converter} implementation
  665        *
  666        * @throws NullPointerException if <code>converterId</code>
  667        *  or <code>converterClass</code> is <code>null</code>
  668        */
  669       public abstract void addConverter(String converterId, 
  670   				      String converterClass);
  671   
  672   
  673       /**
  674        * <p>Register a new converter class that is capable of performing
  675        * conversions for the specified target class.</p>
  676        *
  677        * @param targetClass The class for which this converter is registered
  678        * @param converterClass The fully qualified class name of the
  679        *  corresponding {@link Converter} implementation
  680        *
  681        * @throws NullPointerException if <code>targetClass</code>
  682        *  or <code>converterClass</code> is <code>null</code>
  683        */
  684       public abstract void addConverter(Class targetClass,
  685                                         String converterClass);
  686   
  687   
  688       /**
  689        * <p>Instantiate and return a new {@link Converter} instance of the
  690        * class specified by a previous call to <code>addConverter()</code>
  691        * for the specified converter id.  If there is no such registration
  692        * for this converter id, return <code>null</code>.</p>
  693        *
  694        * @param converterId The converter id for which to create and
  695        *  return a new {@link Converter} instance
  696        *
  697        * @throws FacesException if the {@link Converter} cannot be
  698        *  created
  699        * @throws NullPointerException if <code>converterId</code>
  700        *  is <code>null</code>
  701        */ 
  702       public abstract Converter createConverter(String converterId);
  703   
  704   
  705       /**
  706        * <p>Instantiate and return a new {@link Converter} instance of the
  707        * class that has registered itself as capable of performing conversions
  708        * for objects of the specified type.  If no such {@link Converter} class
  709        * can be identified, return <code>null</code>.</p>
  710        *
  711        * <p>To locate an appropriate {@link Converter} class, the following
  712        * algorithm is performed, stopping as soon as an appropriate {@link
  713        * Converter} class is found:</p>
  714        * <ul>
  715        * <li>Locate a {@link Converter} registered for the target class itself.
  716        *     </li>
  717        * <li>Locate a {@link Converter} registered for interfaces that are
  718        *     implemented by the target class (directly or indirectly).</li>
  719        * <li>Locate a {@link Converter} registered for the superclass (if any)
  720        *     of the target class, recursively working up the inheritance
  721        *     hierarchy.</li>
  722        * </ul>
  723        *
  724        * <p>If the <code>Converter</code> has a single argument constructor that
  725        * accepts a <code>Class</code>, instantiate the <code>Converter</code>
  726        * using that constructor, passing the argument <code>targetClass</code> as
  727        * the sole argument.  Otherwise, simply use the zero-argument constructor.
  728        * </p>
  729        *
  730        * @param targetClass Target class for which to return a {@link Converter}
  731        *
  732        * @throws FacesException if the {@link Converter} cannot be
  733        *  created
  734        * @throws NullPointerException if <code>targetClass</code>
  735        *  is <code>null</code>
  736        */
  737       public abstract Converter createConverter(Class targetClass);
  738   
  739   
  740       /**
  741        * <p>Return an <code>Iterator</code> over the set of currently registered
  742        * converter ids for this <code>Application</code>.</p>
  743        */
  744       public abstract Iterator<String> getConverterIds();
  745   
  746       
  747       /**
  748        * <p>Return an <code>Iterator</code> over the set of <code>Class</code>
  749        * instances for which {@link Converter} classes have been explicitly
  750        * registered.</p>
  751        */
  752       public abstract Iterator<Class> getConverterTypes();
  753   
  754       /**
  755        * <p>Return the {@link ExpressionFactory} instance for this
  756        * application.  This instance is used by the convenience method
  757        * {@link #evaluateExpressionGet}.</p>
  758        *
  759        * <p>The implementation must return the
  760        * <code>ExpressionFactory</code> from the JSP container by calling
  761        * <code>JspFactory.getDefaultFactory().getJspApplicationContext(servletContext).getExpressionFactory()</code>. </p>
  762        *
  763        * <p>An implementation is provided that throws 
  764        * <code>UnsupportedOperationException</code> so that users that decorate
  765        * the <code>Application</code> continue to work.
  766        *
  767        * @since 1.2
  768        */
  769   
  770       public ExpressionFactory getExpressionFactory() {
  771           Application app = getRIApplicationImpl();
  772           if (app != null) {
  773               //noinspection TailRecursion
  774               return app.getExpressionFactory();
  775           }
  776   
  777           throw new UnsupportedOperationException();
  778       }
  779   
  780       /**
  781        * <p>Get a value by evaluating an expression.</p>
  782        *
  783        * <p>Call {@link #getExpressionFactory} then call {@link
  784        * ExpressionFactory#createValueExpression} passing the argument
  785        * <code>expression</code> and <code>expectedType</code>.  Call
  786        * {@link FacesContext#getELContext} and pass it to {@link
  787        * ValueExpression#getValue}, returning the result.</p>
  788        *
  789        * <p>An implementation is provided that throws 
  790        * <code>UnsupportedOperationException</code> so that users that decorate
  791        * the <code>Application</code> continue to work.
  792        *
  793        */
  794   
  795       public Object evaluateExpressionGet(FacesContext context,
  796                                           String expression,
  797                                           Class expectedType) throws ELException {
  798           Application app = getRIApplicationImpl(context);
  799           if (app != null) {
  800               //noinspection TailRecursion
  801               return app.evaluateExpressionGet(context, expression, expectedType);
  802           }
  803           throw new UnsupportedOperationException();
  804       }
  805   
  806       /**
  807        * <p>Call {@link #getExpressionFactory} then call {@link
  808        * ExpressionFactory#createMethodExpression}, passing the given
  809        * arguments, and wrap the result in a <code>MethodBinding</code>
  810        * implementation, returning it.</p>
  811        *
  812        * @param ref Method binding expression for which to return a
  813        *  {@link MethodBinding} instance
  814        * @param params Parameter signatures that must be compatible with those
  815        *  of the method to be invoked, or a zero-length array or <code>null</code>
  816        *  for a method that takes no parameters
  817        *
  818        * @throws NullPointerException if <code>ref</code>
  819        *  is <code>null</code>
  820        * @throws ReferenceSyntaxException if the specified <code>ref</code>
  821        *  has invalid syntax
  822        *
  823        * @deprecated This has been replaced by calling {@link
  824        * #getExpressionFactory} then {@link
  825        * ExpressionFactory#createMethodExpression}.
  826        */
  827       public abstract MethodBinding createMethodBinding(String ref,
  828                                                         Class params[])
  829           throws ReferenceSyntaxException;
  830   
  831   
  832       /**
  833        * <p>Return an <code>Iterator</code> over the supported
  834        * <code>Locale</code>s for this appication.</p>
  835        */ 
  836       public abstract Iterator<Locale> getSupportedLocales();
  837   
  838   
  839       /**
  840        * <p>Set the <code>Locale</code> instances representing the supported
  841        * <code>Locale</code>s for this application.</p>
  842        *
  843        * @param locales The set of supported <code>Locale</code>s
  844        *  for this application
  845        *
  846        * @throws NullPointerException if the argument
  847        * <code>newLocales</code> is <code>null</code>.
  848        *
  849        */ 
  850       public abstract void setSupportedLocales(Collection<Locale> locales);
  851   
  852       /**
  853        * <p>Provide a way for Faces applications to register an
  854        * <code>ELContextListener</code> that will be notified on creation
  855        * of <code>ELContext</code> instances.  This listener will be
  856        * called once per request.</p>
  857        * 
  858        * <p>An implementation is provided that throws 
  859        * <code>UnsupportedOperationException</code> so that users that decorate
  860        * the <code>Application</code> continue to work.
  861        *
  862        * @since 1.2
  863        */
  864   
  865       public void addELContextListener(ELContextListener listener) {
  866           Application app = getRIApplicationImpl();
  867           if (app != null) {
  868               app.addELContextListener(listener);
  869           } else {
  870               throw new UnsupportedOperationException();
  871           }
  872       }
  873   
  874       /**
  875        * <p>Remove the argument <code>listener</code> from the list of
  876        * {@link ELContextListener}s.  If <code>listener</code> is null, no
  877        * exception is thrown and no action is performed.  If
  878        * <code>listener</code> is not in the list, no exception is thrown
  879        * and no action is performed.</p>
  880        *
  881        * <p>An implementation is provided that throws 
  882        * <code>UnsupportedOperationException</code> so that users that decorate
  883        * the <code>Application</code> continue to work.
  884        * 
  885        * @since 1.2
  886        */
  887   
  888       public void removeELContextListener(ELContextListener listener) {
  889           Application app = getRIApplicationImpl();
  890           if (app != null) {
  891               app.removeELContextListener(listener);
  892           } else {
  893               throw new UnsupportedOperationException();
  894           }
  895   
  896       }
  897   
  898       /**
  899        * <p>If no calls have been made to {@link #addELContextListener},
  900        * this method must return an empty array.</p>
  901        *
  902        * <p>Otherwise, return an array representing the list of listeners
  903        * added by calls to {@link #addELContextListener}.</p>
  904        *
  905        * <p>An implementation is provided that throws 
  906        * <code>UnsupportedOperationException</code> so that users that decorate
  907        * the <code>Application</code> continue to work.
  908        *
  909        * @since 1.2
  910        */
  911   
  912       public ELContextListener [] getELContextListeners() {
  913           Application app = getRIApplicationImpl();
  914           if (app != null) {
  915               //noinspection TailRecursion
  916               return app.getELContextListeners();
  917           } else {
  918               throw new UnsupportedOperationException();
  919           }
  920       }
  921   
  922   
  923       /**
  924        * <p>Register a new mapping of validator id to the name of the
  925        * corresponding {@link Validator} class.  This allows subsequent calls
  926        * to <code>createValidator()</code> to serve as a factory for
  927        * {@link Validator} instances.</p>
  928        *
  929        * @param validatorId The validator id to be registered
  930        * @param validatorClass The fully qualified class name of the
  931        *  corresponding {@link Validator} implementation
  932        *
  933        * @throws NullPointerException if <code>validatorId</code>
  934        *  or <code>validatorClass</code> is <code>null</code>
  935        */
  936       public abstract void addValidator(String validatorId, 
  937   				      String validatorClass);
  938   
  939   
  940       /**
  941        * <p>Instantiate and return a new {@link Validator} instance of the
  942        * class specified by a previous call to <code>addValidator()</code>
  943        * for the specified validator id.</p>
  944        *
  945        * @param validatorId The validator id for which to create and
  946        *  return a new {@link Validator} instance
  947        *
  948        * @throws FacesException if a {@link Validator} of the
  949        *  specified id cannot be created
  950        * @throws NullPointerException if <code>validatorId</code>
  951        *  is <code>null</code>
  952        */ 
  953       public abstract Validator createValidator(String validatorId)
  954           throws FacesException;
  955   
  956   
  957       /**
  958        * <p>Return an <code>Iterator</code> over the set of currently registered
  959        * validator ids for this <code>Application</code>.</p>
  960        */
  961       public abstract Iterator<String> getValidatorIds();
  962   
  963   
  964       /**
  965        * <p>Call {@link #getExpressionFactory} then call {@link
  966        * ExpressionFactory#createValueExpression}, passing the argument
  967        * <code>ref</code>, <code>Object.class</code> for the expectedType,
  968        * and <code>null</code>, for the fnMapper.</p>
  969        *
  970        *
  971        * @param ref Value binding expression for which to return a
  972        *  {@link ValueBinding} instance
  973        *
  974        * @throws NullPointerException if <code>ref</code>
  975        *  is <code>null</code>
  976        * @throws ReferenceSyntaxException if the specified <code>ref</code>
  977        *  has invalid syntax
  978        *
  979        * @deprecated This has been replaced by calling {@link
  980        * #getExpressionFactory} then {@link
  981        * ExpressionFactory#createValueExpression}.
  982        */
  983       public abstract ValueBinding createValueBinding(String ref)
  984           throws ReferenceSyntaxException;
  985   
  986   
  987       // --------------------------------------------------------- Private Methods
  988   
  989   
  990       private static Application getRIApplicationImpl(FacesContext context) {
  991           ExternalContext extContext;
  992           if (context != null) {
  993               extContext = context.getExternalContext();
  994           } else {
  995               extContext =
  996                    FacesContext.getCurrentInstance().getExternalContext();
  997           }
  998           if (extContext != null) {
  999               return ((Application) extContext.getApplicationMap().
 1000                    get("com.sun.faces.ApplicationImpl"));
 1001           }
 1002           return null;
 1003       }
 1004   
 1005       private static Application getRIApplicationImpl() {
 1006           return getRIApplicationImpl(null);
 1007       }
 1008   
 1009   }

Save This Page
Home » mojarra-1.2_09-b02-FCS-source » javax.faces.application » [javadoc | source]