[seam-commits] Seam SVN: r12182 - in modules/faces/trunk: src/main/java and 8 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Mar 11 18:09:40 EST 2010


Author: lincolnthree
Date: 2010-03-11 18:09:39 -0500 (Thu, 11 Mar 2010)
New Revision: 12182

Added:
   modules/faces/trunk/src/main/java/META-INF/
   modules/faces/trunk/src/main/java/META-INF/MANIFEST.MF
   modules/faces/trunk/src/main/java/javax/
   modules/faces/trunk/src/main/java/javax/faces/
   modules/faces/trunk/src/main/java/javax/faces/bean/
   modules/faces/trunk/src/main/java/javax/faces/bean/FlashScoped.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedContext.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedExtension.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedContext.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedExtension.java
Removed:
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/scopes/
Modified:
   modules/faces/trunk/pom.xml
   modules/faces/trunk/src/main/resources/META-INF/faces-config.xml
   modules/faces/trunk/src/main/resources/META-INF/seam-faces.taglib.xml
   modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
Log:
* FlashScope is functional (perhaps barely, but functional)

Modified: modules/faces/trunk/pom.xml
===================================================================
--- modules/faces/trunk/pom.xml	2010-03-11 15:47:36 UTC (rev 12181)
+++ modules/faces/trunk/pom.xml	2010-03-11 23:09:39 UTC (rev 12182)
@@ -10,8 +10,8 @@
    </parent>
 
    <artifactId>seam-faces</artifactId>
+   <version>3.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
-   <version>3.0.0-SNAPSHOT</version>
    <name>Seam Faces Module</name>
    
    <!-- Snapshots repo to get parent -->

Added: modules/faces/trunk/src/main/java/META-INF/MANIFEST.MF
===================================================================
--- modules/faces/trunk/src/main/java/META-INF/MANIFEST.MF	                        (rev 0)
+++ modules/faces/trunk/src/main/java/META-INF/MANIFEST.MF	2010-03-11 23:09:39 UTC (rev 12182)
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

Added: modules/faces/trunk/src/main/java/javax/faces/bean/FlashScoped.java
===================================================================
--- modules/faces/trunk/src/main/java/javax/faces/bean/FlashScoped.java	                        (rev 0)
+++ modules/faces/trunk/src/main/java/javax/faces/bean/FlashScoped.java	2010-03-11 23:09:39 UTC (rev 12182)
@@ -0,0 +1,25 @@
+package javax.faces.bean;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+import javax.enterprise.context.NormalScope;
+
+/**
+ * Defines a CDI bean as Flash scoped. A bean put in the JSF2 flash will survive
+ * one page transition, or navigation, then be cleared.
+ * 
+ * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
+ */
+ at NormalScope
+ at Inherited
+ at Documented
+ at Target(ElementType.TYPE)
+ at Retention(value = RetentionPolicy.RUNTIME)
+public @interface FlashScoped {
+
+}

