You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by ge...@apache.org on 2001/09/10 12:36:09 UTC

cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection ClassMap.java Introspector.java

geirm       01/09/10 03:36:09

  Modified:    src/java/org/apache/velocity/util/introspection
                        ClassMap.java Introspector.java
  Log:
  PROVISIONAL changes to Introspector that mix reengineering by
  Atilla Szegedi and a patch to revert *that* back to using
  Class as the key to the map, with a second map to hold
  name->class for dumping.
  
  I think I got it all together correctly - if not, yell :)
  
  Revision  Changes    Path
  1.13      +9 -1      jakarta-velocity/src/java/org/apache/velocity/util/introspection/ClassMap.java
  
  Index: ClassMap.java
  ===================================================================
  RCS file: /home/cvs/jakarta-velocity/src/java/org/apache/velocity/util/introspection/ClassMap.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- ClassMap.java	2001/08/11 19:04:21	1.12
  +++ ClassMap.java	2001/09/10 10:36:09	1.13
  @@ -70,7 +70,7 @@
    * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
    * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
    * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  - * @version $Id: ClassMap.java,v 1.12 2001/08/11 19:04:21 geirm Exp $
  + * @version $Id: ClassMap.java,v 1.13 2001/09/10 10:36:09 geirm Exp $
    */
   public class ClassMap
   {
  @@ -101,6 +101,14 @@
           this.clazz = clazz;
           populateMethodCache();
       }
  +    
  +    /**
  +     * @return the class object whose methods are cached by this map.
  +     */
  +     Class getCachedClass()
  +     {
  +         return clazz;
  +     }
       
       /**
        * Find a Method using the methodKey
  
  
  
  1.11      +1 -179    jakarta-velocity/src/java/org/apache/velocity/util/introspection/Introspector.java
  
  Index: Introspector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-velocity/src/java/org/apache/velocity/util/introspection/Introspector.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- Introspector.java	2001/09/09 21:50:33	1.10
  +++ Introspector.java	2001/09/10 10:36:09	1.11
  @@ -1,179 +1 @@
  -package org.apache.velocity.util.introspection;
  -
  -/*
  - * The Apache Software License, Version 1.1
  - *
  - * Copyright (c) 2001 The Apache Software Foundation.  All rights
  - * reserved.
  - *
  - * Redistribution and use in source and binary forms, with or without
  - * modification, are permitted provided that the following conditions
  - * are met:
  - *
  - * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer.
  - *
  - * 2. Redistributions in binary form must reproduce the above copyright
  - *    notice, this list of conditions and the following disclaimer in
  - *    the documentation and/or other materials provided with the
  - *    distribution.
  - *
  - * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:
  - *       "This product includes software developed by the
  - *        Apache Software Foundation (http://www.apache.org/)."
  - *    Alternately, this acknowlegement may appear in the software itself,
  - *    if and wherever such third-party acknowlegements normally appear.
  - *
  - * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
  - *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written
  - *    permission, please contact apache@apache.org.
  - *
  - * 5. Products derived from this software may not be called "Apache"
  - *    nor may "Apache" appear in their names without prior written
  - *    permission of the Apache Group.
  - *
  - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  - * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  - * SUCH DAMAGE.
  - * ====================================================================
  - *
  - * This software consists of voluntary contributions made by many
  - * individuals on behalf of the Apache Software Foundation.  For more
  - * information on the Apache Software Foundation, please see
  - * <http://www.apache.org/>.
  - */
  -
  -import java.util.Hashtable;
  -
  -import java.lang.reflect.Method;
  -import java.lang.reflect.Modifier;
  -
  -import org.apache.velocity.runtime.RuntimeServices;
  -
  -/**
  - * This basic function of this class is to return a Method
  - * object for a particular class given the name of a method
  - * and the parameters to the method in the form of an Object[]
  - *
  - * The first time the Introspector sees a 
  - * class it creates a class method map for the
  - * class in question. Basically the class method map
  - * is a Hastable where Method objects are keyed by a
  - * concatenation of the method name and the names of
  - * classes that make up the parameters.
  - *
  - * For example, a method with the following signature:
  - *
  - * public void method(String a, StringBuffer b)
  - *
  - * would be mapped by the key:
  - *
  - * "method" + "java.lang.String" + "java.lang.StringBuffer"
  - *
  - * This mapping is performed for all the methods in a class
  - * and stored for 
  - * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
  - * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
  - * @version $Id: Introspector.java,v 1.10 2001/09/09 21:50:33 geirm Exp $
  - */
  -public class Introspector
  -{
  -    private static Hashtable classMethodMaps = new Hashtable();
  -    private RuntimeServices rsvc = null;
  -
  -    public void init( RuntimeServices r )
  -    {
  -        this.rsvc = r;
  -    }
  -
  -    public Method getMethod(Class c, String name, Object[] params)
  -        throws Exception
  -    {       
  -        if (c == null)
  -        {
  -            throw new Exception ( 
  -                "Introspector.getMethod(): Class method key was null: " + name );
  -        }                
  -
  -        /* 
  -         * If this is the first time seeing this class
  -         * then create a method map for this class and
  -         * store it in Hashtable of class method maps.
  -         */
  -        if (!classMethodMaps.containsKey(c))
  -        {
  -            /*
  -             * Lots of threads might be whizzing through here,
  -             * so we do a double-checked lock, which only involves
  -             * synchronization when there's a key-miss.  Avoids
  -             * doing duplicate work, and constructing objects twice
  -             * in particular race conditions
  -             */
  -
  -            /* 
  -             * Though, some folks say that double-checked-locking
  -             * doesn't necessarily work-as-expected in Java on
  -             * multi-proc machines.  Doesn't make things worse,
  -             * but just doesn't help as much as you'd imagine it
  -             * would.  Darn re-ordering of instructions.
  -             */
  -            synchronized (classMethodMaps)
  -            {
  -                if (!classMethodMaps.containsKey(c))
  -                {
  -                    classMethodMaps.put(c, new ClassMap(c));
  -                }
  -            }
  -        }
  -        return findMethod(c, name, params);
  -    }
  -
  -    /**
  -     * Find a method in a class.
  -     *
  -     * @param Class class to search
  -     * @param String name of method
  -     * @param Object[] parameters
  -     */
  -    private Method findMethod(Class c, String name, Object[] params)
  -    {
  -        ClassMap classMethodMap = (ClassMap) classMethodMaps.get(c);
  -        return classMethodMap.findMethod(name, params);
  -    }
  -
  -    /**
  -     * Checks whether the provided object implements a given method.
  -     *
  -     *
  -     * @param object     The object to check.
  -     * @param methodName The method to check for.
  -     * @return           Whether the method is implemented.
  -     */
  -    public  boolean implementsMethod(Object object, String methodName)
  -    {
  -        int m;
  -        
  -        Method[] methods = object.getClass().getMethods();
  -        
  -        for (m = 0 ; m < methods.length ; ++m)
  -        {
  -            if (methodName.equals(methods[m].getName()))
  -            {
  -                break;
  -            }
  -        }            
  -        
  -        return (m < methods.length);
  -    }
  -}
  +package org.apache.velocity.util.introspection;

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.util.*;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.apache.velocity.runtime.RuntimeServices;

