You are viewing a plain text version of this content. The canonical link for it is here.
Posted to adffaces-commits@incubator.apache.org by aw...@apache.org on 2007/02/07 23:19:01 UTC

svn commit: r504730 - in /incubator/adffaces/branches/faces-1_2-070201/trinidad: ./ trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/

Author: awiner
Date: Wed Feb  7 15:18:58 2007
New Revision: 504730

URL: http://svn.apache.org/viewvc?view=rev&rev=504730
Log:
ADFFACES-373: JSF 1.2: ChildPropertyTreeModel and SortableModel will throw NPE if used outside of the JSF lifecycle
- Switch SortableModel and ChildPropertyTreeModel from using PropertyResolver to ELResolver (far more likely to be successful)
- Since these API classes now use ELResolver, upgrade from Shale Test 1.0.3 to 1.0.4 - we need ELResolver support on MockApplication.
- Add an ELResolver implementation to the renderkit test framework

Added:
    incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MELResolver.java
Modified:
    incubator/adffaces/branches/faces-1_2-070201/trinidad/pom.xml
    incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
    incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java
    incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MApplication.java

Modified: incubator/adffaces/branches/faces-1_2-070201/trinidad/pom.xml
URL: http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2-070201/trinidad/pom.xml?view=diff&rev=504730&r1=504729&r2=504730
==============================================================================
--- incubator/adffaces/branches/faces-1_2-070201/trinidad/pom.xml (original)
+++ incubator/adffaces/branches/faces-1_2-070201/trinidad/pom.xml Wed Feb  7 15:18:58 2007
@@ -363,7 +363,7 @@
       <dependency>
         <groupId>org.apache.shale</groupId>
         <artifactId>shale-test</artifactId>
-        <version>1.0.3</version>
+        <version>1.0.4</version>
         <scope>test</scope>
 	<!-- Ignore the references to myfaces and the JSP API -->
 	<!-- We could force shale to JSF RI 1.2, but it's better