Added: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedContext.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedContext.java	                        (rev 0)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedContext.java	2010-03-11 23:09:39 UTC (rev 12182)
@@ -0,0 +1,165 @@
+package org.jboss.seam.faces.context;
+
+import java.lang.annotation.Annotation;
+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.faces.bean.FlashScoped;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.Flash;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+/**
+ * This class provides the contexts lifecycle for the new JSF2 Flash Context
+ * 
+ * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
+ */
+public class FlashScopedContext implements Context, PhaseListener
+{
+    private final static String COMPONENT_MAP_NAME = "org.jboss.seam.faces.flash.componentInstanceMap";
+    private final static String CREATIONAL_MAP_NAME = "org.jboss.seam.faces.flash.creationalInstanceMap";
+    private final ThreadLocal<Map<Contextual<?>, Object>> lastComponentInstanceMap = new ThreadLocal<Map<Contextual<?>, Object>>();
+    private final ThreadLocal<Map<Contextual<?>, CreationalContext<?>>> lastCreationalContextMap = new ThreadLocal<Map<Contextual<?>, CreationalContext<?>>>();
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(final Contextual<T> component)
+    {
+        assertActive();
+        Map<Contextual<?>, Object> componentInstanceMap = getComponentInstanceMap();
+        T instance = (T) componentInstanceMap.get(component);
+        return instance;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(final Contextual<T> component, final CreationalContext<T> creationalContext)
+    {
+        assertActive();
+
+        T instance = get(component);
+
+        if (instance == null)
+        {
+            Map<Contextual<?>, CreationalContext<?>> creationalContextMap = getCreationalContextMap();
+            Map<Contextual<?>, Object> componentInstanceMap = getComponentInstanceMap();
+
+            synchronized (componentInstanceMap)
+            {
+                instance = (T) componentInstanceMap.get(component);
+                if (instance == null)
+                {
+                    instance = component.create(creationalContext);
+
+                    if (instance != null)
+                    {
+                        componentInstanceMap.put(component, instance);
+                        creationalContextMap.put(component, creationalContext);
+                    }
+                }
+            }
+        }
+
+        return instance;
+    }
+
+    public Class<? extends Annotation> getScope()
+    {
+        return FlashScoped.class;
+    }
+
+    private Flash getFlash()
+    {
+        FacesContext currentInstance = FacesContext.getCurrentInstance();
+        if (currentInstance != null)
+        {
+            ExternalContext externalContext = currentInstance.getExternalContext();
+            return externalContext.getFlash();
+        }
+        return null;
+    }
+
+    public boolean isActive()
+    {
+        return getFlash() != null;
+    }
+
+    private void assertActive()
+    {
+        if (!isActive())
+        {
+            throw new ContextNotActiveException(
+                    "WebBeans context with scope annotation @FlashScoped is not active with respect to the current thread");
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<Contextual<?>, Object> getComponentInstanceMap()
+    {
+        Flash flash = getFlash();
+        ConcurrentHashMap<Contextual<?>, Object> map = (ConcurrentHashMap<Contextual<?>, Object>) flash
+                .get(COMPONENT_MAP_NAME);
+        if (map == null)
+        {
+            map = new ConcurrentHashMap<Contextual<?>, Object>();
+            flash.put(COMPONENT_MAP_NAME, map);
+        }
+        return map;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<Contextual<?>, CreationalContext<?>> getCreationalContextMap()
+    {
+        Flash flash = getFlash();
+        Map<Contextual<?>, CreationalContext<?>> map = (ConcurrentHashMap<Contextual<?>, CreationalContext<?>>) flash
+                .get(CREATIONAL_MAP_NAME);
+        if (map == null)
+        {
+            map = new ConcurrentHashMap<Contextual<?>, CreationalContext<?>>();
+            flash.put(CREATIONAL_MAP_NAME, map);
+        }
+        return map;
+    }
+
+    public void beforePhase(final PhaseEvent event)
+    {
+        this.lastComponentInstanceMap.set(getComponentInstanceMap());
+        this.lastCreationalContextMap.set(getCreationalContextMap());
+    }
+
+    @SuppressWarnings("unchecked")
+    public void afterPhase(final PhaseEvent event)
+    {
+        // TODO verify that this is actually destroying the beans we want to be
+        // destroyed... flash is confusing, tests will make sense of it
+        Map<Contextual<?>, Object> componentInstanceMap = lastComponentInstanceMap.get();
+        Map<Contextual<?>, CreationalContext<?>> creationalContextMap = lastCreationalContextMap.get();
+
+        if (componentInstanceMap != null)
+        {
+            for (Entry<Contextual<?>, Object> componentEntry : componentInstanceMap.entrySet())
+            {
+                Contextual contextual = componentEntry.getKey();
+                Object instance = componentEntry.getValue();
+                CreationalContext creational = creationalContextMap.get(contextual);
+
+                contextual.destroy(instance, creational);
+            }
+        }
+
+        this.lastComponentInstanceMap.remove();
+        this.lastCreationalContextMap.remove();
+    }
+
+    public PhaseId getPhaseId()
+    {
+        return PhaseId.RENDER_RESPONSE;
+    }
+
+}

Added: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedExtension.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedExtension.java	                        (rev 0)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FlashScopedExtension.java	2010-03-11 23:09:39 UTC (rev 12182)
@@ -0,0 +1,32 @@
+/*
+ * To change this template, choose Tools | Templates and open the template in
+ * the editor.
+ */
+
+package org.jboss.seam.faces.context;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.faces.bean.FlashScoped;
+
+/**
+ * An extension to provide @FlashScoped CDI / JSF2 integration.
+ * 
+ * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
+ */
+public class FlashScopedExtension implements Extension
+{
+
+    public void addScope(@Observes final BeforeBeanDiscovery event)
+    {
+        event.addScope(FlashScoped.class, true, true);
+    }
+
+    public void registerContext(@Observes final AfterBeanDiscovery event)
+    {
+        event.addContext(new FlashScopedContext());
+    }
+
+}

Copied: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedContext.java (from rev 12181, modules/faces/trunk/src/main/java/org/jboss/seam/faces/scopes/ViewScopedContext.java)
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedContext.java	                        (rev 0)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedContext.java	2010-03-11 23:09:39 UTC (rev 12182)
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.jboss.seam.faces.context;
+
+import java.lang.annotation.Annotation;
+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.faces.bean.ViewScoped;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PreDestroyViewMapEvent;
+import javax.faces.event.SystemEvent;
+import javax.faces.event.SystemEventListener;
+
+/**
+ * This class provides the contexts lifecycle for the new JSF-2 &#064;ViewScoped
+ * Context
+ * 
+ * @author <a href="mailto:struberg at yahoo.de">Mark Struberg</a>
+ * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
+ */
+public class ViewScopedContext implements Context, SystemEventListener
+{
+
+    private final static String COMPONENT_MAP_NAME = "org.jboss.seam.faces.viewscope.componentInstanceMap";
+    private final static String CREATIONAL_MAP_NAME = "org.jboss.seam.faces.viewscope.creationalInstanceMap";
+
+    private boolean isJsfSubscribed = false;
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(final Contextual<T> component)
+    {
+        assertActive();
+
+        if (!isJsfSubscribed)
+        {
+            FacesContext.getCurrentInstance().getApplication().subscribeToEvent(PreDestroyViewMapEvent.class, this);
+
+            isJsfSubscribed = true;
+        }
+
+        Map<String, Object> viewMap = getViewMap();
+
+        ConcurrentHashMap<Contextual<?>, Object> componentInstanceMap = (ConcurrentHashMap<Contextual<?>, Object>) viewMap
+                .get(COMPONENT_MAP_NAME);
+
+        if (componentInstanceMap == null)
+        {
+            return null;
+        }
+
+        T instance = (T) componentInstanceMap.get(component);
+
+        return instance;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(final Contextual<T> component, final CreationalContext<T> creationalContext)
+    {
+        assertActive();
+
+        Map<String, Object> viewMap = getViewMap();
+
+        ConcurrentHashMap<Contextual<?>, Object> componentInstanceMap = (ConcurrentHashMap<Contextual<?>, Object>) viewMap
+                .get(COMPONENT_MAP_NAME);
+
+        if (componentInstanceMap == null)
+        {
+            // TODO we now need to start being carefull with reentrancy...
+            componentInstanceMap = new ConcurrentHashMap<Contextual<?>, Object>();
+            viewMap.put(COMPONENT_MAP_NAME, componentInstanceMap);
+        }
+
+        ConcurrentHashMap<Contextual<?>, CreationalContext<?>> creationalContextMap = (ConcurrentHashMap<Contextual<?>, CreationalContext<?>>) viewMap
+                .get(CREATIONAL_MAP_NAME);
+        if (creationalContextMap == null)
+        {
+            // TODO we now need to start being carefull with reentrancy...
+            creationalContextMap = new ConcurrentHashMap<Contextual<?>, CreationalContext<?>>();
+            viewMap.put(CREATIONAL_MAP_NAME, creationalContextMap);
+        }
+
+        T instance = (T) componentInstanceMap.get(component);
+        if (instance != null)
+        {
+            return instance;
+        }
+
+        if (creationalContext == null)
+        {
+            return null;
+        }
+
+        synchronized (componentInstanceMap)
+        {
+            // just to make sure...
+            T i = (T) componentInstanceMap.get(component);
+            if (i != null)
+            {
+                return i;
+            }
+
+            instance = component.create(creationalContext);
+
+            if (instance != null)
+            {
+                componentInstanceMap.put(component, instance);
+                creationalContextMap.put(component, creationalContext);
+            }
+        }
+
+        return instance;
+    }
+
+    public Class<? extends Annotation> getScope()
+    {
+        return ViewScoped.class;
+    }
+
+    /**
+     * The view context is active if a valid ViewRoot could be detected.
+     */
+    public boolean isActive()
+    {
+        return getViewRoot() != null;
+    }
+
+    private void assertActive()
+    {
+        if (!isActive())
+        {
+            throw new ContextNotActiveException(
+                    "WebBeans context with scope annotation @ViewScoped is not active with respect to the current thread");
+        }
+    }
+
+    public boolean isListenerForSource(final Object source)
+    {
+        if (source instanceof UIViewRoot)
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * We get PreDestroyViewMapEvent events from the JSF servlet and destroy our
+     * contextual instances. This should (theoretically!) also get fired if the
+     * webapp closes, so there should be no need to manually track all view
+     * scopes and destroy them at a shutdown.
+     * 
+     * @see javax.faces.event.SystemEventListener#processEvent(javax.faces.event.SystemEvent)
+     */
+    @SuppressWarnings("unchecked")
+    public void processEvent(final SystemEvent event)
+    {
+        if (event instanceof PreDestroyViewMapEvent)
+        {
+            // better use the viewmap we get from the event to prevent
+            // concurrent modification problems
+            Map<String, Object> viewMap = ((UIViewRoot) event.getSource()).getViewMap();
+
+            ConcurrentHashMap<Contextual<?>, Object> componentInstanceMap = (ConcurrentHashMap<Contextual<?>, Object>) viewMap
+                    .get(COMPONENT_MAP_NAME);
+
+            ConcurrentHashMap<Contextual<?>, CreationalContext<?>> creationalContextMap = (ConcurrentHashMap<Contextual<?>, CreationalContext<?>>) viewMap
+                    .get(CREATIONAL_MAP_NAME);
+
+            if (componentInstanceMap != null)
+            {
+                for (Entry<Contextual<?>, Object> componentEntry : componentInstanceMap.entrySet())
+                {
+                    // there is no nice way to explain the Java Compiler that we
+                    // are handling the same type T,
+                    // therefore we need completely drop the type information :(
+                    Contextual contextual = componentEntry.getKey();
+                    Object instance = componentEntry.getValue();
+                    CreationalContext creational = creationalContextMap.get(contextual);
+
+                    contextual.destroy(instance, creational);
+                }
+            }
+        }
+    }
+
+    protected UIViewRoot getViewRoot()
+    {
+        FacesContext context = FacesContext.getCurrentInstance();
+
+        if (context != null)
+        {
+            return context.getViewRoot();
+        }
+
+        return null;
+    }
+
+    protected Map<String, Object> getViewMap()
+    {
+        UIViewRoot viewRoot = getViewRoot();
+
+        if (viewRoot != null)
+        {
+            return viewRoot.getViewMap(true);
+        }
+
+        return null;
+    }
+}
\ No newline at end of file

Copied: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedExtension.java (from rev 12181, modules/faces/trunk/src/main/java/org/jboss/seam/faces/scopes/ViewScopedExtension.java)
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedExtension.java	                        (rev 0)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/ViewScopedExtension.java	2010-03-11 23:09:39 UTC (rev 12182)
@@ -0,0 +1,32 @@
+/*
+ * To change this template, choose Tools | Templates and open the template in
+ * the editor.
+ */
+
+package org.jboss.seam.faces.context;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.faces.bean.ViewScoped;
+
+/**
+ * An extension to provide @ViewScoped CDI / JSF2 integration.
+ * 
+ * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
+ */
+public class ViewScopedExtension implements Extension
+{
+
+    public void addScope(@Observes final BeforeBeanDiscovery event)
+    {
+        event.addScope(ViewScoped.class, true, true);
+    }
+
+    public void registerContext(@Observes final AfterBeanDiscovery event)
+    {
+        event.addContext(new ViewScopedContext());
+    }
+
+}

Modified: modules/faces/trunk/src/main/resources/META-INF/faces-config.xml
===================================================================
--- modules/faces/trunk/src/main/resources/META-INF/faces-config.xml	2010-03-11 15:47:36 UTC (rev 12181)
+++ modules/faces/trunk/src/main/resources/META-INF/faces-config.xml	2010-03-11 23:09:39 UTC (rev 12182)
@@ -12,7 +12,13 @@
          <name>webbeans</name>
       </after>
    </ordering>
-
+   
+   
+   <lifecycle>
+      <phase-listener>org.jboss.seam.faces.context.FlashScopedContext</phase-listener>
+   </lifecycle>
+	
+	<!--
    <factory>
       <application-factory>org.jboss.seam.faces.application.SeamApplicationFactory</application-factory>
    </factory>
@@ -29,9 +35,7 @@
    </application>
 
    <lifecycle>
-      <!-- Not ready for this yet, it is just testing
       <phase-listener>org.jboss.seam.faces.lifecycle.SeamPhaseListener</phase-listener>
-      -->
    </lifecycle>
 
    <component>
@@ -43,6 +47,7 @@
       <component-type>org.jboss.seam.faces.RestrictView</component-type>
       <component-class>org.jboss.seam.faces.component.UIRestrictView</component-class>
    </component>
+   -->
    
    <component>
       <component-type>org.jboss.seam.faces.ViewAction</component-type>

Modified: modules/faces/trunk/src/main/resources/META-INF/seam-faces.taglib.xml
===================================================================
--- modules/faces/trunk/src/main/resources/META-INF/seam-faces.taglib.xml	2010-03-11 15:47:36 UTC (rev 12181)
+++ modules/faces/trunk/src/main/resources/META-INF/seam-faces.taglib.xml	2010-03-11 23:09:39 UTC (rev 12182)
@@ -5,21 +5,6 @@
    <namespace>http://jboss.com/products/seam/faces</namespace>
 
    <tag>
-      <tag-name>import</tag-name>
-      <component>
-         <component-type>org.jboss.seam.faces.Import</component-type>
-      </component>
-   </tag>
-   
-   <tag>
-      <tag-name>restrictView</tag-name>
-      <component>
-         <component-type>org.jboss.seam.faces.RestrictView</component-type>
-         <handler-class>org.jboss.seam.faces.facelets.DeferredValueExpressionHandler</handler-class>
-      </component>
-   </tag>
-   
-   <tag>
       <tag-name>viewAction</tag-name>
       <component>
          <component-type>org.jboss.seam.faces.ViewAction</component-type>

Modified: modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
===================================================================
--- modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension	2010-03-11 15:47:36 UTC (rev 12181)
+++ modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension	2010-03-11 23:09:39 UTC (rev 12182)
@@ -1 +1,2 @@
-org.jboss.seam.faces.scopes.ViewScopedExtension
\ No newline at end of file
+org.jboss.seam.faces.context.ViewScopedExtension
+org.jboss.seam.faces.context.FlashScopedExtension
\ No newline at end of file



More information about the seam-commits mailing list