Author: henning
Date: Sun Nov 19 17:14:22 2006
New Revision: 477003

URL: http://svn.apache.org/viewvc?view=rev&rev=477003
Log:
Rewriting the reflection logic in ClassMap should not only make it much
easier to understand but it should also work when running under a 
SecurityManager, thus fixing VELTOOLS-66.

This sort of a algorithm change; the code still passes all the unit
tests (and yes, I did break them a few times) but it definitely wants
testing. 

Modified:
    
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ClassMap.java
    
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/Introspector.java
    
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
    
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java

Modified: 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ClassMap.java
URL: 
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ClassMap.java?view=diff&rev=477003&r1=477002&r2=477003
==============================================================================
--- 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ClassMap.java
 (original)
+++ 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ClassMap.java
 Sun Nov 19 17:14:22 2006
@@ -21,9 +21,14 @@
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
+import org.apache.velocity.runtime.log.Log;
+
 /**
  * A cache of introspection information for a specific class instance.
  * Keys [EMAIL PROTECTED] java.lang.reflect.Method} objects by a concatenation 
of the
@@ -33,501 +38,336 @@
  * @author <a href="mailto:[EMAIL PROTECTED]">Bob McWhirter</a>
  * @author <a href="mailto:[EMAIL PROTECTED]">Attila Szegedi</a>
  * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
  * @version $Id$
  */
 public class ClassMap
 {
-    private static final class CacheMiss { }
-    private static final CacheMiss CACHE_MISS = new CacheMiss();
-    private static final Object OBJECT = new Object();
+    /** Set true if you want to debug the reflection code */
+    private static final boolean debugReflection = false;
 
+    /** Class logger */
+    private final Log log;
+    
     /**
      * Class passed into the constructor used to as
      * the basis for the Method map.
      */
+    private final Class clazz;
 
-    private Class clazz;
-
-    /**
-     * Cache of Methods, or CACHE_MISS, keyed by method
-     * name and actual arguments used to find it.
-     */
-    private Map methodCache = new Hashtable();
-
-    private MethodMap methodMap = new MethodMap();
+    private final MethodCache methodCache;
 
     /**
      * Standard constructor
-     * @param clazz
+     * @param clazz The class for which this ClassMap gets constructed.
      */
-    public ClassMap( Class clazz)
+    public ClassMap(final Class clazz, final Log log)
     {
         this.clazz = clazz;
+        this.log = log;
+        
+        if (debugReflection && log.isDebugEnabled())
+        {
+            
log.debug("=================================================================");
+            log.debug("== Class: " + clazz);
+        }
+        
+        methodCache = new MethodCache(log);
+        
         populateMethodCache();
-    }
 
-    private ClassMap()
-    {
+        if (debugReflection && log.isDebugEnabled())
+        {
+            
log.debug("=================================================================");
+        }
     }
 
     /**
-     * @return the class object whose methods are cached by this map.
+     * Returns the class object whose methods are cached by this map.
+     *
+     * @return The class object whose methods are cached by this map.
      */
-     Class getCachedClass()
-     {
-         return clazz;
-     }
+    public Class getCachedClass()
+    {
+        return clazz;
+    }
 
     /**
-     * Find a Method using the methodKey
-     * provided.
-     *
-     * Look in the methodMap for an entry.  If found,
-     * it'll either be a CACHE_MISS, in which case we
-     * simply give up, or it'll be a Method, in which
-     * case, we return it.
+     * Find a Method using the method name and parameter objects.
      *
-     * If nothing is found, then we must actually go
-     * and introspect the method from the MethodMap.
-     * @param name
-     * @param params
-     * @return Method object.
-     * @throws MethodMap.AmbiguousException
+     * @param name The method name to look up.
+     * @param params An array of parameters for the method.
+     * @return A Method object representing the method to invoke or null.
+     * @throws MethodMap.AmbiguousException When more than one method is a 
match for the parameters.
      */
-    public Method findMethod(String name, Object[] params)
-        throws MethodMap.AmbiguousException
+    public Method findMethod(final String name, final Object[] params)
+            throws MethodMap.AmbiguousException
     {
-        String methodKey = makeMethodKey(name, params);
-        Object cacheEntry = methodCache.get( methodKey );
-
-        if (cacheEntry == CACHE_MISS)
-        {
-            return null;
-        }
-
-        if (cacheEntry == null)
-        {
-            try
-            {
-                cacheEntry = methodMap.find( name,
-                                             params );
-            }
-            catch( MethodMap.AmbiguousException ae )
-            {
-                /*
-                 *  that's a miss :)
-                 */
-
-                methodCache.put( methodKey,
-                                 CACHE_MISS );
-
-                throw ae;
-            }
-
-            if ( cacheEntry == null )
-            {
-                methodCache.put( methodKey,
-                                 CACHE_MISS );
-            }
-            else
-            {
-                methodCache.put( methodKey,
-                                 cacheEntry );
-            }
-        }
-
-        // Yes, this might just be null.
-
-        return (Method) cacheEntry;
+        return methodCache.get(name, params);
     }
 
     /**
      * Populate the Map of direct hits. These
      * are taken from all the public methods
-     * that our class provides.
+     * that our class, its parents and their implemented interfaces provide.
      */
     private void populateMethodCache()
     {
-        /*
-         *  get all publicly accessible methods
-         */
-
-        Method[] methods = getAccessibleMethods(clazz);
-
-        /*
-         * map and cache them
-         */
-
-        for (int i = 0; i < methods.length; i++)
+       //
+       // Build a list of all elements in the class hierarchy. This one is 
bottom-first (i.e. we start
+       // with the actual declaring class and its interfaces and then move up 
(superclass etc.) until we
+       // hit java.lang.Object. That is important because it will give us the 
methods of the declaring class
+       // which might in turn be abstract further up the tree.
+       //
+       // We also ignore all SecurityExceptions that might happen due to 
SecurityManager restrictions (prominently 
+       // hit with Tomcat 5.5).
+       //
+       // We can also omit all that complicated getPublic, getAccessible and 
upcast logic that the class map had up
+       // until Velocity 1.4. As we always reflect all elements of the tree 
(that's what we have a cache for), we will
+       // hit the public elements sooner or later because we reflect all the 
public elements anyway.
+       //
+        List classesToReflect = new ArrayList();
+        
+        // Ah, the miracles of Java for(;;) ... 
+        for (Class classToReflect = getCachedClass(); classToReflect != null ; 
classToReflect = classToReflect.getSuperclass())
         {
-            Method method = methods[i];
-
-            /*
-             *  now get the 'public method', the method declared by a
-             *  public interface or class. (because the actual implementing
-             *  class may be a facade...
-             */
-
-            Method publicMethod = getPublicMethod( method );
-
-            /*
-             *  it is entirely possible that there is no public method for
-             *  the methods of this class (i.e. in the facade, a method
-             *  that isn't on any of the interfaces or superclass
-             *  in which case, ignore it.  Otherwise, map and cache
-             */
-
-            if ( publicMethod != null)
+            if (Modifier.isPublic(classToReflect.getModifiers()))
+            {
+                classesToReflect.add(classToReflect);
+                if (debugReflection && log.isDebugEnabled())
+                {
+                    log.debug("Adding " + classToReflect + " for reflection");
+                }
+            }
+            Class [] interfaces = classToReflect.getInterfaces();
+            for (int i = 0; i < interfaces.length; i++)
             {
-                methodMap.add( publicMethod );
-                methodCache.put(  makeMethodKey( publicMethod), publicMethod);
+                if (Modifier.isPublic(interfaces[i].getModifiers()))
+                {
+                    classesToReflect.add(interfaces[i]);
+                    if (debugReflection && log.isDebugEnabled())
+                    {
+                        log.debug("Adding " + interfaces[i] + " for 
reflection");
+                    }
+                }
             }
         }
-    }
-
-    /**
-     * Make a methodKey for the given method using
-     * the concatenation of the name and the
-     * types of the method parameters.
-     * 
-     * @param method to be stored as key
-     * @return key for ClassMap
-     */
-    private String makeMethodKey(Method method)
-    {
-        Class[] parameterTypes = method.getParameterTypes();
-
-        StringBuffer methodKey = new StringBuffer(method.getName());
 
-        for (int j = 0; j < parameterTypes.length; j++)
+        for (Iterator it = classesToReflect.iterator(); it.hasNext(); )
         {
-            /*
-             * If the argument type is primitive then we want
-             * to convert our primitive type signature to the
-             * corresponding Object type so introspection for
-             * methods with primitive types will work correctly.
-             */
-            if (parameterTypes[j].isPrimitive())
+            Class classToReflect = (Class) it.next();
+            if (debugReflection && log.isDebugEnabled())
             {
-                if (parameterTypes[j].equals(Boolean.TYPE))
-                    methodKey.append("java.lang.Boolean");
-                else if (parameterTypes[j].equals(Byte.TYPE))
-                    methodKey.append("java.lang.Byte");
-                else if (parameterTypes[j].equals(Character.TYPE))
-                    methodKey.append("java.lang.Character");
-                else if (parameterTypes[j].equals(Double.TYPE))
-                    methodKey.append("java.lang.Double");
-                else if (parameterTypes[j].equals(Float.TYPE))
-                    methodKey.append("java.lang.Float");
-                else if (parameterTypes[j].equals(Integer.TYPE))
-                    methodKey.append("java.lang.Integer");
-                else if (parameterTypes[j].equals(Long.TYPE))
-                    methodKey.append("java.lang.Long");
-                else if (parameterTypes[j].equals(Short.TYPE))
-                    methodKey.append("java.lang.Short");
+                log.debug("Reflecting " + classToReflect);
             }
-            else
-            {
-                methodKey.append(parameterTypes[j].getName());
-            }
-        }
+            
 
-        return methodKey.toString();
-    }
-
-    private static String makeMethodKey(String method, Object[] params)
-    {
-        StringBuffer methodKey = new StringBuffer().append(method);
-
-        for (int j = 0; j < params.length; j++)
-        {
-            Object arg = params[j];
+            try
+            {
+                Method[] methods = classToReflect.getMethods();
 
-            if (arg == null)
+                for (int i = 0; i < methods.length; i++)
+                {
+                    // Strictly spoken that check shouldn't be necessary
+                    // because getMethods only returns public methods.
+                    int modifiers = methods[i].getModifiers();
+                    if (Modifier.isPublic(modifiers)) //  && !)
+                   {
+                        // Some of the interfaces contain abstract methods. 
That is fine, because the actual object must 
+                        // implement them anyway (else it wouldn't be 
implementing the interface). If we find an abstract
+                        // method in a non-interface, we skip it, because we 
do want to make sure that no abstract methods end up in
+                        // the cache.                       
+                        if (classToReflect.isInterface() || 
!Modifier.isAbstract(modifiers))
+                        {
+                            methodCache.put(methods[i]);
+                        }
+                    }
+                }
+            }
+            catch (SecurityException se) // Everybody feels better with...
             {
-                arg = OBJECT;
+               if (log.isDebugEnabled())
+               {
+                   log.debug("While accessing methods of " + classToReflect + 
": ", se);
+               }
             }
-
-            methodKey.append(arg.getClass().getName());
         }
-
-        return methodKey.toString();
     }
 
     /**
-     * Retrieves public methods for a class. In case the class is not
-     * public, retrieves methods with same signature as its public methods
-     * from public superclasses and interfaces (if they exist). Basically
-     * upcasts every method to the nearest acccessible method.
+     * This is the cache to store and look up the method information. 
      * 
-     * @param clazz class to check methods
-     * @return array of all public methods
+     * @author <a href="mailto:[EMAIL PROTECTED]">Henning P. Schmiedehausen</a>
+     * @version $Id$
      */
-    private static Method[] getAccessibleMethods(Class clazz)
+    private static final class MethodCache
     {
-        Method[] methods = clazz.getMethods();
+        private static final class CacheMiss { }
+        
+        private static final CacheMiss CACHE_MISS = new CacheMiss();
 
-        /*
-         *  Short circuit for the (hopefully) majority of cases where the
-         *  clazz is public
-         */
+        private static final Object OBJECT = new Object();
+
+        private static final Map convertPrimitives = new HashMap();
 
-        if (Modifier.isPublic(clazz.getModifiers()))
+        static
         {
-            return methods;
+            convertPrimitives.put(Boolean.TYPE,   Boolean.class.getName());
+            convertPrimitives.put(Byte.TYPE,      Byte.class.getName());
+            convertPrimitives.put(Character.TYPE, Character.class.getName());
+            convertPrimitives.put(Double.TYPE,    Double.class.getName());
+            convertPrimitives.put(Float.TYPE,     Float.class.getName());
+            convertPrimitives.put(Integer.TYPE,   Integer.class.getName());
+            convertPrimitives.put(Long.TYPE,      Long.class.getName());
+            convertPrimitives.put(Short.TYPE,     Short.class.getName());
         }
 
-        /*
-         *  No luck - the class is not public, so we're going the longer way.
+       /** Class logger */
+       private final Log log;
+
+        /**
+         * Cache of Methods, or CACHE_MISS, keyed by method
+         * name and actual arguments used to find it.
          */
+        private final Map cache = new HashMap();
 
-        MethodInfo[] methodInfos = new MethodInfo[methods.length];
+        /** Map of methods that are searchable according to method parameters 
to find a match */
+        private final MethodMap methodMap = new MethodMap();
 
-        for(int i = methods.length; i-- > 0; )
+        private MethodCache(Log log)
         {
-            methodInfos[i] = new MethodInfo(methods[i]);
+            this.log = log;
         }
 
-        int upcastCount = getAccessibleMethods(clazz, methodInfos, 0);
-
-        /*
-         *  Reallocate array in case some method had no accessible counterpart.
+        /**
+         * Find a Method using the method name and parameter objects.
+         *
+         * Look in the methodMap for an entry.  If found,
+         * it'll either be a CACHE_MISS, in which case we
+         * simply give up, or it'll be a Method, in which
+         * case, we return it.
+         *
+         * If nothing is found, then we must actually go
+         * and introspect the method from the MethodMap.
+         *
+         * @param name The method name to look up.
+         * @param params An array of parameters for the method.
+         * @return A Method object representing the method to invoke or null.
+         * @throws MethodMap.AmbiguousException When more than one method is a 
match for the parameters.
          */
-
-        if(upcastCount < methods.length)
+        public synchronized Method get(final String name, final Object [] 
params)
+                throws MethodMap.AmbiguousException
         {
-            methods = new Method[upcastCount];
-        }
+            String methodKey = makeMethodKey(name, params);
 
-        int j = 0;
-        for(int i = 0; i < methodInfos.length; ++i)
-        {
-            MethodInfo methodInfo = methodInfos[i];
-            if(methodInfo.upcast)
+            Object cacheEntry = cache.get(methodKey);
+
+            // We looked this up before and failed. 
+            if (cacheEntry == CACHE_MISS)
             {
-                methods[j++] = methodInfo.method;
+                return null;
             }
-        }
-        return methods;
-    }
-
-    /**
-     *  Recursively finds a match for each method, starting with the class, 
and then
-     *  searching the superclass and interfaces.
-     *
-     *  @param clazz Class to check
-     *  @param methodInfos array of methods we are searching to match
-     *  @param upcastCount current number of methods we have matched
-     *  @return count of matched methods
-     */
-    private static int getAccessibleMethods( Class clazz, MethodInfo[] 
methodInfos, int upcastCount)
-    {
-        int l = methodInfos.length;
-
-        /*
-         *  if this class is public, then check each of the currently
-         *  'non-upcasted' methods to see if we have a match
-         */
 
-        if( Modifier.isPublic(clazz.getModifiers()) )
-        {
-            for(int i = 0; i < l && upcastCount < l; ++i)
+            if (cacheEntry == null)
             {
                 try
                 {
-                    MethodInfo methodInfo = methodInfos[i];
-
-                    if(!methodInfo.upcast)
-                    {
-                        methodInfo.tryUpcasting(clazz);
-                        upcastCount++;
-                    }
+                    // That one is expensive...
+                    cacheEntry = methodMap.find(name, params);
                 }
-                catch(NoSuchMethodException e)
+                catch(MethodMap.AmbiguousException ae)
                 {
                     /*
-                     *  Intentionally ignored - it means
-                     *  it wasn't found in the current class
+                     *  that's a miss :-)
                      */
+                    cache.put(methodKey, CACHE_MISS);
+                    throw ae;
                 }
-            }
 
-            /*
-             *  Short circuit if all methods were upcast
-             */
-
-            if(upcastCount == l)
-            {
-                return upcastCount;
+                cache.put(methodKey, 
+                        (cacheEntry != null) ? cacheEntry : CACHE_MISS);
             }
-        }
-
-        /*
-         *   Examine superclass
-         */
 
-        Class superclazz = clazz.getSuperclass();
+            // Yes, this might just be null.
 
-        if(superclazz != null)
-        {
-            upcastCount = getAccessibleMethods(superclazz , methodInfos, 
upcastCount);
-
-            /*
-             *  Short circuit if all methods were upcast
-             */
-
-            if(upcastCount == l)
-            {
-                return upcastCount;
-            }
+            return (Method) cacheEntry;
         }
 
-        /*
-         *  Examine interfaces. Note we do it even if superclazz == null.
-         *  This is redundant as currently java.lang.Object does not implement
-         *  any interfaces, however nothing guarantees it will not in future.
-         */
-
-        Class[] interfaces = clazz.getInterfaces();
-
-        for(int i = interfaces.length; i-- > 0; )
+        public synchronized void put(Method method)
         {
-            upcastCount = getAccessibleMethods(interfaces[i], methodInfos, 
upcastCount);
-
-            /*
-             *  Short circuit if all methods were upcast
-             */
-
-            if(upcastCount == l)
+            String methodKey = makeMethodKey(method);
+            
+            // We don't overwrite methods. Especially not if we fill the
+            // cache from defined class towards java.lang.Object because 
+            // abstract methods in superclasses would else overwrite concrete
+            // classes further down the hierarchy.
+            if (cache.get(methodKey) == null)
             {
-                return upcastCount;
+               cache.put(methodKey, method);
+               methodMap.add(method);
+               if (debugReflection && log.isDebugEnabled())
+               {
+                   log.debug("Adding " + method);
+               }
             }
         }
 
-        return upcastCount;
-    }
-
-    /**
-     *  For a given method, retrieves its publicly accessible counterpart.
-     *  This method will look for a method with same name
-     *  and signature declared in a public superclass or implemented interface 
of this
-     *  method's declaring class. This counterpart method is publicly callable.
-     *
-     *  @param method a method whose publicly callable counterpart is 
requested.
-     *  @return the publicly callable counterpart method. Note that if the 
parameter
-     *  method is itself declared by a public class, this method is an identity
-     *  function.
-     */
-    public static Method getPublicMethod(Method method)
-    {
-        Class clazz = method.getDeclaringClass();
-
-        /*
-         *   Short circuit for (hopefully the majority of) cases where the 
declaring
-         *   class is public.
+        /**
+         * Make a methodKey for the given method using
+         * the concatenation of the name and the
+         * types of the method parameters.
+         * 
+         * @param method to be stored as key
+         * @return key for ClassMap
          */
-
-        if((clazz.getModifiers() & Modifier.PUBLIC) != 0)
+        private String makeMethodKey(final Method method)
         {
-            return method;
-        }
+            Class[] parameterTypes = method.getParameterTypes();
 
-        return getPublicMethod(clazz, method.getName(), 
method.getParameterTypes());
-    }
+            StringBuffer methodKey = new StringBuffer(method.getName());
 
-    /**
-     *  Looks up the method with specified name and signature in the first 
public
-     *  superclass or implemented interface of the class.
-     *
-     *  @param clazz the class whose method is sought
-     *  @param name the name of the method
-     *  @param paramTypes the classes of method parameters
-     *  @return applicable method
-     */
-    private static Method getPublicMethod(Class clazz, String name, Class[] 
paramTypes)
-    {
-        /*
-         *  if this class is public, then try to get it
-         */
-
-        if((clazz.getModifiers() & Modifier.PUBLIC) != 0)
-        {
-            try
-            {
-                return clazz.getMethod(name, paramTypes);
-            }
-            catch(NoSuchMethodException e)
+            for (int j = 0; j < parameterTypes.length; j++)
             {
                 /*
-                 *  If the class does not have the method, then neither its
-                 *  superclass nor any of its interfaces has it so quickly 
return
-                 *  null.
+                 * If the argument type is primitive then we want
+                 * to convert our primitive type signature to the
+                 * corresponding Object type so introspection for
+                 * methods with primitive types will work correctly.
+                 *
+                 * The lookup map (convertPrimitives) contains all eight
+                 * primitives (boolean, byte, char, double, float, int, long, 
short)
+                 * known to Java. So it should never return null for the key 
passed in.
                  */
-                 return null;
+                if (parameterTypes[j].isPrimitive())
+                {
+                    methodKey.append((String) 
convertPrimitives.get(parameterTypes[j]));
+                }
+                else
+                {
+                    methodKey.append(parameterTypes[j].getName());
+                }
             }
-        }
 
-        /*
-         *  try the superclass
-         */
-
-
-        Class superclazz = clazz.getSuperclass();
-
-        if ( superclazz != null )
-        {
-            Method superclazzMethod = getPublicMethod(superclazz, name, 
paramTypes);
-
-            if(superclazzMethod != null)
-            {
-                return superclazzMethod;
-            }
+            return methodKey.toString();
         }
 
-        /*
-         *  and interfaces
-         */
-
-        Class[] interfaces = clazz.getInterfaces();
-
-        for(int i = 0; i < interfaces.length; ++i)
+        private String makeMethodKey(String method, Object[] params)
         {
-            Method interfaceMethod = getPublicMethod(interfaces[i], name, 
paramTypes);
+            StringBuffer methodKey = new StringBuffer().append(method);
 
-            if(interfaceMethod != null)
+            for (int j = 0; j < params.length; j++)
             {
-                return interfaceMethod;
-            }
-        }
-
-        return null;
-    }
+                Object arg = params[j];
 
-    /**
-     *  Used for the iterative discovery process for public methods.
-     */
-    private static final class MethodInfo
-    {
-        Method method;
-        String name;
-        Class[] parameterTypes;
-        boolean upcast;
+                if (arg == null)
+                {
+                    arg = OBJECT;
+                }
 
-        MethodInfo(Method method)
-        {
-            this.method = null;
-            name = method.getName();
-            parameterTypes = method.getParameterTypes();
-            upcast = false;
-        }
+                methodKey.append(arg.getClass().getName());
+            }
 
-        void tryUpcasting(Class clazz)
-            throws NoSuchMethodException
-        {
-            method = clazz.getMethod(name, parameterTypes);
-            name = null;
-            parameterTypes = null;
-            upcast = true;
+            return methodKey.toString();
         }
     }
 }

Modified: 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/Introspector.java
URL: 
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/Introspector.java?view=diff&rev=477003&r1=477002&r2=477003
==============================================================================
--- 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/Introspector.java
 (original)
+++ 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/Introspector.java
 Sun Nov 19 17:14:22 2006
@@ -65,16 +65,11 @@
         "Introspector: detected classloader change. Dumping cache.";
 
     /**
-     * The Log we use
-     */
-    protected final Log log;
-
-    /**
      * @param log A Log object to use for the introspector.
      */
     public Introspector(final Log log)
     {
-        this.log = log;
+        super(log);
     }
 
     /**

Modified: 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
URL: 
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java?view=diff&rev=477003&r1=477002&r2=477003
==============================================================================
--- 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
 (original)
+++ 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
 Sun Nov 19 17:14:22 2006
@@ -21,6 +21,8 @@
 
 import java.lang.reflect.Method;
 
+import org.apache.velocity.runtime.log.Log;
+
 /**
  * Lookup a a Method object for a particular class given the name of a method
  * and its parameters.
@@ -52,16 +54,20 @@
 public abstract class IntrospectorBase
        implements IntrospectorCacheListener
 {
+    /** Class logger */
+    protected final Log log;
+
     /** The Introspector Cache */
     private final IntrospectorCache introspectorCache;
     
     /**
      * C'tor.
      */
-    protected IntrospectorBase()
+    protected IntrospectorBase(final Log log)
     {
-        introspectorCache = new IntrospectorCacheImpl(); // TODO: Load that 
from properties.
-        introspectorCache.addListener(this);
+       this.log = log;
+       introspectorCache = new IntrospectorCacheImpl(log); // TODO: Load that 
from properties.
+       introspectorCache.addListener(this);
     }
     
     /**

Modified: 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java
URL: 
http://svn.apache.org/viewvc/jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java?view=diff&rev=477003&r1=477002&r2=477003
==============================================================================
--- 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java
 (original)
+++ 
jakarta/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java
 Sun Nov 19 17:14:22 2006
@@ -25,6 +25,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.velocity.runtime.log.Log;
+
 /**
  * This is the internal introspector cache implementation.
  *
@@ -34,6 +36,9 @@
 public final class IntrospectorCacheImpl
         implements IntrospectorCache
 {
+    /** Class logger */
+    private final Log log;
+    
     /**
      * Holds the method maps for the classes we know about. Map: Class --&gt; 
ClassMap object.
      */
@@ -55,8 +60,9 @@
     /**
      * C'tor
      */
-    public IntrospectorCacheImpl()
+    public IntrospectorCacheImpl(final Log log)
     {
+       this.log = log;
     }
 
     /**
@@ -122,7 +128,7 @@
      */
     public synchronized ClassMap put(final Class c)
     {
-        ClassMap classMap = new ClassMap(c);
+        ClassMap classMap = new ClassMap(c, log);
         classMapCache.put(c, classMap);
         classNameCache.add(c.getName());
         



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to