/**
 * This basic function of this class is to return a Method
 * object for a particular class given the name of a method
 * and the parameters to the method in the form of an Object[]
 *
 * The first time the Introspector sees a 
 * class it creates a class method map for the
 * class in question. Basically the class method map
 * is a Hastable where Method objects are keyed by a
 * concatenation of the method name and the names of
 * classes that make up the parameters.
 *
 * For example, a method with the following signature:
 *
 * public void method(String a, StringBuffer b)
 *
 * would be mapped by the key:
 *
 * "method" + "java.lang.String" + "java.lang.StringBuffer"
 *
 * This mapping is performed for all the methods in a class
 * and stored for 
 * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
 * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
 * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
 * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
 * @version $Id: Introspector.java,v 1.11 2001/09/10 10:36:09 geirm Exp $
 */
public class Introspector
{
    private RuntimeServices rsvc = null;

    /*
     *  Holds the method maps for the classes we know about,
     *  keyed by Class
     */ 
    private final Map classMethodMaps = new HashMap();
    
    /*
     *  Holds the qualified class name to Class mapping
     */
    private final Map classByName = new HashMap();

    /**
     *  Recieves our RuntimeServices object
     */
    public void init( RuntimeServices r )
    {
        this.rsvc = r;
    }
   
    public Method getMethod(Class c, String name, Object[] params)
        throws Exception
    {
        if (c == null)
        {
            throw new Exception ( 
                "Introspector.getMethod(): Class method key was null: " + name );
        }                

        ClassMap classMap = null;
        
        synchronized(classMethodMaps)
        {
            classMap = (ClassMap)classMethodMaps.get(c);
          
            /*
             *  if we don't have this, check to see if we have it
             *  by name.  if so, then we have a classloader change
             *  so dump our caches.
             */
             
            if ( classMap == null)
            {
                Class cachedClass = (Class) classByName.get( c.getName() );
                
                if ( cachedClass != null)
                {
                    clearCache();
                    rsvc.info("Introspector : detected classloader change. Dumping cache.");
                }
                 
                classMap = createClassMap(c);
            }
        }
        
        return classMap.findMethod(name, params);
    }

