You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/08/30 14:52:51 UTC

[commons-ognl] branch master updated: Move Apache license header to the top of the file

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-ognl.git


The following commit(s) were added to refs/heads/master by this push:
     new 1d2048d  Move Apache license header to the top of the file
1d2048d is described below

commit 1d2048db25b79b3f53b969f5b3971e0d7c17d797
Author: Gary Gregory <gg...@rocketsoftware.com>
AuthorDate: Tue Aug 30 10:52:47 2022 -0400

    Move Apache license header to the top of the file
---
 .../commons/ognl/enhance/ContextClassLoader.java   |  114 +-
 .../commons/ognl/enhance/EnhancedClassLoader.java  |   84 +-
 .../commons/ognl/enhance/ExpressionAccessor.java   |  116 +-
 .../commons/ognl/enhance/ExpressionCompiler.java   | 1690 ++++++++++----------
 .../commons/ognl/enhance/LocalReference.java       |   96 +-
 .../commons/ognl/enhance/LocalReferenceImpl.java   |  242 +--
 .../ognl/enhance/OgnlExpressionCompiler.java       |  250 +--
 .../apache/commons/ognl/enhance/OrderedReturn.java |   87 +-
 .../enhance/UnsupportedCompilationException.java   |   96 +-
 .../apache/commons/ognl/enhance/package-info.java  |   48 +-
 10 files changed, 1411 insertions(+), 1412 deletions(-)

