1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id:
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.runtime;
  20. import java.util.Vector;
  21. import java.lang.reflect.Modifier;
  22. import java.lang.reflect.Constructor;
  23. import java.lang.reflect.InvocationTargetException;
  24. import java.lang.reflect.Method;
  25. import java.lang.IllegalAccessException;
  26. import java.lang.IllegalArgumentException;
  27. import java.lang.InstantiationException;
  28. /**
  29. * Resolve the function dynamically
  30. */
  31. public final class CallFunction {
  32. public static String className;
  33. public static String methodName;
  34. public static int nArgs;
  35. public static Class clazz;
  36. public static String invokeMethod(String _className, String _methodName, Object [] _arguments){
  37. className = _className;
  38. methodName = _methodName;
  39. int size = _arguments.length-1;
  40. Object [] arguments = new Object[size];
  41. Object object= _arguments[0];
  42. clazz =null;
  43. try {
  44. clazz = ObjectFactory.findProviderClass(className, ObjectFactory.findClassLoader(), true);
  45. if (clazz == null) {
  46. throw new RuntimeException("Couldn't load the class");
  47. }
  48. }catch (ClassNotFoundException e) {
  49. throw new RuntimeException("Couldn't load the class");
  50. }
  51. for(int i=0,j=1;i<size;i++,++j){
  52. arguments[i] = _arguments[j];
  53. }
  54. nArgs = size;
  55. if( methodName != null ){
  56. Method method;
  57. if((method = findMethods(arguments)) == null){
  58. throw new RuntimeException("Method not found");
  59. }
  60. try{
  61. Object obj = method.invoke(object,arguments);
  62. return obj.toString() ;
  63. }
  64. catch(IllegalAccessException e){
  65. throw new RuntimeException("Error: Method is inaccessible");
  66. }
  67. catch(IllegalArgumentException e){
  68. throw new RuntimeException("Error: Number of actual and formal argument differ ");
  69. }
  70. catch(InvocationTargetException e){
  71. throw new RuntimeException("Error: underlying constructor throws an exception ");
  72. }
  73. }
  74. else {
  75. Constructor constructor;
  76. if((constructor = findConstructor(arguments)) == null){
  77. throw new RuntimeException("Constructor not found");
  78. }
  79. try{
  80. Object obs = constructor.newInstance(arguments);
  81. return obs.toString() ;
  82. }catch(InvocationTargetException e){
  83. throw new RuntimeException("Error: constructor throws an exception ");
  84. }
  85. catch(IllegalAccessException e){
  86. throw new RuntimeException("Error: constructor is inaccessible");
  87. }
  88. catch(IllegalArgumentException e){
  89. throw new RuntimeException("Error: Number of actual and formal argument differ ");
  90. }
  91. catch(InstantiationException e){
  92. throw new RuntimeException("Error: Class that declares the underlying constructor represents an abstract class");
  93. }
  94. }
  95. }
  96. /**
  97. * Returns a Constructor
  98. */
  99. private static Constructor findConstructor(Object[] arguments) {
  100. Vector constructors =null;
  101. final Constructor[] c_constructors = clazz.getConstructors();
  102. for (int i = 0; i < c_constructors.length; i++) {
  103. final int mods = c_constructors[i].getModifiers();
  104. // Is it public, static and same number of args ?
  105. if (Modifier.isPublic(mods) && c_constructors[i].getParameterTypes().length == nArgs){
  106. if (constructors == null) {
  107. constructors = new Vector();
  108. }
  109. constructors.addElement(c_constructors[i]);
  110. }
  111. }
  112. if (constructors == null) {
  113. // Method not found in this class
  114. throw new RuntimeException("CONSTRUCTOR_NOT_FOUND_ERR" + className +":"+ methodName);
  115. }
  116. int nConstructors = constructors.size();
  117. boolean accept=false;
  118. for (int j, i = 0; i < nConstructors; i++) {
  119. // Check if all parameters to this constructor can be converted
  120. final Constructor constructor = (Constructor)constructors.elementAt(i);
  121. final Class[] paramTypes = constructor.getParameterTypes();
  122. for (j = 0; j < nArgs; j++) {
  123. Class argumentClass = arguments[j].getClass();
  124. if (argumentClass == paramTypes[j]){
  125. accept= true;
  126. }
  127. else if(argumentClass.isAssignableFrom(paramTypes[j])){
  128. accept=true;
  129. }
  130. else {
  131. accept =false;
  132. break;
  133. }
  134. }
  135. if (accept)
  136. return constructor;
  137. }
  138. return null;
  139. }
  140. /**
  141. * Return the Method
  142. */
  143. private static Method findMethods(Object[] arguments) {
  144. Vector methods = null;
  145. final Method[] m_methods = clazz.getMethods();
  146. for (int i = 0; i < m_methods.length; i++){
  147. final int mods = m_methods[i].getModifiers();
  148. // Is it public and same number of args ?
  149. if( Modifier.isPublic(mods)
  150. && m_methods[i].getName().equals(methodName)
  151. && m_methods[i].getParameterTypes().length == nArgs){
  152. if (methods == null){
  153. methods = new Vector();
  154. }
  155. methods.addElement(m_methods[i]);
  156. }
  157. }
  158. if (methods == null) {
  159. // Method not found in this class
  160. throw new RuntimeException("METHOD_NOT_FOUND_ERR" + className +":"+ methodName);
  161. }
  162. int nMethods = methods.size();
  163. boolean accept=false;
  164. for (int j, i = 0; i < nMethods; i++) {
  165. // Check if all parameters to this constructor can be converted
  166. final Method method = (Method)methods.elementAt(i);
  167. final Class[] paramTypes = method.getParameterTypes();
  168. for (j = 0; j < nArgs; j++) {
  169. Class argumentClass = arguments[j].getClass();
  170. if (argumentClass == paramTypes[j]){
  171. accept= true;
  172. }
  173. else if(argumentClass.isAssignableFrom(paramTypes[j])){
  174. accept=true;
  175. }
  176. else if(paramTypes[j].isPrimitive() ){
  177. arguments[j] = isPrimitive(paramTypes[j],arguments[j]);
  178. accept = true;
  179. }
  180. else {
  181. accept =false;
  182. break;
  183. }
  184. }
  185. if (accept)
  186. return method;
  187. }
  188. return null;
  189. }
  190. public static Object isPrimitive(Class paramType, Object argument){
  191. if( argument.getClass() == Integer.class )
  192. return typeCast(paramType,(Integer)argument);
  193. else if( argument.getClass() == Float.class )
  194. return typeCast(paramType,(Float)argument);
  195. else if( argument.getClass() == Double.class )
  196. return typeCast(paramType,(Double)argument);
  197. else if( argument.getClass() == Long.class )
  198. return typeCast(paramType,(Long)argument);
  199. else if( argument.getClass() == Boolean.class )
  200. return (Boolean)argument;
  201. else if( argument.getClass() == Byte.class )
  202. return (Byte)argument;
  203. else
  204. return null;
  205. }
  206. static Object typeCast(Class paramType, Double object){
  207. if (paramType == Long.TYPE)
  208. return new Long(object.longValue());
  209. else if (paramType == Integer.TYPE)
  210. return new Integer(object.intValue());
  211. else if (paramType == Float.TYPE)
  212. return new Float(object.floatValue());
  213. else if (paramType == Short.TYPE)
  214. return new Short(object.shortValue());
  215. else if (paramType == Byte.TYPE)
  216. return new Byte(object.byteValue());
  217. else
  218. return object;
  219. }
  220. static Object typeCast(Class paramType, Long object){
  221. if (paramType == Integer.TYPE)
  222. return new Integer(object.intValue());
  223. else if (paramType == Float.TYPE)
  224. return new Float(object.floatValue());
  225. else if (paramType == Short.TYPE)
  226. return new Short(object.shortValue());
  227. else if (paramType == Byte.TYPE)
  228. return new Byte(object.byteValue());
  229. else
  230. return object;
  231. }
  232. static Object typeCast(Class paramType, Integer object){
  233. if(paramType == Double.TYPE)
  234. return new Double(object.doubleValue());
  235. else if (paramType == Float.TYPE)
  236. return new Float(object.floatValue());
  237. else if (paramType == Short.TYPE)
  238. return new Short(object.shortValue());
  239. else if (paramType == Byte.TYPE)
  240. return new Byte(object.byteValue());
  241. else
  242. return object;
  243. }
  244. static Object typeCast(Class paramType, Float object){
  245. if(paramType == Double.TYPE)
  246. return new Double(object.doubleValue());
  247. else if (paramType == Integer.TYPE)
  248. return new Float(object.intValue());
  249. else if (paramType == Short.TYPE)
  250. return new Short(object.shortValue());
  251. else if (paramType == Byte.TYPE)
  252. return new Byte(object.byteValue());
  253. else
  254. return object;
  255. }
  256. }