    /**
     * Creates a class map for specific class and registers it in the
     * cache.  Also adds the qualified name to the name->class map
     * for later Classloader change detection.
     */
    private ClassMap createClassMap(Class c)
    {
        ClassMap classMap = new ClassMap(c);        
        classMethodMaps.put( c, classMap);
        classByName.put(c.getName(), c);

        return classMap;
    }

    /**
     * Clears the classmap and classname
     * caches
     */
    private void clearCache()
    {            
        classMethodMaps.clear();
        classByName.clear();    
    }
        
    /**
     * Checks whether the provided object implements a given method.
     *
     *
     * @param object     The object to check.
     * @param methodName The method to check for.
     * @return           Whether the method is implemented.
     */
    public boolean implementsMethod(Object object, String methodName)
    {
        int m;
        
        Method[] methods = object.getClass().getMethods();
        
        for (m = 0 ; m < methods.length ; ++m)
        {
            if (methodName.equals(methods[m].getName()))
            {
                break;
            }
        }            
        
        return (m < methods.length);
    }
}

  \ No newline at end of file
  
  
  

Re: cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection ClassMap.java Introspector.java

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 9/10/01 4:38 AM, "Attila Szegedi" <sz...@freemail.hu> wrote:

> If I REALLY want to split hairs, then I'd say that in clearCache() you could
> do "classByName = new HashMap()" instead of "classByName.clear()". This is
> similar to what you proposed for "classMethodMaps.clear()" (but which in
> that particular case is bad because of synchronization issues I described in
> an earlier post).

Yes, I think you are right, as the sych issues aren't there.  I just left it
parallel so it's clear, w/o having to describe why one is that way, and one
isn't.  As you noted in our conversation, it's infrequent.  If a problem, we
can always do that...

geir

 
> Attila.
> 
> ----- Original Message -----
> From: <ge...@apache.org>
> To: <ja...@apache.org>
> Sent: 2001. szeptember 10. 12:36
> Subject: cvs commit:
> jakarta-velocity/src/java/org/apache/velocity/util/introspection
> ClassMap.java Introspector.java
> 
> 
>> geirm       01/09/10 03:36:09
>> 
>>   Modified:    src/java/org/apache/velocity/util/introspection
>>                         ClassMap.java Introspector.java
>>   Log:
>>   PROVISIONAL changes to Introspector that mix reengineering by
>>   Atilla Szegedi and a patch to revert *that* back to using
>>   Class as the key to the map, with a second map to hold
>>   name->class for dumping.
>> 
>>   I think I got it all together correctly - if not, yell :)
>> 
> 
> 

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
If you look up, there are no limits - Japanese Proverb


Re: cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection ClassMap.java Introspector.java

