1 cananian 1.1.2.1 // INClass.java, created Mon Dec 28 21:24:34 1998 by cananian
  2 cananian 1.1.2.3 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.3 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1 package harpoon.Interpret.Quads;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.2 import harpoon.ClassFile.HClass;
  7 cananian 1.1.2.2 import harpoon.ClassFile.HMethod;
  8 cananian 1.1.2.5 import harpoon.ClassFile.NoSuchClassException;
  9 cananian 1.1.2.1 
 10 cananian 1.1.2.7 import harpoon.Util.Util;
 11 cananian 1.1.2.7 
 12 cananian 1.1.2.1 import java.lang.reflect.Modifier;
 13 cananian 1.1.2.1 import java.util.Hashtable;
 14 cananian 1.1.2.1 /**
 15 cananian 1.1.2.1  * <code>INClass</code> provides implementations of the native methods in
 16 cananian 1.1.2.1  * <code>java.lang.Class</code>.
 17 cananian 1.1.2.1  * 
 18 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 19 cananian 1.4      * @version $Id: INClass.java,v 1.4 2002/04/10 03:05:50 cananian Exp $
 20 cananian 1.1.2.1  */
 21 cananian 1.1.2.5 public class INClass {
 22 cananian 1.1.2.1     static final void register(StaticState ss) {
 23 cananian 1.1.2.7         try { // JDK 1.2 only
 24 cananian 1.1.2.7             ss.register(forName0(ss));
 25 cananian 1.1.2.7         } catch (NoSuchMethodError e) { // JDK 1.1 fallback.
 26 cananian 1.1.2.7             ss.register(forName(ss));
 27 cananian 1.1.2.7         }
 28 cananian 1.1.2.5         ss.register(getComponentType(ss));
 29 cananian 1.1.2.5         ss.register(getInterfaces(ss));
 30 cananian 1.1.2.5         ss.register(getModifiers(ss));
 31 cananian 1.1.2.5         ss.register(getName(ss));
 32 cananian 1.1.2.5         ss.register(getPrimitiveClass(ss));
 33 cananian 1.1.2.5         ss.register(getSuperclass(ss));
 34 cananian 1.1.2.5         ss.register(isArray(ss));
 35 cananian 1.1.2.5         ss.register(isInterface(ss));
 36 cananian 1.1.2.5         ss.register(isPrimitive(ss));
 37 cananian 1.1.2.7         try { // JDK 1.2 only
 38 cananian 1.1.2.7             ss.register(newInstance0(ss));
 39 cananian 1.1.2.7         } catch (NoSuchMethodError e) { // JDK 1.1 fallback.
 40 cananian 1.1.2.7             ss.register(newInstance(ss));
 41 cananian 1.1.2.7         }
 42 cananian 1.1.2.1         // registry for name->class mapping
 43 cananian 1.1.2.5         ss.putNativeClosure(ss.HCclass, new Hashtable());
 44 cananian 1.1.2.4         // JDK 1.2 only
 45 cananian 1.1.2.5         try { ss.register(registerNatives(ss)); } catch (NoSuchMethodError e){}
 46 cananian 1.1.2.6         try { ss.register(getClassLoader0(ss)); } catch (NoSuchMethodError e){}
 47 cananian 1.1.2.1     }
 48 cananian 1.1.2.1     static final ObjectRef forClass(StaticState ss, HClass hc)
 49 cananian 1.1.2.1         throws InterpretedThrowable {
 50 cananian 1.1.2.5         Hashtable registry = (Hashtable) ss.getNativeClosure(ss.HCclass);
 51 cananian 1.1.2.1         ObjectRef obj = (ObjectRef) registry.get(hc);
 52 cananian 1.1.2.1         if (obj!=null) return obj;
 53 cananian 1.1.2.5         obj = new ObjectRef(ss, ss.HCclass);
 54 cananian 1.1.2.5         Method.invoke(ss, ss.HCclass.getConstructor(new HClass[0]),
 55 cananian 1.1.2.1                       new Object[] { obj } );
 56 cananian 1.1.2.1         obj.putClosure(hc);
 57 cananian 1.1.2.1         registry.put(hc, obj);
 58 cananian 1.1.2.1         return obj;
 59 cananian 1.1.2.1     }
 60 cananian 1.1.2.5     private static final NativeMethod forName(StaticState ss0) {
 61 cananian 1.1.2.1         final HMethod hm =
 62 cananian 1.1.2.5             ss0.HCclass.getMethod("forName", new HClass[] { ss0.HCstring });
 63 cananian 1.1.2.1         return new NativeMethod() {
 64 cananian 1.1.2.1             HMethod getMethod() { return hm; }
 65 cananian 1.1.2.1             // throws ClassNotFoundException
 66 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params)
 67 cananian 1.1.2.1                 throws InterpretedThrowable {
 68 cananian 1.1.2.1                 String clsname = ss.ref2str((ObjectRef)params[0]);
 69 cananian 1.1.2.1                 try {
 70 cananian 1.1.2.5                     return forClass(ss, ss.linker.forName(clsname));
 71 cananian 1.1.2.5                 } catch (NoSuchClassException e) {
 72 cananian 1.1.2.5                     ObjectRef obj = ss.makeThrowable(ss.HCclassnotfoundE);
 73 cananian 1.1.2.1                     throw new InterpretedThrowable(obj, ss);
 74 cananian 1.1.2.1                 }
 75 cananian 1.1.2.1             }
 76 cananian 1.1.2.1         };
 77 cananian 1.1.2.1     }
 78 cananian 1.1.2.7     // JDK 1.2 version of forName()
 79 cananian 1.1.2.7     private static final NativeMethod forName0(StaticState ss0) {
 80 cananian 1.1.2.7         final HMethod hm = ss0.HCclass.getMethod
 81 cananian 1.1.2.7             ("forName0", 
 82 cananian 1.1.2.7              "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
 83 cananian 1.1.2.7         return new NativeMethod() {
 84 cananian 1.1.2.7             HMethod getMethod() { return hm; }
 85 cananian 1.1.2.7             // throws ClassNotFoundException
 86 cananian 1.1.2.7             Object invoke(StaticState ss, Object[] params)
 87 cananian 1.1.2.7                 throws InterpretedThrowable {
 88 cananian 1.1.2.7                 String name = ss.ref2str((ObjectRef) params[0]);
 89 cananian 1.1.2.7                 boolean initialize = ((Boolean) params[1]).booleanValue();
 90 cananian 1.1.2.7                 ObjectRef loader = (ObjectRef) params[2];
 91 cananian 1.3.2.1                 assert loader==null : "Haven't implemented class loading "+
 92 cananian 1.3.2.1                             "from a ClassLoader object.";
 93 cananian 1.3.2.1                 assert initialize : "Haven't implemented uninitialized "+
 94 cananian 1.3.2.1                             "class loading.";
 95 cananian 1.1.2.7                 try {
 96 cananian 1.1.2.7                     return forClass(ss, ss.linker.forName(name));
 97 cananian 1.1.2.7                 } catch (NoSuchClassException e) {
 98 cananian 1.1.2.7                     ObjectRef obj = ss.makeThrowable(ss.HCclassnotfoundE);
 99 cananian 1.1.2.7                     throw new InterpretedThrowable(obj, ss);
100 cananian 1.1.2.7                 }
101 cananian 1.1.2.7             }
102 cananian 1.1.2.7         };
103 cananian 1.1.2.7     }
104 cananian 1.1.2.5     private static final NativeMethod getPrimitiveClass(StaticState ss0) {
105 cananian 1.1.2.1         final HMethod hm =
106 cananian 1.1.2.5             ss0.HCclass.getMethod("getPrimitiveClass",
107 cananian 1.1.2.5                                   new HClass[] {ss0.HCstring});
108 cananian 1.1.2.1         return new NativeMethod() {
109 cananian 1.1.2.1             HMethod getMethod() { return hm; }
110 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params)
111 cananian 1.1.2.1                 throws InterpretedThrowable {
112 cananian 1.1.2.1                 String name = ss.ref2str((ObjectRef)params[0]);
113 cananian 1.1.2.1                 if (name.equals("boolean")) return forClass(ss,HClass.Boolean);
114 cananian 1.1.2.1                 if (name.equals("byte"))    return forClass(ss,HClass.Byte);
115 cananian 1.1.2.1                 if (name.equals("char"))    return forClass(ss,HClass.Char);
116 cananian 1.1.2.1                 if (name.equals("double"))  return forClass(ss,HClass.Double);
117 cananian 1.1.2.1                 if (name.equals("float"))   return forClass(ss,HClass.Float);
118 cananian 1.1.2.1                 if (name.equals("int"))     return forClass(ss,HClass.Int);
119 cananian 1.1.2.1                 if (name.equals("long"))    return forClass(ss,HClass.Long);
120 cananian 1.1.2.1                 if (name.equals("short"))   return forClass(ss,HClass.Short);
121 cananian 1.1.2.1                 if (name.equals("void"))    return forClass(ss,HClass.Void);
122 cananian 1.1.2.1                 // oops.  throw exception.
123 cananian 1.1.2.5                 ObjectRef obj = ss.makeThrowable(ss.HCclassnotfoundE);
124 cananian 1.1.2.1                 throw new InterpretedThrowable(obj, ss);
125 cananian 1.1.2.1             }
126 cananian 1.1.2.1         };
127 cananian 1.1.2.1     }
128 cananian 1.1.2.5     private static final NativeMethod getName(StaticState ss0) {
129 cananian 1.1.2.5         final HMethod hm = ss0.HCclass.getMethod("getName", new HClass[0]);
130 cananian 1.1.2.1         return new NativeMethod() {
131 cananian 1.1.2.1             HMethod getMethod() { return hm; }
132 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
133 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
134 cananian 1.1.2.1                 String name = ((HClass)obj.getClosure()).getName();
135 cananian 1.1.2.1                 return ss.makeString(name);
136 cananian 1.1.2.1             }
137 cananian 1.1.2.1         };
138 cananian 1.1.2.1     }
139 cananian 1.1.2.5     private static final NativeMethod getSuperclass(StaticState ss0) {
140 cananian 1.1.2.5         final HMethod hm=ss0.HCclass.getMethod("getSuperclass", new HClass[0]);
141 cananian 1.1.2.1         return new NativeMethod() {
142 cananian 1.1.2.1             HMethod getMethod() { return hm; }
143 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
144 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
145 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
146 cananian 1.1.2.1                 return forClass(ss, hc.getSuperclass());
147 cananian 1.1.2.1             }
148 cananian 1.1.2.1         };
149 cananian 1.1.2.1     }
150 cananian 1.1.2.5     private static final NativeMethod getInterfaces(StaticState ss0) {
151 cananian 1.1.2.5         final HMethod hm=ss0.HCclass.getMethod("getInterfaces", new HClass[0]);
152 cananian 1.1.2.1         return new NativeMethod() {
153 cananian 1.1.2.1             HMethod getMethod() { return hm; }
154 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
155 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
156 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
157 cananian 1.1.2.1                 HClass in[] = hc.getInterfaces();
158 cananian 1.1.2.5                 ArrayRef af=new ArrayRef(ss,ss.HCclassA, new int[]{in.length});
159 cananian 1.1.2.1                 for (int i=0; i<in.length; i++)
160 cananian 1.1.2.1                     af.update(i, forClass(ss, in[i]));
161 cananian 1.1.2.1                 return af;
162 cananian 1.1.2.1             }
163 cananian 1.1.2.1         };
164 cananian 1.1.2.1     }
165 cananian 1.1.2.5     private static final NativeMethod getComponentType(StaticState ss0) {
166 cananian 1.1.2.5         final HMethod hm = ss0.HCclass.getMethod("getComponentType",
167 cananian 1.1.2.5                                                  new HClass[0]);
168 cananian 1.1.2.1         return new NativeMethod() {
169 cananian 1.1.2.1             HMethod getMethod() { return hm; }
170 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
171 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
172 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
173 cananian 1.1.2.1                 return forClass(ss, hc.getComponentType());
174 cananian 1.1.2.1             }
175 cananian 1.1.2.1         };
176 cananian 1.1.2.1     }
177 cananian 1.1.2.5     private static final NativeMethod getModifiers(StaticState ss0) {
178 cananian 1.1.2.5         final HMethod hm = ss0.HCclass.getMethod("getModifiers",new HClass[0]);
179 cananian 1.1.2.1         return new NativeMethod() {
180 cananian 1.1.2.1             HMethod getMethod() { return hm; }
181 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
182 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
183 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
184 cananian 1.1.2.1                 return new Integer(hc.getModifiers());
185 cananian 1.1.2.1             }
186 cananian 1.1.2.1         };
187 cananian 1.1.2.1     }
188 cananian 1.1.2.5     private static final NativeMethod newInstance(StaticState ss0) {
189 cananian 1.1.2.5         final HMethod hm0 = ss0.HCclass.getMethod("newInstance",new HClass[0]);
190 cananian 1.1.2.1         return new NativeMethod() {
191 cananian 1.1.2.1             HMethod getMethod() { return hm0; }
192 cananian 1.1.2.1             private InterpretedThrowable inst(StaticState ss)
193 cananian 1.1.2.1                 throws InterpretedThrowable {
194 cananian 1.1.2.5                 ObjectRef obj = ss.makeThrowable(ss.HCinstantiationE);
195 cananian 1.1.2.1                 return new InterpretedThrowable(obj, ss);
196 cananian 1.1.2.1             }
197 cananian 1.1.2.1             private InterpretedThrowable illacc(StaticState ss)
198 cananian 1.1.2.1                 throws InterpretedThrowable {
199 cananian 1.1.2.5                 ObjectRef obj = ss.makeThrowable(ss.HCillegalaccessE);
200 cananian 1.1.2.1                 return new InterpretedThrowable(obj, ss);
201 cananian 1.1.2.1             }
202 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
203 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
204 cananian 1.1.2.1                 try {
205 cananian 1.1.2.1                     HClass hc = (HClass) obj.getClosure();
206 cananian 1.1.2.1                     if (hc.isInterface() || 
207 cananian 1.1.2.1                         Modifier.isAbstract(hc.getModifiers()))
208 cananian 1.1.2.1                         throw inst(ss);
209 cananian 1.1.2.1                     HMethod hm = hc.getConstructor(new HClass[0]);
210 cananian 1.1.2.8                     int modf = hm.getModifiers();
211 cananian 1.1.2.8                     if (Modifier.isPrivate(modf))
212 cananian 1.1.2.1                         throw illacc(ss);
213 cananian 1.1.2.8                     if (!Modifier.isPublic(modf)) {
214 cananian 1.1.2.8                         // package or protected.
215 cananian 1.1.2.8                         HClass context = ss.getCaller().getDeclaringClass();
216 cananian 1.1.2.8                         if (context.getPackage().equals(hc.getPackage()) ||
217 cananian 1.1.2.8                             (Modifier.isProtected(modf) &&
218 cananian 1.1.2.8                              context.isInstanceOf(hc)))
219 cananian 1.1.2.8                             /* this case is okay. */;
220 cananian 1.1.2.8                         else throw illacc(ss);
221 cananian 1.1.2.8                     }
222 cananian 1.1.2.1                     obj = new ObjectRef(ss, hc);
223 cananian 1.1.2.1                     Method.invoke(ss, hm, new Object[] { obj } );
224 cananian 1.1.2.1                     return obj;
225 cananian 1.1.2.1                 } catch (InterpretedThrowable e) {
226 cananian 1.1.2.1                     throw inst(ss);
227 cananian 1.1.2.1                 }
228 cananian 1.1.2.7             }
229 cananian 1.1.2.7         };
230 cananian 1.1.2.7     }
231 cananian 1.1.2.7     // JDK 1.2 stub.
232 cananian 1.1.2.7     private static final NativeMethod newInstance0(StaticState ss0) {
233 cananian 1.1.2.7         final HMethod hm = ss0.HCclass.getMethod("newInstance0",new HClass[0]);
234 cananian 1.1.2.7         return new NativeMethod() {
235 cananian 1.1.2.7             HMethod getMethod() { return hm; }
236 cananian 1.1.2.7             Object invoke(StaticState ss, Object[] params) {
237 cananian 1.1.2.7                 return newInstance(ss).invoke(ss, params);
238 cananian 1.1.2.1             }
239 cananian 1.1.2.1         };
240 cananian 1.1.2.1     }
241 cananian 1.1.2.5     private static final NativeMethod isInterface(StaticState ss0) {
242 cananian 1.1.2.5         final HMethod hm = ss0.HCclass.getMethod("isInterface", new HClass[0]);
243 cananian 1.1.2.1         return new NativeMethod() {
244 cananian 1.1.2.1             HMethod getMethod() { return hm; }
245 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
246 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
247 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
248 cananian 1.1.2.1                 return new Boolean(hc.isInterface());
249 cananian 1.1.2.1             }
250 cananian 1.1.2.1         };
251 cananian 1.1.2.1     }
252 cananian 1.1.2.5     private static final NativeMethod isArray(StaticState ss0) {
253 cananian 1.1.2.5         final HMethod hm = ss0.HCclass.getMethod("isArray", new HClass[0]);
254 cananian 1.1.2.1         return new NativeMethod() {
255 cananian 1.1.2.1             HMethod getMethod() { return hm; }
256 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
257 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
258 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
259 cananian 1.1.2.1                 return new Boolean(hc.isArray());
260 cananian 1.1.2.1             }
261 cananian 1.1.2.1         };
262 cananian 1.1.2.1     }
263 cananian 1.1.2.5     private static final NativeMethod isPrimitive(StaticState ss0) {
264 cananian 1.1.2.5         final HMethod hm = ss0.HCclass.getMethod("isPrimitive", new HClass[0]);
265 cananian 1.1.2.1         return new NativeMethod() {
266 cananian 1.1.2.1             HMethod getMethod() { return hm; }
267 cananian 1.1.2.1             Object invoke(StaticState ss, Object[] params) {
268 cananian 1.1.2.1                 ObjectRef obj = (ObjectRef) params[0];
269 cananian 1.1.2.1                 HClass hc = (HClass) obj.getClosure();
270 cananian 1.1.2.1                 return new Boolean(hc.isPrimitive());
271 cananian 1.1.2.1             }
272 cananian 1.1.2.1         };
273 cananian 1.1.2.4     }
274 cananian 1.1.2.4     // JDK 1.2 only: Class.registerNatives()
275 cananian 1.1.2.5     private static final NativeMethod registerNatives(StaticState ss0) {
276 cananian 1.1.2.4         final HMethod hm =
277 cananian 1.1.2.5             ss0.HCclass.getMethod("registerNatives",new HClass[0]);
278 cananian 1.1.2.6         return new NullNativeMethod(hm);
279 cananian 1.1.2.6     }
280 cananian 1.1.2.6     // JDK 1.2 only: Class.getClassLoader0()
281 cananian 1.1.2.6     private static final NativeMethod getClassLoader0(StaticState ss0) {
282 cananian 1.1.2.6         // always return 'null', indicating the boot class loader.
283 cananian 1.1.2.6         final HMethod hm =
284 cananian 1.1.2.6             ss0.HCclass.getMethod("getClassLoader0",new HClass[0]);
285 cananian 1.1.2.4         return new NullNativeMethod(hm);
286 cananian 1.1.2.1     }
287 cananian 1.2     }