1 cananian 1.1.2.5 // HClassCls.java, created Fri Oct 16 2:21:02 1998 by cananian 2 cananian 1.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.ClassFile; 5 cananian 1.1 6 cananian 1.1.2.2 import harpoon.Util.Util; 7 cananian 1.1.2.2 8 cananian 1.1 import java.lang.reflect.Modifier; 9 cananian 1.1 10 cananian 1.1 /** 11 cananian 1.1 * Instances of the class <code>HClassCls</code> represent modifiable 12 cananian 1.1 * classes and interfaces of a java program. Arrays and primitive types 13 cananian 1.1 * are not modifiable, and thus are not represented by 14 cananian 1.1.2.10 * <code>HClassCls</code>. 15 cananian 1.1 * 16 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 17 cananian 1.2 * @version $Id: HClassCls.java,v 1.2 2002/02/25 21:03:03 cananian Exp $ 18 cananian 1.1 * @see harpoon.ClassFile.HClass 19 cananian 1.1 */ 20 cananian 1.1.2.7 abstract class HClassCls extends HClassImpl { 21 cananian 1.1 /** Fully qualified name of the class represented by this 22 cananian 1.1 * <code>HClassCls</code> object. */ 23 cananian 1.1 String name; 24 cananian 1.1 /** Superclass of this <code>HClassCls</code>. */ 25 cananian 1.1.2.3 HPointer superclass; 26 cananian 1.1 /** Interfaces of this <code>HClassCls</code>. */ 27 cananian 1.1.2.3 HPointer interfaces[]; 28 cananian 1.1 /** Access flags for this class. */ 29 cananian 1.1 int modifiers; 30 cananian 1.1 /** List of fields in this <code>HClassCls</code> object. */ 31 cananian 1.1 HField[] declaredFields; 32 cananian 1.1 /** List of methods in this <code>HClassCls</code> object. */ 33 cananian 1.1 HMethod[] declaredMethods; 34 cananian 1.1 /** Name of the source file for this class. */ 35 cananian 1.1 String sourcefile; 36 cananian 1.1.2.3 // CACHES: (reset to null to recompute) 37 cananian 1.1.2.6 transient HConstructor[] constructors = null; 38 cananian 1.1.2.6 transient HField[] fields = null; 39 cananian 1.1.2.6 transient HMethod[] methods = null; 40 cananian 1.1.2.3 41 cananian 1.1 /** Implementations must provide their own constructor to initialize. */ 42 cananian 1.1.2.7 protected HClassCls(Linker l) { super(l); } 43 cananian 1.1 44 cananian 1.1 /** 45 cananian 1.1 * Returns the fully-qualified name of the class 46 cananian 1.1 * represented by this <code>HClassCls</code> object, 47 cananian 1.1 * as a <code>String</code>. 48 cananian 1.1 * @return the fully qualified name of the class or interface 49 cananian 1.1 * represented by this object. 50 cananian 1.1 */ 51 cananian 1.1 public String getName() { return name; } 52 cananian 1.1 53 cananian 1.1 /** 54 cananian 1.1 * Returns a ComponentType descriptor for the class represented by this 55 cananian 1.1 * <code>HClassCls</code> object. 56 cananian 1.1 */ 57 cananian 1.1 public String getDescriptor() { return "L"+getName().replace('.','/')+";"; } 58 cananian 1.1 59 cananian 1.1 /** 60 cananian 1.1 * Returns a <code>HField</code> object that reflects the specified 61 cananian 1.1 * declared field of the class or interface represented by this 62 cananian 1.1 * <code>HClassCls</code> object. The <code>name</code> parameter is a 63 cananian 1.1 * <code>String</code> that specifies the simple name of the 64 cananian 1.1 * desired field. 65 cananian 1.1 * @exception NoSuchFieldError 66 cananian 1.1 * if a field with the specified name is not found. 67 cananian 1.1 * @see HField 68 cananian 1.1 */ 69 cananian 1.1 public HField getDeclaredField(String name) 70 cananian 1.1 throws NoSuchFieldError { 71 cananian 1.1 // look for field name in master list. 72 cananian 1.1 for (int i=0; i<declaredFields.length; i++) 73 cananian 1.1 if (declaredFields[i].getName().equals(name)) 74 cananian 1.1 return declaredFields[i]; 75 cananian 1.1 // not found. 76 cananian 1.1 throw new NoSuchFieldError(name); 77 cananian 1.1 } 78 cananian 1.1 /** 79 cananian 1.1 * Returns an array of <code>HField</code> objects reflecting all the 80 cananian 1.1 * fields declared by the class or interface represented by this 81 cananian 1.1 * <code>HClassCls</code> object. This includes <code>public</code>, 82 cananian 1.1 * <code>protected</code>, default (<code>package</code>) access, 83 cananian 1.1 * and <code>private</code> fields, but excludes inherited fields. 84 cananian 1.1 * Returns an array of length 0 if the class or interface declares 85 cananian 1.1 * no fields. 86 cananian 1.1 * @see "The Java Language Specification,, sections 8.2 and 8.3" 87 cananian 1.1 * @see HField 88 cananian 1.1 */ 89 cananian 1.1 public HField[] getDeclaredFields() { 90 cananian 1.1.2.2 return (HField[]) Util.safeCopy(HField.arrayFactory, declaredFields); 91 cananian 1.1 } 92 cananian 1.1 93 cananian 1.1 /** 94 cananian 1.1 * Returns a <code>HMethod</code> object that reflects the specified 95 cananian 1.1 * declared method of the class or interface represented by this 96 cananian 1.1 * <code>HClass</code> object. The <code>name</code> parameter is a 97 cananian 1.1 * <code>String</code> that specifies the simple name of the desired 98 cananian 1.1 * method, and the <code>parameterTypes</code> parameter is an array 99 cananian 1.1 * of <code>HClass</code> objects that identify the method's formal 100 cananian 1.1 * parameter types, in declared order. 101 cananian 1.1 * @exception NoSuchMethodError 102 cananian 1.1 * if a matching method is not found. 103 cananian 1.1 * @see HMethod 104 cananian 1.1 */ 105 cananian 1.1 public HMethod getDeclaredMethod(String name, HClass parameterTypes[]) 106 cananian 1.1 throws NoSuchMethodError { 107 cananian 1.1 // look for method name/type in master list. 108 cananian 1.1 for (int i=0; i<declaredMethods.length; i++) 109 cananian 1.1 if (declaredMethods[i].getName().equals(name)) { 110 cananian 1.1 HClass[] methodParamTypes = declaredMethods[i].getParameterTypes(); 111 cananian 1.1 if (methodParamTypes.length == parameterTypes.length) { 112 cananian 1.1 int j; for (j=0; j<parameterTypes.length; j++) 113 cananian 1.1 if (methodParamTypes[j] != parameterTypes[j]) 114 cananian 1.1 break; // oops, this one doesn't match. 115 cananian 1.1 if (j==parameterTypes.length) // hey, we made it to the end! 116 cananian 1.1 return declaredMethods[i]; 117 cananian 1.1 } 118 cananian 1.1 } 119 cananian 1.1 // didn't find a match. Oh, well. 120 cananian 1.1.2.11 StringBuffer msg = new StringBuffer(getName()); 121 cananian 1.1.2.11 msg.append('.'); msg.append(name); msg.append('('); 122 cananian 1.1.2.11 for (int i=0; i<parameterTypes.length; i++) 123 cananian 1.1.2.11 msg.append(parameterTypes[i].getDescriptor()); 124 cananian 1.1.2.11 msg.append(')'); 125 cananian 1.1.2.11 throw new NoSuchMethodError(msg.toString()); 126 cananian 1.1 } 127 cananian 1.1 /** 128 cananian 1.1 * Returns a <code>HMethod</code> object that reflects the specified 129 cananian 1.1 * declared method of the class or interface represented by this 130 cananian 1.1 * <code>HClass</code> object. The <code>name</code> parameter is a 131 cananian 1.1 * <code>String</code> that specifies the simple name of the desired 132 cananian 1.1 * method, and <code>descriptor</code> is a string describing 133 cananian 1.1 * the parameter types and return value of the method. 134 cananian 1.1 * @exception NoSuchMethodError 135 cananian 1.1 * if a matching method is not found. 136 cananian 1.1 * @see HMethod#getDescriptor 137 cananian 1.1 */ 138 cananian 1.1 public HMethod getDeclaredMethod(String name, String descriptor) 139 cananian 1.1 throws NoSuchMethodError { 140 cananian 1.1 // look for method name/type in master list. 141 cananian 1.1 for (int i=0; i<declaredMethods.length; i++) 142 cananian 1.1 if (declaredMethods[i].getName().equals(name) && 143 cananian 1.1 declaredMethods[i].getDescriptor().equals(descriptor)) 144 cananian 1.1 return declaredMethods[i]; 145 cananian 1.1 // didn't find a match. Oh, well. 146 cananian 1.1.2.11 throw new NoSuchMethodError(getName()+"."+name+descriptor); 147 cananian 1.1 } 148 cananian 1.1 /** 149 cananian 1.1 * Returns an array of <code>HMethod</code> objects reflecting all the 150 cananian 1.1 * methods declared by the class or interface represented by this 151 cananian 1.1 * <code>HClass</code> object. This includes <code>public</code>, 152 cananian 1.1 * <code>protected</code>, default (<code>package</code>) access, and 153 cananian 1.1 * <code>private</code> methods, but excludes inherited methods. 154 cananian 1.1 * Returns an array of length 0 if the class or interface declares no 155 cananian 1.1 * methods, or if this <code>HClass</code> object represents a primitive 156 cananian 1.1 * type.<p> 157 cananian 1.1 * Constructors are included. 158 cananian 1.1 * @see "The Java Language Specification, section 8.2" 159 cananian 1.1 * @see HMethod 160 cananian 1.1 */ 161 cananian 1.1 public HMethod[] getDeclaredMethods() { 162 cananian 1.1.2.2 return (HMethod[]) Util.safeCopy(HMethod.arrayFactory, declaredMethods); 163 cananian 1.1 } 164 cananian 1.1 165 cananian 1.1 /** 166 cananian 1.1 * Returns the Java language modifiers for this class or interface, 167 cananian 1.1 * encoded in an integer. The modifiers consist of the Java Virtual 168 cananian 1.1 * Machine's constants for public, protected, private, final, and 169 cananian 1.1 * interface; they should be decoded using the methods of class Modifier. 170 cananian 1.1 * @see "The Java Virtual Machine Specification, table 4.1" 171 cananian 1.1 * @see java.lang.reflect.Modifier 172 cananian 1.1 */ 173 cananian 1.1 public int getModifiers() { return modifiers; } 174 cananian 1.1 175 cananian 1.1 /** 176 cananian 1.1 * If this object represents any class other than the class 177 cananian 1.1 * <code>Object</code>, then the object that represents the superclass of 178 cananian 1.1 * that class is returned. 179 cananian 1.1 * <p> If this object is the one that represents the class 180 cananian 1.1 * <code>Object</code> or this object represents an interface, 181 cananian 1.1 * <code>null</code> is returned. 182 cananian 1.1 * @return the superclass of the class represented by this object. 183 cananian 1.1 */ 184 cananian 1.1.2.3 public HClass getSuperclass() { 185 cananian 1.1.2.4 try { 186 cananian 1.1.2.4 return (HClass) superclass; // works if superclass is null, too. 187 cananian 1.1.2.4 } catch (ClassCastException e) { // superclass was ClassPointer. 188 cananian 1.1.2.4 HClass sc = superclass.actual(); // loads HClass from ClassPointer. 189 cananian 1.1.2.4 superclass = sc; 190 cananian 1.1.2.4 return sc; 191 cananian 1.1.2.4 } 192 cananian 1.1.2.3 } 193 cananian 1.1 194 cananian 1.1 /** 195 cananian 1.1 * Determines the interfaces implemented by the class or interface 196 cananian 1.1 * represented by this object. 197 cananian 1.1 * <p> If this object represents a class, the return value is an 198 cananian 1.1 * array containing objects representing all interfaces implemented by 199 cananian 1.1 * the class. The order of the interface objects in the array corresponds 200 cananian 1.1 * to the order of the interface names in the implements clause of the 201 cananian 1.1 * declaration of the class represented by this object. 202 cananian 1.1 * <p> If the object represents an interface, the array contains objects 203 cananian 1.1 * representing all interfaces extended by the interface. The order of 204 cananian 1.1 * the interface objects in the array corresponds to the order of the 205 cananian 1.1 * interface names in the extends clause of the declaration of the 206 cananian 1.1 * interface represented by this object. 207 cananian 1.1 * <p> If the class or interface implements no interfaces, the method 208 cananian 1.1 * returns an array of length 0. 209 cananian 1.1 * @return an array of interfaces implemented by this class. 210 cananian 1.1 */ 211 cananian 1.1.2.4 public HClass[] getInterfaces() { // should really safeCopy? 212 cananian 1.1.2.3 HClass[] in; 213 cananian 1.1.2.4 try { 214 cananian 1.1.2.4 in = (HClass[]) interfaces; 215 cananian 1.1.2.4 } catch (ClassCastException e) { // interfaces was HPointer. 216 cananian 1.1.2.3 in = new HClass[interfaces.length]; 217 cananian 1.1.2.3 for (int i=0; i<in.length; i++) 218 cananian 1.1.2.3 in[i] = interfaces[i].actual(); 219 cananian 1.1.2.3 interfaces = in; 220 cananian 1.1.2.3 } 221 cananian 1.1.2.4 return (HClass[]) Util.safeCopy(HClass.arrayFactory, in); 222 cananian 1.1.2.3 } 223 cananian 1.1 224 cananian 1.1 /** 225 cananian 1.1 * Return the name of the source file for this class, or a 226 cananian 1.1 * zero-length string if the information is not available. 227 cananian 1.1 */ 228 cananian 1.1 public String getSourceFile() { return sourcefile==null?"":sourcefile; } 229 cananian 1.1 230 cananian 1.1 /** 231 cananian 1.1 * Determines if the specified <code>HClass</code> object represents an 232 cananian 1.1 * interface type. 233 cananian 1.1 * @return <code>true</code> is this object represents an interface; 234 cananian 1.1 * <code>false</code> otherwise. 235 cananian 1.1 */ 236 cananian 1.1 public boolean isInterface() { 237 cananian 1.1 return Modifier.isInterface(getModifiers()); 238 cananian 1.1 } 239 cananian 1.1 240 cananian 1.1.2.3 // CACHING CODE: 241 cananian 1.1.2.3 public HConstructor[] getConstructors() { 242 cananian 1.1.2.3 if (constructors==null) 243 cananian 1.1.2.3 constructors = super.getConstructors(); 244 cananian 1.1.2.3 return (HConstructor[]) Util.safeCopy(HConstructor.arrayFactory, 245 cananian 1.1.2.3 constructors); 246 cananian 1.1.2.3 } 247 cananian 1.1.2.3 public HField[] getFields() { 248 cananian 1.1.2.3 if (fields==null) 249 cananian 1.1.2.3 fields = super.getFields(); 250 cananian 1.1.2.3 return (HField[]) Util.safeCopy(HField.arrayFactory, fields); 251 cananian 1.1.2.3 } 252 cananian 1.1.2.3 public HMethod[] getMethods() { 253 cananian 1.1.2.3 if (methods==null) 254 cananian 1.1.2.3 methods = super.getMethods(); 255 cananian 1.1.2.3 return (HMethod[]) Util.safeCopy(HMethod.arrayFactory, methods); 256 cananian 1.1 } 257 cananian 1.1 } 258 cananian 1.1 // set emacs indentation style. 259 cananian 1.1 // Local Variables: 260 cananian 1.1 // c-basic-offset:2 261 cananian 1.1 // End: