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: