1
2
3
4 package joeq.ClassLib.Common.java.lang.reflect;
5
6 import joeq.Class.jq_Class;
7 import joeq.Class.jq_InstanceMethod;
8 import joeq.Class.jq_Method;
9 import joeq.Class.jq_NameAndDesc;
10 import joeq.Class.jq_Primitive;
11 import joeq.Class.jq_Reference;
12 import joeq.Class.jq_Type;
13 import joeq.ClassLib.ClassLibInterface;
14 import joeq.ClassLib.Common.ClassUtils;
15 import joeq.Main.jq;
16 import joeq.Memory.HeapAddress;
17 import joeq.Runtime.Reflection;
18 import joeq.Runtime.TypeCheck;
19 import joeq.UTF.Utf8;
20 import jwutil.util.Assert;
21 import jwutil.util.Convert;
22
23 /***
24 * Method
25 *
26 * @author John Whaley <jwhaley@alum.mit.edu>
27 * @version $Id: Method.java 1941 2004-09-30 03:37:06Z joewhaley $
28 */
29 public class Method extends AccessibleObject {
30
31
32 public final jq_Method jq_method;
33
34 private java.lang.Class clazz;
35 private java.lang.String name;
36 private java.lang.Class[] parameterTypes;
37 private java.lang.Class returnType;
38 private java.lang.Class[] exceptionTypes;
39 private int modifiers;
40 private int slot;
41
42 private Method(jq_Method m) {
43 this.jq_method = m;
44 }
45 private Method(java.lang.Class clazz,
46 java.lang.String name,
47 java.lang.Class[] parameterTypes,
48 java.lang.Class returnType,
49 java.lang.Class[] exceptionTypes,
50 int modifiers,
51 int slot) {
52 this.clazz = clazz;
53 this.name = name;
54 this.parameterTypes = parameterTypes;
55 this.returnType = returnType;
56 this.exceptionTypes = exceptionTypes;
57 this.modifiers = modifiers;
58 this.slot = slot;
59
60 jq_Class k = (jq_Class) ClassLibInterface.DEFAULT.getJQType(clazz);
61 StringBuffer desc = new StringBuffer();
62 desc.append('(');
63 for (int i=0; i<parameterTypes.length; ++i) {
64 desc.append(Reflection.getJQType(parameterTypes[i]).getDesc().toString());
65 }
66 desc.append(')');
67 desc.append(Reflection.getJQType(returnType).getDesc().toString());
68 jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get(name), Utf8.get(desc.toString()));
69 nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(k, nd);
70 jq_Method m = (jq_Method) k.getDeclaredMember(nd);
71 if (m == null) {
72 if (java.lang.reflect.Modifier.isStatic(modifiers))
73 m = k.getOrCreateStaticMethod(nd);
74 else
75 m = k.getOrCreateInstanceMethod(nd);
76 }
77 this.jq_method = m;
78 }
79
80 public java.lang.Object invoke(java.lang.Object obj,
81 java.lang.Object[] initargs)
82 throws java.lang.InstantiationException, java.lang.IllegalAccessException,
83 java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException
84 {
85 jq_Method jq_m = this.jq_method;
86 jq_Class k = jq_m.getDeclaringClass();
87 if (!jq_m.isStatic()) {
88 jq_Reference t = jq_Reference.getTypeOf(obj);
89 if (!TypeCheck.isAssignable(t, k))
90 throw new java.lang.IllegalArgumentException(t+" is not assignable to "+k);
91 }
92 if (!this.isAccessible()) ClassUtils.checkCallerAccess(jq_m, 2);
93 int offset;
94 if (jq_m.isStatic()) {
95 obj = null; offset = 0;
96 } else {
97 offset = 1;
98 }
99 jq_Type[] argtypes = jq_m.getParamTypes();
100 int nargs = initargs==null ? 0 : initargs.length;
101 if (nargs != argtypes.length-offset)
102 throw new java.lang.IllegalArgumentException();
103 if (jq_m.isStatic()) {
104 k.cls_initialize();
105 } else {
106 jq_Reference t = jq_Reference.getTypeOf(obj);
107 jq_m = t.getVirtualMethod(jq_m.getNameAndDesc());
108 if (jq_m == null || jq_m.isAbstract())
109 throw new java.lang.AbstractMethodError();
110 }
111 jq_Type retType = jq_m.getReturnType();
112 if (retType.isReferenceType())
113 return ((HeapAddress) Reflection.invokeA(jq_m, obj, initargs)).asObject();
114 long result = Reflection.invoke(jq_m, obj, initargs);
115 if (retType == jq_Primitive.VOID) return null;
116 if (retType == jq_Primitive.INT) return new Integer((int)result);
117 if (retType == jq_Primitive.LONG) return new Long(result);
118 if (retType == jq_Primitive.FLOAT) return new Float(Float.intBitsToFloat((int)result));
119 if (retType == jq_Primitive.DOUBLE) return new Double(Double.longBitsToDouble(result));
120 if (retType == jq_Primitive.BOOLEAN) return Convert.getBoolean((int)result!=0);
121 if (retType == jq_Primitive.BYTE) return new Byte((byte)result);
122 if (retType == jq_Primitive.SHORT) return new Short((short)result);
123 if (retType == jq_Primitive.CHAR) return new Character((char)result);
124 Assert.UNREACHABLE(); return null;
125 }
126
127
128 public static java.lang.reflect.Method createNewMethod(jq_Method jq_method) {
129 Object o = new Method(jq_method);
130 return (java.lang.reflect.Method)o;
131 }
132
133 public static void initNewMethod(Method o, jq_Method jq_method) {
134 if (!jq.RunningNative) return;
135 java.lang.String name = jq_method.getName().toString();
136 o.name = name;
137 java.lang.Class clazz = jq_method.getDeclaringClass().getJavaLangClassObject();
138 Assert._assert(clazz != null);
139 o.clazz = clazz;
140 java.lang.Class returnType = jq_method.getReturnType().getJavaLangClassObject();
141 Assert._assert(returnType != null);
142 o.returnType = returnType;
143 jq_Type[] paramTypes = jq_method.getParamTypes();
144 int offset;
145 if (jq_method instanceof jq_InstanceMethod)
146 offset = 1;
147 else
148 offset = 0;
149 java.lang.Class[] parameterTypes = new java.lang.Class[paramTypes.length-offset];
150 for (int i=offset; i<paramTypes.length; ++i) {
151 parameterTypes[i-offset] = Reflection.getJDKType(paramTypes[i]);
152 Assert._assert(parameterTypes[i-offset] != null);
153 }
154 o.parameterTypes = parameterTypes;
155
156 java.lang.Class[] exceptionTypes = new java.lang.Class[0];
157 o.exceptionTypes = exceptionTypes;
158 int modifiers = jq_method.getAccessFlags();
159 o.modifiers = modifiers;
160 }
161 }