You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/11/18 16:16:49 UTC

svn commit: r881798 - in /myfaces/core/trunk: api/src/main/java/javax/faces/component/ impl/src/main/java/org/apache/myfaces/config/ impl/src/main/java/org/apache/myfaces/el/unified/resolver/ impl/src/test/java/org/apache/myfaces/config/ impl/src/test/...

Author: lu4242
Date: Wed Nov 18 15:16:45 2009
New Revision: 881798

URL: http://svn.apache.org/viewvc?rev=881798&view=rev
Log:
MYFACES-2399 ManagedBeanResolver does not handle view scope (Thanks to Jakob Korherr for this patch)

Modified:
    myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolver.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ScopedAttributeResolver.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/ManagedBeanBuilderTest.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolverTest.java

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java?rev=881798&r1=881797&r2=881798&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java Wed Nov 18 15:16:45 2009
@@ -1338,8 +1338,13 @@
         }
     }
 
-    private class ViewScope extends HashMap<String, Object>
+    // we cannot make this class a inner class, because the 
+    // enclosing class (UIViewRoot) would also have to be serialized.
+    private static class ViewScope extends HashMap<String, Object>
     {
+        
+        private static final long serialVersionUID = -1088893802269478164L;
+        
         @Override
         public void clear()
         {
@@ -1348,10 +1353,12 @@
              * Application.publishEvent(java.lang.Class, java.lang.Object) to be called, passing
              * ViewMapDestroyedEvent.class as the first argument and this UIViewRoot instance as the second argument.
              */
-            FacesContext facesContext = getFacesContext(); 
-            facesContext.getApplication().publishEvent(facesContext, PreDestroyViewMapEvent.class, UIViewRoot.this);
+            FacesContext facesContext = FacesContext.getCurrentInstance();
+            facesContext.getApplication().publishEvent(facesContext, 
+                    PreDestroyViewMapEvent.class, facesContext.getViewRoot());
             
             super.clear();
         }
+        
     }
 }

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java?rev=881798&r1=881797&r2=881798&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java Wed Nov 18 15:16:45 2009
@@ -67,13 +67,14 @@
     private static Logger log = Logger.getLogger(ManagedBeanBuilder.class.getName());
     private RuntimeConfig _runtimeConfig;
     public final static String REQUEST = "request";
+    public final static String VIEW = "view";
     public final static String APPLICATION = "application";
     public final static String SESSION = "session";
     public final static String NONE = "none";
     
     /**
      * Comparator used to compare Scopes in the following order:
-     * REQUEST SESSION APPLICATION NONE
+     * REQUEST VIEW SESSION APPLICATION NONE
      * @author Jakob Korherr
      */
     private final static Comparator<String> scopeComparator = new Comparator<String>()
@@ -106,9 +107,9 @@
             }
             if (o1.equalsIgnoreCase(SESSION))
             {
-                if (o2.equalsIgnoreCase(REQUEST))
+                if (o2.equalsIgnoreCase(REQUEST) || o2.equalsIgnoreCase(VIEW))
                 {
-                    // session is greater than request
+                    // session is greater than request and view
                     return 1;
                 }
                 else
@@ -117,6 +118,19 @@
                     return -1;
                 }
             }
+            if (o1.equalsIgnoreCase(VIEW))
+            {
+                if (o2.equalsIgnoreCase(REQUEST))
+                {
+                    // view is greater than request
+                    return 1;
+                }
+                else
+                {
+                    // ..but smaller than any other scope
+                    return -1;
+                }
+            }
             if (o1.equalsIgnoreCase(REQUEST))
             {
                 // request is smaller than any other scope
@@ -394,6 +408,11 @@
                                                 beanConfiguration
                                                     .getManagedBeanScopeValueExpression(facesContext)
                                                     .getExpressionString());
+                // if we could not obtain a targetScope, return true
+                if (targetScope == null)
+                {
+                    return true;
+                }
             }
         }
         else
@@ -415,6 +434,12 @@
                                               property.getValueBinding(facesContext)
                                                   .getExpressionString());
         
+        // if we could not obtain a valueScope, return true
+        if (valueScope == null)
+        {
+            return true;
+        }
+        
         // the target scope needs to have a shorter (or equal) lifetime than the value scope
         return (scopeComparator.compare(targetScope, valueScope) <= 0);
     }
@@ -428,7 +453,9 @@
     private String getNarrowestScope(FacesContext facesContext, String valueExpression)
     {
         List<String> expressions = extractExpressions(valueExpression);
-        String narrowestScope = NONE;
+        // exclude NONE scope, if there are more than one ValueExpressions (see Spec for details)
+        String narrowestScope = expressions.size() == 1 ? NONE : APPLICATION;
+        boolean scopeFound = false;
         
         for (String expression : expressions)
         {
@@ -437,13 +464,15 @@
             {
                 continue;
             }
+            // we have found at least one valid scope at this point
+            scopeFound = true;
             if (scopeComparator.compare(valueScope, narrowestScope) < 0)
             {
                 narrowestScope = valueScope;
             }
         }
         
-        return narrowestScope;
+        return scopeFound ? narrowestScope : null;
     }
     
     private String getScope(FacesContext facesContext, String expression)
