1. opensymphony
  2. ognl

Commits

jkuh...@d4b077e3-5828-0410-b394-cb2b42183085  committed 3cde858

Re-factored OgnlContext type / accessor logic to use backing List objects so that the full type chain can be evaluated after the fact.

  • Participants
  • Parent commits e7482d2
  • Branches default

Comments (0)

Files changed (3)

File src/java/ognl/OgnlContext.java

View file
  • Ignore whitespace
             // restricted access environment, just keep defaults
         }
     }
-    
-    /**
-     * Indicates the current "type" of object being evaluated on the stack, this is used 
-     * for javassist bytecode enhancement logic to do proper casting / return type generations.
-     */
-    private Class _currentType;
-    
-    /**
-     * Like {@link #_currentType}, provides runtime class type information important for
-     * javassist casting/evaluation of generated java code expressions.
-     */
-    private Class _previousType;
-    
-    private Class _currentAccessor;
-    
-    private Class _previousAccessor;
+
+    private List _typeStack = new ArrayList();
+
+    private List _accessorStack = new ArrayList();
     
     /**
      * Constructs a new OgnlContext with the default class resolver, type converter and member
      */
     public OgnlContext()
     {
-        super();
     }
 
     /**
     
     public void setCurrentAccessor(Class type)
     {
-        _previousAccessor = _currentAccessor;
-        _currentAccessor = type;
+        _accessorStack.add(type);        
     }
     
     public Class getCurrentAccessor()
     {
-        return _currentAccessor;
+        if (_accessorStack.isEmpty())
+            return null;
+        
+        return (Class) _accessorStack.get(_accessorStack.size() - 1);
     }
     
     public Class getPreviousAccessor()
     {
-        return _previousAccessor;
+        if (_accessorStack.isEmpty())
+            return null;
+
+        if (_accessorStack.size() > 1)
+            return (Class) _accessorStack.get(_accessorStack.size() - 2);
+        else
+            return null;
     }
-    
+
+    public Class getFirstAccessor()
+    {
+        if (_accessorStack.isEmpty())
+            return null;
+
+        return (Class)_accessorStack.get(0);
+    }
+
     /**
      * Gets the current class type being evaluated on the stack, as set by {@link #setCurrentType(Class)}.
      * 
      */
     public Class getCurrentType()
     {
-       return _currentType; 
+        if (_typeStack.isEmpty())
+            return null;
+
+       return (Class) _typeStack.get(_typeStack.size() - 1); 
     }
     
     public void setCurrentType(Class type)
     {
-        _previousType = _currentType;
-        _currentType = type;
+        _typeStack.add(type);
     }
     
     /**
      */
     public Class getPreviousType()
     {
-        return _previousType;
+        if (_typeStack.isEmpty())
+            return null;
+
+        if (_typeStack.size() > 1)
+            return (Class)_typeStack.get(_typeStack.size() - 2);
+        else
+            return null;
     }
     
     public void setPreviousType(Class type)
     {
-        _previousType = type;
+        if (_typeStack.isEmpty() || _typeStack.size() < 2)
+            return;
+
+        _typeStack.set(_typeStack.size() - 2, type);
+    }
+
+    public Class getFirstType()
+    {
+        if (_typeStack.isEmpty())
+            return null;
+
+        return (Class)_typeStack.get(0);
     }
 
     public void setCurrentNode(Node value)
     public void clear()
     {
         _values.clear();
+        _typeStack.clear();
+        _accessorStack.clear();
+        
         setRoot(null);
         setCurrentObject(null);
         setRootEvaluation(null);

File src/java/ognl/enhance/ExpressionCompiler.java

View file
  • Ignore whitespace
         if (clazz.getInterfaces() != null && clazz.getInterfaces().length > 0) {
 
             Class[] intfs = clazz.getInterfaces();
-            Class intClass = null;
+            Class intClass;
             for (int i = 0; i < intfs.length; i++) {
                 intClass = getSuperOrInterfaceClass(m, intfs[i]);
 
              && root != null) || (root != null && ASTRootVarRef.class.isInstance(expression))) {
 
             Class castClass = root.getClass();
-            if (context.getCurrentAccessor() != null && context.getCurrentAccessor().isInstance(root))
-                castClass = context.getCurrentAccessor();
 
+            if (context.getFirstAccessor() != null && context.getFirstAccessor().isInstance(context.getRoot()))
+                castClass = context.getFirstAccessor();
+            
             if (castClass.isArray() || ASTRootVarRef.class.isInstance(expression)
                 || ASTThisVarRef.class.isInstance(expression)) {
 
         if (expression.getAccessor() != null)
             return;
 
-        String getBody = null;
-        String setBody = null;
+        String getBody, setBody;
 
         EnhancedClassLoader loader = getClassLoader(context);
         ClassPool pool = getClassPool(context, loader);
     {
         String pre = "";
         String post = "";
-        String body = null;
+        String body;
 
         context.setRoot(root);
         context.setCurrentObject(root);
         context.setCurrentObject(root);
         context.remove(PRE_CAST);
 
-        String body = null;
+        String body;
 
         String setterCode = expression.toSetSourceString(context, root);
         String castExpression = (String) context.get(PRE_CAST);
 
         // System.out.println("Setter Body: ===================================\n" + body);
 
-        if (setterCode.indexOf("$3") < 0)
-            setterCode = "";
-
         valueSetter.setBody(body);
 
         newClass.addMethod(valueSetter);

File src/java/ognl/enhance/OgnlExpressionCompiler.java

View file
  • Ignore whitespace
 import java.lang.reflect.Method;
 
 /**
- * @author jkuhnert
  */
 public interface OgnlExpressionCompiler {
-    
+
+    String ROOT_TYPE = "-ognl-root-type";
+
     void compileExpression(OgnlContext context, Node expression, Object root)
             throws Exception;
 
     Class getInterfaceClass(Class clazz);
 
     Class getSuperOrInterfaceClass(Method m, Class clazz);
-
+    
     String castExpression(OgnlContext context, Node expression, String body);
 
     String createLocalReference(OgnlContext context, String expression, Class type);