001: /*
002: * Copyright 2001-2004 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: * $Id:
018: */
019:
020: package org.apache.xalan.xsltc.runtime;
021:
022: import java.util.Vector;
023: import java.lang.reflect.Modifier;
024: import java.lang.reflect.Constructor;
025: import java.lang.reflect.InvocationTargetException;
026: import java.lang.reflect.Method;
027: import java.lang.IllegalAccessException;
028: import java.lang.IllegalArgumentException;
029: import java.lang.InstantiationException;
030:
031: /**
032: * Resolve the function dynamically
033: */
034: public final class CallFunction {
035:
036: public static String className;
037: public static String methodName;
038: public static int nArgs;
039: public static Class clazz;
040:
041: public static String invokeMethod(String _className,
042: String _methodName, Object[] _arguments) {
043: className = _className;
044: methodName = _methodName;
045: int size = _arguments.length - 1;
046: Object[] arguments = new Object[size];
047: Object object = _arguments[0];
048: clazz = null;
049: try {
050: clazz = ObjectFactory.findProviderClass(className,
051: ObjectFactory.findClassLoader(), true);
052: if (clazz == null) {
053: throw new RuntimeException("Couldn't load the class");
054: }
055: } catch (ClassNotFoundException e) {
056: throw new RuntimeException("Couldn't load the class");
057: }
058:
059: for (int i = 0, j = 1; i < size; i++, ++j) {
060: arguments[i] = _arguments[j];
061: }
062: nArgs = size;
063: if (methodName != null) {
064: Method method;
065: if ((method = findMethods(arguments)) == null) {
066: throw new RuntimeException("Method not found");
067: }
068:
069: try {
070: Object obj = method.invoke(object, arguments);
071: return obj.toString();
072: } catch (IllegalAccessException e) {
073: throw new RuntimeException(
074: "Error: Method is inaccessible");
075: } catch (IllegalArgumentException e) {
076: throw new RuntimeException(
077: "Error: Number of actual and formal argument differ ");
078: } catch (InvocationTargetException e) {
079: throw new RuntimeException(
080: "Error: underlying constructor throws an exception ");
081: }
082: } else {
083: Constructor constructor;
084: if ((constructor = findConstructor(arguments)) == null) {
085: throw new RuntimeException("Constructor not found");
086: }
087: try {
088: Object obs = constructor.newInstance(arguments);
089: return obs.toString();
090: } catch (InvocationTargetException e) {
091: throw new RuntimeException(
092: "Error: constructor throws an exception ");
093: } catch (IllegalAccessException e) {
094: throw new RuntimeException(
095: "Error: constructor is inaccessible");
096: } catch (IllegalArgumentException e) {
097: throw new RuntimeException(
098: "Error: Number of actual and formal argument differ ");
099: } catch (InstantiationException e) {
100: throw new RuntimeException(
101: "Error: Class that declares the underlying constructor represents an abstract class");
102: }
103: }
104:
105: }
106:
107: /**
108: * Returns a Constructor
109: */
110: private static Constructor findConstructor(Object[] arguments) {
111: Vector constructors = null;
112:
113: final Constructor[] c_constructors = clazz.getConstructors();
114:
115: for (int i = 0; i < c_constructors.length; i++) {
116: final int mods = c_constructors[i].getModifiers();
117: // Is it public, static and same number of args ?
118: if (Modifier.isPublic(mods)
119: && c_constructors[i].getParameterTypes().length == nArgs) {
120: if (constructors == null) {
121: constructors = new Vector();
122: }
123: constructors.addElement(c_constructors[i]);
124: }
125: }
126:
127: if (constructors == null) {
128: // Method not found in this class
129: throw new RuntimeException("CONSTRUCTOR_NOT_FOUND_ERR"
130: + className + ":" + methodName);
131: }
132:
133: int nConstructors = constructors.size();
134: boolean accept = false;
135: for (int j, i = 0; i < nConstructors; i++) {
136: // Check if all parameters to this constructor can be converted
137: final Constructor constructor = (Constructor) constructors
138: .elementAt(i);
139: final Class[] paramTypes = constructor.getParameterTypes();
140:
141: for (j = 0; j < nArgs; j++) {
142: Class argumentClass = arguments[j].getClass();
143: if (argumentClass == paramTypes[j]) {
144: accept = true;
145: } else if (argumentClass
146: .isAssignableFrom(paramTypes[j])) {
147: accept = true;
148: } else {
149: accept = false;
150: break;
151: }
152: }
153: if (accept)
154: return constructor;
155: }
156: return null;
157: }
158:
159: /**
160: * Return the Method
161: */
162: private static Method findMethods(Object[] arguments) {
163: Vector methods = null;
164:
165: final Method[] m_methods = clazz.getMethods();
166:
167: for (int i = 0; i < m_methods.length; i++) {
168: final int mods = m_methods[i].getModifiers();
169: // Is it public and same number of args ?
170: if (Modifier.isPublic(mods)
171: && m_methods[i].getName().equals(methodName)
172: && m_methods[i].getParameterTypes().length == nArgs) {
173: if (methods == null) {
174: methods = new Vector();
175: }
176: methods.addElement(m_methods[i]);
177: }
178: }
179:
180: if (methods == null) {
181: // Method not found in this class
182: throw new RuntimeException("METHOD_NOT_FOUND_ERR"
183: + className + ":" + methodName);
184: }
185: int nMethods = methods.size();
186: boolean accept = false;
187: for (int j, i = 0; i < nMethods; i++) {
188: // Check if all parameters to this constructor can be converted
189: final Method method = (Method) methods.elementAt(i);
190: final Class[] paramTypes = method.getParameterTypes();
191:
192: for (j = 0; j < nArgs; j++) {
193: Class argumentClass = arguments[j].getClass();
194: if (argumentClass == paramTypes[j]) {
195: accept = true;
196: } else if (argumentClass
197: .isAssignableFrom(paramTypes[j])) {
198: accept = true;
199: } else if (paramTypes[j].isPrimitive()) {
200: arguments[j] = isPrimitive(paramTypes[j],
201: arguments[j]);
202: accept = true;
203: } else {
204: accept = false;
205: break;
206: }
207:
208: }
209: if (accept)
210: return method;
211: }
212:
213: return null;
214: }
215:
216: public static Object isPrimitive(Class paramType, Object argument) {
217:
218: if (argument.getClass() == Integer.class)
219: return typeCast(paramType, (Integer) argument);
220: else if (argument.getClass() == Float.class)
221: return typeCast(paramType, (Float) argument);
222: else if (argument.getClass() == Double.class)
223: return typeCast(paramType, (Double) argument);
224: else if (argument.getClass() == Long.class)
225: return typeCast(paramType, (Long) argument);
226: else if (argument.getClass() == Boolean.class)
227: return (Boolean) argument;
228: else if (argument.getClass() == Byte.class)
229: return (Byte) argument;
230: else
231: return null;
232: }
233:
234: static Object typeCast(Class paramType, Double object) {
235: if (paramType == Long.TYPE)
236: return new Long(object.longValue());
237: else if (paramType == Integer.TYPE)
238: return new Integer(object.intValue());
239: else if (paramType == Float.TYPE)
240: return new Float(object.floatValue());
241: else if (paramType == Short.TYPE)
242: return new Short(object.shortValue());
243: else if (paramType == Byte.TYPE)
244: return new Byte(object.byteValue());
245: else
246: return object;
247: }
248:
249: static Object typeCast(Class paramType, Long object) {
250: if (paramType == Integer.TYPE)
251: return new Integer(object.intValue());
252: else if (paramType == Float.TYPE)
253: return new Float(object.floatValue());
254: else if (paramType == Short.TYPE)
255: return new Short(object.shortValue());
256: else if (paramType == Byte.TYPE)
257: return new Byte(object.byteValue());
258: else
259: return object;
260: }
261:
262: static Object typeCast(Class paramType, Integer object) {
263: if (paramType == Double.TYPE)
264: return new Double(object.doubleValue());
265: else if (paramType == Float.TYPE)
266: return new Float(object.floatValue());
267: else if (paramType == Short.TYPE)
268: return new Short(object.shortValue());
269: else if (paramType == Byte.TYPE)
270: return new Byte(object.byteValue());
271: else
272: return object;
273: }
274:
275: static Object typeCast(Class paramType, Float object) {
276: if (paramType == Double.TYPE)
277: return new Double(object.doubleValue());
278: else if (paramType == Integer.TYPE)
279: return new Float(object.intValue());
280: else if (paramType == Short.TYPE)
281: return new Short(object.shortValue());
282: else if (paramType == Byte.TYPE)
283: return new Byte(object.byteValue());
284: else
285: return object;
286: }
287:
288: }
|