View Javadoc

1   // Method.java, created Thu Jul  4  4:50:03 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
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      // additional instance field.
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     // additional methods.
127     // ONLY TO BE CALLED BY jq_Member CONSTRUCTOR!!!
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         // TODO: exception types
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 }