Posted by Attila Szegedi <sz...@freemail.hu>.
If I REALLY want to split hairs, then I'd say that in clearCache() you could
do "classByName = new HashMap()" instead of "classByName.clear()". This is
similar to what you proposed for "classMethodMaps.clear()" (but which in
that particular case is bad because of synchronization issues I described in
an earlier post).

Attila.

----- Original Message -----
From: <ge...@apache.org>
To: <ja...@apache.org>
Sent: 2001. szeptember 10. 12:36
Subject: cvs commit:
jakarta-velocity/src/java/org/apache/velocity/util/introspection
ClassMap.java Introspector.java


> geirm       01/09/10 03:36:09
>
>   Modified:    src/java/org/apache/velocity/util/introspection
>                         ClassMap.java Introspector.java
>   Log:
>   PROVISIONAL changes to Introspector that mix reengineering by
>   Atilla Szegedi and a patch to revert *that* back to using
>   Class as the key to the map, with a second map to hold
>   name->class for dumping.
>
>   I think I got it all together correctly - if not, yell :)
>



RE: cvs commit:jakarta-velocity/src/java/org/apache/velocity/util/introspectionClassMap.java Introspector.java

Posted by Paulo Gaspar <pa...@krankikom.de>.
Absolutely right! 

I started using a Map because I thought I would need to compare the stored 
Class somewhere. However, then I only needed to use the class name but did 
never remember turning the Map into a Set.

I also like better the "cachedClassNames" name.


Have fun,
Paulo

> -----Original Message-----
> From: Geir Magnusson Jr. [mailto:geirm@optonline.net]
> Sent: Tuesday, September 11, 2001 12:55 AM
> To: velocity-dev@jakarta.apache.org
> Subject: Re: cvs
> commit:jakarta-velocity/src/java/org/apache/velocity/util/introspectionC
> lassMap.java Introspector.java
> 
> 
> On 9/10/01 6:09 AM, "Attila Szegedi" <sz...@freemail.hu> wrote:
> 
> > "Map classByName" could as well be "Set cachedClassNames", storing only
> > class names and using "cachedClassNames.contains(className)" instead of
> > "classByName.get(name) != null". It can be somewhat confusing to code
> > readers why do we store the class beside its name - we don't 
> use the stored
> > class object anywhere.
> 
> That's a good idea too...
> 
> Lets beat on this a while first, then we can nip and tuck.
> 
> geir
> -- 
> Geir Magnusson Jr.     geirm@optonline.net
> System and Software Consulting
> Developing for the web?  See http://jakarta.apache.org/velocity/
> If you look up, there are no limits - Japanese Proverb
> 

Re: cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection ClassMap.java Introspector.java

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 9/10/01 6:09 AM, "Attila Szegedi" <sz...@freemail.hu> wrote:

> "Map classByName" could as well be "Set cachedClassNames", storing only
> class names and using "cachedClassNames.contains(className)" instead of
> "classByName.get(name) != null". It can be somewhat confusing to code
> readers why do we store the class beside its name - we don't use the stored
> class object anywhere.

That's a good idea too...

Lets beat on this a while first, then we can nip and tuck.

geir
-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
If you look up, there are no limits - Japanese Proverb


Re: cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection ClassMap.java Introspector.java

Posted by Attila Szegedi <sz...@freemail.hu>.
"Map classByName" could as well be "Set cachedClassNames", storing only
class names and using "cachedClassNames.contains(className)" instead of
"classByName.get(name) != null". It can be somewhat confusing to code
readers why do we store the class beside its name - we don't use the stored
class object anywhere.

Attila.


----- Original Message -----
From: <ge...@apache.org>
To: <ja...@apache.org>
Sent: 2001. szeptember 10. 12:36
Subject: cvs commit:
jakarta-velocity/src/java/org/apache/velocity/util/introspection
ClassMap.java Introspector.java


