001: package org.apache.velocity.util.introspection;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.lang.reflect.Method;
023:
024: import org.apache.velocity.runtime.log.Log;
025:
026: /**
027: * Lookup a a Method object for a particular class given the name of a method
028: * and its parameters.
029: *
030: * The first time the Introspector sees a
031: * class it creates a class method map for the
032: * class in question. Basically the class method map
033: * is a Hashtable where Method objects are keyed by a
034: * concatenation of the method name and the names of
035: * classes that make up the parameters.
036: *
037: * For example, a method with the following signature:
038: *
039: * public void method(String a, StringBuffer b)
040: *
041: * would be mapped by the key:
042: *
043: * "method" + "java.lang.String" + "java.lang.StringBuffer"
044: *
045: * This mapping is performed for all the methods in a class
046: * and stored for.
047: * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
048: * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
049: * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
050: * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
051: * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
052: * @version $Id: IntrospectorBase.java 477003 2006-11-20 01:14:22Z henning $
053: */
054: public abstract class IntrospectorBase implements
055: IntrospectorCacheListener {
056: /** Class logger */
057: protected final Log log;
058:
059: /** The Introspector Cache */
060: private final IntrospectorCache introspectorCache;
061:
062: /**
063: * C'tor.
064: */
065: protected IntrospectorBase(final Log log) {
066: this .log = log;
067: introspectorCache = new IntrospectorCacheImpl(log); // TODO: Load that from properties.
068: introspectorCache.addListener(this );
069: }
070:
071: /**
072: * Gets the method defined by <code>name</code> and
073: * <code>params</code> for the Class <code>c</code>.
074: *
075: * @param c Class in which the method search is taking place
076: * @param name Name of the method being searched for
077: * @param params An array of Objects (not Classes) that describe the
078: * the parameters
079: *
080: * @return The desired Method object.
081: * @throws IllegalArgumentException When the parameters passed in can not be used for introspection.
082: * @throws MethodMap.AmbiguousException When the method map contains more than one match for the requested signature.
083: */
084: public Method getMethod(final Class c, final String name,
085: final Object[] params) throws IllegalArgumentException,
086: MethodMap.AmbiguousException {
087: if (c == null) {
088: throw new IllegalArgumentException("class object is null!");
089: }
090:
091: if (params == null) {
092: throw new IllegalArgumentException("params object is null!");
093: }
094:
095: ClassMap classMap = null;
096:
097: IntrospectorCache ic = getIntrospectorCache();
098:
099: synchronized (ic) {
100: classMap = ic.get(c);
101:
102: if (classMap == null) {
103: classMap = ic.put(c);
104: }
105: }
106:
107: return classMap.findMethod(name, params);
108: }
109:
110: /**
111: * Return the internal IntrospectorCache object.
112: *
113: * @return The internal IntrospectorCache object.
114: */
115: protected IntrospectorCache getIntrospectorCache() {
116: return introspectorCache;
117: }
118:
119: /**
120: * Clears the internal cache.
121: *
122: * @deprecated Use getIntrospectorCache().clear();
123: */
124: protected void clearCache() {
125: getIntrospectorCache().clear();
126: }
127:
128: /**
129: * Creates a class map for specific class and registers it in the
130: * cache. Also adds the qualified name to the name->class map
131: * for later Classloader change detection.
132: *
133: * @param c The class for which the class map gets generated.
134: * @return A ClassMap object.
135: *
136: * @deprecated Use getIntrospectorCache().put(c);
137: */
138: protected ClassMap createClassMap(final Class c) {
139: return getIntrospectorCache().put(c);
140: }
141:
142: /**
143: * Lookup a given Class object in the cache. If it does not exist,
144: * check whether this is due to a class change and purge the caches
145: * eventually.
146: *
147: * @param c The class to look up.
148: * @return A ClassMap object or null if it does not exist in the cache.
149: *
150: * @deprecated Use getIntrospectorCache().get(c);
151: */
152: protected ClassMap lookupClassMap(final Class c) {
153: return getIntrospectorCache().get(c);
154: }
155:
156: /**
157: * @see IntrospectorCacheListener#triggerClear()
158: */
159: public void triggerClear() {
160: }
161:
162: /**
163: * @see IntrospectorCacheListener#triggerGet(Class, ClassMap)
164: */
165: public void triggerGet(Class c, ClassMap classMap) {
166: }
167:
168: /**
169: * @see IntrospectorCacheListener#triggerPut(Class, ClassMap)
170: */
171: public void triggerPut(Class c, ClassMap classMap) {
172: }
173: }
|