1 cananian 1.1.4.1 // HClassImpl.java, created Fri Jul 31  4:33:28 1998 by cananian
  2 cananian 1.1.4.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.4.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.4.1 package harpoon.ClassFile;
  5 cananian 1.1.4.1 
  6 cananian 1.1.4.1 import harpoon.Util.ArrayFactory;
  7 cananian 1.3     import net.cscott.jutil.ReferenceUnique;
  8 cananian 1.3     import net.cscott.jutil.UniqueVector;
  9 cananian 1.1.4.1 import harpoon.Util.Util;
 10 cananian 1.1.4.1 
 11 cananian 1.1.4.1 import java.lang.reflect.Modifier;
 12 cananian 1.1.4.1 
 13 cananian 1.1.4.1 /**
 14 cananian 1.1.4.1  * <code>HClassImpl</code> is a common parent for implementations of
 15 cananian 1.1.4.1  * <code>HClass</code>.  Linker proxy classes should instead have
 16 cananian 1.1.4.1  * <code>HClassProxy</code> as a parent.
 17 cananian 1.1.4.1  * <p>
 18 cananian 1.1.4.1  * There is no public constructor for the class <code>HClassImpl</code>.
 19 cananian 1.1.4.1  * <code>HClass</code> objects are created with the <code>forName</code>,
 20 cananian 1.1.4.1  * <code>forDescriptor</code> and <code>forClass</code> methods of a
 21 cananian 1.1.4.1  * <code>Linker</code> object.
 22 cananian 1.1.4.1  * 
 23 cananian 1.1.4.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 24 cananian 1.3      * @version $Id: HClassImpl.java,v 1.3 2004/02/08 01:58:03 cananian Exp $
 25 cananian 1.1.4.1  * @see harpoon.IR.RawClass.ClassFile
 26 cananian 1.1.4.1  * @see java.lang.Class
 27 cananian 1.1.4.1  */
 28 cananian 1.1.4.1 abstract class HClassImpl extends HClass
 29 cananian 1.1.4.1   implements java.io.Serializable {
 30 cananian 1.1.4.1 
 31 cananian 1.1.4.1   /** Protected constructor, not for external use. */
 32 cananian 1.1.4.1   HClassImpl(Linker l) { super(l); }
 33 cananian 1.1.4.1 
 34 cananian 1.1.4.1   /**
 35 cananian 1.1.4.1    * If this class represents an array type, returns the <code>HClass</code>
 36 cananian 1.1.4.1    * object representing the component type of the array; otherwise returns
 37 cananian 1.1.4.1    * null.
 38 cananian 1.1.4.1    * @see java.lang.reflect.Array
 39 cananian 1.1.4.1    */
 40 cananian 1.1.4.1   public HClass getComponentType() { return null; }
 41 cananian 1.1.4.1 
 42 cananian 1.1.4.1   /** 
 43 cananian 1.1.4.1    * Returns the fully-qualified name of the type (class, interface,
 44 cananian 1.1.4.1    * array, or primitive) represented by this <code>HClass</code> object,
 45 cananian 1.1.4.1    * as a <code>String</code>. 
 46 cananian 1.1.4.1    * @return the fully qualified name of the class or interface
 47 cananian 1.1.4.1    *         represented by this object.
 48 cananian 1.1.4.1    */
 49 cananian 1.1.4.1   public abstract String getName();
 50 cananian 1.1.4.1 
 51 cananian 1.1.4.1   /**
 52 cananian 1.1.4.1    * Returns the package name of this <code>HClass</code>.  If this
 53 cananian 1.1.4.1    * <code>HClass</code> represents a primitive or array type,
 54 cananian 1.1.4.1    * then returns null.  Returns <code>""</code> (a zero-length string)
 55 cananian 1.1.4.1    * if this class is not in a package.
 56 cananian 1.1.4.1    */
 57 cananian 1.1.4.1   public String getPackage() {
 58 cananian 1.1.4.1     if (isPrimitive() || isArray()) return null;
 59 cananian 1.1.4.1     String fullname = getName();
 60 cananian 1.1.4.1     int lastdot = fullname.lastIndexOf('.');
 61 cananian 1.1.4.1     if (lastdot<0) return ""; // no package.
 62 cananian 1.1.4.1     else return fullname.substring(0, lastdot);
 63 cananian 1.1.4.1   }
 64 cananian 1.1.4.1   /**
 65 cananian 1.1.4.1    * Returns a ComponentType descriptor for the type represented by this
 66 cananian 1.1.4.1    * <code>HClass</code> object.
 67 cananian 1.1.4.1    */
 68 cananian 1.1.4.1   public abstract String getDescriptor();
 69 cananian 1.1.4.1 
 70 cananian 1.1.4.1   /**
 71 cananian 1.1.4.1    * Returns a <code>HField</code> object that reflects the specified
 72 cananian 1.1.4.1    * declared field of the class or interface represented by this
 73 cananian 1.1.4.1    * <code>HClass</code> object.  The <code>name</code> parameter is a 
 74 cananian 1.1.4.1    * <code>String</code> that specifies the simple name of the
 75 cananian 1.1.4.1    * desired field.
 76 cananian 1.1.4.1    * @exception NoSuchFieldError
 77 cananian 1.1.4.1    *            if a field with the specified name is not found.
 78 cananian 1.1.4.1    * @see HField
 79 cananian 1.1.4.1    */
 80 cananian 1.1.4.1   public HField getDeclaredField(String name)
 81 cananian 1.1.4.1     throws NoSuchFieldError {
 82 cananian 1.1.4.1     // construct master declaredField list, if we haven't already.
 83 cananian 1.1.4.1     HField[] declaredFields=getDeclaredFields();
 84 cananian 1.1.4.1     // look for field name in master list.
 85 cananian 1.1.4.1     for (int i=0; i<declaredFields.length; i++)
 86 cananian 1.1.4.1       if (declaredFields[i].getName().equals(name))
 87 cananian 1.1.4.1         return declaredFields[i];
 88 cananian 1.1.4.1     // not found.
 89 cananian 1.1.4.1     throw new NoSuchFieldError(getName()+"."+name);
 90 cananian 1.1.4.1   }
 91 cananian 1.1.4.1   /**
 92 cananian 1.1.4.1    * Returns an array of <code>HField</code> objects reflecting all the
 93 cananian 1.1.4.1    * fields declared by the class or interface represented by this
 94 cananian 1.1.4.1    * <code>HClass</code> object.  This includes <code>public</code>,
 95 cananian 1.1.4.1    * <code>protected</code>, default (<code>package</code>) access,
 96 cananian 1.1.4.1    * and <code>private</code> fields, but excludes inherited fields.
 97 cananian 1.1.4.1    * Returns an array of length 0 if the class or interface declares
 98 cananian 1.1.4.1    * no fields, or if this <code>HClass</code> object represents a
 99 cananian 1.1.4.1    * primitive type.
100 cananian 1.1.4.1    * @see "The Java Language Specification, sections 8.2 and 8.3"
101 cananian 1.1.4.1    * @see HField
102 cananian 1.1.4.1    */
103 cananian 1.1.4.1   public abstract HField[] getDeclaredFields();
104 cananian 1.1.4.1 
105 cananian 1.1.4.1   /**
106 cananian 1.1.4.1    * Returns a <code>HMethod</code> object that reflects the specified 
107 cananian 1.1.4.1    * declared method of the class or interface represented by this 
108 cananian 1.1.4.1    * <code>HClass</code> object.  The <code>name</code> parameter is a
109 cananian 1.1.4.1    * <code>String</code> that specifies the simple name of the desired
110 cananian 1.1.4.1    * method, and the <code>parameterTypes</code> parameter is an array
111 cananian 1.1.4.1    * of <code>HClass</code> objects that identify the method's formal
112 cananian 1.1.4.1    * parameter types, in declared order.
113 cananian 1.1.4.1    * @exception NoSuchMethodError
114 cananian 1.1.4.1    *            if a matching method is not found.
115 cananian 1.1.4.1    * @see HMethod
116 cananian 1.1.4.1    */
117 cananian 1.1.4.1   public HMethod getDeclaredMethod(String name, HClass parameterTypes[])
118 cananian 1.1.4.1     throws NoSuchMethodError {
119 cananian 1.1.4.1     // construct master declaredMethod list, if we haven't already.
120 cananian 1.1.4.1     HMethod[] declaredMethods=getDeclaredMethods();
121 cananian 1.1.4.1     // look for method name/type in master list.
122 cananian 1.1.4.1     for (int i=0; i<declaredMethods.length; i++)
123 cananian 1.1.4.1       if (declaredMethods[i].getName().equals(name)) {
124 cananian 1.1.4.1         HClass[] methodParamTypes = declaredMethods[i].getParameterTypes();
125 cananian 1.1.4.1         if (methodParamTypes.length == parameterTypes.length) {
126 cananian 1.1.4.1           int j; for (j=0; j<parameterTypes.length; j++)
127 cananian 1.1.4.1             if (methodParamTypes[j] != parameterTypes[j])
128 cananian 1.1.4.1               break; // oops, this one doesn't match.
129 cananian 1.1.4.1           if (j==parameterTypes.length) // hey, we made it to the end!
130 cananian 1.1.4.1             return declaredMethods[i];
131 cananian 1.1.4.1         }
132 cananian 1.1.4.1       }
133 cananian 1.1.4.1     // didn't find a match.  Oh, well.
134 cananian 1.1.4.1     throw new NoSuchMethodError(getName()+"."+name);
135 cananian 1.1.4.1   }
136 cananian 1.1.4.1   /**
137 cananian 1.1.4.1    * Returns a <code>HMethod</code> object that reflects the specified 
138 cananian 1.1.4.1    * declared method of the class or interface represented by this 
139 cananian 1.1.4.1    * <code>HClass</code> object.  The <code>name</code> parameter is a
140 cananian 1.1.4.1    * <code>String</code> that specifies the simple name of the desired
141 cananian 1.1.4.1    * method, and <code>descriptor</code> is a string describing
142 cananian 1.1.4.1    * the parameter types and return value of the method.
143 cananian 1.1.4.1    * @exception NoSuchMethodError
144 cananian 1.1.4.1    *            if a matching method is not found.
145 cananian 1.1.4.1    * @see HMethod#getDescriptor
146 cananian 1.1.4.1    */
147 cananian 1.1.4.1   public HMethod getDeclaredMethod(String name, String descriptor)
148 cananian 1.1.4.1     throws NoSuchMethodError {
149 cananian 1.1.4.1     // construct master declaredMethod list, if we haven't already.
150 cananian 1.1.4.1     HMethod[] declaredMethods=getDeclaredMethods();
151 cananian 1.1.4.1     // look for method name/type in master list.
152 cananian 1.1.4.1     for (int i=0; i<declaredMethods.length; i++)
153 cananian 1.1.4.1       if (declaredMethods[i].getName().equals(name) &&
154 cananian 1.1.4.1           declaredMethods[i].getDescriptor().equals(descriptor))
155 cananian 1.1.4.1         return declaredMethods[i];
156 cananian 1.1.4.1     // didn't find a match.  Oh, well.
157 cananian 1.1.4.1     throw new NoSuchMethodError(getName()+"."+name+"/"+descriptor);
158 cananian 1.1.4.1   }
159 cananian 1.1.4.1   /**
160 cananian 1.1.4.1    * Returns an array of <code>HMethod</code> objects reflecting all the
161 cananian 1.1.4.1    * methods declared by the class or interface represented by this
162 cananian 1.1.4.1    * <code>HClass</code> object.  This includes <code>public</code>,
163 cananian 1.1.4.1    * <code>protected</code>, default (<code>package</code>) access, and
164 cananian 1.1.4.1    * <code>private</code> methods, but excludes inherited methods.
165 cananian 1.1.4.1    * Returns an array of length 0 if the class or interface declares no
166 cananian 1.1.4.1    * methods, or if this <code>HClass</code> object represents a primitive
167 cananian 1.1.4.1    * type.<p>
168 cananian 1.1.4.1    * Constructors are included.
169 cananian 1.1.4.1    * @see "The Java Language Specification, section 8.2"
170 cananian 1.1.4.1    * @see HMethod
171 cananian 1.1.4.1    */
172 cananian 1.1.4.1   public abstract HMethod[] getDeclaredMethods();
173 cananian 1.1.4.1 
174 cananian 1.1.4.1   /**
175 cananian 1.1.4.1    * Returns an <code>HConstructor</code> object that reflects the 
176 cananian 1.1.4.1    * specified declared constructor of the class or interface represented 
177 cananian 1.1.4.1    * by this <code>HClass</code> object.  The <code>parameterTypes</code>
178 cananian 1.1.4.1    * parameter is an array of <code>HClass</code> objects that
179 cananian 1.1.4.1    * identify the constructor's formal parameter types, in declared order.
180 cananian 1.1.4.1    * @exception NoSuchMethodError if a matching method is not found.
181 cananian 1.1.4.1    */
182 cananian 1.1.4.1   public HConstructor getConstructor(HClass parameterTypes[])
183 cananian 1.1.4.1     throws NoSuchMethodError {
184 cananian 1.1.4.1     return (HConstructor) getDeclaredMethod("<init>", parameterTypes);
185 cananian 1.1.4.1   }
186 cananian 1.1.4.1 
187 cananian 1.1.4.1   /**
188 cananian 1.1.4.1    * Returns an array of <code>HConstructor</code> objects reflecting
189 cananian 1.1.4.1    * all the constructors declared by the class represented by the
190 cananian 1.1.4.1    * <code>HClass</code> object.  These are <code>public</code>,
191 cananian 1.1.4.1    * <code>protected</code>, default (package) access, and
192 cananian 1.1.4.1    * <code>private</code> constructors.  Returns an array of length 0
193 cananian 1.1.4.1    * if this <code>HClass</code> object represents an interface or a
194 cananian 1.1.4.1    * primitive type.
195 cananian 1.1.4.1    * @see "The Java Language Specification, section 8.2"
196 cananian 1.1.4.1    */
197 cananian 1.1.4.1   public HConstructor[] getConstructors() {
198 cananian 1.1.4.1     HConstructor[] constructors;
199 cananian 1.1.4.1     if (isPrimitive() || isArray() || isInterface())
200 cananian 1.1.4.1       constructors = new HConstructor[0];
201 cananian 1.1.4.1     else {
202 cananian 1.1.4.1       HMethod[] hm = getMethods();
203 cananian 1.1.4.1       int n=0;
204 cananian 1.1.4.1       for (int i=0; i<hm.length; i++)
205 cananian 1.1.4.1         if (hm[i] instanceof HConstructor)
206 cananian 1.1.4.1           n++;
207 cananian 1.1.4.1       constructors = new HConstructor[n];
208 cananian 1.1.4.1       for (int i=0; i<hm.length; i++)
209 cananian 1.1.4.1         if (hm[i] instanceof HConstructor)
210 cananian 1.1.4.1           constructors[--n] = (HConstructor) hm[i];
211 cananian 1.1.4.1     }
212 cananian 1.1.4.1     return constructors;
213 cananian 1.1.4.1   }
214 cananian 1.1.4.1 
215 cananian 1.1.4.1   /**
216 cananian 1.1.4.1    * Returns the class initializer method, if there is one; otherwise
217 cananian 1.1.4.1    * <code>null</code>.
218 cananian 1.1.4.1    * @see "The Java Virtual Machine Specification, section 3.8"
219 cananian 1.1.4.1    */
220 cananian 1.1.4.1   public HInitializer getClassInitializer() {
221 cananian 1.1.4.1     try {
222 cananian 1.1.4.1       return (HInitializer) getDeclaredMethod("<clinit>", new HClass[0]);
223 cananian 1.1.4.1     } catch (NoSuchMethodError e) {
224 cananian 1.1.4.1       return null;
225 cananian 1.1.4.1     }
226 cananian 1.1.4.1   }
227 cananian 1.1.4.1 
228 cananian 1.1.4.1   /**
229 cananian 1.1.4.1    * Returns the Java language modifiers for this class or interface,
230 cananian 1.1.4.1    * encoded in an integer.  The modifiers consist of the Java Virtual
231 cananian 1.1.4.1    * Machine's constants for public, protected, private, final, and 
232 cananian 1.1.4.1    * interface; they should be decoded using the methods of class Modifier.
233 cananian 1.1.4.1    * @see "The Java Virtual Machine Specification, table 4.1"
234 cananian 1.1.4.1    * @see java.lang.reflect.Modifier
235 cananian 1.1.4.1    */
236 cananian 1.1.4.1   public abstract int getModifiers();
237 cananian 1.1.4.1 
238 cananian 1.1.4.1   /**
239 cananian 1.1.4.1    * If this object represents any class other than the class 
240 cananian 1.1.4.1    * <code>Object</code>, then the object that represents the superclass of 
241 cananian 1.1.4.1    * that class is returned. 
242 cananian 1.1.4.1    * <p> If this object is the one that represents the class
243 cananian 1.1.4.1    * <code>Object</code> or this object represents an interface, 
244 cananian 1.1.4.1    * <code>null</code> is returned.
245 cananian 1.1.4.1    * If this object represents an array, then the <code>HClass</code>
246 cananian 1.1.4.1    * representing <code>java.lang.Object</code> is returned.
247 cananian 1.1.4.1    * @return the superclass of the class represented by this object.
248 cananian 1.1.4.1    */
249 cananian 1.1.4.1   public abstract HClass getSuperclass();
250 cananian 1.1.4.1 
251 cananian 1.1.4.1   /**
252 cananian 1.1.4.1    * Determines the interfaces implemented by the class or interface 
253 cananian 1.1.4.1    * represented by this object. 
254 cananian 1.1.4.1    * <p> If this object represents a class, the return value is an
255 cananian 1.1.4.1    * array containing objects representing all interfaces implemented by 
256 cananian 1.1.4.1    * the class.  The order of the interface objects in the array corresponds 
257 cananian 1.1.4.1    * to the order of the interface names in the implements clause of the 
258 cananian 1.1.4.1    * declaration of the class represented by this object.
259 cananian 1.1.4.1    * <p> If the object represents an interface, the array contains objects
260 cananian 1.1.4.1    * representing all interfaces extended by the interface.  The order of
261 cananian 1.1.4.1    * the interface objects in the array corresponds to the order of the
262 cananian 1.1.4.1    * interface names in the extends clause of the declaration of the 
263 cananian 1.1.4.1    * interface represented by this object.
264 cananian 1.1.4.1    * <p> If the class or interface implements no interfaces, the method
265 cananian 1.1.4.1    * returns an array of length 0.
266 cananian 1.1.4.1    * <p><b>NOTE THAT the array returned does NOT contain interfaces
267 cananian 1.1.4.1    * implemented by superclasses.</b>  Thus the interface list may
268 cananian 1.1.4.1    * be incomplete.  This is pretty bogus behaviour, but it's what
269 cananian 1.1.4.1    * our prototype, <code>java.lang.Class</code>, does.
270 cananian 1.1.4.1    * @return an array of interfaces implemented by this class.
271 cananian 1.1.4.1    */
272 cananian 1.1.4.1   public abstract HClass[] getInterfaces();
273 cananian 1.1.4.1 
274 cananian 1.1.4.1   /**
275 cananian 1.1.4.1    * Return the name of the source file for this class, or a
276 cananian 1.1.4.1    * zero-length string if the information is not available.
277 cananian 1.1.4.1    * @see harpoon.IR.RawClass.AttributeSourceFile
278 cananian 1.1.4.1    */
279 cananian 1.1.4.1   public String getSourceFile() { return ""; }
280 cananian 1.1.4.1 
281 cananian 1.1.4.1   /**
282 cananian 1.1.4.1    * If this <code>HClass</code> object represents an array type, 
283 cananian 1.1.4.1    * returns <code>true</code>, otherwise returns <code>false</code>.
284 cananian 1.1.4.1    */
285 cananian 1.1.4.1   public boolean isArray() { return false; }
286 cananian 1.1.4.1   /**
287 cananian 1.1.4.1    * Determines if the specified <code>HClass</code> object represents an
288 cananian 1.1.4.1    * interface type.
289 cananian 1.1.4.1    * @return <code>true</code> is this object represents an interface;
290 cananian 1.1.4.1    *         <code>false</code> otherwise.
291 cananian 1.1.4.1    */
292 cananian 1.1.4.1   public boolean isInterface() { return false; }
293 cananian 1.1.4.1 
294 cananian 1.1.4.1   /**
295 cananian 1.1.4.1    * Determines if the specified <code>HClass</code> object represents a
296 cananian 1.1.4.1    * primitive Java type. <p>
297 cananian 1.1.4.1    * There are nine predefined <code>HClass</code> objects to represent
298 cananian 1.1.4.1    * the eight primitive Java types and void.
299 cananian 1.1.4.1    */
300 cananian 1.1.4.1   public boolean isPrimitive() { return false; }
301 cananian 1.1.4.1 
302 cananian 1.1.4.1   /** Serializable interface. Override if implementation has information
303 cananian 1.1.4.1    *  which the linker cannot reconstruct. */
304 cananian 1.1.4.1   public Object writeReplace() {
305 cananian 1.1.4.1     if (!hasBeenModified()) return new HClassStub(this);
306 cananian 1.1.4.1     else return this; // cannot reconstruct; write this out instead
307 cananian 1.1.4.1   }
308 cananian 1.1.4.1   private static final class HClassStub implements java.io.Serializable {
309 cananian 1.1.4.1     private final String desc; private final Linker l;
310 cananian 1.1.4.1     HClassStub(HClass c) // store only descriptor and linker for resolution.
311 cananian 1.1.4.1     { this.desc = c.getDescriptor().intern(); this.l = c.getLinker(); }
312 cananian 1.1.4.1     public Object readResolve() { return l.forDescriptor(desc); }
313 cananian 1.1.4.1   }
314 cananian 1.1.4.1 }
315 cananian 1.1.4.1 // set emacs indentation style.
316 cananian 1.1.4.1 // Local Variables:
317 cananian 1.1.4.1 // c-basic-offset:2
318 cananian 1.2     // End: