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 -->
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]