/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: */ package org.apache.xalan.xsltc.runtime; import java.util.Vector; import java.lang.reflect.Modifier; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.IllegalAccessException; import java.lang.IllegalArgumentException; import java.lang.InstantiationException; /** * Resolve the function dynamically */ public final class CallFunction { public static String className; public static String methodName; public static int nArgs; public static Class clazz; public static String invokeMethod(String _className, String _methodName, Object [] _arguments){ className = _className; methodName = _methodName; int size = _arguments.length-1; Object [] arguments = new Object[size]; Object object= _arguments[0]; clazz =null; try { clazz = ObjectFactory.findProviderClass(className, ObjectFactory.findClassLoader(), true); if (clazz == null) { throw new RuntimeException("Couldn't load the class"); } }catch (ClassNotFoundException e) { throw new RuntimeException("Couldn't load the class"); } for(int i=0,j=1;i<size;i++,++j){ arguments[i] = _arguments[j]; } nArgs = size; if( methodName != null ){ Method method; if((method = findMethods(arguments)) == null){ throw new RuntimeException("Method not found"); } try{ Object obj = method.invoke(object,arguments); return obj.toString() ; } catch(IllegalAccessException e){ throw new RuntimeException("Error: Method is inaccessible"); } catch(IllegalArgumentException e){ throw new RuntimeException("Error: Number of actual and formal argument differ "); } catch(InvocationTargetException e){ throw new RuntimeException("Error: underlying constructor throws an exception "); } } else { Constructor constructor; if((constructor = findConstructor(arguments)) == null){ throw new RuntimeException("Constructor not found"); } try{ Object obs = constructor.newInstance(arguments); return obs.toString() ; }catch(InvocationTargetException e){ throw new RuntimeException("Error: constructor throws an exception "); } catch(IllegalAccessException e){ throw new RuntimeException("Error: constructor is inaccessible"); } catch(IllegalArgumentException e){ throw new RuntimeException("Error: Number of actual and formal argument differ "); } catch(InstantiationException e){ throw new RuntimeException("Error: Class that declares the underlying constructor represents an abstract class"); } } } /** * Returns a Constructor */ private static Constructor findConstructor(Object[] arguments) { Vector constructors =null; final Constructor[] c_constructors = clazz.getConstructors(); for (int i = 0; i < c_constructors.length; i++) { final int mods = c_constructors[i].getModifiers(); // Is it public, static and same number of args ? if (Modifier.isPublic(mods) && c_constructors[i].getParameterTypes().length == nArgs){ if (constructors == null) { constructors = new Vector(); } constructors.addElement(c_constructors[i]); } } if (constructors == null) { // Method not found in this class throw new RuntimeException("CONSTRUCTOR_NOT_FOUND_ERR" + className +":"+ methodName); } int nConstructors = constructors.size(); boolean accept=false; for (int j, i = 0; i < nConstructors; i++) { // Check if all parameters to this constructor can be converted final Constructor constructor = (Constructor)constructors.elementAt(i); final Class[] paramTypes = constructor.getParameterTypes(); for (j = 0; j < nArgs; j++) { Class argumentClass = arguments[j].getClass(); if (argumentClass == paramTypes[j]){ accept= true; } else if(argumentClass.isAssignableFrom(paramTypes[j])){ accept=true; } else { accept =false; break; } } if (accept) return constructor; } return null; } /** * Return the Method */ private static Method findMethods(Object[] arguments) { Vector methods = null; final Method[] m_methods = clazz.getMethods(); for (int i = 0; i < m_methods.length; i++){ final int mods = m_methods[i].getModifiers(); // Is it public and same number of args ? if( Modifier.isPublic(mods) && m_methods[i].getName().equals(methodName) && m_methods[i].getParameterTypes().length == nArgs){ if (methods == null){ methods = new Vector(); } methods.addElement(m_methods[i]); } } if (methods == null) { // Method not found in this class throw new RuntimeException("METHOD_NOT_FOUND_ERR" + className +":"+ methodName); } int nMethods = methods.size(); boolean accept=false; for (int j, i = 0; i < nMethods; i++) { // Check if all parameters to this constructor can be converted final Method method = (Method)methods.elementAt(i); final Class[] paramTypes = method.getParameterTypes(); for (j = 0; j < nArgs; j++) { Class argumentClass = arguments[j].getClass(); if (argumentClass == paramTypes[j]){ accept= true; } else if(argumentClass.isAssignableFrom(paramTypes[j])){ accept=true; } else if(paramTypes[j].isPrimitive() ){ arguments[j] = isPrimitive(paramTypes[j],arguments[j]); accept = true; } else { accept =false; break; } } if (accept) return method; } return null; } public static Object isPrimitive(Class paramType, Object argument){ if( argument.getClass() == Integer.class ) return typeCast(paramType,(Integer)argument); else if( argument.getClass() == Float.class ) return typeCast(paramType,(Float)argument); else if( argument.getClass() == Double.class ) return typeCast(paramType,(Double)argument); else if( argument.getClass() == Long.class ) return typeCast(paramType,(Long)argument); else if( argument.getClass() == Boolean.class ) return (Boolean)argument; else if( argument.getClass() == Byte.class ) return (Byte)argument; else return null; } static Object typeCast(Class paramType, Double object){ if (paramType == Long.TYPE) return new Long(object.longValue()); else if (paramType == Integer.TYPE) return new Integer(object.intValue()); else if (paramType == Float.TYPE) return new Float(object.floatValue()); else if (paramType == Short.TYPE) return new Short(object.shortValue()); else if (paramType == Byte.TYPE) return new Byte(object.byteValue()); else return object; } static Object typeCast(Class paramType, Long object){ if (paramType == Integer.TYPE) return new Integer(object.intValue()); else if (paramType == Float.TYPE) return new Float(object.floatValue()); else if (paramType == Short.TYPE) return new Short(object.shortValue()); else if (paramType == Byte.TYPE) return new Byte(object.byteValue()); else return object; } static Object typeCast(Class paramType, Integer object){ if(paramType == Double.TYPE) return new Double(object.doubleValue()); else if (paramType == Float.TYPE) return new Float(object.floatValue()); else if (paramType == Short.TYPE) return new Short(object.shortValue()); else if (paramType == Byte.TYPE) return new Byte(object.byteValue()); else return object; } static Object typeCast(Class paramType, Float object){ if(paramType == Double.TYPE) return new Double(object.doubleValue()); else if (paramType == Integer.TYPE) return new Float(object.intValue()); else if (paramType == Short.TYPE) return new Short(object.shortValue()); else if (paramType == Byte.TYPE) return new Byte(object.byteValue()); else return object; } }