Package com.sun.faces.flow

Source Code of com.sun.faces.flow.FlowCDIContext$FlowBeanInfo

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.faces.flow;

import java.io.Serializable;
import javax.faces.flow.FlowScoped;
import java.lang.annotation.Annotation;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.flow.Flow;
import javax.faces.flow.FlowHandler;
import javax.faces.lifecycle.ClientWindow;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;

public class FlowCDIContext implements Context, Serializable {
   
    private static final long serialVersionUID = -7144653402477623609L;
   
    private transient Map<Contextual<?>, FlowBeanInfo> flowIds;
   
    private static final FlowScopeMapKey FLOW_SCOPE_MAP_KEY = new FlowScopeMapKey();
   
    static class FlowBeanInfo {
        String definingDocumentId;
        String id;
    }
   
    // This should be vended from a factory for decoration purposes.
   
    public FlowCDIContext(Map<Contextual<?>, FlowBeanInfo> flowIds) {
        this.flowIds = new ConcurrentHashMap<Contextual<?>, FlowBeanInfo>(flowIds);
    }
   
    private static final String PER_SESSION_BEAN_MAP_LIST = FlowCDIContext.class.getPackage().getName() + ".PER_SESSION_BEAN_MAP_LIST";
    private static final String PER_SESSION_CREATIONAL_LIST = FlowCDIContext.class.getPackage().getName() + ".PER_SESSION_CREATIONAL_LIST";
   
    // -------------------------------------------------------- Private Methods
   
    // <editor-fold defaultstate="collapsed" desc="Private helpers">      
   
    private static Map<Contextual<?>, Object> getFlowScopedBeanMapForCurrentFlow() {

        Map<Contextual<?>, Object> result;
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext extContext = context.getExternalContext();
        Map<String, Object> sessionMap = extContext.getSessionMap();
        Flow currentFlow = getCurrentFlow(context);
       
        if (null == currentFlow) {
            return null;
        }
       
        ClientWindow curWindow = context.getExternalContext().getClientWindow();
        if (null == curWindow) {
            throw new IllegalStateException("Unable to obtain current ClientWindow.  Is the ClientWindow feature enabled?");
        }

        String flowBeansForClientWindow = currentFlow.getClientWindowFlowId(curWindow) + "_beans";
        result = (Map<Contextual<?>, Object>) sessionMap.get(flowBeansForClientWindow);
        if (null == result) {
            result = new ConcurrentHashMap<Contextual<?>, Object>();
            sessionMap.put(flowBeansForClientWindow, result);
            ensureBeanMapCleanupOnSessionDestroyed(sessionMap, flowBeansForClientWindow);
        }
       
        return result;
    }
   
    private static Map<Contextual<?>, CreationalContext<?>> getFlowScopedCreationalMapForCurrentFlow() {
        Map<Contextual<?>, CreationalContext<?>> result;
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext extContext = context.getExternalContext();
        Map<String, Object> sessionMap = extContext.getSessionMap();
        Flow currentFlow = getCurrentFlow(context);

        ClientWindow curWindow = context.getExternalContext().getClientWindow();
        if (null == curWindow) {
            throw new IllegalStateException("Unable to obtain current ClientWindow.  Is the ClientWindow feature enabled?");
        }

        String creationalForClientWindow = currentFlow.getClientWindowFlowId(curWindow) + "_creational";
        result = (Map<Contextual<?>, CreationalContext<?>>) sessionMap.get(creationalForClientWindow);
        if (null == result) {
            result = new ConcurrentHashMap<Contextual<?>, CreationalContext<?>>();
            sessionMap.put(creationalForClientWindow, result);
            ensureCreationalCleanupOnSessionDestroyed(sessionMap, creationalForClientWindow);
        }
       
        return result;

    }
   
    private static void ensureBeanMapCleanupOnSessionDestroyed(Map<String, Object> sessionMap, String flowBeansForClientWindow) {
        List<String> beanMapList = (List<String>) sessionMap.get(PER_SESSION_BEAN_MAP_LIST);
        if (null == beanMapList) {
            beanMapList = new ArrayList<String>();
            sessionMap.put(PER_SESSION_BEAN_MAP_LIST, beanMapList);
        }
        beanMapList.add(flowBeansForClientWindow);
    }
   
    private static void ensureCreationalCleanupOnSessionDestroyed(Map<String, Object> sessionMap, String creationalForClientWindow) {
        List<String> beanMapList = (List<String>) sessionMap.get(PER_SESSION_CREATIONAL_LIST);
        if (null == beanMapList) {
            beanMapList = new ArrayList<String>();
            sessionMap.put(PER_SESSION_CREATIONAL_LIST, beanMapList);
        }
        beanMapList.add(creationalForClientWindow);
    }
   
    @SuppressWarnings({"FinalPrivateMethod"})
    private final void assertNotReleased() {
        if (!isActive()) {
            throw new IllegalStateException();
        }
    }
   
    private Flow getCurrentFlow() {
        Flow result = null;
       
        FacesContext context = FacesContext.getCurrentInstance();
        result = getCurrentFlow(context);
       
        return result;
    }
   
    private static Flow getCurrentFlow(FacesContext context) {
        FlowHandler flowHandler = context.getApplication().getFlowHandler();
        if (null == flowHandler) {
            return null;
        }
       
        Flow result = flowHandler.getCurrentFlow(context);
       
        return result;
       
    }
   
    private static class FlowScopeMapKey implements Contextual<Object> {

        public Object create(CreationalContext<Object> cc) {
            return cc;
        }

        public void destroy(Object t, CreationalContext<Object> cc) {
            Map<Object,Object> flowScope = (Map<Object,Object>) t;
            flowScope.clear();
        }
       
    }
   
   
    // </editor-fold>   

    // <editor-fold defaultstate="collapsed" desc="Called from code not related to flow">      
   
    /*
     * Called from WebappLifecycleListener.sessionDestroyed()
     */
   
    public static void sessionDestroyed(HttpSessionEvent hse) {
        HttpSession session = hse.getSession();
       
        List<String> beanMapList = (List<String>) session.getAttribute(PER_SESSION_BEAN_MAP_LIST);
        if (null != beanMapList) {
            for (String cur : beanMapList) {
                Map<Contextual<?>, Object> beanMap =
                        (Map<Contextual<?>, Object>) session.getAttribute(cur);
                beanMap.clear();
                session.removeAttribute(cur);
            }
            session.removeAttribute(PER_SESSION_BEAN_MAP_LIST);
            beanMapList.clear();
        }
       
        List<String> creationalList = (List<String>) session.getAttribute(PER_SESSION_CREATIONAL_LIST);
        if (null != creationalList) {
            for (String cur : creationalList) {
                Map<Contextual<?>, CreationalContext<?>> beanMap =
                        (Map<Contextual<?>, CreationalContext<?>>) session.getAttribute(cur);
                beanMap.clear();
                session.removeAttribute(cur);
            }
            session.removeAttribute(PER_SESSION_CREATIONAL_LIST);
            creationalList.clear();
        }
       
       
    }
   
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Called from code related to flow"> 
   
    static Map<Object, Object> getCurrentFlowScope() {
        Map<Contextual<?>, Object> flowScopedBeanMap = getFlowScopedBeanMapForCurrentFlow();
        Map<Object, Object> result = null;
        if (null != flowScopedBeanMap) {
            result = (Map<Object, Object>) flowScopedBeanMap.get(FLOW_SCOPE_MAP_KEY);
            if (null == result) {
                result = new ConcurrentHashMap<Object, Object>();
                flowScopedBeanMap.put(FLOW_SCOPE_MAP_KEY, result);
            }
        }
        return result;
    }
       
    static void flowExited() {
        Map<Contextual<?>, Object> flowScopedBeanMap = getFlowScopedBeanMapForCurrentFlow();
        Map<Contextual<?>, CreationalContext<?>> creationalMap = getFlowScopedCreationalMapForCurrentFlow();
        assert(!flowScopedBeanMap.isEmpty());
        assert(!creationalMap.isEmpty());
        List<Contextual<?>> flowScopedBeansToRemove = new ArrayList<Contextual<?>>();
       
        for (Entry<Contextual<?>, Object> entry : flowScopedBeanMap.entrySet()) {
            Contextual owner = entry.getKey();
            Object bean = entry.getValue();
            CreationalContext creational = creationalMap.get(owner);
           
            owner.destroy(bean, creational);
            flowScopedBeansToRemove.add(owner);
        }
       
        for (Contextual<?> cur : flowScopedBeansToRemove) {
            flowScopedBeanMap.remove(cur);
            creationalMap.remove(cur);
        }
       
    }
   
    static void flowEntered() {
        getFlowScopedBeanMapForCurrentFlow();
        getFlowScopedCreationalMapForCurrentFlow();
       
        getCurrentFlowScope();
       
    }

// </editor-fold>
   
    // <editor-fold defaultstate="collapsed" desc="spi.Context implementation">      
   
    @Override
    public <T> T get(Contextual<T> contextual, CreationalContext<T> creational) {
        assertNotReleased();
       
        T result = get(contextual);
       
        if (null == result) {
            Map<Contextual<?>, Object> flowScopedBeanMap = getFlowScopedBeanMapForCurrentFlow();
            Map<Contextual<?>, CreationalContext<?>> creationalMap = getFlowScopedCreationalMapForCurrentFlow();
           
            synchronized (flowScopedBeanMap) {
                result = (T) flowScopedBeanMap.get(contextual);
                if (null == result) {
                   
                    FacesContext facesContext = FacesContext.getCurrentInstance();
                    FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
                   
                    if (null == flowHandler) {
                        return null;
                    }
                   
                    FlowBeanInfo fbi = flowIds.get(contextual);
                    if (!flowHandler.isActive(facesContext, fbi.definingDocumentId, fbi.id)) {
                        throw new ContextNotActiveException("Request to activate bean in flow '" + fbi + "', but that flow is not active.");
                    }

                   
                    result = contextual.create(creational);
                   
                    if (null != result) {
                        flowScopedBeanMap.put(contextual, result);
                        creationalMap.put(contextual, creational);
                    }
                }
            }
        }
       
        return result;

    }
   
    @Override
    public <T> T get(Contextual<T> contextual) {
        assertNotReleased();
       
        return (T) getFlowScopedBeanMapForCurrentFlow().get(contextual);
    }
   
    @Override
    public Class<? extends Annotation> getScope() {
        return FlowScoped.class;
    }
   
    @Override
    public boolean isActive() {
        return null != getCurrentFlow();
    }
   
    void beforeShutdown(@Observes final BeforeShutdown event, BeanManager beanManager) {
    }
   
    // </editor-fold>
   
}
TOP

Related Classes of com.sun.faces.flow.FlowCDIContext$FlowBeanInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.