View Javadoc

1   package org.apache.velocity.util.introspection;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.lang.reflect.Method;
23  
24  import org.apache.velocity.runtime.log.Log;
25  
26  /**
27   * Lookup a a Method object for a particular class given the name of a method
28   * and its parameters.
29   *
30   * The first time the Introspector sees a
31   * class it creates a class method map for the
32   * class in question. Basically the class method map
33   * is a Hashtable where Method objects are keyed by a
34   * concatenation of the method name and the names of
35   * classes that make up the parameters.
36   *
37   * For example, a method with the following signature:
38   *
39   * public void method(String a, StringBuffer b)
40   *
41   * would be mapped by the key:
42   *
43   * "method" + "java.lang.String" + "java.lang.StringBuffer"
44   *
45   * This mapping is performed for all the methods in a class
46   * and stored for.
47   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
48   * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
49   * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
50   * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
51   * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
52   * @version $Id: IntrospectorBase.java 477003 2006-11-20 01:14:22Z henning $
53   */
54  public abstract class IntrospectorBase
55  	implements IntrospectorCacheListener
56  {
57      /** Class logger */
58      protected final Log log;
59  
60      /** The Introspector Cache */
61      private final IntrospectorCache introspectorCache;
62      
63      /**
64       * C'tor.
65       */
66      protected IntrospectorBase(final Log log)
67      {
68  	this.log = log;
69  	introspectorCache = new IntrospectorCacheImpl(log); // TODO: Load that from properties.
70  	introspectorCache.addListener(this);
71      }
72      
73      /**
74       * Gets the method defined by <code>name</code> and
75       * <code>params</code> for the Class <code>c</code>.
76       *
77       * @param c Class in which the method search is taking place
78       * @param name Name of the method being searched for
79       * @param params An array of Objects (not Classes) that describe the
80       *               the parameters
81       *
82       * @return The desired Method object.
83       * @throws IllegalArgumentException When the parameters passed in can not be used for introspection.
84       * @throws MethodMap.AmbiguousException When the method map contains more than one match for the requested signature.
85       */
86      public Method getMethod(final Class c, final String name, final Object[] params)
87              throws IllegalArgumentException,MethodMap.AmbiguousException
88      {
89          if (c == null)
90          {
91              throw new IllegalArgumentException ("class object is null!");
92          }
93          
94          if (params == null)
95          {
96              throw new IllegalArgumentException("params object is null!");
97          }
98  
99          ClassMap classMap = null;
100 
101         IntrospectorCache ic = getIntrospectorCache();
102         
103         synchronized(ic)
104         {
105             classMap = ic.get(c);
106 
107             if (classMap == null)
108             {
109                 classMap = ic.put(c);
110             }
111         }
112 
113         return classMap.findMethod(name, params);
114     }
115 
116     /**
117      * Return the internal IntrospectorCache object.
118      * 
119      * @return The internal IntrospectorCache object.
120      */
121     protected IntrospectorCache getIntrospectorCache()
122     {
123 	return introspectorCache;
124     }
125     
126     /**
127      * Clears the internal cache.
128      * 
129      * @deprecated Use getIntrospectorCache().clear();
130      */
131     protected void clearCache()
132     {
133         getIntrospectorCache().clear();
134     }
135 
136     /**
137      * Creates a class map for specific class and registers it in the
138      * cache.  Also adds the qualified name to the name-&gt;class map
139      * for later Classloader change detection.
140      *
141      * @param c The class for which the class map gets generated.
142      * @return A ClassMap object.
143      * 
144      * @deprecated Use getIntrospectorCache().put(c);
145      */
146     protected ClassMap createClassMap(final Class c)
147     {
148         return getIntrospectorCache().put(c);
149     }
150 
151     /**
152      * Lookup a given Class object in the cache. If it does not exist, 
153      * check whether this is due to a class change and purge the caches
154      * eventually.
155      *
156      * @param c The class to look up.
157      * @return A ClassMap object or null if it does not exist in the cache.
158      * 
159      * @deprecated Use getIntrospectorCache().get(c);
160      */
161     protected ClassMap lookupClassMap(final Class c)
162     {
163         return getIntrospectorCache().get(c);
164     }
165     
166     /**
167      * @see IntrospectorCacheListener#triggerClear()
168      */
169     public void triggerClear()
170     {
171     }
172     
173     /**
174      * @see IntrospectorCacheListener#triggerGet(Class, ClassMap)
175      */
176     public void triggerGet(Class c, ClassMap classMap)
177     {
178     }
179 
180     /**
181      * @see IntrospectorCacheListener#triggerPut(Class, ClassMap)
182      */
183     public void triggerPut(Class c, ClassMap classMap)
184     {
185     }
186 }