diff --git a/src/main/java/org/apache/commons/ognl/enhance/ContextClassLoader.java b/src/main/java/org/apache/commons/ognl/enhance/ContextClassLoader.java
index 1c5d765..f8814f1 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/ContextClassLoader.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/ContextClassLoader.java
@@ -1,57 +1,57 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-import org.apache.commons.ognl.OgnlContext;
-
-public class ContextClassLoader
-    extends ClassLoader
-{
-    private final OgnlContext context;
-
-    /*
-     * =================================================================== Constructors
-     * ===================================================================
-     */
-    public ContextClassLoader( ClassLoader parentClassLoader, OgnlContext context )
-    {
-        super( parentClassLoader );
-        this.context = context;
-    }
-
-    /*
-     * =================================================================== Overridden methods
-     * ===================================================================
-     */
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Class<?> findClass( String name )
-        throws ClassNotFoundException
-    {
-        if ( ( context != null ) && ( context.getClassResolver() != null ) )
-        {
-            return context.getClassResolver().classForName( name, context );
-        }
-        return super.findClass( name );
-    }
-
-}
+/*
+ * 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.commons.ognl.enhance;
+
+import org.apache.commons.ognl.OgnlContext;
+
+public class ContextClassLoader
+    extends ClassLoader
+{
+    private final OgnlContext context;
+
+    /*
+     * =================================================================== Constructors
+     * ===================================================================
+     */
+    public ContextClassLoader( ClassLoader parentClassLoader, OgnlContext context )
+    {
+        super( parentClassLoader );
+        this.context = context;
+    }
+
+    /*
+     * =================================================================== Overridden methods
+     * ===================================================================
+     */
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Class<?> findClass( String name )
+        throws ClassNotFoundException
+    {
+        if ( ( context != null ) && ( context.getClassResolver() != null ) )
+        {
+            return context.getClassResolver().classForName( name, context );
+        }
+        return super.findClass( name );
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/EnhancedClassLoader.java b/src/main/java/org/apache/commons/ognl/enhance/EnhancedClassLoader.java
index 84cb8db..8470a82 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/EnhancedClassLoader.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/EnhancedClassLoader.java
@@ -1,42 +1,42 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-public class EnhancedClassLoader
-    extends ClassLoader
-{
-    /*
-     * =================================================================== Constructors
-     * ===================================================================
-     */
-    public EnhancedClassLoader( ClassLoader parentClassLoader )
-    {
-        super( parentClassLoader );
-    }
-
-    /*
-     * =================================================================== Overridden methods
-     * ===================================================================
-     */
-    public Class<?> defineClass( String enhancedClassName, byte[] byteCode )
-    {
-        return defineClass( enhancedClassName, byteCode, 0, byteCode.length );
-    }
-}
+/*
+ * 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.commons.ognl.enhance;
+
+public class EnhancedClassLoader
+    extends ClassLoader
+{
+    /*
+     * =================================================================== Constructors
+     * ===================================================================
+     */
+    public EnhancedClassLoader( ClassLoader parentClassLoader )
+    {
+        super( parentClassLoader );
+    }
+
+    /*
+     * =================================================================== Overridden methods
+     * ===================================================================
+     */
+    public Class<?> defineClass( String enhancedClassName, byte[] byteCode )
+    {
+        return defineClass( enhancedClassName, byteCode, 0, byteCode.length );
+    }
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/ExpressionAccessor.java b/src/main/java/org/apache/commons/ognl/enhance/ExpressionAccessor.java
index 7b51efc..6905516 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/ExpressionAccessor.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/ExpressionAccessor.java
@@ -1,58 +1,58 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-import org.apache.commons.ognl.Node;
-import org.apache.commons.ognl.OgnlContext;
-
-/**
- * Provides pure java expression paths to get/set values from an ognl expression. This is achieved by taking an existing
- * {@link Node} parsed expression and using bytecode enhancements to do the same work using pure java vs the ognl
- * interpreter.
- */
-public interface ExpressionAccessor
-{
-
-    /**
-     * Gets the value represented by this expression path, if any.
-     *
-     * @param context The standard ognl context used for variable substitution/etc.
-     * @param target The root object this expression is meant for.
-     * @return The evaluated value, if any.
-     */
-    Object get( OgnlContext context, Object target );
-
-    /**
-     * Sets the value represented by this expression path, if possible.
-     *
-     * @param context The standard ognl context used for variable substitution/etc.
-     * @param target The root object this expression is meant for.
-     * @param value The new value to set if this expression references a settable property.
-     */
-    void set( OgnlContext context, Object target, Object value );
-
-    /**
-     * Used to set the original root expression node on instances where the compiled version has to fall back to
-     * interpreted syntax because of compilation failures.
-     *
-     * @param expression The root expression node used to generate this accessor.
-     */
-    void setExpression( Node expression );
-}
+/*
+ * 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.commons.ognl.enhance;
+
+import org.apache.commons.ognl.Node;
+import org.apache.commons.ognl.OgnlContext;
+
+/**
+ * Provides pure java expression paths to get/set values from an ognl expression. This is achieved by taking an existing
+ * {@link Node} parsed expression and using bytecode enhancements to do the same work using pure java vs the ognl
+ * interpreter.
+ */
+public interface ExpressionAccessor
+{
+
+    /**
+     * Gets the value represented by this expression path, if any.
+     *
+     * @param context The standard ognl context used for variable substitution/etc.
+     * @param target The root object this expression is meant for.
+     * @return The evaluated value, if any.
+     */
+    Object get( OgnlContext context, Object target );
+
+    /**
+     * Sets the value represented by this expression path, if possible.
+     *
+     * @param context The standard ognl context used for variable substitution/etc.
+     * @param target The root object this expression is meant for.
+     * @param value The new value to set if this expression references a settable property.
+     */
+    void set( OgnlContext context, Object target, Object value );
+
+    /**
+     * Used to set the original root expression node on instances where the compiled version has to fall back to
+     * interpreted syntax because of compilation failures.
+     *
+     * @param expression The root expression node used to generate this accessor.
+     */
+    void setExpression( Node expression );
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/ExpressionCompiler.java b/src/main/java/org/apache/commons/ognl/enhance/ExpressionCompiler.java
index 628af40..e75eadc 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/ExpressionCompiler.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/ExpressionCompiler.java
@@ -1,845 +1,845 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-import javassist.CannotCompileException;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.CtMethod;
-import javassist.CtNewConstructor;
-import javassist.CtNewMethod;
-import javassist.LoaderClassPath;
-import javassist.NotFoundException;
-import org.apache.commons.ognl.ASTAnd;
-import org.apache.commons.ognl.ASTChain;
-import org.apache.commons.ognl.ASTConst;
-import org.apache.commons.ognl.ASTCtor;
-import org.apache.commons.ognl.ASTList;
-import org.apache.commons.ognl.ASTMethod;
-import org.apache.commons.ognl.ASTOr;
-import org.apache.commons.ognl.ASTProperty;
-import org.apache.commons.ognl.ASTRootVarRef;
-import org.apache.commons.ognl.ASTStaticField;
-import org.apache.commons.ognl.ASTStaticMethod;
-import org.apache.commons.ognl.ASTThisVarRef;
-import org.apache.commons.ognl.ASTVarRef;
-import org.apache.commons.ognl.ClassResolver;
-import org.apache.commons.ognl.ExpressionNode;
-import org.apache.commons.ognl.Node;
-import org.apache.commons.ognl.OgnlContext;
-import org.apache.commons.ognl.OgnlRuntime;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static java.lang.String.format;
-
-/**
- * Responsible for managing/providing functionality related to compiling generated java source expressions via bytecode
- * enhancements for a given ognl expression.
- */
-public class ExpressionCompiler
-    implements OgnlExpressionCompiler
-{
-
-    /**
-     * Key used to store any java source string casting statements in the {@link OgnlContext} during class compilation.
-     */
-    public static final String PRE_CAST = "_preCast";
-
-    /**
-     * {@link ClassLoader} instances.
-     */
-    protected Map<ClassResolver, EnhancedClassLoader> loaders = new HashMap<ClassResolver, EnhancedClassLoader>();
-
-    /**
-     * Javassist class definition poool.
-     */
-    protected ClassPool pool;
-
-    protected int classCounter = 0;
-
-    /**
-     * Used by {@link #castExpression(org.apache.commons.ognl.OgnlContext, org.apache.commons.ognl.Node, String)} to
-     * store the cast java source string in to the current {@link org.apache.commons.ognl.OgnlContext}. This will either
-     * add to the existing string present if it already exists or create a new instance and store it using the static
-     * key of {@link #PRE_CAST}.
-     *
-     * @param context The current execution context.
-     * @param cast The java source string to store in to the context.
-     */
-    public static void addCastString( OgnlContext context, String cast )
-    {
-        String value = (String) context.get( PRE_CAST );
-
-        if ( value != null )
-        {
-            value = cast + value;
-        }
-        else
-        {
-            value = cast;
-        }
-
-        context.put( PRE_CAST, value );
-    }
-
-    /**
-     * Returns the appropriate casting expression (minus parens) for the specified class type.
-     * <p/>
-     * For instance, if given an {@link Integer} object the string <code>"java.lang.Integer"</code> would be returned.
-     * For an array of primitive ints <code>"int[]"</code> and so on..
-     * </p>
-     *
-     * @param type The class to cast a string expression for.
-     * @return The converted raw string version of the class name.
-     */
-    public static String getCastString( Class<?> type )
-    {
-        if ( type == null )
-        {
-            return null;
-        }
-
-        return type.isArray() ? type.getComponentType().getName() + "[]" : type.getName();
-    }
-
-    /**
-     * Convenience method called by many different property/method resolving AST types to get a root expression
-     * resolving string for the given node. The callers are mostly ignorant and rely on this method to properly
-     * determine if the expression should be cast at all and take the appropriate actions if it should.
-     *
-     * @param expression The node to check and generate a root expression to if necessary.
-     * @param root The root object for this execution.
-     * @param context The current execution context.
-     * @return Either an empty string or a root path java source string compatible with javassist compilations from the
-     *         root object up to the specified {@link Node}.
-     */
-    public static String getRootExpression( Node expression, Object root, OgnlContext context )
-    {
-        String rootExpr = "";
-
-        if ( !shouldCast( expression ) )
-        {
-            return rootExpr;
-        }
-
-        if ( ( !(expression instanceof ASTList) && !(expression instanceof ASTVarRef)
-            && !(expression instanceof ASTStaticMethod) && !(expression instanceof ASTStaticField)
-            && !(expression instanceof ASTConst) && !(expression instanceof ExpressionNode)
-            && !(expression instanceof ASTCtor) && !(expression instanceof ASTStaticMethod)
-            && root != null ) || ( root != null && expression instanceof ASTRootVarRef) )
-        {
-
-            Class<?> castClass = OgnlRuntime.getCompiler( context ).getRootExpressionClass( expression, context );
-
-            if ( castClass.isArray() || expression instanceof ASTRootVarRef || expression instanceof ASTThisVarRef)
-            {
-                rootExpr = "((" + getCastString( castClass ) + ")$2)";
-
-                if ( expression instanceof ASTProperty && !( (ASTProperty) expression ).isIndexedAccess() )
-                {
-                    rootExpr += ".";
-                }
-            }
-            else if ( ( expression instanceof ASTProperty && ( (ASTProperty) expression ).isIndexedAccess() )
-                || expression instanceof ASTChain)
-            {
-                rootExpr = "((" + getCastString( castClass ) + ")$2)";
-            }
-            else
-            {
-                rootExpr = "((" + getCastString( castClass ) + ")$2).";
-            }
-        }
-
-        return rootExpr;
-    }
-
-    /**
-     * Used by {@link #getRootExpression(org.apache.commons.ognl.Node, Object, org.apache.commons.ognl.OgnlContext)} to
-     * determine if the expression needs to be cast at all.
-     *
-     * @param expression The node to check against.
-     * @return Yes if the node type should be cast - false otherwise.
-     */
-    public static boolean shouldCast( Node expression )
-    {
-        if (expression instanceof ASTChain)
-        {
-            Node child = expression.jjtGetChild( 0 );
-            if ( child instanceof ASTConst || child instanceof ASTStaticMethod
-                || child instanceof ASTStaticField || ( child instanceof ASTVarRef
-                && !(child instanceof ASTRootVarRef)) )
-            {
-                return false;
-            }
-        }
-
-        return !(expression instanceof ASTConst);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String castExpression( OgnlContext context, Node expression, String body )
-    {
-        //TODO: ok - so this looks really f-ed up ...and it is ..eh if you can do it better I'm all for it :)
-
-        if ( context.getCurrentAccessor() == null || context.getPreviousType() == null
-            || context.getCurrentAccessor().isAssignableFrom( context.getPreviousType() ) || (
-            context.getCurrentType() != null && context.getCurrentObject() != null
-                && context.getCurrentType().isAssignableFrom( context.getCurrentObject().getClass() )
-                && context.getCurrentAccessor().isAssignableFrom( context.getPreviousType() ) ) || body == null
-            || body.trim().length() < 1 || ( context.getCurrentType() != null && context.getCurrentType().isArray() && (
-            context.getPreviousType() == null || context.getPreviousType() != Object.class ) )
-            || expression instanceof ASTOr || expression instanceof ASTAnd
-            || expression instanceof ASTRootVarRef || context.getCurrentAccessor() == Class.class || (
-            context.get( ExpressionCompiler.PRE_CAST ) != null && ( (String) context.get(
-                ExpressionCompiler.PRE_CAST ) ).startsWith( "new" ) ) || expression instanceof ASTStaticField
-            || expression instanceof ASTStaticMethod || ( expression instanceof OrderedReturn
-            && ( (OrderedReturn) expression ).getLastExpression() != null ) )
-        {
-            return body;
-        }
-
-        /*
-         * System.out.println("castExpression() with expression " + expression + " expr class: " + expression.getClass()
-         * + " currentType is: " + context.getCurrentType() + " previousType: " + context.getPreviousType() +
-         * "\n current Accessor: " + context.getCurrentAccessor() + " previous Accessor: " +
-         * context.getPreviousAccessor() + " current object " + context.getCurrentObject());
-         */
-
-        ExpressionCompiler.addCastString( context,
-                                          "((" + ExpressionCompiler.getCastString( context.getCurrentAccessor() )
-                                              + ")" );
-
-        return ")" + body;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getClassName( Class<?> clazz )
-    {
-        if ( "java.util.AbstractList$Itr".equals( clazz.getName() ) )
-        {
-            return Iterator.class.getName();
-        }
-
-        if ( Modifier.isPublic( clazz.getModifiers() ) && clazz.isInterface() )
-        {
-            return clazz.getName();
-        }
-
-        Class<?>[] interfaces = clazz.getInterfaces();
-
-        for ( Class<?> intface : interfaces )
-        {
-            if ( intface.getName().indexOf( "util.List" ) > 0 )
-            {
-                return intface.getName();
-            }
-            if ( intface.getName().indexOf( "Iterator" ) > 0 )
-            {
-                return intface.getName();
-            }
-        }
-
-        if ( clazz.getSuperclass() != null && clazz.getSuperclass().getInterfaces().length > 0 )
-        {
-            return getClassName( clazz.getSuperclass() );
-        }
-
-        return clazz.getName();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Class<?> getSuperOrInterfaceClass( Method m, Class<?> clazz )
-    {
-        if ( clazz.getInterfaces() != null && clazz.getInterfaces().length > 0 )
-        {
-            Class<?>[] intfs = clazz.getInterfaces();
-            Class<?> intClass;
-
-            for ( Class<?> intf : intfs )
-            {
-                intClass = getSuperOrInterfaceClass( m, intf );
-
-                if ( intClass != null )
-                {
-                    return intClass;
-                }
-
-                if ( Modifier.isPublic( intf.getModifiers() ) && containsMethod( m, intf ) )
-                {
-                    return intf;
-                }
-            }
-        }
-
-        if ( clazz.getSuperclass() != null )
-        {
-            Class<?> superClass = getSuperOrInterfaceClass( m, clazz.getSuperclass() );
-
-            if ( superClass != null )
-            {
-                return superClass;
-            }
-        }
-
-        if ( Modifier.isPublic( clazz.getModifiers() ) && containsMethod( m, clazz ) )
-        {
-            return clazz;
-        }
-
-        return null;
-    }
-
-    /**
-     * Helper utility method used by compiler to help resolve class->method mappings during method calls to
-     * {@link OgnlExpressionCompiler#getSuperOrInterfaceClass(java.lang.reflect.Method, Class)}.
-     *
-     * @param m The method to check for existance of.
-     * @param clazz The class to check for the existance of a matching method definition to the method passed in.
-     * @return True if the class contains the specified method, false otherwise.
-     */
-    public boolean containsMethod( Method m, Class<?> clazz )
-    {
-        Method[] methods = clazz.getMethods();
-
-        if ( methods == null )
-        {
-            return false;
-        }
-
-        for ( Method method : methods )
-        {
-            if ( method.getName().equals( m.getName() ) && method.getReturnType() == m.getReturnType() )
-            {
-                Class<?>[] parms = m.getParameterTypes();
-                if ( parms == null )
-                {
-                    continue;
-                }
-
-                Class<?>[] mparms = method.getParameterTypes();
-                if ( mparms == null || mparms.length != parms.length )
-                {
-                    continue;
-                }
-
-                boolean parmsMatch = true;
-                for ( int p = 0; p < parms.length; p++ )
-                {
-                    if ( parms[p] != mparms[p] )
-                    {
-                        parmsMatch = false;
-                        break;
-                    }
-                }
-
-                if ( !parmsMatch )
-                {
-                    continue;
-                }
-
-                Class<?>[] exceptions = m.getExceptionTypes();
-                if ( exceptions == null )
-                {
-                    continue;
-                }
-
-                Class<?>[] mexceptions = method.getExceptionTypes();
-                if ( mexceptions == null || mexceptions.length != exceptions.length )
-                {
-                    continue;
-                }
-
-                boolean exceptionsMatch = true;
-                for ( int e = 0; e < exceptions.length; e++ )
-                {
-                    if ( exceptions[e] != mexceptions[e] )
-                    {
-                        exceptionsMatch = false;
-                        break;
-                    }
-                }
-
-                if ( !exceptionsMatch )
-                {
-                    continue;
-                }
-
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Class<?> getInterfaceClass( Class<?> clazz )
-    {
-        if ( "java.util.AbstractList$Itr".equals( clazz.getName() ) )
-        {
-            return Iterator.class;
-        }
-
-        if ( Modifier.isPublic( clazz.getModifiers() ) && clazz.isInterface() || clazz.isPrimitive() )
-        {
-            return clazz;
-        }
-
-        Class<?>[] intf = clazz.getInterfaces();
-
-        for ( Class<?> anIntf : intf )
-        {
-            if ( List.class.isAssignableFrom( anIntf ) )
-            {
-                return List.class;
-            }
-            if ( Iterator.class.isAssignableFrom( anIntf ) )
-            {
-                return Iterator.class;
-            }
-            if ( Map.class.isAssignableFrom( anIntf ) )
-            {
-                return Map.class;
-            }
-            if ( Set.class.isAssignableFrom( anIntf ) )
-            {
-                return Set.class;
-            }
-            if ( Collection.class.isAssignableFrom( anIntf ) )
-            {
-                return Collection.class;
-            }
-        }
-
-        if ( clazz.getSuperclass() != null && clazz.getSuperclass().getInterfaces().length > 0 )
-        {
-            return getInterfaceClass( clazz.getSuperclass() );
-        }
-
-        return clazz;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Class<?> getRootExpressionClass( Node rootNode, OgnlContext context )
-    {
-        if ( context.getRoot() == null )
-        {
-            return null;
-        }
-
-        Class<?> ret = context.getRoot().getClass();
-
-        if ( context.getFirstAccessor() != null && context.getFirstAccessor().isInstance( context.getRoot() ) )
-        {
-            ret = context.getFirstAccessor();
-        }
-
-        return ret;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void compileExpression( OgnlContext context, Node expression, Object root )
-        throws Exception
-    {
-        // System.out.println("Compiling expr class " + expression.getClass().getName() + " and root " + root);
-
-        if ( expression.getAccessor() != null )
-        {
-            return;
-        }
-
-        String getBody, setBody;
-
-        EnhancedClassLoader loader = getClassLoader( context );
-        ClassPool classPool = getClassPool( context, loader );
-
-        CtClass newClass = classPool.makeClass(
-            expression.getClass().getName() + expression.hashCode() + classCounter++ + "Accessor" );
-        newClass.addInterface( getCtClass( ExpressionAccessor.class ) );
-
-        CtClass ognlClass = getCtClass( OgnlContext.class );
-        CtClass objClass = getCtClass( Object.class );
-
-        CtMethod valueGetter = new CtMethod( objClass, "get", new CtClass[] { ognlClass, objClass }, newClass );
-        CtMethod valueSetter =
-            new CtMethod( CtClass.voidType, "set", new CtClass[] { ognlClass, objClass, objClass }, newClass );
-
-        CtField nodeMember = null; // will only be set if uncompilable exception is thrown
-
-        CtClass nodeClass = getCtClass( Node.class );
-        CtMethod setExpression = null;
-
-        try
-        {
-
-            getBody = generateGetter( context, newClass, objClass, classPool, valueGetter, expression, root );
-
-        }
-        catch ( UnsupportedCompilationException uc )
-        {
-            nodeMember = new CtField( nodeClass, "_node", newClass );
-            newClass.addField( nodeMember );
-
-            getBody = generateOgnlGetter( newClass, valueGetter, nodeMember );
-
-            setExpression = CtNewMethod.setter( "setExpression", nodeMember );
-            newClass.addMethod( setExpression );
-        }
-
-        try
-        {
-
-            setBody = generateSetter( context, newClass, objClass, classPool, valueSetter, expression, root );
-
-        }
-        catch ( UnsupportedCompilationException uc )
-        {
-            if ( nodeMember == null )
-            {
-                nodeMember = new CtField( nodeClass, "_node", newClass );
-                newClass.addField( nodeMember );
-            }
-
-            setBody = generateOgnlSetter( newClass, valueSetter, nodeMember );
-
-            if ( setExpression == null )
-            {
-                setExpression = CtNewMethod.setter( "setExpression", nodeMember );
-                newClass.addMethod( setExpression );
-            }
-        }
-
-        try
-        {
-            newClass.addConstructor( CtNewConstructor.defaultConstructor( newClass ) );
-
-            Class<?> clazz = classPool.toClass( newClass );
-            newClass.detach();
-
-            expression.setAccessor( (ExpressionAccessor) clazz.newInstance() );
-
-            // need to set expression on node if the field was just defined.
-
-            if ( nodeMember != null )
-            {
-                expression.getAccessor().setExpression( expression );
-            }
-
-        }
-        catch ( Throwable t )
-        {
-            throw new RuntimeException( "Error compiling expression on object " + root + " with expression node "
-                + expression + " getter body: " + getBody + " setter body: " + setBody, t );
-        }
-
-    }
-
-    protected String generateGetter( OgnlContext context, CtClass newClass, CtClass objClass, ClassPool classPool,
-                                     CtMethod valueGetter, Node expression, Object root )
-        throws Exception
-    {
-        String pre = "";
-        String post = "";
-        String body;
-
-        context.setRoot( root );
-
-        // the ExpressionAccessor API has to reference the generic Object class for get/set operations, so this sets up
-        // that known
-        // type beforehand
-
-        context.remove( PRE_CAST );
-
-        // Recursively generate the java source code representation of the top level expression
-
-        String getterCode = expression.toGetSourceString( context, root );
-
-        if ( getterCode == null || getterCode.trim().isEmpty()
-            && !ASTVarRef.class.isAssignableFrom( expression.getClass() ) )
-        {
-            getterCode = "null";
-        }
-
-        String castExpression = (String) context.get( PRE_CAST );
-
-        if ( context.getCurrentType() == null || context.getCurrentType().isPrimitive()
-            || Character.class.isAssignableFrom( context.getCurrentType() )
-            || Object.class == context.getCurrentType() )
-        {
-            pre = pre + " ($w) (";
-            post = post + ")";
-        }
-
-        String rootExpr = !"null".equals( getterCode ) ? getRootExpression( expression, root, context ) : "";
-
-        String noRoot = (String) context.remove( "_noRoot" );
-        if ( noRoot != null )
-        {
-            rootExpr = "";
-        }
-
-        createLocalReferences( context, classPool, newClass, objClass, valueGetter.getParameterTypes() );
-
-        if ( expression instanceof OrderedReturn
-            && ( (OrderedReturn) expression ).getLastExpression() != null )
-        {
-            body = "{ " + ( expression instanceof ASTMethod || expression instanceof ASTChain
-                ? rootExpr
-                : "" ) + ( castExpression != null ? castExpression : "" )
-                + ( (OrderedReturn) expression ).getCoreExpression() + " return " + pre
-                + ( (OrderedReturn) expression ).getLastExpression() + post + ";}";
-
-        }
-        else
-        {
-
-            body =
-                "{  return " + pre + ( castExpression != null ? castExpression : "" ) + rootExpr + getterCode + post
-                    + ";}";
-        }
-
-        body = body.replaceAll( "\\.\\.", "." );
-
-        // System.out.println("Getter Body: ===================================\n" + body);
-        valueGetter.setBody( body );
-        newClass.addMethod( valueGetter );
-
-        return body;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String createLocalReference( OgnlContext context, String expression, Class<?> type )
-    {
-        String referenceName = "ref" + context.incrementLocalReferenceCounter();
-        context.addLocalReference( referenceName, new LocalReferenceImpl( referenceName, expression, type ) );
-
-        String castString = "";
-        if ( !type.isPrimitive() )
-        {
-            castString = "(" + ExpressionCompiler.getCastString( type ) + ") ";
-        }
-
-        return castString + referenceName + "($$)";
-    }
-
-    void createLocalReferences( OgnlContext context, ClassPool classPool, CtClass clazz, CtClass unused,
-                                CtClass[] params )
-        throws NotFoundException, CannotCompileException
-    {
-        Map<String, LocalReference> referenceMap = context.getLocalReferences();
-        if ( referenceMap == null || referenceMap.isEmpty() )
-        {
-            return;
-        }
-
-        Iterator<LocalReference> it = referenceMap.values().iterator();
-        while( it.hasNext() )
-        {
-            LocalReference ref = it.next();
-            String widener = ref.getType().isPrimitive() ? " " : " ($w) ";
-
-            String body = format( "{ return %s %s; }", widener, ref.getExpression() ).replaceAll( "\\.\\.", "." );
-
-            // System.out.println("adding method " + ref.getName() + " with body:\n" + body + " and return type: " +
-            // ref.getType());
-
-            CtMethod method =
-                new CtMethod( classPool.get( getCastString( ref.getType() ) ), ref.getName(), params, clazz );
-            method.setBody( body );
-
-            clazz.addMethod( method );
-            it.remove();
-        }
-    }
-
-    protected String generateSetter( OgnlContext context, CtClass newClass, CtClass objClass, ClassPool classPool,
-                                     CtMethod valueSetter, Node expression, Object root )
-        throws Exception
-    {
-        if ( expression instanceof ExpressionNode || expression instanceof ASTConst)
-        {
-            throw new UnsupportedCompilationException( "Can't compile expression/constant setters." );
-        }
-
-        context.setRoot( root );
-        context.remove( PRE_CAST );
-
-        String body;
-
-        String setterCode = expression.toSetSourceString( context, root );
-        String castExpression = (String) context.get( PRE_CAST );
-
-        if ( setterCode == null || setterCode.trim().length() < 1 )
-        {
-            throw new UnsupportedCompilationException( "Can't compile null setter body." );
-        }
-
-        if ( root == null )
-        {
-            throw new UnsupportedCompilationException( "Can't compile setters with a null root object." );
-        }
-
-        String pre = getRootExpression( expression, root, context );
-
-        String noRoot = (String) context.remove( "_noRoot" );
-        if ( noRoot != null )
-        {
-            pre = "";
-        }
-
-        createLocalReferences( context, classPool, newClass, objClass, valueSetter.getParameterTypes() );
-
-        body = "{" + ( castExpression != null ? castExpression : "" ) + pre + setterCode + ";}";
-
-        body = body.replaceAll( "\\.\\.", "." );
-
-        // System.out.println("Setter Body: ===================================\n" + body);
-
-        valueSetter.setBody( body );
-        newClass.addMethod( valueSetter );
-
-        return body;
-    }
-
-    /**
-     * Fail safe getter creation when normal compilation fails.
-     *
-     * @param clazz The javassist class the new method should be attached to.
-     * @param valueGetter The method definition the generated code will be contained within.
-     * @param node The root expression node.
-     * @return The generated source string for this method, the method will still be added via the javassist API either
-     *         way so this is really a convenience for exception reporting / debugging.
-     * @throws Exception If a javassist error occurs.
-     */
-    protected String generateOgnlGetter( CtClass clazz, CtMethod valueGetter, CtField node )
-        throws Exception
-    {
-        String body = "return " + node.getName() + ".getValue($1, $2);";
-
-        valueGetter.setBody( body );
-        clazz.addMethod( valueGetter );
-
-        return body;
-    }
-
-    /**
-     * Fail safe setter creation when normal compilation fails.
-     *
-     * @param clazz The javassist class the new method should be attached to.
-     * @param valueSetter The method definition the generated code will be contained within.
-     * @param node The root expression node.
-     * @return The generated source string for this method, the method will still be added via the javassist API either
-     *         way so this is really a convenience for exception reporting / debugging.
-     * @throws Exception If a javassist error occurs.
-     */
-    protected String generateOgnlSetter( CtClass clazz, CtMethod valueSetter, CtField node )
-        throws Exception
-    {
-        String body = node.getName() + ".setValue($1, $2, $3);";
-
-        valueSetter.setBody( body );
-        clazz.addMethod( valueSetter );
-
-        return body;
-    }
-
-    /**
-     * Creates a {@link ClassLoader} instance compatible with the javassist classloader and normal OGNL class resolving
-     * semantics.
-     *
-     * @param context The current execution context.
-     * @return The created {@link ClassLoader} instance.
-     */
-    protected EnhancedClassLoader getClassLoader( OgnlContext context )
-    {
-        EnhancedClassLoader ret = loaders.get( context.getClassResolver() );
-
-        if ( ret != null )
-        {
-            return ret;
-        }
-
-        ClassLoader classLoader = new ContextClassLoader( OgnlContext.class.getClassLoader(), context );
-
-        ret = new EnhancedClassLoader( classLoader );
-        loaders.put( context.getClassResolver(), ret );
-
-        return ret;
-    }
-
-    /**
-     * Loads a new class definition via javassist for the specified class.
-     *
-     * @param searchClass The class to load.
-     * @return The javassist class equivalent.
-     * @throws javassist.NotFoundException When the class definition can't be found.
-     */
-    protected CtClass getCtClass( Class<?> searchClass )
-        throws NotFoundException
-    {
-        return pool.get( searchClass.getName() );
-    }
-
-    /**
-     * Gets either a new or existing {@link ClassPool} for use in compiling javassist classes. A new class path object
-     * is inserted in to the returned {@link ClassPool} using the passed in <code>loader</code> instance if a new pool
-     * needs to be created.
-     *
-     * @param context The current execution context.
-     * @param loader The {@link ClassLoader} instance to use - as returned by
-     *            {@link #getClassLoader(org.apache.commons.ognl.OgnlContext)}.
-     * @return The existing or new {@link ClassPool} instance.
-     */
-    protected ClassPool getClassPool( OgnlContext context, EnhancedClassLoader loader )
-    {
-        if ( pool != null )
-        {
-            return pool;
-        }
-
-        pool = ClassPool.getDefault();
-        pool.insertClassPath( new LoaderClassPath( loader.getParent() ) );
-
-        return pool;
-    }
-}
+/*
+ * 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.commons.ognl.enhance;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewConstructor;
+import javassist.CtNewMethod;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+import org.apache.commons.ognl.ASTAnd;
+import org.apache.commons.ognl.ASTChain;
+import org.apache.commons.ognl.ASTConst;
+import org.apache.commons.ognl.ASTCtor;
+import org.apache.commons.ognl.ASTList;
+import org.apache.commons.ognl.ASTMethod;
+import org.apache.commons.ognl.ASTOr;
+import org.apache.commons.ognl.ASTProperty;
+import org.apache.commons.ognl.ASTRootVarRef;
+import org.apache.commons.ognl.ASTStaticField;
+import org.apache.commons.ognl.ASTStaticMethod;
+import org.apache.commons.ognl.ASTThisVarRef;
+import org.apache.commons.ognl.ASTVarRef;
+import org.apache.commons.ognl.ClassResolver;
+import org.apache.commons.ognl.ExpressionNode;
+import org.apache.commons.ognl.Node;
+import org.apache.commons.ognl.OgnlContext;
+import org.apache.commons.ognl.OgnlRuntime;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static java.lang.String.format;
+
+/**
+ * Responsible for managing/providing functionality related to compiling generated java source expressions via bytecode
+ * enhancements for a given ognl expression.
+ */
+public class ExpressionCompiler
+    implements OgnlExpressionCompiler
+{
+
+    /**
+     * Key used to store any java source string casting statements in the {@link OgnlContext} during class compilation.
+     */
+    public static final String PRE_CAST = "_preCast";
+
+    /**
+     * {@link ClassLoader} instances.
+     */
+    protected Map<ClassResolver, EnhancedClassLoader> loaders = new HashMap<ClassResolver, EnhancedClassLoader>();
+
+    /**
+     * Javassist class definition poool.
+     */
+    protected ClassPool pool;
+
+    protected int classCounter = 0;
+
+    /**
+     * Used by {@link #castExpression(org.apache.commons.ognl.OgnlContext, org.apache.commons.ognl.Node, String)} to
+     * store the cast java source string in to the current {@link org.apache.commons.ognl.OgnlContext}. This will either
+     * add to the existing string present if it already exists or create a new instance and store it using the static
+     * key of {@link #PRE_CAST}.
+     *
+     * @param context The current execution context.
+     * @param cast The java source string to store in to the context.
+     */
+    public static void addCastString( OgnlContext context, String cast )
+    {
+        String value = (String) context.get( PRE_CAST );
+
+        if ( value != null )
+        {
+            value = cast + value;
+        }
+        else
+        {
+            value = cast;
+        }
+
+        context.put( PRE_CAST, value );
+    }
+
+    /**
+     * Returns the appropriate casting expression (minus parens) for the specified class type.
+     * <p/>
+     * For instance, if given an {@link Integer} object the string <code>"java.lang.Integer"</code> would be returned.
+     * For an array of primitive ints <code>"int[]"</code> and so on..
+     * </p>
+     *
+     * @param type The class to cast a string expression for.
+     * @return The converted raw string version of the class name.
+     */
+    public static String getCastString( Class<?> type )
+    {
+        if ( type == null )
+        {
+            return null;
+        }
+
+        return type.isArray() ? type.getComponentType().getName() + "[]" : type.getName();
+    }
+
+    /**
+     * Convenience method called by many different property/method resolving AST types to get a root expression
+     * resolving string for the given node. The callers are mostly ignorant and rely on this method to properly
+     * determine if the expression should be cast at all and take the appropriate actions if it should.
+     *
+     * @param expression The node to check and generate a root expression to if necessary.
+     * @param root The root object for this execution.
+     * @param context The current execution context.
+     * @return Either an empty string or a root path java source string compatible with javassist compilations from the
+     *         root object up to the specified {@link Node}.
+     */
+    public static String getRootExpression( Node expression, Object root, OgnlContext context )
+    {
+        String rootExpr = "";
+
+        if ( !shouldCast( expression ) )
+        {
+            return rootExpr;
+        }
+
+        if ( ( !(expression instanceof ASTList) && !(expression instanceof ASTVarRef)
+            && !(expression instanceof ASTStaticMethod) && !(expression instanceof ASTStaticField)
+            && !(expression instanceof ASTConst) && !(expression instanceof ExpressionNode)
+            && !(expression instanceof ASTCtor) && !(expression instanceof ASTStaticMethod)
+            && root != null ) || ( root != null && expression instanceof ASTRootVarRef) )
+        {
+
+            Class<?> castClass = OgnlRuntime.getCompiler( context ).getRootExpressionClass( expression, context );
+
+            if ( castClass.isArray() || expression instanceof ASTRootVarRef || expression instanceof ASTThisVarRef)
+            {
+                rootExpr = "((" + getCastString( castClass ) + ")$2)";
+
+                if ( expression instanceof ASTProperty && !( (ASTProperty) expression ).isIndexedAccess() )
+                {
+                    rootExpr += ".";
+                }
+            }
+            else if ( ( expression instanceof ASTProperty && ( (ASTProperty) expression ).isIndexedAccess() )
+                || expression instanceof ASTChain)
+            {
+                rootExpr = "((" + getCastString( castClass ) + ")$2)";
+            }
+            else
+            {
+                rootExpr = "((" + getCastString( castClass ) + ")$2).";
+            }
+        }
+
+        return rootExpr;
+    }
+
+    /**
+     * Used by {@link #getRootExpression(org.apache.commons.ognl.Node, Object, org.apache.commons.ognl.OgnlContext)} to
+     * determine if the expression needs to be cast at all.
+     *
+     * @param expression The node to check against.
+     * @return Yes if the node type should be cast - false otherwise.
+     */
+    public static boolean shouldCast( Node expression )
+    {
+        if (expression instanceof ASTChain)
+        {
+            Node child = expression.jjtGetChild( 0 );
+            if ( child instanceof ASTConst || child instanceof ASTStaticMethod
+                || child instanceof ASTStaticField || ( child instanceof ASTVarRef
+                && !(child instanceof ASTRootVarRef)) )
+            {
+                return false;
+            }
+        }
+
+        return !(expression instanceof ASTConst);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String castExpression( OgnlContext context, Node expression, String body )
+    {
+        //TODO: ok - so this looks really f-ed up ...and it is ..eh if you can do it better I'm all for it :)
+
+        if ( context.getCurrentAccessor() == null || context.getPreviousType() == null
+            || context.getCurrentAccessor().isAssignableFrom( context.getPreviousType() ) || (
+            context.getCurrentType() != null && context.getCurrentObject() != null
+                && context.getCurrentType().isAssignableFrom( context.getCurrentObject().getClass() )
+                && context.getCurrentAccessor().isAssignableFrom( context.getPreviousType() ) ) || body == null
+            || body.trim().length() < 1 || ( context.getCurrentType() != null && context.getCurrentType().isArray() && (
+            context.getPreviousType() == null || context.getPreviousType() != Object.class ) )
+            || expression instanceof ASTOr || expression instanceof ASTAnd
+            || expression instanceof ASTRootVarRef || context.getCurrentAccessor() == Class.class || (
+            context.get( ExpressionCompiler.PRE_CAST ) != null && ( (String) context.get(
+                ExpressionCompiler.PRE_CAST ) ).startsWith( "new" ) ) || expression instanceof ASTStaticField
+            || expression instanceof ASTStaticMethod || ( expression instanceof OrderedReturn
+            && ( (OrderedReturn) expression ).getLastExpression() != null ) )
+        {
+            return body;
+        }
+
+        /*
+         * System.out.println("castExpression() with expression " + expression + " expr class: " + expression.getClass()
+         * + " currentType is: " + context.getCurrentType() + " previousType: " + context.getPreviousType() +
+         * "\n current Accessor: " + context.getCurrentAccessor() + " previous Accessor: " +
+         * context.getPreviousAccessor() + " current object " + context.getCurrentObject());
+         */
+
+        ExpressionCompiler.addCastString( context,
+                                          "((" + ExpressionCompiler.getCastString( context.getCurrentAccessor() )
+                                              + ")" );
+
+        return ")" + body;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getClassName( Class<?> clazz )
+    {
+        if ( "java.util.AbstractList$Itr".equals( clazz.getName() ) )
+        {
+            return Iterator.class.getName();
+        }
+
+        if ( Modifier.isPublic( clazz.getModifiers() ) && clazz.isInterface() )
+        {
+            return clazz.getName();
+        }
+
+        Class<?>[] interfaces = clazz.getInterfaces();
+
+        for ( Class<?> intface : interfaces )
+        {
+            if ( intface.getName().indexOf( "util.List" ) > 0 )
+            {
+                return intface.getName();
+            }
+            if ( intface.getName().indexOf( "Iterator" ) > 0 )
+            {
+                return intface.getName();
+            }
+        }
+
+        if ( clazz.getSuperclass() != null && clazz.getSuperclass().getInterfaces().length > 0 )
+        {
+            return getClassName( clazz.getSuperclass() );
+        }
+
+        return clazz.getName();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<?> getSuperOrInterfaceClass( Method m, Class<?> clazz )
+    {
+        if ( clazz.getInterfaces() != null && clazz.getInterfaces().length > 0 )
+        {
+            Class<?>[] intfs = clazz.getInterfaces();
+            Class<?> intClass;
+
+            for ( Class<?> intf : intfs )
+            {
+                intClass = getSuperOrInterfaceClass( m, intf );
+
+                if ( intClass != null )
+                {
+                    return intClass;
+                }
+
+                if ( Modifier.isPublic( intf.getModifiers() ) && containsMethod( m, intf ) )
+                {
+                    return intf;
+                }
+            }
+        }
+
+        if ( clazz.getSuperclass() != null )
+        {
+            Class<?> superClass = getSuperOrInterfaceClass( m, clazz.getSuperclass() );
+
+            if ( superClass != null )
+            {
+                return superClass;
+            }
+        }
+
+        if ( Modifier.isPublic( clazz.getModifiers() ) && containsMethod( m, clazz ) )
+        {
+            return clazz;
+        }
+
+        return null;
+    }
+
+    /**
+     * Helper utility method used by compiler to help resolve class->method mappings during method calls to
+     * {@link OgnlExpressionCompiler#getSuperOrInterfaceClass(java.lang.reflect.Method, Class)}.
+     *
+     * @param m The method to check for existance of.
+     * @param clazz The class to check for the existance of a matching method definition to the method passed in.
+     * @return True if the class contains the specified method, false otherwise.
+     */
+    public boolean containsMethod( Method m, Class<?> clazz )
+    {
+        Method[] methods = clazz.getMethods();
+
+        if ( methods == null )
+        {
+            return false;
+        }
+
+        for ( Method method : methods )
+        {
+            if ( method.getName().equals( m.getName() ) && method.getReturnType() == m.getReturnType() )
+            {
+                Class<?>[] parms = m.getParameterTypes();
+                if ( parms == null )
+                {
+                    continue;
+                }
+
+                Class<?>[] mparms = method.getParameterTypes();
+                if ( mparms == null || mparms.length != parms.length )
+                {
+                    continue;
+                }
+
+                boolean parmsMatch = true;
+                for ( int p = 0; p < parms.length; p++ )
+                {
+                    if ( parms[p] != mparms[p] )
+                    {
+                        parmsMatch = false;
+                        break;
+                    }
+                }
+
+                if ( !parmsMatch )
+                {
+                    continue;
+                }
+
+                Class<?>[] exceptions = m.getExceptionTypes();
+                if ( exceptions == null )
+                {
+                    continue;
+                }
+
+                Class<?>[] mexceptions = method.getExceptionTypes();
+                if ( mexceptions == null || mexceptions.length != exceptions.length )
+                {
+                    continue;
+                }
+
+                boolean exceptionsMatch = true;
+                for ( int e = 0; e < exceptions.length; e++ )
+                {
+                    if ( exceptions[e] != mexceptions[e] )
+                    {
+                        exceptionsMatch = false;
+                        break;
+                    }
+                }
+
+                if ( !exceptionsMatch )
+                {
+                    continue;
+                }
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<?> getInterfaceClass( Class<?> clazz )
+    {
+        if ( "java.util.AbstractList$Itr".equals( clazz.getName() ) )
+        {
+            return Iterator.class;
+        }
+
+        if ( Modifier.isPublic( clazz.getModifiers() ) && clazz.isInterface() || clazz.isPrimitive() )
+        {
+            return clazz;
+        }
+
+        Class<?>[] intf = clazz.getInterfaces();
+
+        for ( Class<?> anIntf : intf )
+        {
+            if ( List.class.isAssignableFrom( anIntf ) )
+            {
+                return List.class;
+            }
+            if ( Iterator.class.isAssignableFrom( anIntf ) )
+            {
+                return Iterator.class;
+            }
+            if ( Map.class.isAssignableFrom( anIntf ) )
+            {
+                return Map.class;
+            }
+            if ( Set.class.isAssignableFrom( anIntf ) )
+            {
+                return Set.class;
+            }
+            if ( Collection.class.isAssignableFrom( anIntf ) )
+            {
+                return Collection.class;
+            }
+        }
+
+        if ( clazz.getSuperclass() != null && clazz.getSuperclass().getInterfaces().length > 0 )
+        {
+            return getInterfaceClass( clazz.getSuperclass() );
+        }
+
+        return clazz;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<?> getRootExpressionClass( Node rootNode, OgnlContext context )
+    {
+        if ( context.getRoot() == null )
+        {
+            return null;
+        }
+
+        Class<?> ret = context.getRoot().getClass();
+
+        if ( context.getFirstAccessor() != null && context.getFirstAccessor().isInstance( context.getRoot() ) )
+        {
+            ret = context.getFirstAccessor();
+        }
+
+        return ret;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void compileExpression( OgnlContext context, Node expression, Object root )
+        throws Exception
+    {
+        // System.out.println("Compiling expr class " + expression.getClass().getName() + " and root " + root);
+
+        if ( expression.getAccessor() != null )
+        {
+            return;
+        }
+
+        String getBody, setBody;
+
+        EnhancedClassLoader loader = getClassLoader( context );
+        ClassPool classPool = getClassPool( context, loader );
+
+        CtClass newClass = classPool.makeClass(
+            expression.getClass().getName() + expression.hashCode() + classCounter++ + "Accessor" );
+        newClass.addInterface( getCtClass( ExpressionAccessor.class ) );
+
+        CtClass ognlClass = getCtClass( OgnlContext.class );
+        CtClass objClass = getCtClass( Object.class );
+
+        CtMethod valueGetter = new CtMethod( objClass, "get", new CtClass[] { ognlClass, objClass }, newClass );
+        CtMethod valueSetter =
+            new CtMethod( CtClass.voidType, "set", new CtClass[] { ognlClass, objClass, objClass }, newClass );
+
+        CtField nodeMember = null; // will only be set if uncompilable exception is thrown
+
+        CtClass nodeClass = getCtClass( Node.class );
+        CtMethod setExpression = null;
+
+        try
+        {
+
+            getBody = generateGetter( context, newClass, objClass, classPool, valueGetter, expression, root );
+
+        }
+        catch ( UnsupportedCompilationException uc )
+        {
+            nodeMember = new CtField( nodeClass, "_node", newClass );
+            newClass.addField( nodeMember );
+
+            getBody = generateOgnlGetter( newClass, valueGetter, nodeMember );
+
+            setExpression = CtNewMethod.setter( "setExpression", nodeMember );
+            newClass.addMethod( setExpression );
+        }
+
+        try
+        {
+
+            setBody = generateSetter( context, newClass, objClass, classPool, valueSetter, expression, root );
+
+        }
+        catch ( UnsupportedCompilationException uc )
+        {
+            if ( nodeMember == null )
+            {
+                nodeMember = new CtField( nodeClass, "_node", newClass );
+                newClass.addField( nodeMember );
+            }
+
+            setBody = generateOgnlSetter( newClass, valueSetter, nodeMember );
+
+            if ( setExpression == null )
+            {
+                setExpression = CtNewMethod.setter( "setExpression", nodeMember );
+                newClass.addMethod( setExpression );
+            }
+        }
+
+        try
+        {
+            newClass.addConstructor( CtNewConstructor.defaultConstructor( newClass ) );
+
+            Class<?> clazz = classPool.toClass( newClass );
+            newClass.detach();
+
+            expression.setAccessor( (ExpressionAccessor) clazz.newInstance() );
+
+            // need to set expression on node if the field was just defined.
+
+            if ( nodeMember != null )
+            {
+                expression.getAccessor().setExpression( expression );
+            }
+
+        }
+        catch ( Throwable t )
+        {
+            throw new RuntimeException( "Error compiling expression on object " + root + " with expression node "
+                + expression + " getter body: " + getBody + " setter body: " + setBody, t );
+        }
+
+    }
+
+    protected String generateGetter( OgnlContext context, CtClass newClass, CtClass objClass, ClassPool classPool,
+                                     CtMethod valueGetter, Node expression, Object root )
+        throws Exception
+    {
+        String pre = "";
+        String post = "";
+        String body;
+
+        context.setRoot( root );
+
+        // the ExpressionAccessor API has to reference the generic Object class for get/set operations, so this sets up
+        // that known
+        // type beforehand
+
+        context.remove( PRE_CAST );
+
+        // Recursively generate the java source code representation of the top level expression
+
+        String getterCode = expression.toGetSourceString( context, root );
+
+        if ( getterCode == null || getterCode.trim().isEmpty()
+            && !ASTVarRef.class.isAssignableFrom( expression.getClass() ) )
+        {
+            getterCode = "null";
+        }
+
+        String castExpression = (String) context.get( PRE_CAST );
+
+        if ( context.getCurrentType() == null || context.getCurrentType().isPrimitive()
+            || Character.class.isAssignableFrom( context.getCurrentType() )
+            || Object.class == context.getCurrentType() )
+        {
+            pre = pre + " ($w) (";
+            post = post + ")";
+        }
+
+        String rootExpr = !"null".equals( getterCode ) ? getRootExpression( expression, root, context ) : "";
+
+        String noRoot = (String) context.remove( "_noRoot" );
+        if ( noRoot != null )
+        {
+            rootExpr = "";
+        }
+
+        createLocalReferences( context, classPool, newClass, objClass, valueGetter.getParameterTypes() );
+
+        if ( expression instanceof OrderedReturn
+            && ( (OrderedReturn) expression ).getLastExpression() != null )
+        {
+            body = "{ " + ( expression instanceof ASTMethod || expression instanceof ASTChain
+                ? rootExpr
+                : "" ) + ( castExpression != null ? castExpression : "" )
+                + ( (OrderedReturn) expression ).getCoreExpression() + " return " + pre
+                + ( (OrderedReturn) expression ).getLastExpression() + post + ";}";
+
+        }
+        else
+        {
+
+            body =
+                "{  return " + pre + ( castExpression != null ? castExpression : "" ) + rootExpr + getterCode + post
+                    + ";}";
+        }
+
+        body = body.replaceAll( "\\.\\.", "." );
+
+        // System.out.println("Getter Body: ===================================\n" + body);
+        valueGetter.setBody( body );
+        newClass.addMethod( valueGetter );
+
+        return body;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String createLocalReference( OgnlContext context, String expression, Class<?> type )
+    {
+        String referenceName = "ref" + context.incrementLocalReferenceCounter();
+        context.addLocalReference( referenceName, new LocalReferenceImpl( referenceName, expression, type ) );
+
+        String castString = "";
+        if ( !type.isPrimitive() )
+        {
+            castString = "(" + ExpressionCompiler.getCastString( type ) + ") ";
+        }
+
+        return castString + referenceName + "($$)";
+    }
+
+    void createLocalReferences( OgnlContext context, ClassPool classPool, CtClass clazz, CtClass unused,
+                                CtClass[] params )
+        throws NotFoundException, CannotCompileException
+    {
+        Map<String, LocalReference> referenceMap = context.getLocalReferences();
+        if ( referenceMap == null || referenceMap.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator<LocalReference> it = referenceMap.values().iterator();
+        while( it.hasNext() )
+        {
+            LocalReference ref = it.next();
+            String widener = ref.getType().isPrimitive() ? " " : " ($w) ";
+
+            String body = format( "{ return %s %s; }", widener, ref.getExpression() ).replaceAll( "\\.\\.", "." );
+
+            // System.out.println("adding method " + ref.getName() + " with body:\n" + body + " and return type: " +
+            // ref.getType());
+
+            CtMethod method =
+                new CtMethod( classPool.get( getCastString( ref.getType() ) ), ref.getName(), params, clazz );
+            method.setBody( body );
+
+            clazz.addMethod( method );
+            it.remove();
+        }
+    }
+
+    protected String generateSetter( OgnlContext context, CtClass newClass, CtClass objClass, ClassPool classPool,
+                                     CtMethod valueSetter, Node expression, Object root )
+        throws Exception
+    {
+        if ( expression instanceof ExpressionNode || expression instanceof ASTConst)
+        {
+            throw new UnsupportedCompilationException( "Can't compile expression/constant setters." );
+        }
+
+        context.setRoot( root );
+        context.remove( PRE_CAST );
+
+        String body;
+
+        String setterCode = expression.toSetSourceString( context, root );
+        String castExpression = (String) context.get( PRE_CAST );
+
+        if ( setterCode == null || setterCode.trim().length() < 1 )
+        {
+            throw new UnsupportedCompilationException( "Can't compile null setter body." );
+        }
+
+        if ( root == null )
+        {
+            throw new UnsupportedCompilationException( "Can't compile setters with a null root object." );
+        }
+
+        String pre = getRootExpression( expression, root, context );
+
+        String noRoot = (String) context.remove( "_noRoot" );
+        if ( noRoot != null )
+        {
+            pre = "";
+        }
+
+        createLocalReferences( context, classPool, newClass, objClass, valueSetter.getParameterTypes() );
+
+        body = "{" + ( castExpression != null ? castExpression : "" ) + pre + setterCode + ";}";
+
+        body = body.replaceAll( "\\.\\.", "." );
+
+        // System.out.println("Setter Body: ===================================\n" + body);
+
+        valueSetter.setBody( body );
+        newClass.addMethod( valueSetter );
+
+        return body;
+    }
+
+    /**
+     * Fail safe getter creation when normal compilation fails.
+     *
+     * @param clazz The javassist class the new method should be attached to.
+     * @param valueGetter The method definition the generated code will be contained within.
+     * @param node The root expression node.
+     * @return The generated source string for this method, the method will still be added via the javassist API either
+     *         way so this is really a convenience for exception reporting / debugging.
+     * @throws Exception If a javassist error occurs.
+     */
+    protected String generateOgnlGetter( CtClass clazz, CtMethod valueGetter, CtField node )
+        throws Exception
+    {
+        String body = "return " + node.getName() + ".getValue($1, $2);";
+
+        valueGetter.setBody( body );
+        clazz.addMethod( valueGetter );
+
+        return body;
+    }
+
+    /**
+     * Fail safe setter creation when normal compilation fails.
+     *
+     * @param clazz The javassist class the new method should be attached to.
+     * @param valueSetter The method definition the generated code will be contained within.
+     * @param node The root expression node.
+     * @return The generated source string for this method, the method will still be added via the javassist API either
+     *         way so this is really a convenience for exception reporting / debugging.
+     * @throws Exception If a javassist error occurs.
+     */
+    protected String generateOgnlSetter( CtClass clazz, CtMethod valueSetter, CtField node )
+        throws Exception
+    {
+        String body = node.getName() + ".setValue($1, $2, $3);";
+
+        valueSetter.setBody( body );
+        clazz.addMethod( valueSetter );
+
+        return body;
+    }
+
+    /**
+     * Creates a {@link ClassLoader} instance compatible with the javassist classloader and normal OGNL class resolving
+     * semantics.
+     *
+     * @param context The current execution context.
+     * @return The created {@link ClassLoader} instance.
+     */
+    protected EnhancedClassLoader getClassLoader( OgnlContext context )
+    {
+        EnhancedClassLoader ret = loaders.get( context.getClassResolver() );
+
+        if ( ret != null )
+        {
+            return ret;
+        }
+
+        ClassLoader classLoader = new ContextClassLoader( OgnlContext.class.getClassLoader(), context );
+
+        ret = new EnhancedClassLoader( classLoader );
+        loaders.put( context.getClassResolver(), ret );
+
+        return ret;
+    }
+
+    /**
+     * Loads a new class definition via javassist for the specified class.
+     *
+     * @param searchClass The class to load.
+     * @return The javassist class equivalent.
+     * @throws javassist.NotFoundException When the class definition can't be found.
+     */
+    protected CtClass getCtClass( Class<?> searchClass )
+        throws NotFoundException
+    {
+        return pool.get( searchClass.getName() );
+    }
+
+    /**
+     * Gets either a new or existing {@link ClassPool} for use in compiling javassist classes. A new class path object
+     * is inserted in to the returned {@link ClassPool} using the passed in <code>loader</code> instance if a new pool
+     * needs to be created.
+     *
+     * @param context The current execution context.
+     * @param loader The {@link ClassLoader} instance to use - as returned by
+     *            {@link #getClassLoader(org.apache.commons.ognl.OgnlContext)}.
+     * @return The existing or new {@link ClassPool} instance.
+     */
+    protected ClassPool getClassPool( OgnlContext context, EnhancedClassLoader loader )
+    {
+        if ( pool != null )
+        {
+            return pool;
+        }
+
+        pool = ClassPool.getDefault();
+        pool.insertClassPath( new LoaderClassPath( loader.getParent() ) );
+
+        return pool;
+    }
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/LocalReference.java b/src/main/java/org/apache/commons/ognl/enhance/LocalReference.java
index 57a9be3..a9c18cd 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/LocalReference.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/LocalReference.java
@@ -1,48 +1,48 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-/**
- * Container class for {@link OgnlExpressionCompiler} generated local method block references.
- */
-public interface LocalReference
-{
-
-    /**
-     * The name of the assigned variable reference.
-     *
-     * @return The name of the reference as it will be when compiled.
-     */
-    String getName();
-
-    /**
-     * The expression that sets the value, ie the part after <code><class type> refName = <expression></code>.
-     *
-     * @return The setting expression.
-     */
-    String getExpression();
-
-    /**
-     * The type of reference.
-     *
-     * @return The type.
-     */
-    Class<?> getType();
-}
+/*
+ * 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.commons.ognl.enhance;
+
+/**
+ * Container class for {@link OgnlExpressionCompiler} generated local method block references.
+ */
+public interface LocalReference
+{
+
+    /**
+     * The name of the assigned variable reference.
+     *
+     * @return The name of the reference as it will be when compiled.
+     */
+    String getName();
+
+    /**
+     * The expression that sets the value, ie the part after <code><class type> refName = <expression></code>.
+     *
+     * @return The setting expression.
+     */
+    String getExpression();
+
+    /**
+     * The type of reference.
+     *
+     * @return The type.
+     */
+    Class<?> getType();
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/LocalReferenceImpl.java b/src/main/java/org/apache/commons/ognl/enhance/LocalReferenceImpl.java
index 0ebddd3..cb078bb 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/LocalReferenceImpl.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/LocalReferenceImpl.java
@@ -1,121 +1,121 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-/**
- * Implementation of {@link LocalReference}.
- */
-public class LocalReferenceImpl
-    implements LocalReference
-{
-
-    private final String name;
-
-    private final Class<?> type;
-
-    private final String expression;
-
-    public LocalReferenceImpl( String name, String expression, Class<?> type )
-    {
-        this.name = name;
-        this.type = type;
-        this.expression = expression;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName()
-    {
-        return name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getExpression()
-    {
-        return expression;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Class<?> getType()
-    {
-        return type;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object o )
-    {
-        if ( this == o )
-        {
-            return true;
-        }
-        if ( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        LocalReferenceImpl that = (LocalReferenceImpl) o;
-
-        if ( expression != null ? !expression.equals( that.expression ) : that.expression != null )
-        {
-            return false;
-        }
-        if ( name != null ? !name.equals( that.name ) : that.name != null )
-        {
-            return false;
-        }
-        if ( type != null ? !type.equals( that.type ) : that.type != null )
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode()
-    {
-        int result;
-        result = ( name != null ? name.hashCode() : 0 );
-        result = 31 * result + ( type != null ? type.hashCode() : 0 );
-        result = 31 * result + ( expression != null ? expression.hashCode() : 0 );
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString()
-    {
-        return "LocalReferenceImpl[" + "_name='" + name + '\'' + '\n' + ", _type=" + type + '\n' + ", _expression='"
-            + expression + '\'' + '\n' + ']';
-    }
-}
+/*
+ * 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.commons.ognl.enhance;
+
+/**
+ * Implementation of {@link LocalReference}.
+ */
+public class LocalReferenceImpl
+    implements LocalReference
+{
+
+    private final String name;
+
+    private final Class<?> type;
+
+    private final String expression;
+
+    public LocalReferenceImpl( String name, String expression, Class<?> type )
+    {
+        this.name = name;
+        this.type = type;
+        this.expression = expression;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getExpression()
+    {
+        return expression;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<?> getType()
+    {
+        return type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        LocalReferenceImpl that = (LocalReferenceImpl) o;
+
+        if ( expression != null ? !expression.equals( that.expression ) : that.expression != null )
+        {
+            return false;
+        }
+        if ( name != null ? !name.equals( that.name ) : that.name != null )
+        {
+            return false;
+        }
+        if ( type != null ? !type.equals( that.type ) : that.type != null )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode()
+    {
+        int result;
+        result = ( name != null ? name.hashCode() : 0 );
+        result = 31 * result + ( type != null ? type.hashCode() : 0 );
+        result = 31 * result + ( expression != null ? expression.hashCode() : 0 );
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString()
+    {
+        return "LocalReferenceImpl[" + "_name='" + name + '\'' + '\n' + ", _type=" + type + '\n' + ", _expression='"
+            + expression + '\'' + '\n' + ']';
+    }
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/OgnlExpressionCompiler.java b/src/main/java/org/apache/commons/ognl/enhance/OgnlExpressionCompiler.java
index 3ef9255..55b1421 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/OgnlExpressionCompiler.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/OgnlExpressionCompiler.java
@@ -1,125 +1,125 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-import org.apache.commons.ognl.Node;
-import org.apache.commons.ognl.OgnlContext;
-
-import java.lang.reflect.Method;
-
-/**
- * Core interface implemented by expression compiler instances.
- */
-public interface OgnlExpressionCompiler
-{
-
-    /** Static constant used in conjunction with {@link OgnlContext} to store temporary references. */
-    String ROOT_TYPE = "-ognl-root-type";
-
-    /**
-     * The core method executed to compile a specific expression. It is expected that this expression always return a
-     * {@link Node} with a non null {@link org.apache.commons.ognl.Node#getAccessor()} instance - unless an exception is
-     * thrown by the method or the statement wasn't compilable in this instance because of missing/null objects in the
-     * expression. These instances may in some cases continue to call this compilation method until the expression is
-     * resolvable.
-     *
-     * @param context The context of execution.
-     * @param expression The pre-parsed root expression node to compile.
-     * @param root The root object for the expression - may be null in many instances so some implementations may exit
-     * @throws Exception If an error occurs compiling the expression and no strategy has been implemented to handle
-     *             incremental expression compilation for incomplete expression members.
-     */
-    void compileExpression( OgnlContext context, Node expression, Object root )
-        throws Exception;
-
-    /**
-     * Gets a javassist safe class string for the given class instance. This is especially useful for handling array vs.
-     * normal class casting strings.
-     *
-     * @param clazz The class to get a string equivalent javassist compatible string reference for.
-     * @return The string equivalent of the class.
-     */
-    String getClassName( Class<?> clazz );
-
-    /**
-     * Used in places where the preferred {@link #getSuperOrInterfaceClass(java.lang.reflect.Method, Class)} isn't
-     * possible because the method isn't known for a class. Attempts to upcast the given class to the next available
-     * non-private accessible class so that compiled expressions can reference the interface class of an instance so as
-     * not to be compiled in to overly specific statements.
-     *
-     * @param clazz The class to attempt to find a compatible interface for.
-     * @return The same class if no higher level interface could be matched against or the interface equivalent class.
-     */
-    Class<?> getInterfaceClass( Class<?> clazz );
-
-    /**
-     * For the given {@link Method} and class finds the highest level interface class this combination can be cast to.
-     *
-     * @param m The method the class must implement.
-     * @param clazz The current class being worked with.
-     * @return The highest level interface / class that the referenced {@link Method} is declared in.
-     */
-    Class<?> getSuperOrInterfaceClass( Method m, Class<?> clazz );
-
-    /**
-     * For a given root object type returns the base class type to be used in root referenced expressions. This helps in
-     * some instances where the root objects themselves are compiled javassist instances that need more generic class
-     * equivalents to cast to.
-     *
-     * @param rootNode The root expression node.
-     * @param context The current execution context.
-     * @return The root expression class type to cast to for this node.
-     */
-    Class<?> getRootExpressionClass( Node rootNode, OgnlContext context );
-
-    /**
-     * Used primarily by AST types like {@link org.apache.commons.ognl.ASTChain} where <code>foo.bar.id</code> type
-     * references may need to be cast multiple times in order to properly resolve the members in a compiled statement.
-     * <p>
-     * This method should be using the various {@link org.apache.commons.ognl.OgnlContext#getCurrentType()} /
-     * {@link org.apache.commons.ognl.OgnlContext#getCurrentAccessor()} methods to inspect the type stack and properly
-     * cast to the right classes - but only when necessary.
-     * </p>
-     *
-     * @param context The current execution context.
-     * @param expression The node being checked for casting.
-     * @param body The java source string generated by the given node.
-     * @return The body string parameter plus any additional casting syntax needed to make the expression resolvable.
-     */
-    String castExpression( OgnlContext context, Node expression, String body );
-
-    /**
-     * Method is used for expressions where multiple inner parameter method calls in generated java source strings cause
-     * javassit failures. It is hacky and cumbersome to have to generate expressions this way but it's the only current
-     * known way to make javassist happy.
-     * <p>
-     * Takes an expression block generated by a node and creates a new method on the base object being compiled so that
-     * sufficiently complicated sub expression blocks can be broken out in to distinct methods to be referenced by the
-     * core accessor / setter methods in the base compiled root object.
-     * </p>
-     *
-     * @param context The current execution context.
-     * @param expression The java source expression to dump in to a seperate method reference.
-     * @param type The return type that should be specified for the new method.
-     * @return The method name that will be used to reference the sub expression in place of the actual sub expression
-     *         itself.
-     */
-    String createLocalReference( OgnlContext context, String expression, Class<?> type );
-}
+/*
+ * 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.commons.ognl.enhance;
+
+import org.apache.commons.ognl.Node;
+import org.apache.commons.ognl.OgnlContext;
+
+import java.lang.reflect.Method;
+
+/**
+ * Core interface implemented by expression compiler instances.
+ */
+public interface OgnlExpressionCompiler
+{
+
+    /** Static constant used in conjunction with {@link OgnlContext} to store temporary references. */
+    String ROOT_TYPE = "-ognl-root-type";
+
+    /**
+     * The core method executed to compile a specific expression. It is expected that this expression always return a
+     * {@link Node} with a non null {@link org.apache.commons.ognl.Node#getAccessor()} instance - unless an exception is
+     * thrown by the method or the statement wasn't compilable in this instance because of missing/null objects in the
+     * expression. These instances may in some cases continue to call this compilation method until the expression is
+     * resolvable.
+     *
+     * @param context The context of execution.
+     * @param expression The pre-parsed root expression node to compile.
+     * @param root The root object for the expression - may be null in many instances so some implementations may exit
+     * @throws Exception If an error occurs compiling the expression and no strategy has been implemented to handle
+     *             incremental expression compilation for incomplete expression members.
+     */
+    void compileExpression( OgnlContext context, Node expression, Object root )
+        throws Exception;
+
+    /**
+     * Gets a javassist safe class string for the given class instance. This is especially useful for handling array vs.
+     * normal class casting strings.
+     *
+     * @param clazz The class to get a string equivalent javassist compatible string reference for.
+     * @return The string equivalent of the class.
+     */
+    String getClassName( Class<?> clazz );
+
+    /**
+     * Used in places where the preferred {@link #getSuperOrInterfaceClass(java.lang.reflect.Method, Class)} isn't
+     * possible because the method isn't known for a class. Attempts to upcast the given class to the next available
+     * non-private accessible class so that compiled expressions can reference the interface class of an instance so as
+     * not to be compiled in to overly specific statements.
+     *
+     * @param clazz The class to attempt to find a compatible interface for.
+     * @return The same class if no higher level interface could be matched against or the interface equivalent class.
+     */
+    Class<?> getInterfaceClass( Class<?> clazz );
+
+    /**
+     * For the given {@link Method} and class finds the highest level interface class this combination can be cast to.
+     *
+     * @param m The method the class must implement.
+     * @param clazz The current class being worked with.
+     * @return The highest level interface / class that the referenced {@link Method} is declared in.
+     */
+    Class<?> getSuperOrInterfaceClass( Method m, Class<?> clazz );
+
+    /**
+     * For a given root object type returns the base class type to be used in root referenced expressions. This helps in
+     * some instances where the root objects themselves are compiled javassist instances that need more generic class
+     * equivalents to cast to.
+     *
+     * @param rootNode The root expression node.
+     * @param context The current execution context.
+     * @return The root expression class type to cast to for this node.
+     */
+    Class<?> getRootExpressionClass( Node rootNode, OgnlContext context );
+
+    /**
+     * Used primarily by AST types like {@link org.apache.commons.ognl.ASTChain} where <code>foo.bar.id</code> type
+     * references may need to be cast multiple times in order to properly resolve the members in a compiled statement.
+     * <p>
+     * This method should be using the various {@link org.apache.commons.ognl.OgnlContext#getCurrentType()} /
+     * {@link org.apache.commons.ognl.OgnlContext#getCurrentAccessor()} methods to inspect the type stack and properly
+     * cast to the right classes - but only when necessary.
+     * </p>
+     *
+     * @param context The current execution context.
+     * @param expression The node being checked for casting.
+     * @param body The java source string generated by the given node.
+     * @return The body string parameter plus any additional casting syntax needed to make the expression resolvable.
+     */
+    String castExpression( OgnlContext context, Node expression, String body );
+
+    /**
+     * Method is used for expressions where multiple inner parameter method calls in generated java source strings cause
+     * javassit failures. It is hacky and cumbersome to have to generate expressions this way but it's the only current
+     * known way to make javassist happy.
+     * <p>
+     * Takes an expression block generated by a node and creates a new method on the base object being compiled so that
+     * sufficiently complicated sub expression blocks can be broken out in to distinct methods to be referenced by the
+     * core accessor / setter methods in the base compiled root object.
+     * </p>
+     *
+     * @param context The current execution context.
+     * @param expression The java source expression to dump in to a seperate method reference.
+     * @param type The return type that should be specified for the new method.
+     * @return The method name that will be used to reference the sub expression in place of the actual sub expression
+     *         itself.
+     */
+    String createLocalReference( OgnlContext context, String expression, Class<?> type );
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/OrderedReturn.java b/src/main/java/org/apache/commons/ognl/enhance/OrderedReturn.java
index 70ee790..56b91ad 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/OrderedReturn.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/OrderedReturn.java
@@ -1,44 +1,43 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-
-/**
- * Marks an ognl expression {@link org.apache.commons.ognl.Node} as needing to have the return portion of a getter
- * method happen in a specific
- * part of the generated expression vs just having the whole expression returned in one chunk.
- */
-public interface OrderedReturn
-{
-
-    /**
-     * Get the core expression to execute first before any return foo logic is started.
-     *
-     * @return The core standalone expression that shouldn't be pre-pended with a return keyword.
-     */
-    String getCoreExpression();
-
-    /**
-     * Gets the last expression to be pre-pended with a return &lt;expression&gt; block.
-     *
-     * @return The expression representing the return portion of a statement;
-     */
-    String getLastExpression();
-}
+/*
+ * 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.commons.ognl.enhance;
+
+/**
+ * Marks an ognl expression {@link org.apache.commons.ognl.Node} as needing to have the return portion of a getter
+ * method happen in a specific
+ * part of the generated expression vs just having the whole expression returned in one chunk.
+ */
+public interface OrderedReturn
+{
+
+    /**
+     * Get the core expression to execute first before any return foo logic is started.
+     *
+     * @return The core standalone expression that shouldn't be pre-pended with a return keyword.
+     */
+    String getCoreExpression();
+
+    /**
+     * Gets the last expression to be pre-pended with a return &lt;expression&gt; block.
+     *
+     * @return The expression representing the return portion of a statement;
+     */
+    String getLastExpression();
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/UnsupportedCompilationException.java b/src/main/java/org/apache/commons/ognl/enhance/UnsupportedCompilationException.java
index 24f9a72..9639799 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/UnsupportedCompilationException.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/UnsupportedCompilationException.java
@@ -1,48 +1,48 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-/**
- * Thrown during bytecode enhancement conversions of ognl expressions to indicate that a certain expression isn't
- * currently supported as a pure java bytecode enhanced version.
- * <p>
- * If this exception is thrown it is expected that ognl will fall back to default ognl evaluation of the expression.
- * </p>
- */
-public class UnsupportedCompilationException
-    extends RuntimeException
-{
-
-    /**
-     *
-     */
-    private static final long serialVersionUID = 4961625077128174947L;
-
-    public UnsupportedCompilationException( String message )
-    {
-        super( message );
-    }
-
-    public UnsupportedCompilationException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-
-}
+/*
+ * 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.commons.ognl.enhance;
+
+/**
+ * Thrown during bytecode enhancement conversions of ognl expressions to indicate that a certain expression isn't
+ * currently supported as a pure java bytecode enhanced version.
+ * <p>
+ * If this exception is thrown it is expected that ognl will fall back to default ognl evaluation of the expression.
+ * </p>
+ */
+public class UnsupportedCompilationException
+    extends RuntimeException
+{
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 4961625077128174947L;
+
+    public UnsupportedCompilationException( String message )
+    {
+        super( message );
+    }
+
+    public UnsupportedCompilationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/ognl/enhance/package-info.java b/src/main/java/org/apache/commons/ognl/enhance/package-info.java
index e96f047..b3b6099 100644
--- a/src/main/java/org/apache/commons/ognl/enhance/package-info.java
+++ b/src/main/java/org/apache/commons/ognl/enhance/package-info.java
@@ -1,24 +1,24 @@
-package org.apache.commons.ognl.enhance;
-
-/*
- * 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.
- */
-
-/*
- * Enhanced basic Java components.
- */
+/*
+ * 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.commons.ognl.enhance;
+
+/*
+ * Enhanced basic Java components.
+ */