> geirm       01/09/10 03:36:09
>
>   Modified:    src/java/org/apache/velocity/util/introspection
>                         ClassMap.java Introspector.java
>   Log:
>   PROVISIONAL changes to Introspector that mix reengineering by
>   Atilla Szegedi and a patch to revert *that* back to using
>   Class as the key to the map, with a second map to hold
>   name->class for dumping.
>
>   I think I got it all together correctly - if not, yell :)
>
>   Revision  Changes    Path
>   1.13      +9 -1
jakarta-velocity/src/java/org/apache/velocity/util/introspection/ClassMap.ja
va
>
>   Index: ClassMap.java
>   ===================================================================
>   RCS file:
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/util/introspection/C
lassMap.java,v
>   retrieving revision 1.12
>   retrieving revision 1.13
>   diff -u -r1.12 -r1.13
>   --- ClassMap.java 2001/08/11 19:04:21 1.12
>   +++ ClassMap.java 2001/09/10 10:36:09 1.13
>   @@ -70,7 +70,7 @@
>     * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
>     * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
>     * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
>   - * @version $Id: ClassMap.java,v 1.12 2001/08/11 19:04:21 geirm Exp $
>   + * @version $Id: ClassMap.java,v 1.13 2001/09/10 10:36:09 geirm Exp $
>     */
>    public class ClassMap
>    {
>   @@ -101,6 +101,14 @@
>            this.clazz = clazz;
>            populateMethodCache();
>        }
>   +
>   +    /**
>   +     * @return the class object whose methods are cached by this map.
>   +     */
>   +     Class getCachedClass()
>   +     {
>   +         return clazz;
>   +     }
>
>        /**
>         * Find a Method using the methodKey
>
>
>
>   1.11      +1 -179
jakarta-velocity/src/java/org/apache/velocity/util/introspection/Introspecto
r.java
>
>   Index: Introspector.java
>   ===================================================================
>   RCS file:
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/util/introspection/I
ntrospector.java,v
>   retrieving revision 1.10
>   retrieving revision 1.11
>   diff -u -r1.10 -r1.11
>   --- Introspector.java 2001/09/09 21:50:33 1.10
>   +++ Introspector.java 2001/09/10 10:36:09 1.11
>   @@ -1,179 +1 @@
>   -package org.apache.velocity.util.introspection;
>   -
>   -/*
>   - * The Apache Software License, Version 1.1
>   - *
>   - * Copyright (c) 2001 The Apache Software Foundation.  All rights
>   - * reserved.
>   - *
>   - * Redistribution and use in source and binary forms, with or without
>   - * modification, are permitted provided that the following conditions
>   - * are met:
>   - *
>   - * 1. Redistributions of source code must retain the above copyright
>   - *    notice, this list of conditions and the following disclaimer.
>   - *
>   - * 2. Redistributions in binary form must reproduce the above copyright
>   - *    notice, this list of conditions and the following disclaimer in
>   - *    the documentation and/or other materials provided with the
>   - *    distribution.
>   - *
>   - * 3. The end-user documentation included with the redistribution, if
>   - *    any, must include the following acknowlegement:
>   - *       "This product includes software developed by the
>   - *        Apache Software Foundation (http://www.apache.org/)."
>   - *    Alternately, this acknowlegement may appear in the software
itself,
>   - *    if and wherever such third-party acknowlegements normally appear.
>   - *
>   - * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
>   - *    Foundation" must not be used to endorse or promote products
derived
>   - *    from this software without prior written permission. For written
>   - *    permission, please contact apache@apache.org.
>   - *
>   - * 5. Products derived from this software may not be called "Apache"
>   - *    nor may "Apache" appear in their names without prior written
>   - *    permission of the Apache Group.
>   - *
>   - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>   - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>   - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>   - * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>   - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>   - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>   - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>   - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>   - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>   - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>   - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>   - * SUCH DAMAGE.
>   - * ====================================================================
>   - *
>   - * This software consists of voluntary contributions made by many
>   - * individuals on behalf of the Apache Software Foundation.  For more
>   - * information on the Apache Software Foundation, please see
>   - * <http://www.apache.org/>.
>   - */
>   -
>   -import java.util.Hashtable;
>   -
>   -import java.lang.reflect.Method;
>   -import java.lang.reflect.Modifier;
>   -
>   -import org.apache.velocity.runtime.RuntimeServices;
>   -
>   -/**
>   - * This basic function of this class is to return a Method
>   - * object for a particular class given the name of a method
>   - * and the parameters to the method in the form of an Object[]
>   - *
>   - * The first time the Introspector sees a
>   - * class it creates a class method map for the
>   - * class in question. Basically the class method map
>   - * is a Hastable where Method objects are keyed by a
>   - * concatenation of the method name and the names of
>   - * classes that make up the parameters.
>   - *
>   - * For example, a method with the following signature:
>   - *
>   - * public void method(String a, StringBuffer b)
>   - *
>   - * would be mapped by the key:
>   - *
>   - * "method" + "java.lang.String" + "java.lang.StringBuffer"
>   - *
>   - * This mapping is performed for all the methods in a class
>   - * and stored for
>   - * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
>   - * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
>   - * @version $Id: Introspector.java,v 1.10 2001/09/09 21:50:33 geirm Exp
$
>   - */
>   -public class Introspector
>   -{
>   -    private static Hashtable classMethodMaps = new Hashtable();
>   -    private RuntimeServices rsvc = null;
>   -
>   -    public void init( RuntimeServices r )
>   -    {
>   -        this.rsvc = r;
>   -    }
>   -
>   -    public Method getMethod(Class c, String name, Object[] params)
>   -        throws Exception
>   -    {
>   -        if (c == null)
>   -        {
>   -            throw new Exception (
>   -                "Introspector.getMethod(): Class method key was null: "
+ name );
>   -        }
>   -
>   -        /*
>   -         * If this is the first time seeing this class
>   -         * then create a method map for this class and
>   -         * store it in Hashtable of class method maps.
>   -         */
>   -        if (!classMethodMaps.containsKey(c))
>   -        {
>   -            /*
>   -             * Lots of threads might be whizzing through here,
>   -             * so we do a double-checked lock, which only involves
>   -             * synchronization when there's a key-miss.  Avoids
>   -             * doing duplicate work, and constructing objects twice
>   -             * in particular race conditions
>   -             */
>   -
>   -            /*
>   -             * Though, some folks say that double-checked-locking
>   -             * doesn't necessarily work-as-expected in Java on
>   -             * multi-proc machines.  Doesn't make things worse,
>   -             * but just doesn't help as much as you'd imagine it
>   -             * would.  Darn re-ordering of instructions.
>   -             */
>   -            synchronized (classMethodMaps)
>   -            {
>   -                if (!classMethodMaps.containsKey(c))
>   -                {
>   -                    classMethodMaps.put(c, new ClassMap(c));
>   -                }
>   -            }
>   -        }
>   -        return findMethod(c, name, params);
>   -    }
>   -
>   -    /**
>   -     * Find a method in a class.
>   -     *
>   -     * @param Class class to search
>   -     * @param String name of method
>   -     * @param Object[] parameters
>   -     */
>   -    private Method findMethod(Class c, String name, Object[] params)
>   -    {
>   -        ClassMap classMethodMap = (ClassMap) classMethodMaps.get(c);
>   -        return classMethodMap.findMethod(name, params);
>   -    }
>   -
>   -    /**
>   -     * Checks whether the provided object implements a given method.
>   -     *
>   -     *
>   -     * @param object     The object to check.
>   -     * @param methodName The method to check for.
>   -     * @return           Whether the method is implemented.
>   -     */
>   -    public  boolean implementsMethod(Object object, String methodName)
>   -    {
>   -        int m;
>   -
>   -        Method[] methods = object.getClass().getMethods();
>   -
>   -        for (m = 0 ; m < methods.length ; ++m)
>   -        {
>   -            if (methodName.equals(methods[m].getName()))
>   -            {
>   -                break;
>   -            }
>   -        }
>   -
>   -        return (m < methods.length);
>   -    }
>   -}
>   +package org.apache.velocity.util.introspection;/* * The Apache Software
License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation.
All rights * reserved. * * Redistribution and use in source and binary
forms, with or without * modification, are permitted provided that the
following conditions * are met: * * 1. Redistributions of source code must
retain the above copyright *    notice, this list of conditions and the
following disclaimer. * * 2. Redistributions in binary form must reproduce
the above copyright *    notice, this list of conditions and the following
disclaimer in *    the documentation and/or other materials provided with
the *    distribution. * * 3. The end-user documentation included with the
redistribution, if *    any, must include the following acknowlegement: *
"This product includes software developed by the *        Apache Software
Foundation (http://www.apache.org/)." *    Alternately, this acknowlegement
may appear in the software itself, *    if and wherever such third-party
acknowlegements normally appear. * * 4. The names "The Jakarta Project",
"Velocity", and "Apache Software *    Foundation" must not be used to
endorse or promote products derived *    from this software without prior
written permission. For written *    permission, please contact
apache@apache.org. * * 5. Products derived from this software may not be
called "Apache" *    nor may "Apache" appear in their names without prior
written *    permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED
``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE
FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *
==================================================================== * *
This software consists of voluntary contributions made by many * individuals
on behalf of the Apache Software Foundation.  For more * information on the
Apache Software Foundation, please see * <http://www.apache.org/>. */import
java.util.*;import java.lang.reflect.Method;import
java.lang.reflect.Modifier;import
org.apache.velocity.runtime.RuntimeServices;/** * This basic function of
this class is to return a Method * object for a particular class given the
name of a method * and the parameters to the method in the form of an
Object[] * * The first time the Introspector sees a * class it creates a
class method map for the * class in question. Basically the class method map
* is a Hastable where Method objects are keyed by a * concatenation of the
method name and the names of * classes that make up the parameters. * * For
example, a method with the following signature: * * public void
method(String a, StringBuffer b) * * would be mapped by the key: * *
"method" + "java.lang.String" + "java.lang.StringBuffer" * * This mapping is
performed for all the methods in a class * and stored for * @author <a
href="mailto:jvanzyl@periapt.com">Jason van Zyl</a> * @author <a
href="mailto:bob@werken.com">Bob McWhirter</a> * @author <a
href="mailto:szegedia@freemail.hu">Attila Szegedi</a> * @author <a
href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a> * @version $Id:
Introspector.java,v 1.11 2001/09/10 10:36:09 geirm Exp $ */public class
Introspector{    private RuntimeServices rsvc = null;    /*     *  Holds the
method maps for the classes we know about,     *  keyed by Class     */
private final Map classMethodMaps = new HashMap();        /*     *  Holds
the qualified class name to Class mapping     */    private final Map
classByName = new HashMap();    /**     *  Recieves our RuntimeServices
object     */    public void init( RuntimeServices r )    {        this.rsvc
= r;    }       public Method getMethod(Class c, String name, Object[]
params)        throws Exception    {        if (c == null)
{            throw new Exception (
"Introspector.getMethod(): Class method key was null: " + name );        }
ClassMap classMap = null;                synchronized(classMethodMaps)
{            classMap = (ClassMap)classMethodMaps.get(c);
/*             *  if we don't have this, check to see if we have it
*  by name.  if so, then we have a classloader change             *  so dump
our caches.             */                         if ( classMap == null)
{                Class cachedClass = (Class) classByName.get( c.getName() );
if ( cachedClass != null)                {                    clearCache();
rsvc.info("Introspector : detected classloader change. Dumping
          }                                 classMap =
Map(c);            }        }                return
classMap.findMethod(name, params);    }    /**     * Creates a class map for
specific class and registers it in the     * cache.  Also adds the qualified
name to the name->class map     * for later Classloader change detection.
*/    private ClassMap createClassMap(Class c)    {        ClassMap classMap
= new ClassMap(c);                classMethodMaps.put( c, classMap);
classByName.put(c.getName(), c);        return classMap;    }    /**     *
Clears the classmap and classname     * caches     */    private void
clearCache()    {                    classMethodMaps.clear();
classByName.clear();        }            /**     * Checks whether the
provided object implements a given method.     *     *     * @param object
The object to check.     * @param methodName The method to check for.     *
@return           Whether the method is implemented.     */    public
boolean implementsMethod(Object object, String methodName)    {        int
m;                Method[] methods = object.getClass().getMethods();
for (m = 0 ; m < methods.length ; ++m)        {            if
(methodName.equals(methods[m].getName()))            {
    break;            }        }                            return (m <
methods.length);    }}
>   \ No newline at end of file
>
>
>
>


Re: OFF TOPIC: Open Source Advocacy: USED TO BE: cvs commit: Introspector.java

Posted by Attila Szegedi <sz...@freemail.hu>.
Y'know, the sole reason I'm in it is that it greatly builds my vanity when I
read alike testimonials.
;-)

