com.sun.faces.application.ApplicationAssociate.java Source code

Java tutorial

Introduction

Here is the source code for com.sun.faces.application.ApplicationAssociate.java

Source

/*
 * $Id: ApplicationAssociate.java,v 1.3.26.1.2.2.2.1 2006/04/12 19:32:02 ofung Exp $
 */

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License). You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the License at
 * https://javaserverfaces.dev.java.net/CDDL.html or
 * legal/CDDLv1.0.txt. 
 * See the License for the specific language governing
 * permission and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at legal/CDDLv1.0.txt.    
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * [Name of File] [ver.__] [Date]
 * 
 * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
 */

package com.sun.faces.application;

import com.sun.faces.util.Util;
import com.sun.faces.RIConstants;
import com.sun.faces.config.ConfigureListener;

import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.Comparator;
import java.util.Collections;

import javax.faces.context.FacesContext;
import javax.faces.context.ExternalContext;
import javax.faces.FacesException;

import com.sun.faces.config.ManagedBeanFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <p>Break out the things that are associated with the Application, but
 * need to be present even when the user has replaced the Application
 * instance.</p>
 * 
 * <p>For example: the user replaces ApplicationFactory, and wants to
 * intercept calls to createValueBinding() and createMethodBinding() for
 * certain kinds of expressions, but allow the existing application to
 * handle the rest.</p>
 */

public class ApplicationAssociate {

    protected static Log log = LogFactory.getLog(ApplicationImpl.class);

    //
    // This map stores "managed bean name" | "managed bean factory"
    // mappings.
    //
    private Map managedBeanFactoriesMap = null;

    // These maps stores "navigation rule" mappings.
    //

    /**
     * Overall Map containing <code>from-view-id</code> key and
     * <code>ArrayList</code> of <code>ConfigNavigationCase</code>
     * objects for that key; The <code>from-view-id</code> strings in
     * this map will be stored as specified in the configuration file -
     * some of them will have a trailing asterisk "*" signifying wild
     * card, and some may be specified as an asterisk "*".
     */
    private Map caseListMap = null;

    /**
     * The List that contains the <code>ConfigNavigationCase</code>
     * objects for a <code>from-view-id</code>.
     */
    private List caseList = null;

    /**
     * The List that contains all view identifier strings ending in an
     * asterisk "*".  The entries are stored without the trailing
     * asterisk.
     */
    private TreeSet wildcardMatchList = null;

    // Flag indicating that a response has been rendered.
    private boolean responseRendered = false;

    private static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + "ApplicationAssociate";

    public ApplicationAssociate() {

        ExternalContext externalContext = null;
        if (null == (externalContext = ConfigureListener.getExternalContextDuringInitialize())) {
            // PENDING I18N
            throw new IllegalStateException(
                    "ApplicationAssociate ctor not called in same callstack as ConfigureListener.contextInitialized()");
        }
        // PENDING I18N
        if (null != externalContext.getApplicationMap().get(ASSOCIATE_KEY)) {
            throw new IllegalStateException("ApplicationAssociate already exists for this webapp");
        }
        externalContext.getApplicationMap().put(ASSOCIATE_KEY, this);
        managedBeanFactoriesMap = new HashMap();
        caseListMap = new HashMap();
        wildcardMatchList = new TreeSet(new SortIt());

    }

    public static ApplicationAssociate getInstance(ExternalContext externalContext) {
        Map applicationMap = externalContext.getApplicationMap();
        return ((ApplicationAssociate) applicationMap.get(ASSOCIATE_KEY));
    }

    public static void clearInstance(ExternalContext externalContext) {
        Map applicationMap = externalContext.getApplicationMap();
        applicationMap.remove(ASSOCIATE_KEY);
    }

    /**
     * Add a navigation case to the internal case list.  If a case list
     * does not already exist in the case list map containing this case
     * (identified by <code>from-view-id</code>), start a new list,
     * add the case to it, and store the list in the case list map.
     * If a case list already exists, see if a case entry exists in the list
     * with a matching <code>from-view-id</code><code>from-action</code>
     * <code>from-outcome</code> combination.  If there is suach an entry,
     * overwrite it with this new case.  Otherwise, add the case to the list.
     *
     * @param navigationCase the navigation case containing navigation
     *                       mapping information from the configuration file.
     */
    public void addNavigationCase(ConfigNavigationCase navigationCase) {

        String fromViewId = navigationCase.getFromViewId();
        synchronized (this) {
            caseList = (List) caseListMap.get(fromViewId);
            if (caseList == null) {
                caseList = new ArrayList();
                caseList.add(navigationCase);
                caseListMap.put(fromViewId, caseList);
            } else {
                String key = navigationCase.getKey();
                boolean foundIt = false;
                for (int i = 0; i < caseList.size(); i++) {
                    ConfigNavigationCase navCase = (ConfigNavigationCase) caseList.get(i);
                    // if there already is a case existing for the
                    // fromviewid/fromaction.fromoutcome combination,
                    // replace it ...  (last one wins).
                    //
                    if (key.equals(navCase.getKey())) {
                        caseList.set(i, navigationCase);
                        foundIt = true;
                        break;
                    }
                }
                if (!foundIt) {
                    caseList.add(navigationCase);
                }
            }
            if (fromViewId.endsWith("*")) {
                fromViewId = fromViewId.substring(0, fromViewId.lastIndexOf("*"));
                wildcardMatchList.add(fromViewId);
            }
        }
    }