@@ -474,7 +503,6 @@
         {
             return REQUEST;
         }
-
         if (beanName.equalsIgnoreCase("header"))
         {
             return REQUEST;
@@ -483,11 +511,6 @@
         {
             return REQUEST;
         }
-
-        if (beanName.equalsIgnoreCase("initParam"))
-        {
-            return APPLICATION;
-        }
         if (beanName.equalsIgnoreCase("param"))
         {
             return REQUEST;
@@ -496,10 +519,22 @@
         {
             return REQUEST;
         }
-        if (beanName.equalsIgnoreCase("view"))
+        if (beanName.equalsIgnoreCase("request"))
         {
             return REQUEST;
         }
+        if (beanName.equalsIgnoreCase("view")) // Spec says that view is considered to be in request scope
+        {
+            return REQUEST;
+        }
+        if (beanName.equalsIgnoreCase("application"))
+        {
+            return APPLICATION;
+        }
+        if (beanName.equalsIgnoreCase("initParam"))
+        {
+            return APPLICATION;
+        }
 
         // not found so far - check all scopes
         if (externalContext.getRequestMap().get(beanName) != null)
@@ -514,6 +549,10 @@
         {
             return APPLICATION;
         }
+        if (facesContext.getViewRoot().getViewMap().get(beanName) != null)
+        {
+            return VIEW;
+        }
 
         //not found - check mangaged bean config
 
@@ -530,8 +569,7 @@
                 // However, we do check the references, if we are not in Production stage
                 if (facesContext.getApplication().getProjectStage() == ProjectStage.Production)
                 {
-                    // we return NONE, because the NONE scope can be referenced by any other scope
-                    return NONE;
+                    return null;
                 }
                 else
                 {

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolver.java?rev=881798&r1=881797&r2=881798&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolver.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolver.java Wed Nov 18 15:16:45 2009
@@ -62,7 +62,7 @@
     {
         s_standardScopes.put("request", new Scope()
         {
-            public void put(ExternalContext extContext, String name, Object obj)
+            public void put(FacesContext facesContext, ExternalContext extContext, String name, Object obj)
             {
                 extContext.getRequestMap().put(name, obj);
             }
@@ -70,7 +70,7 @@
 
         s_standardScopes.put("session", new Scope()
         {
-            public void put(ExternalContext extContext, String name, Object obj)
+            public void put(FacesContext facesContext, ExternalContext extContext, String name, Object obj)
             {
                 extContext.getSessionMap().put(name, obj);
             }
@@ -78,7 +78,7 @@
 
         s_standardScopes.put("application", new Scope()
         {
-            public void put(ExternalContext extContext, String name, Object obj)
+            public void put(FacesContext facesContext, ExternalContext extContext, String name, Object obj)
             {
                 extContext.getApplicationMap().put(name, obj);
             }
@@ -86,11 +86,20 @@
 
         s_standardScopes.put("none", new Scope()
         {
-            public void put(ExternalContext extContext, String name, Object obj)
+            public void put(FacesContext facesContext, ExternalContext extContext, String name, Object obj)
             {
                 // do nothing
             }
         });
+        
+        // jsf 2.0 view scope
+        s_standardScopes.put("view", new Scope()
+        {
+            public void put(FacesContext facesContext, ExternalContext extContext, String name, Object obj)
+            {
+                facesContext.getViewRoot().getViewMap().put(name, obj);
+            }
+        });
     }
 
     /**
@@ -161,12 +170,19 @@
             throw new PropertyNotFoundException();
         }
 
-        final ExternalContext extContext = externalContext(context);
-
+        final FacesContext facesContext = facesContext(context);
+        if (facesContext == null)
+            return null;
+        
+        final ExternalContext extContext = facesContext.getExternalContext();
         if (extContext == null)
             return null;
+        
         if (extContext.getRequestMap().containsKey(property))
             return null;
+        Map<String, Object> viewMap = facesContext.getViewRoot().getViewMap(false);
+        if (viewMap != null && viewMap.containsKey(property))
+            return null;
         if (extContext.getSessionMap().containsKey(property))
             return null;
         if (extContext.getApplicationMap().containsKey(property))
@@ -181,7 +197,6 @@
         Object beanInstance = null;
         if (managedBean != null)
         {
-            FacesContext facesContext = facesContext(context);
             context.setPropertyResolved(true);
             
             // managed-bean-scope could be a ValueExpression pointing to a Map (since 2.0)
@@ -311,7 +326,7 @@
             final Scope scope = _scopes.get(scopeKey);
             if (scope != null)
             {
-                scope.put(extContext, managedBeanName, obj);
+                scope.put(facesContext, extContext, managedBeanName, obj);
             }
             else if (managedBean.isManagedBeanScopeValueExpression())
             {
@@ -428,6 +443,6 @@
 
     interface Scope
     {
-        public void put(ExternalContext extContext, String name, Object obj);
+        public void put(FacesContext facesContext, ExternalContext extContext, String name, Object obj);
     }
 }

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ScopedAttributeResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ScopedAttributeResolver.java?rev=881798&r1=881797&r2=881798&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ScopedAttributeResolver.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ScopedAttributeResolver.java Wed Nov 18 15:16:45 2009
@@ -61,7 +61,7 @@
             throw new PropertyNotFoundException();
         }
 
-        final Map<String, Object> scopedMap = findScopedMap(externalContext(context), property);
+        final Map<String, Object> scopedMap = findScopedMap(facesContext(context), property);
         if (scopedMap != null)
         {
             scopedMap.put((String)property, value);
@@ -102,7 +102,7 @@
 
         context.setPropertyResolved(true);
 
-        final Map<String, Object> scopedMap = findScopedMap(externalContext(context), property);
+        final Map<String, Object> scopedMap = findScopedMap(facesContext(context), property);
         if (scopedMap != null)
         {
             return scopedMap.get(property);
@@ -178,14 +178,23 @@
     }
 
     // returns null if not found
-    private static Map<String, Object> findScopedMap(final ExternalContext extContext, final Object property)
+    private static Map<String, Object> findScopedMap(final FacesContext facesContext, final Object property)
     {
+        if (facesContext == null)
+            return null;
+        
+        final ExternalContext extContext = facesContext.getExternalContext();
         if (extContext == null)
             return null;
 
         Map<String, Object> scopedMap = extContext.getRequestMap();
         if (scopedMap.containsKey(property))
             return scopedMap;
+        
+        // jsf 2.0 view scope
+        scopedMap = facesContext.getViewRoot().getViewMap(false);
+        if (scopedMap != null && scopedMap.containsKey(property))
+            return scopedMap;
 
         scopedMap = extContext.getSessionMap();
         if (scopedMap.containsKey(property))

Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/ManagedBeanBuilderTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/ManagedBeanBuilderTest.java?rev=881798&r1=881797&r2=881798&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/ManagedBeanBuilderTest.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/ManagedBeanBuilderTest.java Wed Nov 18 15:16:45 2009
@@ -195,5 +195,44 @@
         }
         fail();
     }
+    
+    /**
+     * Tests, if the ManagedBeanBuilder checks that no property of the managed bean
+     * references to a scope with a potentially shorter lifetime.
+     * E.g. a managed bean of scope session is only allowed to reference an object in
+     * the session, the application and the none scope.
+     * This test is to test the view scope, introduced in jsf 2.0.
+     */
+    public void testIsInValidScopeViewScope()
+    {
+        // create viewBean referencing requestBean
+        ManagedBean viewBean = new ManagedBean();
+        viewBean.setBeanClass(TestBean.class.getName());
+        viewBean.setName("viewBean");
+        viewBean.setScope("view");
+        ManagedProperty anotherBeanProperty = new ManagedProperty();
+        anotherBeanProperty.setPropertyName("anotherBean");
+        anotherBeanProperty.setValue("#{requestBean}");
+        viewBean.addProperty(anotherBeanProperty);
+        runtimeConfig.addManagedBean("viewBean", viewBean);
+        
+        // create requestBean
+        ManagedBean requestBean = new ManagedBean();
+        requestBean.setBeanClass(TestBean.class.getName());
+        requestBean.setName("requestBean");
+        requestBean.setScope("request");
+        runtimeConfig.addManagedBean("requestBean", requestBean);
+        
+        try
+        {
+            new MockValueExpression("#{viewBean}", TestBean.class).getValue(facesContext.getELContext());
+        }
+        catch (FacesException e)
+        {
+            // success --> the ManagedBeanBuilder discovered the reference to a shorter lifetime
+            return;
+        }
+        fail();
+    }
 
 }

Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolverTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolverTest.java?rev=881798&r1=881797&r2=881798&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolverTest.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/el/unified/resolver/ManagedBeanResolverTest.java Wed Nov 18 15:16:45 2009
@@ -215,5 +215,29 @@
         }
         fail();
     }
+    
+    /**
+     * Tests the view scope, which was introduced in jsf 2.0
+     */
+    public void testViewScope()
+    {
+        // create the managed bean
+        ManagedBean beanInViewScope = new ManagedBean();
+        beanInViewScope.setBeanClass(ArrayList.class.getName());
+        beanInViewScope.setName("beanInViewScope");
+        beanInViewScope.setScope("view");
+        runtimeConfig.addManagedBean("beanInViewScope", beanInViewScope);
+        
+        // resolve the managed bean
+        Object resolvedBeanInCustomScope = new MockValueExpression("#{beanInViewScope}", List.class)
+                                                   .getValue(facesContext.getELContext());
+        
+        // get the view map
+        Map<String, Object> viewMap = facesContext.getViewRoot().getViewMap();
+        
+        // the custom scope has to contain the resolved bean
+        assertTrue(viewMap.containsKey("beanInViewScope"));
+        assertTrue(viewMap.get("beanInViewScope").equals(resolvedBeanInCustomScope));
+    }
 
 }