Attila.

----- Original Message -----
From: "Bojan Smojver" <bo...@binarix.com>
To: <ve...@jakarta.apache.org>
Sent: 2001. szeptember 11. 2:48
Subject: OFF TOPIC: Open Source Advocacy: USED TO BE: cvs commit:
Introspector.java


> Attila Szegedi wrote:
> >
> > I've read through it several times, and it looks OK to me. Bojan will
also
> > be happy as there is now one introspector per runtime instance, so
dumping
> > cache in one webapp won't negatively affect performance in others.
>
> Let me first state the obvious: you guys are legends!
>
> Now, you might not believe this, but this is the stuff that I talk with
> my sales team about. In what other kind of environment could one discuss
> the relevant issues of development in an open, friendly and rational
> manner and be given this kind of support and VIP treatment? I'd say
> people that are paying $$$ for support are sometimes not treated this
> way.
>
> So, if you are a reader that just bumped into this list by accident, be
> warned: open source developers will listen to what you have to say! It
> can be truly shocking - they'll give you advice and tips, they'll even
> spend their own time to help you!
>
> Bojan
>


Re: OFF TOPIC: Open Source Advocacy: USED TO BE: cvs commit: Introspector.java

Posted by Jon Stevens <jo...@latchkey.com>.
on 9/10/01 5:48 PM, "Bojan Smojver" <bo...@binarix.com> wrote:

> So, if you are a reader that just bumped into this list by accident, be
> warned: open source developers will listen to what you have to say! It
> can be truly shocking - they'll give you advice and tips, they'll even
> spend their own time to help you!
> 
> Bojan

Could you repeat that? I didn't hear you.

:-) :-) :-)

-jon


OFF TOPIC: Open Source Advocacy: USED TO BE: cvs commit: Introspector.java

Posted by Bojan Smojver <bo...@binarix.com>.
Attila Szegedi wrote:
> 
> I've read through it several times, and it looks OK to me. Bojan will also
> be happy as there is now one introspector per runtime instance, so dumping
> cache in one webapp won't negatively affect performance in others.

Let me first state the obvious: you guys are legends!

Now, you might not believe this, but this is the stuff that I talk with
my sales team about. In what other kind of environment could one discuss
the relevant issues of development in an open, friendly and rational
manner and be given this kind of support and VIP treatment? I'd say
people that are paying $$$ for support are sometimes not treated this
way.

So, if you are a reader that just bumped into this list by accident, be
warned: open source developers will listen to what you have to say! It
can be truly shocking - they'll give you advice and tips, they'll even
spend their own time to help you!

Bojan

Re: cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection ClassMap.java Introspector.java

Posted by Attila Szegedi <sz...@freemail.hu>.
I've read through it several times, and it looks OK to me. Bojan will also
be happy as there is now one introspector per runtime instance, so dumping
cache in one webapp won't negatively affect performance in others.

Attila.


----- Original Message -----
From: <ge...@apache.org>
To: <ja...@apache.org>
Sent: 2001. szeptember 10. 12:36
Subject: cvs commit:
jakarta-velocity/src/java/org/apache/velocity/util/introspection
ClassMap.java Introspector.java


> geirm       01/09/10 03:36:09
>
>   Modified:    src/java/org/apache/velocity/util/introspection
>                         ClassMap.java Introspector.java
>   Log:
>   PROVISIONAL changes to Introspector that mix reengineering by
>   Atilla Szegedi and a patch to revert *that* back to using
>   Class as the key to the map, with a second map to hold
>   name->class for dumping.
>
>   I think I got it all together correctly - if not, yell :)
>

<snip/>