Save This Page
Home » mojarra-1.2_09-b02-FCS-source » com.sun.faces.application » [javadoc | source]
    1   /*
    2    * $Id: ApplicationAssociate.java,v 1.49.4.5 2008/06/11 18:03:03 rlubke 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 com.sun.faces.application;
   42   
   43   import java.util.ArrayList;
   44   import java.util.Collections;
   45   import java.util.Comparator;
   46   import java.util.HashMap;
   47   import java.util.List;
   48   import java.util.Locale;
   49   import java.util.Map;
   50   import java.util.ResourceBundle;
   51   import java.util.TreeSet;
   52   
   53   import javax.el.CompositeELResolver;
   54   import javax.el.ELResolver;
   55   import javax.el.ExpressionFactory;
   56   import javax.faces.component.UIViewRoot;
   57   import javax.faces.context.ExternalContext;
   58   import javax.faces.context.FacesContext;
   59   import javax.faces.el.PropertyResolver;
   60   import javax.faces.el.VariableResolver;
   61   import javax.servlet.ServletContext;
   62   
   63   import com.sun.faces.RIConstants;
   64   import com.sun.faces.config.WebConfiguration;
   65   import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter;
   66   import com.sun.faces.scripting.GroovyHelper;
   67   import com.sun.faces.mgbean.BeanManager;
   68   import com.sun.faces.spi.InjectionProvider;
   69   import com.sun.faces.spi.InjectionProviderFactory;
   70   import com.sun.faces.util.MessageUtils;
   71   
   72   /**
   73    * <p>Break out the things that are associated with the Application, but
   74    * need to be present even when the user has replaced the Application
   75    * instance.</p>
   76    * <p/>
   77    * <p>For example: the user replaces ApplicationFactory, and wants to
   78    * intercept calls to createValueExpression() and createMethodExpression() for
   79    * certain kinds of expressions, but allow the existing application to
   80    * handle the rest.</p>
   81    */
   82   
   83   public class ApplicationAssociate {
   84   
   85   
   86       private static final String APPLICATION_IMPL_ATTR_NAME =
   87             RIConstants.FACES_PREFIX + "ApplicationImpl";
   88   
   89       private ApplicationImpl app = null;
   90   
   91   
   92   
   93   
   94       /**
   95        * Overall Map containing <code>from-view-id</code> key and
   96        * <code>ArrayList</code> of <code>ConfigNavigationCase</code>
   97        * objects for that key; The <code>from-view-id</code> strings in
   98        * this map will be stored as specified in the configuration file -
   99        * some of them will have a trailing asterisk "*" signifying wild
  100        * card, and some may be specified as an asterisk "*".
  101        */
  102       private Map<String, List<ConfigNavigationCase>> caseListMap = null;
  103   
  104       /**
  105        * The List that contains all view identifier strings ending in an
  106        * asterisk "*".  The entries are stored without the trailing
  107        * asterisk.
  108        */
  109       private TreeSet<String> wildcardMatchList = null;
  110   
  111       // Flag indicating that a response has been rendered.
  112       private boolean responseRendered = false;
  113   
  114       private static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX +
  115            "ApplicationAssociate";
  116   
  117       private static ThreadLocal<ApplicationAssociate> instance =
  118           new ThreadLocal<ApplicationAssociate>() {
  119               protected ApplicationAssociate initialValue() {
  120                   return (null);
  121               }
  122           };
  123   
  124       private List<ELResolver> elResolversFromFacesConfig = null;
  125   
  126       @SuppressWarnings("deprecation")
  127       private VariableResolver legacyVRChainHead = null;
  128   
  129       @SuppressWarnings("deprecation")
  130       private PropertyResolver legacyPRChainHead = null;
  131       private ExpressionFactory expressionFactory = null;
  132   
  133       @SuppressWarnings("deprecation")
  134       private PropertyResolver legacyPropertyResolver = null;
  135   
  136       @SuppressWarnings("deprecation")
  137       private VariableResolver legacyVariableResolver = null;
  138       private CompositeELResolver facesELResolverForJsp = null;
  139   
  140       private InjectionProvider injectionProvider;
  141   
  142       private String contextName;
  143       private boolean requestServiced;
  144   
  145       private BeanManager beanManager;
  146       private GroovyHelper groovyHelper;
  147       private boolean devModeEnabled;
  148   
  149       private PropertyEditorHelper propertyEditorHelper;
  150   
  151       public ApplicationAssociate(ApplicationImpl appImpl) {
  152           app = appImpl;
  153   
  154           propertyEditorHelper = new PropertyEditorHelper(appImpl);
  155   
  156           FacesContext ctx = FacesContext.getCurrentInstance();
  157           if (ctx == null) {
  158               throw new IllegalStateException(
  159                    MessageUtils.getExceptionMessageString(
  160                         MessageUtils.APPLICATION_ASSOCIATE_CTOR_WRONG_CALLSTACK_ID));
  161           }
  162           ExternalContext externalContext = ctx.getExternalContext();
  163           if (null != externalContext.getApplicationMap().get(ASSOCIATE_KEY)) {
  164               throw new IllegalStateException(
  165                    MessageUtils.getExceptionMessageString(
  166                         MessageUtils.APPLICATION_ASSOCIATE_EXISTS_ID));
  167           }
  168           externalContext.getApplicationMap().put(APPLICATION_IMPL_ATTR_NAME,
  169                appImpl);
  170           externalContext.getApplicationMap().put(ASSOCIATE_KEY, this);
  171           //noinspection CollectionWithoutInitialCapacity
  172           caseListMap = new HashMap<String, List<ConfigNavigationCase>>();
  173           wildcardMatchList = new TreeSet<String>(new SortIt());
  174           injectionProvider = InjectionProviderFactory.createInstance(externalContext);
  175           WebConfiguration webConfig = WebConfiguration.getInstance(externalContext);
  176           beanManager = new BeanManager(injectionProvider,
  177                                         webConfig.isOptionEnabled(
  178                                              BooleanWebContextInitParameter.EnableLazyBeanValidation));
  179           groovyHelper = GroovyHelper.getCurrentInstance();
  180           devModeEnabled = webConfig.isOptionEnabled(BooleanWebContextInitParameter.DevelopmentMode);
  181       }
  182   
  183       public static ApplicationAssociate getInstance(ExternalContext
  184            externalContext) {
  185           if (externalContext == null) {
  186               return null;
  187           }
  188           Map applicationMap = externalContext.getApplicationMap();
  189           return ((ApplicationAssociate)
  190                applicationMap.get(ASSOCIATE_KEY));
  191       }
  192   
  193       public static ApplicationAssociate getInstance(ServletContext context) {
  194           if (context == null) {
  195               return null;
  196           }
  197           return (ApplicationAssociate) context.getAttribute(ASSOCIATE_KEY);
  198       }
  199   
  200       public static void setCurrentInstance(ApplicationAssociate associate) {
  201   
  202           if (associate == null) {
  203               instance.remove();
  204           } else {
  205               instance.set(associate);
  206           }
  207           
  208       }
  209   
  210       public static ApplicationAssociate getCurrentInstance() {
  211   
  212           ApplicationAssociate associate = instance.get();
  213           if (associate == null) {
  214               // Fallback to ExternalContext lookup
  215               FacesContext fc = FacesContext.getCurrentInstance();
  216               if (fc != null) {
  217                   ExternalContext extContext = fc.getExternalContext();
  218                   if (extContext != null) {
  219                       return ApplicationAssociate.getInstance(extContext);
  220                   }
  221               }
  222           }
  223   
  224           return associate;
  225           
  226       }
  227   
  228       public static void clearInstance(ExternalContext
  229            externalContext) {
  230           Map applicationMap = externalContext.getApplicationMap();
  231           ApplicationAssociate me = (ApplicationAssociate) applicationMap.get(ASSOCIATE_KEY);
  232           if (null != me) {
  233               if (null != me.resourceBundles) {
  234                   me.resourceBundles.clear();
  235               }
  236           }
  237           applicationMap.remove(ASSOCIATE_KEY);        
  238       }
  239   
  240   
  241       public BeanManager getBeanManager() {
  242           return beanManager;
  243       }
  244   
  245       public GroovyHelper getGroovyHelper() {
  246           return groovyHelper;
  247       }
  248   
  249       public boolean isDevModeEnabled() {
  250           return devModeEnabled;
  251       }
  252   
  253       /**
  254        * Obtain the PropertyEditorHelper instance for this app.
  255        *
  256        * @return
  257        */
  258       public PropertyEditorHelper getPropertyEditorHelper() {
  259           return propertyEditorHelper;
  260       }
  261   
  262       /**
  263        * This method is called by <code>ConfigureListener</code> and will
  264        * contain any <code>VariableResolvers</code> defined within
  265        * faces-config configuration files.
  266        *
  267        * @param resolver VariableResolver
  268        */
  269       @SuppressWarnings("deprecation")
  270       public void setLegacyVRChainHead(VariableResolver resolver) {
  271           this.legacyVRChainHead = resolver;
  272       }
  273   
  274       @SuppressWarnings("deprecation")
  275       public VariableResolver getLegacyVRChainHead() {
  276           return legacyVRChainHead;
  277       }
  278   
  279       /**
  280        * This method is called by <code>ConfigureListener</code> and will
  281        * contain any <code>PropertyResolvers</code> defined within
  282        * faces-config configuration files.
  283        *
  284        * @param resolver PropertyResolver
  285        */
  286       @SuppressWarnings("deprecation")
  287       public void setLegacyPRChainHead(PropertyResolver resolver) {
  288           this.legacyPRChainHead = resolver;
  289       }
  290   
  291       @SuppressWarnings("deprecation")
  292       public PropertyResolver getLegacyPRChainHead() {
  293           return legacyPRChainHead;
  294       }
  295   
  296       public CompositeELResolver getFacesELResolverForJsp() {
  297           return facesELResolverForJsp;
  298       }
  299   
  300       public void setFacesELResolverForJsp(CompositeELResolver celr) {
  301           facesELResolverForJsp = celr;
  302       }
  303   
  304       public void setELResolversFromFacesConfig(List<ELResolver> resolvers) {
  305           this.elResolversFromFacesConfig = resolvers;
  306       }
  307   
  308       public List<ELResolver> getELResolversFromFacesConfig() {
  309           return elResolversFromFacesConfig;
  310       }
  311   
  312       public void setExpressionFactory(ExpressionFactory expressionFactory) {
  313           this.expressionFactory = expressionFactory;
  314       }
  315   
  316       public ExpressionFactory getExpressionFactory() {
  317           return this.expressionFactory;
  318       }
  319   
  320       public List<ELResolver> getApplicationELResolvers() {
  321           return app.getApplicationELResolvers();
  322       }
  323   
  324       public InjectionProvider getInjectionProvider() {
  325           return injectionProvider;
  326       }
  327   
  328       public void setContextName(String contextName) {
  329           this.contextName = contextName;
  330       }
  331   
  332       public String getContextName() {
  333           return contextName;
  334       }
  335   
  336       /**
  337        * Maintains the PropertyResolver called through
  338        * Application.setPropertyResolver()
  339        * @param resolver PropertyResolver
  340        */
  341       @SuppressWarnings("deprecation")
  342       public void setLegacyPropertyResolver(PropertyResolver resolver) {
  343           this.legacyPropertyResolver = resolver;
  344       }
  345   
  346       /**
  347        * @return the PropertyResolver called through
  348        * Application.getPropertyResolver()
  349        */
  350       @SuppressWarnings("deprecation")
  351       public PropertyResolver getLegacyPropertyResolver() {
  352           return legacyPropertyResolver;
  353       }
  354   
  355       /**
  356        * Maintains the PropertyResolver called through
  357        * Application.setVariableResolver()
  358        * @param resolver VariableResolver
  359        */
  360       @SuppressWarnings("deprecation")
  361       public void setLegacyVariableResolver(VariableResolver resolver) {
  362           this.legacyVariableResolver = resolver;
  363       }
  364   
  365       /**
  366        * @return the VariableResolver called through
  367        * Application.getVariableResolver()
  368        */
  369       @SuppressWarnings("deprecation")
  370       public VariableResolver getLegacyVariableResolver() {
  371           return legacyVariableResolver;
  372       }
  373   
  374   
  375       /**
  376        * Called by application code to indicate we've processed the
  377        * first request to the application.
  378        */
  379       public void setRequestServiced() {
  380           this.requestServiced = true;
  381       }
  382   
  383       /**
  384        * @return <code>true</code> if we've processed a request, otherwise
  385        *         <code>false</code>
  386        */
  387       public boolean hasRequestBeenServiced() {
  388           return requestServiced;
  389       }
  390   
  391   
  392       /**
  393        * Add a navigation case to the internal case list.  If a case list
  394        * does not already exist in the case list map containing this case
  395        * (identified by <code>from-view-id</code>), start a new list,
  396        * add the case to it, and store the list in the case list map.
  397        * If a case list already exists, see if a case entry exists in the list
  398        * with a matching <code>from-view-id</code><code>from-action</code>
  399        * <code>from-outcome</code> combination.  If there is suach an entry,
  400        * overwrite it with this new case.  Otherwise, add the case to the list.
  401        *
  402        * @param navigationCase the navigation case containing navigation
  403        *                       mapping information from the configuration file.
  404        */
  405       public void addNavigationCase(ConfigNavigationCase navigationCase) {
  406   
  407           String fromViewId = navigationCase.getFromViewId();
  408           List<ConfigNavigationCase> caseList = caseListMap.get(fromViewId);
  409           if (caseList == null) {
  410               //noinspection CollectionWithoutInitialCapacity
  411               caseList = new ArrayList<ConfigNavigationCase>();
  412               caseList.add(navigationCase);
  413               caseListMap.put(fromViewId, caseList);
  414           } else {
  415               String key = navigationCase.getKey();
  416               boolean foundIt = false;
  417               for (int i = 0; i < caseList.size(); i++) {
  418                   ConfigNavigationCase navCase = caseList.get(i);
  419                   // if there already is a case existing for the
  420                   // fromviewid/fromaction.fromoutcome combination,
  421                   // replace it ...  (last one wins).
  422                   //
  423                   if (key.equals(navCase.getKey())) {
  424                       caseList.set(i, navigationCase);
  425                       foundIt = true;
  426                       break;
  427                   }
  428               }
  429               if (!foundIt) {
  430                   caseList.add(navigationCase);
  431               }
  432           }
  433           if (fromViewId.endsWith("*")) {
  434               fromViewId =
  435                    fromViewId.substring(0, fromViewId.lastIndexOf('*'));
  436               wildcardMatchList.add(fromViewId);
  437           }
  438   
  439       }
  440   
  441   
  442       /**
  443        * Return a <code>Map</code> of navigation mappings loaded from
  444        * the configuration system.  The key for the returned <code>Map</code>
  445        * is <code>from-view-id</code>, and the value is a <code>List</code>
  446        * of navigation cases.
  447        *
  448        * @return Map the map of navigation mappings.
  449        */
  450       public Map<String, List<ConfigNavigationCase>> getNavigationCaseListMappings() {
  451           if (caseListMap == null) {
  452               return Collections.emptyMap();
  453           }
  454           return caseListMap;
  455       }
  456   
  457   
  458       /**
  459        * Return all navigation mappings whose <code>from-view-id</code>
  460        * contained a trailing "*".
  461        *
  462        * @return <code>TreeSet</code> The navigation mappings sorted in
  463        *         descending order.
  464        */
  465       public TreeSet<String> getNavigationWildCardList() {
  466           return wildcardMatchList;
  467       }
  468   
  469       public ResourceBundle getResourceBundle(FacesContext context,
  470                                               String var) {
  471           ApplicationResourceBundle bundle = resourceBundles.get(var);
  472           if (bundle == null) {
  473               return null;
  474           }
  475           UIViewRoot root;
  476           // Start out with the default locale
  477           Locale locale;
  478           Locale defaultLocale = Locale.getDefault();
  479           locale = defaultLocale;
  480           // See if this FacesContext has a ViewRoot
  481           if (null != (root = context.getViewRoot())) {
  482               // If so, ask it for its Locale
  483               if (null == (locale = root.getLocale())) {
  484                   // If the ViewRoot has no Locale, fall back to the default.
  485                   locale = defaultLocale;
  486               }
  487           }
  488           assert (null != locale);
  489           //ResourceBundleBean bean = resourceBundles.get(var);
  490           return bundle.getResourceBundle(locale);
  491           
  492       }
  493   
  494       /**
  495        * keys: <var> element from faces-config<p>
  496        * <p/>
  497        * values: ResourceBundleBean instances.
  498        */
  499   
  500       @SuppressWarnings({"CollectionWithoutInitialCapacity"})
  501       Map<String, ApplicationResourceBundle> resourceBundles =
  502            new HashMap<String, ApplicationResourceBundle>();
  503   
  504       public void addResourceBundle(String var, ApplicationResourceBundle bundle) {
  505           resourceBundles.put(var, bundle);
  506       }
  507   
  508       public Map<String, ApplicationResourceBundle> getResourceBundles() {
  509           return resourceBundles;
  510       }
  511   
  512       // This is called by ViewHandlerImpl.renderView().
  513       void responseRendered() {
  514           responseRendered = true;
  515       }
  516   
  517       boolean isResponseRendered() {
  518           return responseRendered;
  519       }
  520   
  521   
  522       /**
  523        * This Comparator class will help sort the <code>ConfigNavigationCase</code> objects
  524        * based on their <code>fromViewId</code> properties in descending order -
  525        * largest string to smallest string.
  526        */
  527       static class SortIt implements Comparator<String> {
  528   
  529           public int compare(String fromViewId1, String fromViewId2) {
  530               return -(fromViewId1.compareTo(fromViewId2));
  531           }
  532       }
  533   
  534   }

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