Modified: incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java?view=diff&rev=504730&r1=504729&r2=504730
==============================================================================
--- incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java (original)
+++ incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java Wed Feb  7 15:18:58 2007
@@ -21,8 +21,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.faces.el.PropertyResolver;
-
 /**
  * Creates a TreeModel from a List of beans.
  * To use this class you must have a tree of beans (or Maps).
@@ -316,8 +314,7 @@
     if (prop == null)
       return null;
     
-    PropertyResolver resolver = SortableModel.__getPropertyResolver();
-    return resolver.getValue(parentData, prop);
+    return SortableModel.__resolveProperty(parentData, prop);
   }
 
   /**

Modified: incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java?view=diff&rev=504730&r1=504729&r2=504730
==============================================================================
--- incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java (original)
+++ incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java Wed Feb  7 15:18:58 2007
@@ -23,10 +23,14 @@
 import java.util.Comparator;
 import java.util.List;
 
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+
 import javax.faces.FactoryFinder;
 import javax.faces.application.ApplicationFactory;
 import javax.faces.context.FacesContext;
-import javax.faces.el.PropertyResolver;
 import javax.faces.model.DataModel;
 
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
@@ -151,9 +155,7 @@
       Object data = _model.getRowData();
       try
       {
-        PropertyResolver resolver = __getPropertyResolver();
-        Object propertyValue = resolver.getValue(data, property);
-
+        Object propertyValue = __resolveProperty(data, property);
         // when the value is null, we don't know if we can sort it.
         // by default let's support sorting of null values, and let the user
         // turn off sorting if necessary:
@@ -251,8 +253,11 @@
     // Make sure the model has that row 0! (It could be empty.)
     if (_model.isRowAvailable())
     {
+      FacesContext context = FacesContext.getCurrentInstance();
+      ELResolver resolver = _getELResolver(context);
+      ELContext elContext = _getELContext(context, resolver);
       Comparator<Integer> comp =
-        new Comp(__getPropertyResolver(), property);
+        new Comp(resolver, elContext, property);
       if (!isAscending)
         comp = new Inverter<Integer>(comp);
 
@@ -331,9 +336,10 @@
 
   private final class Comp implements Comparator<Integer>
   {
-    public Comp(PropertyResolver resolver, String property)
+    public Comp(ELResolver resolver, ELContext context, String property)
     {
       _resolver = resolver;
+      _context  = context;
       _prop = property;
     }
 
@@ -345,11 +351,11 @@
 
       _model.setRowIndex(index1);
       Object instance1 = _model.getRowData();
-      Object value1 = _resolver.getValue(instance1, _prop);
+      Object value1 = _resolver.getValue(_context, instance1, _prop);
 
       _model.setRowIndex(index2);
       Object instance2 = _model.getRowData();
-      Object value2 = _resolver.getValue(instance2, _prop);
+      Object value2 = _resolver.getValue(_context, instance2, _prop);
 
       if (value1 == null)
         return (value2 == null) ? 0 : -1;
@@ -373,7 +379,8 @@
       }
     }
 
-    private final PropertyResolver _resolver;
+    private final ELResolver _resolver;
+    private final ELContext  _context;
     private final String _prop;
   }
 
@@ -392,19 +399,73 @@
     private final Comparator<T> _comp;
   }
 
-  static PropertyResolver __getPropertyResolver()
+  /**
+   * Quickie implementation of ELContext for use
+   * if we're not being called in the JSF lifecycle
+   */
+  private static final class ELContextImpl extends ELContext
+  {
+    public ELContextImpl(ELResolver resolver)
+    {
+      _resolver = resolver;
+    }
+    
+    @Override
+    public ELResolver getELResolver()
+    {
+      return _resolver;
+    }
+
+    @Override
+    public FunctionMapper getFunctionMapper()
+    {
+      // Because we're only really being used to pass
+      // to an ELResolver, no FunctionMapper is needed
+      return null;
+    }
+
+    @Override
+    public VariableMapper getVariableMapper()
+    {
+      // Because we're only really being used to pass
+      // to an ELResolver, no VariableMapper is needed
+      return null;
+    }
+    
+    private final ELResolver _resolver;
+  }
+
+  static Object __resolveProperty(Object object, String propertyName)
   {
-    // First try the FacesContext, which is a faster way to
-    // get the PropertyResolver (and the 99.9% scenario)
     FacesContext context = FacesContext.getCurrentInstance();
+    ELResolver resolver = _getELResolver(context);
+    ELContext elContext = _getELContext(context, resolver);
+    return resolver.getValue(elContext, object, propertyName);
+  }
+
+  static private ELContext _getELContext(
+    FacesContext context, ELResolver resolver)
+  {
+    // Hopefully, we have a FacesContext.  If not, we're
+    // going to have to synthesize one!
+    if (context != null)
+      return context.getELContext();
+   
+    return new ELContextImpl(resolver); 
+  }
+
+  static private ELResolver _getELResolver(FacesContext context)
+  {
+    // First try the FacesContext, which is a faster way to
+    // get the ELResolver (and the 99.9% scenario)
     if (context != null)
-      return context.getApplication().getPropertyResolver();
+      return context.getApplication().getELResolver();
     
     // If that fails, then we're likely outside of the JSF lifecycle.
     // Look to the ApplicationFactory.
     ApplicationFactory factory = (ApplicationFactory)
       FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
-    return factory.getApplication().getPropertyResolver();
+    return factory.getApplication().getELResolver();
     
   }
 

Modified: incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MApplication.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MApplication.java?view=diff&rev=504730&r1=504729&r2=504730
==============================================================================
--- incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MApplication.java (original)
+++ incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MApplication.java Wed Feb  7 15:18:58 2007
@@ -25,8 +25,10 @@
 import java.util.Locale;
 import java.util.Map;
 
+import javax.el.ELResolver;
 import javax.el.ExpressionFactory;
 import javax.el.ELContext;
+import javax.el.MapELResolver;
 import javax.el.MethodExpression;
 import javax.el.MethodInfo;
 import javax.el.ValueExpression;
@@ -363,6 +365,13 @@
     return _exprFactory;
   }
 