    /**
     * Return a <code>Map</code> of navigation mappings loaded from
     * the configuration system.  The key for the returned <code>Map</code>
     * is <code>from-view-id</code>, and the value is a <code>List</code>
     * of navigation cases.
     *
     * @return Map the map of navigation mappings.
     */
    public Map getNavigationCaseListMappings() {
        if (caseListMap == null) {
            return Collections.EMPTY_MAP;
        }
        return caseListMap;
    }

    /**
     * Return all navigation mappings whose <code>from-view-id</code>
     * contained a trailing "*".
     *
     * @return <code>TreeSet</code> The navigation mappings sorted in
     *         descending order.
     */
    public TreeSet getNavigationWildCardList() {
        return wildcardMatchList;
    }

    /**
     * <p>Adds a new mapping of managed bean name to a managed bean
     * factory instance.</p>
     *
     * @param managedBeanName the name of the managed bean that will
     *                        be created by the managed bean factory instance.
     * @param factory         the managed bean factory instance.
     */
    synchronized public void addManagedBeanFactory(String managedBeanName, ManagedBeanFactory factory) {
        managedBeanFactoriesMap.put(managedBeanName, factory);
        factory.setManagedBeanFactoryMap(managedBeanFactoriesMap);
        if (log.isTraceEnabled()) {
            log.trace("Added managedBeanFactory " + factory + " for" + managedBeanName);
        }
    }

    /**
     * <p>The managedBeanFactories HashMap has been populated
     * with ManagedBeanFactory object keyed by the bean name.
     * Find the ManagedBeanFactory object and if it exists instantiate
     * the bean and store it in the appropriate scope, if any.</p>
     *
     * @param context         The Faces context.
     * @param managedBeanName The name identifying the managed bean.
     * @return The managed bean.
     * @throws FacesException if the managed bean
     *                                   could not be created.
     */
    public Object createAndMaybeStoreManagedBeans(FacesContext context, String managedBeanName)
            throws FacesException {
        ManagedBeanFactory managedBean = (ManagedBeanFactory) managedBeanFactoriesMap.get(managedBeanName);
        if (managedBean == null) {
            if (log.isDebugEnabled()) {
                log.debug("Couldn't find a factory for " + managedBeanName);
            }
            return null;
        }

        Object bean = null;
        //add bean to appropriate scope
        String scope = managedBean.getScope();

        if (log.isTraceEnabled()) {
            log.trace("Storing " + managedBeanName + " in scope " + scope);
        }

        boolean scopeIsApplication = false, scopeIsSession = false, scopeIsRequest = false;

        if ((scopeIsApplication = scope.equalsIgnoreCase(RIConstants.APPLICATION))
                || (scopeIsSession = scope.equalsIgnoreCase(RIConstants.SESSION))) {
            synchronized (this) {
                try {
                    bean = managedBean.newInstance(context);
                    if (log.isDebugEnabled()) {
                        log.debug("Created bean " + managedBeanName + " successfully ");
                    }
                } catch (Exception ex) {
                    Object[] params = { ex.getMessage() };
                    if (log.isErrorEnabled()) {
                        log.error("Managedbean " + managedBeanName + " could not be created " + ex.getMessage(),
                                ex);
                    }
                    throw new FacesException(ex);
                }
                if (scopeIsApplication) {
                    context.getExternalContext().getApplicationMap().put(managedBeanName, bean);
                }
                if (scopeIsSession) {
                    Util.getSessionMap(context).put(managedBeanName, bean);
                }
            }
        } else {
            scopeIsRequest = scope.equalsIgnoreCase(RIConstants.REQUEST);
            try {
                bean = managedBean.newInstance(context);
                if (log.isDebugEnabled()) {
                    log.debug("Created bean " + managedBeanName + " successfully ");
                }
            } catch (Exception ex) {
                Object[] params = { ex.getMessage() };
                if (log.isErrorEnabled()) {
                    log.error("Managedbean " + managedBeanName + " could not be created " + ex.getMessage(), ex);
                }
                throw new FacesException(ex);
            }

            if (scopeIsRequest) {
                context.getExternalContext().getRequestMap().put(managedBeanName, bean);
            }
        }
        return bean;
    }

    // This is called by ViewHandlerImpl.renderView().
    synchronized void responseRendered() {
        responseRendered = true;
    }

    boolean isResponseRendered() {
        return responseRendered;
    }

    /**
     * This Comparator class will help sort the <code>ConfigNavigationCase</code> objects
     * based on their <code>fromViewId</code> properties in descending order -
     * largest string to smallest string.
     */
    class SortIt implements Comparator {

        public int compare(Object o1, Object o2) {
            String fromViewId1 = (String) o1;
            String fromViewId2 = (String) o2;
            return -(fromViewId1.compareTo(fromViewId2));
        }
    }

    class CaseStruct {

        String viewId;
        ConfigNavigationCase navCase;
    }

}