PageRenderTime 234ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 1ms

/apache-commons-ognl-3.0.2/src/main/java/org/apache/commons/ognl/OgnlRuntime.java

#
Java | 2782 lines | 1988 code | 399 blank | 395 comment | 588 complexity | 09fef185f02459fa6e4611a4ff7c2a06 MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * $Id$
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. package org.apache.commons.ognl;
  21. import org.apache.commons.ognl.enhance.ExpressionCompiler;
  22. import org.apache.commons.ognl.enhance.OgnlExpressionCompiler;
  23. import org.apache.commons.ognl.internal.ClassCache;
  24. import org.apache.commons.ognl.internal.ClassCacheImpl;
  25. import java.beans.BeanInfo;
  26. import java.beans.IndexedPropertyDescriptor;
  27. import java.beans.IntrospectionException;
  28. import java.beans.Introspector;
  29. import java.beans.MethodDescriptor;
  30. import java.beans.PropertyDescriptor;
  31. import java.lang.reflect.AccessibleObject;
  32. import java.lang.reflect.Array;
  33. import java.lang.reflect.Constructor;
  34. import java.lang.reflect.Field;
  35. import java.lang.reflect.GenericArrayType;
  36. import java.lang.reflect.InvocationTargetException;
  37. import java.lang.reflect.Member;
  38. import java.lang.reflect.Method;
  39. import java.lang.reflect.Modifier;
  40. import java.lang.reflect.ParameterizedType;
  41. import java.lang.reflect.Proxy;
  42. import java.lang.reflect.Type;
  43. import java.lang.reflect.TypeVariable;
  44. import java.math.BigDecimal;
  45. import java.math.BigInteger;
  46. import java.security.Permission;
  47. import java.util.ArrayList;
  48. import java.util.Arrays;
  49. import java.util.Collection;
  50. import java.util.Collections;
  51. import java.util.Enumeration;
  52. import java.util.HashMap;
  53. import java.util.IdentityHashMap;
  54. import java.util.Iterator;
  55. import java.util.List;
  56. import java.util.Map;
  57. import java.util.Set;
  58. /**
  59. * Utility class used by internal OGNL API to do various things like:
  60. *
  61. * <ul>
  62. * <li>Handles majority of reflection logic / caching. </li>
  63. * <li>Utility methods for casting strings / various numeric types used by {@link OgnlExpressionCompiler}.</li.
  64. * <li>Core runtime configuration point for setting/using global {@link TypeConverter} / {@link OgnlExpressionCompiler} /
  65. * {@link NullHandler} instances / etc.. </li>
  66. *</ul>
  67. *
  68. * @author Luke Blanshard (blanshlu@netscape.net)
  69. * @author Drew Davidson (drew@ognl.org)
  70. */
  71. public class OgnlRuntime {
  72. /**
  73. * Constant expression used to indicate that a given method / property couldn't be found
  74. * during reflection operations.
  75. */
  76. public static final Object NotFound = new Object();
  77. public static final List NotFoundList = new ArrayList();
  78. public static final Map NotFoundMap = new HashMap();
  79. public static final Object[] NoArguments = new Object[]{};
  80. public static final Class[] NoArgumentTypes = new Class[]{};
  81. /**
  82. * Token returned by TypeConverter for no conversion possible
  83. */
  84. public static final Object NoConversionPossible = "ognl.NoConversionPossible";
  85. /**
  86. * Not an indexed property
  87. */
  88. public static int INDEXED_PROPERTY_NONE = 0;
  89. /**
  90. * JavaBeans IndexedProperty
  91. */
  92. public static int INDEXED_PROPERTY_INT = 1;
  93. /**
  94. * OGNL ObjectIndexedProperty
  95. */
  96. public static int INDEXED_PROPERTY_OBJECT = 2;
  97. /**
  98. * Constant string representation of null string.
  99. */
  100. public static final String NULL_STRING = "" + null;
  101. /**
  102. * Java beans standard set method prefix.
  103. */
  104. private static final String SET_PREFIX = "set";
  105. /**
  106. * Java beans standard get method prefix.
  107. */
  108. private static final String GET_PREFIX = "get";
  109. /**
  110. * Java beans standard is<Foo> boolean getter prefix.
  111. */
  112. private static final String IS_PREFIX = "is";
  113. /**
  114. * Prefix padding for hexadecimal numbers to HEX_LENGTH.
  115. */
  116. private static final Map HEX_PADDING = new HashMap();
  117. private static final int HEX_LENGTH = 8;
  118. /**
  119. * Returned by <CODE>getUniqueDescriptor()</CODE> when the object is <CODE>null</CODE>.
  120. */
  121. private static final String NULL_OBJECT_STRING = "<null>";
  122. /**
  123. * Used to store the result of determining if current jvm is 1.5 language compatible.
  124. */
  125. private static boolean _jdk15 = false;
  126. private static boolean _jdkChecked = false;
  127. static final ClassCache _methodAccessors = new ClassCacheImpl();
  128. static final ClassCache _propertyAccessors = new ClassCacheImpl();
  129. static final ClassCache _elementsAccessors = new ClassCacheImpl();
  130. static final ClassCache _nullHandlers = new ClassCacheImpl();
  131. static final ClassCache _propertyDescriptorCache = new ClassCacheImpl();
  132. static final ClassCache _constructorCache = new ClassCacheImpl();
  133. static final ClassCache _staticMethodCache = new ClassCacheImpl();
  134. static final ClassCache _instanceMethodCache = new ClassCacheImpl();
  135. static final ClassCache _invokePermissionCache = new ClassCacheImpl();
  136. static final ClassCache _fieldCache = new ClassCacheImpl();
  137. static final List _superclasses = new ArrayList(); /* Used by fieldCache lookup */
  138. static final ClassCache[] _declaredMethods = new ClassCache[]{new ClassCacheImpl(), new ClassCacheImpl()};
  139. static final Map _primitiveTypes = new HashMap(101);
  140. static final ClassCache _primitiveDefaults = new ClassCacheImpl();
  141. static final Map _methodParameterTypesCache = new HashMap(101);
  142. static final Map _genericMethodParameterTypesCache = new HashMap(101);
  143. static final Map _ctorParameterTypesCache = new HashMap(101);
  144. static SecurityManager _securityManager = System.getSecurityManager();
  145. static final EvaluationPool _evaluationPool = new EvaluationPool();
  146. static final ObjectArrayPool _objectArrayPool = new ObjectArrayPool();
  147. static final IntHashMap _methodAccessCache = new IntHashMap();
  148. static final IntHashMap _methodPermCache = new IntHashMap();
  149. static ClassCacheInspector _cacheInspector;
  150. /**
  151. * Expression compiler used by {@link Ognl#compileExpression(OgnlContext, Object, String)} calls.
  152. */
  153. private static OgnlExpressionCompiler _compiler;
  154. /**
  155. * Lazy loading of Javassist library
  156. */
  157. static {
  158. try {
  159. Class.forName("javassist.ClassPool");
  160. _compiler = new ExpressionCompiler();
  161. } catch (ClassNotFoundException e) {
  162. throw new IllegalArgumentException("Javassist library is missing in classpath! Please add missed dependency!",e);
  163. }
  164. }
  165. private static IdentityHashMap PRIMITIVE_WRAPPER_CLASSES = new IdentityHashMap();
  166. /**
  167. * Used to provide primitive type equivalent conversions into and out of
  168. * native / object types.
  169. */
  170. static {
  171. PRIMITIVE_WRAPPER_CLASSES.put(Boolean.TYPE, Boolean.class);
  172. PRIMITIVE_WRAPPER_CLASSES.put(Boolean.class, Boolean.TYPE);
  173. PRIMITIVE_WRAPPER_CLASSES.put(Byte.TYPE, Byte.class);
  174. PRIMITIVE_WRAPPER_CLASSES.put(Byte.class, Byte.TYPE);
  175. PRIMITIVE_WRAPPER_CLASSES.put(Character.TYPE, Character.class);
  176. PRIMITIVE_WRAPPER_CLASSES.put(Character.class, Character.TYPE);
  177. PRIMITIVE_WRAPPER_CLASSES.put(Short.TYPE, Short.class);
  178. PRIMITIVE_WRAPPER_CLASSES.put(Short.class, Short.TYPE);
  179. PRIMITIVE_WRAPPER_CLASSES.put(Integer.TYPE, Integer.class);
  180. PRIMITIVE_WRAPPER_CLASSES.put(Integer.class, Integer.TYPE);
  181. PRIMITIVE_WRAPPER_CLASSES.put(Long.TYPE, Long.class);
  182. PRIMITIVE_WRAPPER_CLASSES.put(Long.class, Long.TYPE);
  183. PRIMITIVE_WRAPPER_CLASSES.put(Float.TYPE, Float.class);
  184. PRIMITIVE_WRAPPER_CLASSES.put(Float.class, Float.TYPE);
  185. PRIMITIVE_WRAPPER_CLASSES.put(Double.TYPE, Double.class);
  186. PRIMITIVE_WRAPPER_CLASSES.put(Double.class, Double.TYPE);
  187. }
  188. private static final Map NUMERIC_CASTS = new HashMap();
  189. /**
  190. * Constant strings for casting different primitive types.
  191. */
  192. static {
  193. NUMERIC_CASTS.put(Double.class, "(double)");
  194. NUMERIC_CASTS.put(Float.class, "(float)");
  195. NUMERIC_CASTS.put(Integer.class, "(int)");
  196. NUMERIC_CASTS.put(Long.class, "(long)");
  197. NUMERIC_CASTS.put(BigDecimal.class, "(double)");
  198. NUMERIC_CASTS.put(BigInteger.class, "");
  199. }
  200. private static final Map NUMERIC_VALUES = new HashMap();
  201. /**
  202. * Constant strings for getting the primitive value of different
  203. * native types on the generic {@link Number} object interface. (or the less
  204. * generic BigDecimal/BigInteger types)
  205. */
  206. static {
  207. NUMERIC_VALUES.put(Double.class, "doubleValue()");
  208. NUMERIC_VALUES.put(Float.class, "floatValue()");
  209. NUMERIC_VALUES.put(Integer.class, "intValue()");
  210. NUMERIC_VALUES.put(Long.class, "longValue()");
  211. NUMERIC_VALUES.put(Short.class, "shortValue()");
  212. NUMERIC_VALUES.put(Byte.class, "byteValue()");
  213. NUMERIC_VALUES.put(BigDecimal.class, "doubleValue()");
  214. NUMERIC_VALUES.put(BigInteger.class, "doubleValue()");
  215. NUMERIC_VALUES.put(Boolean.class, "booleanValue()");
  216. }
  217. private static final Map NUMERIC_LITERALS = new HashMap();
  218. /**
  219. * Numeric primitive literal string expressions.
  220. */
  221. static {
  222. NUMERIC_LITERALS.put(Integer.class, "");
  223. NUMERIC_LITERALS.put(Integer.TYPE, "");
  224. NUMERIC_LITERALS.put(Long.class, "l");
  225. NUMERIC_LITERALS.put(Long.TYPE, "l");
  226. NUMERIC_LITERALS.put(BigInteger.class, "d");
  227. NUMERIC_LITERALS.put(Float.class, "f");
  228. NUMERIC_LITERALS.put(Float.TYPE, "f");
  229. NUMERIC_LITERALS.put(Double.class, "d");
  230. NUMERIC_LITERALS.put(Double.TYPE, "d");
  231. NUMERIC_LITERALS.put(BigInteger.class, "d");
  232. NUMERIC_LITERALS.put(BigDecimal.class, "d");
  233. }
  234. private static final Map NUMERIC_DEFAULTS = new HashMap();
  235. static {
  236. NUMERIC_DEFAULTS.put(Boolean.class, Boolean.FALSE);
  237. NUMERIC_DEFAULTS.put(Byte.class, new Byte((byte) 0));
  238. NUMERIC_DEFAULTS.put(Short.class, new Short((short) 0));
  239. NUMERIC_DEFAULTS.put(Character.class, new Character((char) 0));
  240. NUMERIC_DEFAULTS.put(Integer.class, new Integer(0));
  241. NUMERIC_DEFAULTS.put(Long.class, new Long(0L));
  242. NUMERIC_DEFAULTS.put(Float.class, new Float(0.0f));
  243. NUMERIC_DEFAULTS.put(Double.class, new Double(0.0));
  244. NUMERIC_DEFAULTS.put(BigInteger.class, new BigInteger("0"));
  245. NUMERIC_DEFAULTS.put(BigDecimal.class, new BigDecimal(0.0));
  246. }
  247. static {
  248. PropertyAccessor p = new ArrayPropertyAccessor();
  249. setPropertyAccessor(Object.class, new ObjectPropertyAccessor());
  250. setPropertyAccessor(byte[].class, p);
  251. setPropertyAccessor(short[].class, p);
  252. setPropertyAccessor(char[].class, p);
  253. setPropertyAccessor(int[].class, p);
  254. setPropertyAccessor(long[].class, p);
  255. setPropertyAccessor(float[].class, p);
  256. setPropertyAccessor(double[].class, p);
  257. setPropertyAccessor(Object[].class, p);
  258. setPropertyAccessor(List.class, new ListPropertyAccessor());
  259. setPropertyAccessor(Map.class, new MapPropertyAccessor());
  260. setPropertyAccessor(Set.class, new SetPropertyAccessor());
  261. setPropertyAccessor(Iterator.class, new IteratorPropertyAccessor());
  262. setPropertyAccessor(Enumeration.class, new EnumerationPropertyAccessor());
  263. ElementsAccessor e = new ArrayElementsAccessor();
  264. setElementsAccessor(Object.class, new ObjectElementsAccessor());
  265. setElementsAccessor(byte[].class, e);
  266. setElementsAccessor(short[].class, e);
  267. setElementsAccessor(char[].class, e);
  268. setElementsAccessor(int[].class, e);
  269. setElementsAccessor(long[].class, e);
  270. setElementsAccessor(float[].class, e);
  271. setElementsAccessor(double[].class, e);
  272. setElementsAccessor(Object[].class, e);
  273. setElementsAccessor(Collection.class, new CollectionElementsAccessor());
  274. setElementsAccessor(Map.class, new MapElementsAccessor());
  275. setElementsAccessor(Iterator.class, new IteratorElementsAccessor());
  276. setElementsAccessor(Enumeration.class, new EnumerationElementsAccessor());
  277. setElementsAccessor(Number.class, new NumberElementsAccessor());
  278. NullHandler nh = new ObjectNullHandler();
  279. setNullHandler(Object.class, nh);
  280. setNullHandler(byte[].class, nh);
  281. setNullHandler(short[].class, nh);
  282. setNullHandler(char[].class, nh);
  283. setNullHandler(int[].class, nh);
  284. setNullHandler(long[].class, nh);
  285. setNullHandler(float[].class, nh);
  286. setNullHandler(double[].class, nh);
  287. setNullHandler(Object[].class, nh);
  288. MethodAccessor ma = new ObjectMethodAccessor();
  289. setMethodAccessor(Object.class, ma);
  290. setMethodAccessor(byte[].class, ma);
  291. setMethodAccessor(short[].class, ma);
  292. setMethodAccessor(char[].class, ma);
  293. setMethodAccessor(int[].class, ma);
  294. setMethodAccessor(long[].class, ma);
  295. setMethodAccessor(float[].class, ma);
  296. setMethodAccessor(double[].class, ma);
  297. setMethodAccessor(Object[].class, ma);
  298. _primitiveTypes.put("boolean", Boolean.TYPE);
  299. _primitiveTypes.put("byte", Byte.TYPE);
  300. _primitiveTypes.put("short", Short.TYPE);
  301. _primitiveTypes.put("char", Character.TYPE);
  302. _primitiveTypes.put("int", Integer.TYPE);
  303. _primitiveTypes.put("long", Long.TYPE);
  304. _primitiveTypes.put("float", Float.TYPE);
  305. _primitiveTypes.put("double", Double.TYPE);
  306. _primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
  307. _primitiveDefaults.put(Boolean.class, Boolean.FALSE);
  308. _primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0));
  309. _primitiveDefaults.put(Byte.class, new Byte((byte) 0));
  310. _primitiveDefaults.put(Short.TYPE, new Short((short) 0));
  311. _primitiveDefaults.put(Short.class, new Short((short) 0));
  312. _primitiveDefaults.put(Character.TYPE, new Character((char) 0));
  313. _primitiveDefaults.put(Integer.TYPE, new Integer(0));
  314. _primitiveDefaults.put(Long.TYPE, new Long(0L));
  315. _primitiveDefaults.put(Float.TYPE, new Float(0.0f));
  316. _primitiveDefaults.put(Double.TYPE, new Double(0.0));
  317. _primitiveDefaults.put(BigInteger.class, new BigInteger("0"));
  318. _primitiveDefaults.put(BigDecimal.class, new BigDecimal(0.0));
  319. }
  320. /**
  321. * Clears all of the cached reflection information normally used
  322. * to improve the speed of expressions that operate on the same classes
  323. * or are executed multiple times.
  324. *
  325. * <p>
  326. * <strong>Warning:</strong> Calling this too often can be a huge performance
  327. * drain on your expressions - use with care.
  328. * </p>
  329. */
  330. public static void clearCache()
  331. {
  332. _methodParameterTypesCache.clear();
  333. _ctorParameterTypesCache.clear();
  334. _propertyDescriptorCache.clear();
  335. _constructorCache.clear();
  336. _staticMethodCache.clear();
  337. _instanceMethodCache.clear();
  338. _invokePermissionCache.clear();
  339. _fieldCache.clear();
  340. _superclasses.clear();
  341. _declaredMethods[0].clear();
  342. _declaredMethods[1].clear();
  343. _methodAccessCache.clear();
  344. }
  345. /**
  346. * Checks if the current jvm is java language >= 1.5 compatible.
  347. *
  348. * @return True if jdk15 features are present.
  349. */
  350. public static boolean isJdk15()
  351. {
  352. if (_jdkChecked)
  353. return _jdk15;
  354. try
  355. {
  356. Class.forName("java.lang.annotation.Annotation");
  357. _jdk15 = true;
  358. } catch (Exception e) { /* ignore */ }
  359. _jdkChecked = true;
  360. return _jdk15;
  361. }
  362. public static String getNumericValueGetter(Class type)
  363. {
  364. return (String) NUMERIC_VALUES.get(type);
  365. }
  366. public static Class getPrimitiveWrapperClass(Class primitiveClass)
  367. {
  368. return (Class) PRIMITIVE_WRAPPER_CLASSES.get(primitiveClass);
  369. }
  370. public static String getNumericCast(Class type)
  371. {
  372. return (String) NUMERIC_CASTS.get(type);
  373. }
  374. public static String getNumericLiteral(Class type)
  375. {
  376. return (String) NUMERIC_LITERALS.get(type);
  377. }
  378. public static void setCompiler(OgnlExpressionCompiler compiler)
  379. {
  380. _compiler = compiler;
  381. }
  382. public static OgnlExpressionCompiler getCompiler()
  383. {
  384. return _compiler;
  385. }
  386. public static void compileExpression(OgnlContext context, Node expression, Object root)
  387. throws Exception
  388. {
  389. _compiler.compileExpression(context, expression, root);
  390. }
  391. /**
  392. * Gets the "target" class of an object for looking up accessors that are registered on the
  393. * target. If the object is a Class object this will return the Class itself, else it will
  394. * return object's getClass() result.
  395. */
  396. public static Class getTargetClass(Object o)
  397. {
  398. return (o == null) ? null : ((o instanceof Class) ? (Class) o : o.getClass());
  399. }
  400. /**
  401. * Returns the base name (the class name without the package name prepended) of the object
  402. * given.
  403. */
  404. public static String getBaseName(Object o)
  405. {
  406. return (o == null) ? null : getClassBaseName(o.getClass());
  407. }
  408. /**
  409. * Returns the base name (the class name without the package name prepended) of the class given.
  410. */
  411. public static String getClassBaseName(Class c)
  412. {
  413. String s = c.getName();
  414. return s.substring(s.lastIndexOf('.') + 1);
  415. }
  416. public static String getClassName(Object o, boolean fullyQualified)
  417. {
  418. if (!(o instanceof Class))
  419. {
  420. o = o.getClass();
  421. }
  422. return getClassName((Class) o, fullyQualified);
  423. }
  424. public static String getClassName(Class c, boolean fullyQualified)
  425. {
  426. return fullyQualified ? c.getName() : getClassBaseName(c);
  427. }
  428. /**
  429. * Returns the package name of the object's class.
  430. */
  431. public static String getPackageName(Object o)
  432. {
  433. return (o == null) ? null : getClassPackageName(o.getClass());
  434. }
  435. /**
  436. * Returns the package name of the class given.
  437. */
  438. public static String getClassPackageName(Class c)
  439. {
  440. String s = c.getName();
  441. int i = s.lastIndexOf('.');
  442. return (i < 0) ? null : s.substring(0, i);
  443. }
  444. /**
  445. * Returns a "pointer" string in the usual format for these things - 0x<hex digits>.
  446. */
  447. public static String getPointerString(int num)
  448. {
  449. StringBuffer result = new StringBuffer();
  450. String hex = Integer.toHexString(num), pad;
  451. Integer l = new Integer(hex.length());
  452. // result.append(HEX_PREFIX);
  453. if ((pad = (String) HEX_PADDING.get(l)) == null) {
  454. StringBuffer pb = new StringBuffer();
  455. for (int i = hex.length(); i < HEX_LENGTH; i++) {
  456. pb.append('0');
  457. }
  458. pad = new String(pb);
  459. HEX_PADDING.put(l, pad);
  460. }
  461. result.append(pad);
  462. result.append(hex);
  463. return new String(result);
  464. }
  465. /**
  466. * Returns a "pointer" string in the usual format for these things - 0x<hex digits> for the
  467. * object given. This will always return a unique value for each object.
  468. */
  469. public static String getPointerString(Object o)
  470. {
  471. return getPointerString((o == null) ? 0 : System.identityHashCode(o));
  472. }
  473. /**
  474. * Returns a unique descriptor string that includes the object's class and a unique integer
  475. * identifier. If fullyQualified is true then the class name will be fully qualified to include
  476. * the package name, else it will be just the class' base name.
  477. */
  478. public static String getUniqueDescriptor(Object object, boolean fullyQualified)
  479. {
  480. StringBuffer result = new StringBuffer();
  481. if (object != null) {
  482. if (object instanceof Proxy) {
  483. Class interfaceClass = object.getClass().getInterfaces()[0];
  484. result.append(getClassName(interfaceClass, fullyQualified));
  485. result.append('^');
  486. object = Proxy.getInvocationHandler(object);
  487. }
  488. result.append(getClassName(object, fullyQualified));
  489. result.append('@');
  490. result.append(getPointerString(object));
  491. } else {
  492. result.append(NULL_OBJECT_STRING);
  493. }
  494. return new String(result);
  495. }
  496. /**
  497. * Returns a unique descriptor string that includes the object's class' base name and a unique
  498. * integer identifier.
  499. */
  500. public static String getUniqueDescriptor(Object object)
  501. {
  502. return getUniqueDescriptor(object, false);
  503. }
  504. /**
  505. * Utility to convert a List into an Object[] array. If the list is zero elements this will
  506. * return a constant array; toArray() on List always returns a new object and this is wasteful
  507. * for our purposes.
  508. */
  509. public static Object[] toArray(List list)
  510. {
  511. Object[] result;
  512. int size = list.size();
  513. if (size == 0) {
  514. result = NoArguments;
  515. } else {
  516. result = getObjectArrayPool().create(list.size());
  517. for (int i = 0; i < size; i++) {
  518. result[i] = list.get(i);
  519. }
  520. }
  521. return result;
  522. }
  523. /**
  524. * Returns the parameter types of the given method.
  525. */
  526. public static Class[] getParameterTypes(Method m)
  527. {
  528. synchronized (_methodParameterTypesCache)
  529. {
  530. Class[] result;
  531. if ((result = (Class[]) _methodParameterTypesCache.get(m)) == null)
  532. {
  533. _methodParameterTypesCache.put(m, result = m.getParameterTypes());
  534. }
  535. return result;
  536. }
  537. }
  538. /**
  539. * Finds the appropriate parameter types for the given {@link Method} and
  540. * {@link Class} instance of the type the method is associated with. Correctly
  541. * finds generic types if running in >= 1.5 jre as well.
  542. *
  543. * @param type The class type the method is being executed against.
  544. * @param m The method to find types for.
  545. * @return Array of parameter types for the given method.
  546. */
  547. public static Class[] findParameterTypes(Class type, Method m)
  548. {
  549. if (type == null)
  550. {
  551. return getParameterTypes(m);
  552. }
  553. if (!isJdk15()
  554. || type.getGenericSuperclass() == null
  555. || !ParameterizedType.class.isInstance(type.getGenericSuperclass())
  556. || m.getDeclaringClass().getTypeParameters() == null)
  557. {
  558. return getParameterTypes(m);
  559. }
  560. synchronized (_genericMethodParameterTypesCache)
  561. {
  562. Class[] types;
  563. if ((types = (Class[]) _genericMethodParameterTypesCache.get(m)) != null)
  564. {
  565. ParameterizedType genericSuperclass = (ParameterizedType) type.getGenericSuperclass();
  566. if (Arrays.equals(types, genericSuperclass.getActualTypeArguments())) {
  567. return types;
  568. }
  569. }
  570. ParameterizedType param = (ParameterizedType)type.getGenericSuperclass();
  571. Type[] genTypes = m.getGenericParameterTypes();
  572. TypeVariable[] declaredTypes = m.getDeclaringClass().getTypeParameters();
  573. types = new Class[genTypes.length];
  574. typeSearch:
  575. for (int i=0; i < genTypes.length; i++)
  576. {
  577. TypeVariable paramType = null;
  578. if (TypeVariable.class.isInstance(genTypes[i]))
  579. {
  580. paramType = (TypeVariable)genTypes[i];
  581. } else if (GenericArrayType.class.isInstance(genTypes[i]))
  582. {
  583. paramType = (TypeVariable) ((GenericArrayType)genTypes[i]).getGenericComponentType();
  584. }
  585. else if (ParameterizedType.class.isInstance(genTypes[i]))
  586. {
  587. types[i] = (Class) ((ParameterizedType) genTypes[i]).getRawType();
  588. continue;
  589. } else if (Class.class.isInstance(genTypes[i]))
  590. {
  591. types[i] = (Class) genTypes[i];
  592. continue;
  593. }
  594. Class resolved = resolveType(param, paramType, declaredTypes);
  595. if (resolved != null)
  596. {
  597. if (GenericArrayType.class.isInstance(genTypes[i]))
  598. {
  599. resolved = Array.newInstance(resolved, 0).getClass();
  600. }
  601. types[i] = resolved;
  602. continue;
  603. }
  604. types[i] = m.getParameterTypes()[i];
  605. }
  606. _genericMethodParameterTypesCache.put(m, types);
  607. return types;
  608. }
  609. }
  610. static Class resolveType(ParameterizedType param, TypeVariable var, TypeVariable[] declaredTypes)
  611. {
  612. if (param.getActualTypeArguments().length < 1)
  613. return null;
  614. for (int i=0; i < declaredTypes.length; i++)
  615. {
  616. if (!TypeVariable.class.isInstance( param.getActualTypeArguments()[i])
  617. && declaredTypes[i].getName().equals(var.getName()))
  618. {
  619. return (Class) param.getActualTypeArguments()[i];
  620. }
  621. }
  622. /*
  623. for (int i=0; i < var.getBounds().length; i++)
  624. {
  625. Type t = var.getBounds()[i];
  626. Class resolvedType = null;
  627. if (ParameterizedType.class.isInstance(t))
  628. {
  629. ParameterizedType pparam = (ParameterizedType)t;
  630. for (int e=0; e < pparam.getActualTypeArguments().length; e++)
  631. {
  632. if (!TypeVariable.class.isInstance(pparam.getActualTypeArguments()[e]))
  633. continue;
  634. resolvedType = resolveType(pparam, (TypeVariable)pparam.getActualTypeArguments()[e], declaredTypes);
  635. }
  636. } else
  637. {
  638. resolvedType = findType(param.getActualTypeArguments(), (Class)t);
  639. }
  640. if (resolvedType != null)
  641. return resolvedType;
  642. }
  643. */
  644. return null;
  645. }
  646. static Class findType(Type[] types, Class type)
  647. {
  648. for (int i = 0; i < types.length; i++)
  649. {
  650. if (Class.class.isInstance(types[i]) && type.isAssignableFrom((Class)types[i]))
  651. return (Class)types[i];
  652. }
  653. return null;
  654. }
  655. /**
  656. * Returns the parameter types of the given method.
  657. */
  658. public static Class[] getParameterTypes(Constructor c)
  659. {
  660. synchronized (_ctorParameterTypesCache) {
  661. Class[] result;
  662. if ((result = (Class[]) _ctorParameterTypesCache.get(c)) == null) {
  663. _ctorParameterTypesCache.put(c, result = c.getParameterTypes());
  664. }
  665. return result;
  666. }
  667. }
  668. /**
  669. * Gets the SecurityManager that OGNL uses to determine permissions for invoking methods.
  670. *
  671. * @return SecurityManager for OGNL
  672. */
  673. public static SecurityManager getSecurityManager()
  674. {
  675. return _securityManager;
  676. }
  677. /**
  678. * Sets the SecurityManager that OGNL uses to determine permissions for invoking methods.
  679. *
  680. * @param value SecurityManager to set
  681. */
  682. public static void setSecurityManager(SecurityManager value)
  683. {
  684. _securityManager = value;
  685. }
  686. /**
  687. * Permission will be named "invoke.<declaring-class>.<method-name>".
  688. */
  689. public static Permission getPermission(Method method)
  690. {
  691. Permission result = null;
  692. Class mc = method.getDeclaringClass();
  693. synchronized (_invokePermissionCache) {
  694. Map permissions = (Map) _invokePermissionCache.get(mc);
  695. if (permissions == null) {
  696. _invokePermissionCache.put(mc, permissions = new HashMap(101));
  697. }
  698. if ((result = (Permission) permissions.get(method.getName())) == null) {
  699. result = new OgnlInvokePermission("invoke." + mc.getName() + "." + method.getName());
  700. permissions.put(method.getName(), result);
  701. }
  702. }
  703. return result;
  704. }
  705. public static Object invokeMethod(Object target, Method method, Object[] argsArray)
  706. throws InvocationTargetException, IllegalAccessException
  707. {
  708. boolean syncInvoke = false;
  709. boolean checkPermission = false;
  710. int mHash = method.hashCode();
  711. // only synchronize method invocation if it actually requires it
  712. synchronized(method) {
  713. if (_methodAccessCache.get(mHash) == null
  714. || _methodAccessCache.get(mHash) == Boolean.TRUE) {
  715. syncInvoke = true;
  716. }
  717. if (_securityManager != null && _methodPermCache.get(mHash) == null
  718. || _methodPermCache.get(mHash) == Boolean.FALSE) {
  719. checkPermission = true;
  720. }
  721. }
  722. Object result;
  723. boolean wasAccessible = true;
  724. if (syncInvoke)
  725. {
  726. synchronized(method)
  727. {
  728. if (checkPermission)
  729. {
  730. try
  731. {
  732. _securityManager.checkPermission(getPermission(method));
  733. _methodPermCache.put(mHash, Boolean.TRUE);
  734. } catch (SecurityException ex) {
  735. _methodPermCache.put(mHash, Boolean.FALSE);
  736. throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
  737. }
  738. }
  739. if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
  740. {
  741. if (!(wasAccessible = ((AccessibleObject) method).isAccessible()))
  742. {
  743. ((AccessibleObject) method).setAccessible(true);
  744. _methodAccessCache.put(mHash, Boolean.TRUE);
  745. } else
  746. {
  747. _methodAccessCache.put(mHash, Boolean.FALSE);
  748. }
  749. } else
  750. {
  751. _methodAccessCache.put(mHash, Boolean.FALSE);
  752. }
  753. result = method.invoke(target, argsArray);
  754. if (!wasAccessible)
  755. {
  756. ((AccessibleObject) method).setAccessible(false);
  757. }
  758. }
  759. } else
  760. {
  761. if (checkPermission)
  762. {
  763. try
  764. {
  765. _securityManager.checkPermission(getPermission(method));
  766. _methodPermCache.put(mHash, Boolean.TRUE);
  767. } catch (SecurityException ex) {
  768. _methodPermCache.put(mHash, Boolean.FALSE);
  769. throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
  770. }
  771. }
  772. result = method.invoke(target, argsArray);
  773. }
  774. return result;
  775. }
  776. /**
  777. * Gets the class for a method argument that is appropriate for looking up methods by
  778. * reflection, by looking for the standard primitive wrapper classes and exchanging for them
  779. * their underlying primitive class objects. Other classes are passed through unchanged.
  780. *
  781. * @param arg an object that is being passed to a method
  782. * @return the class to use to look up the method
  783. */
  784. public static final Class getArgClass(Object arg)
  785. {
  786. if (arg == null)
  787. return null;
  788. Class c = arg.getClass();
  789. if (c == Boolean.class)
  790. return Boolean.TYPE;
  791. else if (c.getSuperclass() == Number.class) {
  792. if (c == Integer.class)
  793. return Integer.TYPE;
  794. if (c == Double.class)
  795. return Double.TYPE;
  796. if (c == Byte.class)
  797. return Byte.TYPE;
  798. if (c == Long.class)
  799. return Long.TYPE;
  800. if (c == Float.class)
  801. return Float.TYPE;
  802. if (c == Short.class)
  803. return Short.TYPE;
  804. } else if (c == Character.class)
  805. return Character.TYPE;
  806. return c;
  807. }
  808. /**
  809. * Tells whether the given object is compatible with the given class ---that is, whether the
  810. * given object can be passed as an argument to a method or constructor whose parameter type is
  811. * the given class. If object is null this will return true because null is compatible with any
  812. * type.
  813. */
  814. public static final boolean isTypeCompatible(Object object, Class c)
  815. {
  816. boolean result = true;
  817. if (object != null) {
  818. if (c.isPrimitive()) {
  819. if (getArgClass(object) != c) {
  820. result = false;
  821. }
  822. } else if (!c.isInstance(object)) {
  823. result = false;
  824. }
  825. }
  826. return result;
  827. }
  828. /**
  829. * Tells whether the given array of objects is compatible with the given array of classes---that
  830. * is, whether the given array of objects can be passed as arguments to a method or constructor
  831. * whose parameter types are the given array of classes.
  832. */
  833. public static boolean areArgsCompatible(Object[] args, Class[] classes)
  834. {
  835. return areArgsCompatible(args, classes, null);
  836. }
  837. public static boolean areArgsCompatible(Object[] args, Class[] classes, Method m)
  838. {
  839. boolean result = true;
  840. boolean varArgs = m != null && isJdk15() && m.isVarArgs();
  841. if (args.length != classes.length && !varArgs) {
  842. result = false;
  843. } else if (varArgs) {
  844. for (int index = 0, count = args.length; result && (index < count); ++index) {
  845. if (index >= classes.length){
  846. break;
  847. }
  848. result = isTypeCompatible(args[index], classes[index]);
  849. if (!result && classes[index].isArray()) {
  850. result = isTypeCompatible(args[index], classes[index].getComponentType());
  851. }
  852. }
  853. } else {
  854. for (int index = 0, count = args.length; result && (index < count); ++index) {
  855. result = isTypeCompatible(args[index], classes[index]);
  856. }
  857. }
  858. return result;
  859. }
  860. /**
  861. * Tells whether the first array of classes is more specific than the second. Assumes that the
  862. * two arrays are of the same length.
  863. */
  864. public static final boolean isMoreSpecific(Class[] classes1, Class[] classes2)
  865. {
  866. for (int index = 0, count = classes1.length; index < count; ++index) {
  867. Class c1 = classes1[index], c2 = classes2[index];
  868. if (c1 == c2)
  869. continue;
  870. else if (c1.isPrimitive())
  871. return true;
  872. else if (c1.isAssignableFrom(c2))
  873. return false;
  874. else if (c2.isAssignableFrom(c1))
  875. return true;
  876. }
  877. // They are the same! So the first is not more specific than the second.
  878. return false;
  879. }
  880. public static String getModifierString(int modifiers)
  881. {
  882. String result;
  883. if (Modifier.isPublic(modifiers))
  884. result = "public";
  885. else if (Modifier.isProtected(modifiers))
  886. result = "protected";
  887. else if (Modifier.isPrivate(modifiers))
  888. result = "private";
  889. else
  890. result = "";
  891. if (Modifier.isStatic(modifiers))
  892. result = "static " + result;
  893. if (Modifier.isFinal(modifiers))
  894. result = "final " + result;
  895. if (Modifier.isNative(modifiers))
  896. result = "native " + result;
  897. if (Modifier.isSynchronized(modifiers))
  898. result = "synchronized " + result;
  899. if (Modifier.isTransient(modifiers))
  900. result = "transient " + result;
  901. return result;
  902. }
  903. public static Class classForName(OgnlContext context, String className)
  904. throws ClassNotFoundException
  905. {
  906. Class result = (Class) _primitiveTypes.get(className);
  907. if (result == null) {
  908. ClassResolver resolver;
  909. if ((context == null) || ((resolver = context.getClassResolver()) == null)) {
  910. resolver = OgnlContext.DEFAULT_CLASS_RESOLVER;
  911. }
  912. result = resolver.classForName(className, context);
  913. }
  914. if (result == null)
  915. throw new ClassNotFoundException("Unable to resolve class: " + className);
  916. return result;
  917. }
  918. public static boolean isInstance(OgnlContext context, Object value, String className)
  919. throws OgnlException
  920. {
  921. try {
  922. Class c = classForName(context, className);
  923. return c.isInstance(value);
  924. } catch (ClassNotFoundException e) {
  925. throw new OgnlException("No such class: " + className, e);
  926. }
  927. }
  928. public static Object getPrimitiveDefaultValue(Class forClass)
  929. {
  930. return _primitiveDefaults.get(forClass);
  931. }
  932. public static Object getNumericDefaultValue(Class forClass)
  933. {
  934. return NUMERIC_DEFAULTS.get(forClass);
  935. }
  936. public static Object getConvertedType(OgnlContext context, Object target, Member member, String propertyName,
  937. Object value, Class type)
  938. {
  939. return context.getTypeConverter().convertValue(context, target, member, propertyName, value, type);
  940. }
  941. public static boolean getConvertedTypes(OgnlContext context, Object target, Member member, String propertyName,
  942. Class[] parameterTypes, Object[] args, Object[] newArgs)
  943. {
  944. boolean result = false;
  945. if (parameterTypes.length == args.length) {
  946. result = true;
  947. for (int i = 0, ilast = parameterTypes.length - 1; result && (i <= ilast); i++) {
  948. Object arg = args[i];
  949. Class type = parameterTypes[i];
  950. if (isTypeCompatible(arg, type)) {
  951. newArgs[i] = arg;
  952. } else {
  953. Object v = getConvertedType(context, target, member, propertyName, arg, type);
  954. if (v == OgnlRuntime.NoConversionPossible) {
  955. result = false;
  956. } else {
  957. newArgs[i] = v;
  958. }
  959. }
  960. }
  961. }
  962. return result;
  963. }
  964. public static Method getConvertedMethodAndArgs(OgnlContext context, Object target, String propertyName,
  965. List methods, Object[] args, Object[] newArgs)
  966. {
  967. Method result = null;
  968. TypeConverter converter = context.getTypeConverter();
  969. if ((converter != null) && (methods != null))
  970. {
  971. for (int i = 0, icount = methods.size(); (result == null) && (i < icount); i++)
  972. {
  973. Method m = (Method) methods.get(i);
  974. Class[] parameterTypes = findParameterTypes(target != null ? target.getClass() : null, m);//getParameterTypes(m);
  975. if (getConvertedTypes(context, target, m, propertyName, parameterTypes, args, newArgs))
  976. {
  977. result = m;
  978. }
  979. }
  980. }
  981. return result;
  982. }
  983. public static Constructor getConvertedConstructorAndArgs(OgnlContext context, Object target, List constructors,
  984. Object[] args, Object[] newArgs)
  985. {
  986. Constructor result = null;
  987. TypeConverter converter = context.getTypeConverter();
  988. if ((converter != null) && (constructors != null)) {
  989. for (int i = 0, icount = constructors.size(); (result == null) && (i < icount); i++) {
  990. Constructor ctor = (Constructor) constructors.get(i);
  991. Class[] parameterTypes = getParameterTypes(ctor);
  992. if (getConvertedTypes(context, target, ctor, null, parameterTypes, args, newArgs)) {
  993. result = ctor;
  994. }
  995. }
  996. }
  997. return result;
  998. }
  999. /**
  1000. * Gets the appropriate method to be called for the given target, method name and arguments. If
  1001. * successful this method will return the Method within the target that can be called and the
  1002. * converted arguments in actualArgs. If unsuccessful this method will return null and the
  1003. * actualArgs will be empty.
  1004. *
  1005. * @param context The current execution context.
  1006. * @param source Target object to run against or method name.
  1007. * @param target Instance of object to be run against.
  1008. * @param propertyName Name of property to get method of.
  1009. * @param methods List of current known methods.
  1010. * @param args Arguments originally passed in.
  1011. * @param actualArgs Converted arguments.
  1012. *
  1013. * @return Best method match or null if none could be found.
  1014. */
  1015. public static Method getAppropriateMethod(OgnlContext context, Object source, Object target, String propertyName,
  1016. List methods, Object[] args, Object[] actualArgs)
  1017. {
  1018. Method result = null;
  1019. Class[] resultParameterTypes = null;
  1020. if (methods != null)
  1021. {
  1022. for (int i = 0, icount = methods.size(); i < icount; i++)
  1023. {
  1024. Method m = (Method) methods.get(i);
  1025. Class typeClass = target != null ? target.getClass() : null;
  1026. if (typeClass == null && source != null && Class.class.isInstance(source))
  1027. {
  1028. typeClass = (Class)source;
  1029. }
  1030. Class[] mParameterTypes = findParameterTypes(typeClass, m);
  1031. if (areArgsCompatible(args, mParameterTypes, m)
  1032. && ((result == null) || isMoreSpecific(mParameterTypes, resultParameterTypes)))
  1033. {
  1034. result = m;
  1035. resultParameterTypes = mParameterTypes;
  1036. System.arraycopy(args, 0, actualArgs, 0, args.length);
  1037. for (int j = 0; j < mParameterTypes.length; j++)
  1038. {
  1039. Class type = mParameterTypes[j];
  1040. if (type.isPrimitive() && (actualArgs[j] == null))
  1041. {
  1042. actualArgs[j] = getConvertedType(context, source, result, propertyName, null, type);
  1043. }
  1044. }
  1045. }
  1046. }
  1047. }
  1048. if (result == null)
  1049. {
  1050. result = getConvertedMethodAndArgs(context, target, propertyName, methods, args, actualArgs);
  1051. }
  1052. return result;
  1053. }
  1054. public static Object callAppropriateMethod(OgnlContext context, Object source, Object target, String methodName,
  1055. String propertyName, List methods, Object[] args)
  1056. throws MethodFailedException
  1057. {
  1058. Throwable reason = null;
  1059. Object[] actualArgs = _objectArrayPool.create(args.length);
  1060. try {
  1061. Method method = getAppropriateMethod(context, source, target, propertyName, methods, args, actualArgs);
  1062. if ((method == null) || !isMethodAccessible(context, source, method, propertyName))
  1063. {
  1064. StringBuffer buffer = new StringBuffer();
  1065. String className = "";
  1066. if (target != null)
  1067. {
  1068. className = target.getClass().getName() + ".";
  1069. }
  1070. for (int i = 0, ilast = args.length - 1; i <= ilast; i++)
  1071. {
  1072. Object arg = args[i];
  1073. buffer.append((arg == null) ? NULL_STRING : arg.getClass().getName());
  1074. if (i < ilast)
  1075. {
  1076. buffer.append(", ");
  1077. }
  1078. }
  1079. throw new NoSuchMethodException(className + methodName + "(" + buffer + ")");
  1080. }
  1081. Object[] convertedArgs = actualArgs;
  1082. if (isJdk15() && method.isVarArgs())
  1083. {
  1084. Class[] parmTypes = method.getParameterTypes();
  1085. // split arguments in to two dimensional array for varargs reflection invocation
  1086. // where it is expected that the parameter passed in to invoke the method
  1087. // will look like "new Object[] { arrayOfNonVarArgsArguments, arrayOfVarArgsArguments }"
  1088. for (int i=0; i < parmTypes.length; i++)
  1089. {
  1090. if (parmTypes[i].isArray())
  1091. {
  1092. convertedArgs = new Object[i + 1];
  1093. System.arraycopy(actualArgs, 0, convertedArgs, 0, convertedArgs.length);
  1094. Object[] varArgs;
  1095. // if they passed in varargs arguments grab them and dump in to new varargs array
  1096. if (actualArgs.length > i)
  1097. {
  1098. ArrayList varArgsList = new ArrayList();
  1099. for (int j=i; j < actualArgs.length; j++)
  1100. {
  1101. if (actualArgs[j] != null)
  1102. {
  1103. varArgsList.add(actualArgs[j]);
  1104. }
  1105. }
  1106. varArgs = varArgsList.toArray();
  1107. } else
  1108. {
  1109. varArgs = new Object[0];
  1110. }
  1111. convertedArgs[i] = varArgs;
  1112. break;
  1113. }
  1114. }
  1115. }
  1116. return invokeMethod(target, method, convertedArgs);
  1117. } catch (NoSuchMethodException e) {
  1118. reason = e;
  1119. } catch (IllegalAccessException e) {
  1120. reason = e;
  1121. } catch (InvocationTargetException e) {
  1122. reason = e.getTargetException();
  1123. } finally {
  1124. _objectArrayPool.recycle(actualArgs);
  1125. }
  1126. throw new MethodFailedException(source, methodName, reason);
  1127. }
  1128. public static Object callStaticMethod(OgnlContext context, String className, String methodName, Object[] args)
  1129. throws OgnlException
  1130. {
  1131. try {
  1132. Class targetClass = classForName(context, className);
  1133. if (targetClass == null)
  1134. throw new ClassNotFoundException("Unable to resolve class with name " + className);
  1135. MethodAccessor ma = getMethodAccessor(targetClass);
  1136. return ma.callStaticMethod(context, targetClass, methodName, args);
  1137. } catch (ClassNotFoundException ex) {
  1138. throw new MethodFailedException(className, methodName, ex);
  1139. }
  1140. }
  1141. /**
  1142. * Invokes the specified method against the target object.
  1143. *
  1144. * @param context
  1145. * The current execution context.
  1146. * @param target
  1147. * The object to invoke the method on.
  1148. * @param methodName
  1149. * Name of the method - as in "getValue" or "add", etc..
  1150. * @param propertyName
  1151. * Name of the property to call instead?
  1152. * @param args
  1153. * Optional arguments needed for method.
  1154. * @return Result of invoking method.
  1155. *
  1156. * @deprecated Use {@link #callMethod(OgnlContext, Object, String, Object[])} instead.
  1157. * @throws OgnlException For lots of different reasons.
  1158. */
  1159. public static Object callMethod(OgnlContext context, Object target, String methodName, String propertyName, Object[] args)
  1160. throws OgnlException
  1161. {
  1162. return callMethod(context, target, methodName == null ? propertyName : methodName, args);
  1163. }
  1164. /**
  1165. * Invokes the specified method against the target object.
  1166. *
  1167. * @param context
  1168. * The current execution context.
  1169. * @param target
  1170. * The object to invoke the method on.
  1171. * @param methodName
  1172. * Name of the method - as in "getValue" or "add", etc..
  1173. * @param args
  1174. * Optional arguments needed for method.
  1175. * @return Result of invoking method.
  1176. *
  1177. * @throws OgnlException For lots of different reasons.
  1178. */
  1179. public static Object callMethod(OgnlContext context, Object target, String methodName, Object[] args)
  1180. throws OgnlException
  1181. {
  1182. if (target == null)
  1183. throw new NullPointerException("target is null for method " + methodName);
  1184. return getMethodAccessor(target.getClass()).callMethod(context, target, methodName, args);
  1185. }
  1186. public static Object callConstructor(OgnlContext context, String className, Object[] args)
  1187. throws OgnlException
  1188. {
  1189. Throwable reason = null;
  1190. Object[] actualArgs = args;
  1191. try {
  1192. Constructor ctor = null;
  1193. Class[] ctorParameterTypes = null;
  1194. Class target = classForName(context, className);
  1195. List constructors = getConstructors(target);
  1196. for (int i = 0, icount = constructors.size(); i < icount; i++) {
  1197. Constructor c = (Constructor) constructo

Large files files are truncated, but you can click here to view the full file