+  @Override
+  public ELResolver getELResolver()
+  {
+    return new MELResolver(
+      getVariableResolver(), getPropertyResolver());
+  }
+
   private ExpressionFactory _exprFactory = new ExpressionFactory()
   {
     public Object coerceToType(Object obj, Class<?> targetType)
@@ -394,7 +403,8 @@
       throw new UnsupportedOperationException("Not implemented yet");
     }
   };
-    
+
+
   /**
    * A very rudimentary implementation, to support
    * renderers that might create (but not evaluate) MethodExpressions

Added: incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MELResolver.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MELResolver.java?view=auto&rev=504730
==============================================================================
--- incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MELResolver.java (added)
+++ incubator/adffaces/branches/faces-1_2-070201/trinidad/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/renderkit/MELResolver.java Wed Feb  7 15:18:58 2007
@@ -0,0 +1,165 @@
+/*
+ *  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.apache.myfaces.trinidadinternal.renderkit;
+
+import java.beans.FeatureDescriptor;
+
+import java.lang.reflect.Array;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.PropertyNotFoundException;
+import javax.el.PropertyNotWritableException;
+
+import javax.faces.context.FacesContext;
+import javax.faces.el.PropertyResolver;
+import javax.faces.el.VariableResolver;
+
+public class MELResolver extends ELResolver
+{
+  public MELResolver(VariableResolver vr, PropertyResolver pr)
+  {
+    _vr = vr;
+    _pr = pr;
+  }
+  
+  @Override
+  public Class<?> getCommonPropertyType(ELContext context, Object base)
+  {
+    if (base == null)
+      return String.class;
+    if (_isIndexed(base))
+      return Integer.class;
+    if (base instanceof Map)
+      return Object.class;
+
+    return String.class;
+  }
+
+  @Override
+  public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, 
+                                                           Object base)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public Class<?> getType(ELContext context, Object base, 
+                          Object property)
+  {
+    if (base == null)
+    {
+      Object o = getValue(context, base, property);
+      if (o == null)
+        return null;
+      return o.getClass();
+    }
+    else
+    {
+      if (_isIndexed(base))
+        return _pr.getType(base, _getIndex(property));
+      else
+        return _pr.getType(base, property);
+    }
+  }
+
+  @Override
+  public Object getValue(ELContext context, Object base, 
+                         Object property)
+  {
+    if (base == null)
+    {
+      if (property == null)
+        return null;
+      FacesContext fc = (FacesContext) context.getContext(FacesContext.class);
+      return _vr.resolveVariable(fc, property.toString());
+    }
+    else
+    {
+      if (_isIndexed(base))
+        return _pr.getValue(base, _getIndex(property));
+      else
+        return _pr.getValue(base, property);      
+    }
+  }
+
+  @Override
+  public boolean isReadOnly(ELContext context, Object base, 
+                            Object property)
+  {
+    if (base == null)
+    {
+      return true;
+    }
+    else
+    {
+      if (_isIndexed(base))
+        return _pr.isReadOnly(base, _getIndex(property));
+      else
+        return _pr.isReadOnly(base, property);      
+    }
+  }
+
+  @Override
+  public void setValue(ELContext eLContext, Object base, Object property, 
+                       Object value)
+  {
+    if (base == null)
+    {
+      throw new PropertyNotWritableException();
+    }
+    else
+    {
+      if (_isIndexed(base))
+        _pr.setValue(base, _getIndex(property), value);
+      else
+        _pr.setValue(base, property, value);
+    }
+  }
+  
+  private int _getIndex(Object property)
+  {
+    if (property == null)
+      throw new PropertyNotFoundException();
+    
+    if (property instanceof Number)
+      return ((Number) property).intValue();
+    return Integer.valueOf(property.toString());
+  }
+  private boolean _isIndexed(Object base)
+  {
+    if (base == null)
+      throw new IllegalArgumentException();
+    
+    if ((base instanceof List) ||
+        base.getClass().isArray())
+      return true;
+    
+    return false;
+  }
+  
+  private final PropertyResolver _pr;
+  private final VariableResolver _vr;
+}