001: /*
002: * Copyright 2001-2006 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.commons.jexl.util.introspection;
018:
019: import java.lang.reflect.Method;
020:
021: import org.apache.commons.logging.Log;
022:
023: /**
024: * This basic function of this class is to return a Method
025: * object for a particular class given the name of a method
026: * and the parameters to the method in the form of an Object[]
027: *
028: * The first time the Introspector sees a
029: * class it creates a class method map for the
030: * class in question. Basically the class method map
031: * is a Hashtable where Method objects are keyed by a
032: * concatenation of the method name and the names of
033: * classes that make up the parameters.
034: *
035: * For example, a method with the following signature:
036: *
037: * public void method(String a, StringBuffer b)
038: *
039: * would be mapped by the key:
040: *
041: * "method" + "java.lang.String" + "java.lang.StringBuffer"
042: *
043: * This mapping is performed for all the methods in a class
044: * and stored for
045: * @since 1.0
046: * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
047: * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
048: * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
049: * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
050: * @version $Id: Introspector.java 398171 2006-04-29 14:57:29Z dion $
051: */
052: public class Introspector extends IntrospectorBase {
053: /**
054: * define a public string so that it can be looked for
055: * if interested.
056: */
057:
058: public static final String CACHEDUMP_MSG = "Introspector : detected classloader change. Dumping cache.";
059:
060: /**
061: * our engine runtime services.
062: */
063: private final Log rlog;
064:
065: /**
066: * Recieves our RuntimeServices object.
067: * @param logger a {@link Log}.
068: */
069: public Introspector(Log logger) {
070: this .rlog = logger;
071: }
072:
073: /**
074: * Gets the method defined by <code>name</code> and
075: * <code>params</code> for the Class <code>c</code>.
076: *
077: * @param c Class in which the method search is taking place
078: * @param name Name of the method being searched for
079: * @param params An array of Objects (not Classes) that describe the
080: * the parameters
081: *
082: * @return The desired Method object.
083: * @throws Exception if the superclass does.
084: */
085: public Method getMethod(Class c, String name, Object[] params)
086: throws Exception {
087: /*
088: * just delegate to the base class
089: */
090:
091: try {
092: return super .getMethod(c, name, params);
093: } catch (MethodMap.AmbiguousException ae) {
094: /*
095: * whoops. Ambiguous. Make a nice log message and return null...
096: */
097:
098: StringBuffer msg = new StringBuffer(
099: "Introspection Error : Ambiguous method invocation ")
100: .append(name).append("( ");
101:
102: for (int i = 0; i < params.length; i++) {
103: if (i > 0) {
104: msg.append(", ");
105: }
106:
107: msg.append(params[i].getClass().getName());
108: }
109:
110: msg.append(") for class ").append(c.getName());
111:
112: rlog.error(msg.toString());
113: }
114:
115: return null;
116: }
117:
118: /**
119: * Clears the classmap and classname
120: * caches, and logs that we did so.
121: */
122: protected void clearCache() {
123: super.clearCache();
124: rlog.info(CACHEDUMP_MSG);
125: }
126: }
|