KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > bytecode > ClassType


1 // Copyright (c) 1997, 1998, 1999, 2001, 2002, 2004, 2005 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.bytecode;
5 import java.io.*;
6 import java.util.Vector JavaDoc;
7
8 public class ClassType extends ObjectType
9   implements AttrContainer, Externalizable
10 {
11   // An old but generally valid default value.
12
int classfileFormatVersion = 45 * 0x10000 + 3;
13
14   public short getClassfileMajorVersion ()
15   {
16     return (short) (classfileFormatVersion >> 16);
17   }
18   public short getClassfileMinorVersion ()
19   {
20     return (short) (classfileFormatVersion & 0xFFFF);
21   }
22   public void setClassfileVersion (int major, int minor)
23   {
24     classfileFormatVersion = (major & 0xFFFF) * 0x10000 + (minor * 0xFFFF);
25   }
26   public void setClassfileVersionJava5 ()
27   {
28     setClassfileVersion(49, 0);
29   }
30
31   /** Find a ClassType with the given name, or create a new one.
32    * Use this for "library classes", where you need the field/method types,
33    * but not one where you are about to generate code for.
34    * @param name the name of the class (e..g. "java.lang.String").
35    */

36   public static ClassType make(String JavaDoc name)
37   {
38     return (ClassType) Type.getType(name);
39   }
40
41   public static ClassType make (String JavaDoc name, ClassType superClass)
42   {
43     ClassType type = make(name);
44     if (type.superClass == null)
45       type.setSuper(superClass);
46     return type;
47   }
48
49   int thisClassIndex;
50
51   /** The super (base) class of the current class.
52    * X.superClass == null means the superClass has not been specified,
53    * and defaults to java.lang.Object. */

54   ClassType superClass;
55   /** The constant pool index of the superClass, or -1 if unassigned. */
56   int superClassIndex = -1;
57
58   ClassType[] interfaces;
59   int[] interfaceIndexes;
60   public int access_flags;
61
62   Attribute attributes;
63   public final Attribute getAttributes () { return attributes; }
64   public final void setAttributes (Attribute attributes)
65     { this.attributes = attributes; }
66
67   public static final ClassType[] noClasses = { };
68
69   boolean emitDebugInfo = true;
70
71   ConstantPool constants;
72
73   public final ConstantPool getConstants () { return constants; }
74
75   public final CpoolEntry getConstant(int i)
76   {
77     if (constants == null || constants.pool == null
78     || i > constants.count)
79       return null;
80     return constants.pool[i];
81   }
82
83   /** Return the modifiers (access flags) for this class. */
84   public final int getModifiers()
85   {
86     if (access_flags == 0
87     && (flags & EXISTING_CLASS) != 0 && getReflectClass() != null)
88       access_flags = reflectClass.getModifiers();
89     return access_flags;
90   }
91
92   /** Set the modifiers (access flags) for this class. */
93   public final void setModifiers(int flags) { access_flags = flags; }
94
95   public final boolean hasOuterLink ()
96   {
97     getFields();
98     return (flags & HAS_OUTER_LINK) != 0;
99   }
100
101   public ClassType getOuterLinkType ()
102   {
103     return ! hasOuterLink() ? null
104       : (ClassType) getDeclaredField("this$0").getType();
105   }
106
107   /** Note that this class needs an other link ("this$0") field.
108    * This is only allowed if !isExisting().
109    * Adjust any existing "<init>" methods to take the extra
110    * implicit parameter.
111    * @param outer the outer class
112    */

113   public final Field setOuterLink (ClassType outer)
114   {
115     if ((flags & EXISTING_CLASS) != 0)
116       throw new Error JavaDoc("setOuterLink called for existing class "+getName());
117     Field field = getDeclaredField("this$0");
118     if (field == null)
119       {
120         field = addField("this$0", outer);
121         flags |= HAS_OUTER_LINK;
122         for (Method meth = methods; meth != null; meth = meth.getNext())
123           {
124             if ("<init>".equals(meth.getName()))
125               {
126                 if (meth.code != null)
127                   throw new Error JavaDoc("setOuterLink called when "+meth+" has code");
128                 Type[] arg_types = meth.arg_types;
129                 Type[] new_types = new Type[arg_types.length+1];
130                 System.arraycopy(arg_types, 0, new_types, 1, arg_types.length);
131                 new_types[0] = outer;
132                 meth.arg_types = new_types;
133                 meth.signature = null;
134               }
135           }
136       }
137     else if (! outer.equals(field.getType()))
138       throw new Error JavaDoc("inconsistent setOuterLink call for "+getName());
139     return field;
140   }
141
142   /** Check if a component is accessible from this class.
143    * @param declaring the class containing the component (a field, method,
144    * or inner class)
145    * @param modifiers the access flags of the component
146    * @return true if the specified component can be accessed from this class.
147    */

148   public boolean isAccessible (ClassType declaring, int modifiers)
149   {
150     int cmods = declaring.getModifiers();
151     if ((modifiers & Access.PUBLIC) != 0 && (cmods & Access.PUBLIC) != 0)
152       return true;
153     String JavaDoc callerName = getName();
154     String JavaDoc className = declaring.getName();
155     if (callerName.equals(className))
156       return true;
157     if ((modifiers & Access.PRIVATE) != 0)
158       return false;
159     int dot = callerName.lastIndexOf('.');
160     String JavaDoc callerPackage = dot >= 0 ? callerName.substring(0, dot) : "";
161     dot = className.lastIndexOf('.');
162     String JavaDoc classPackage = dot >= 0 ? className.substring(0, dot) : "";
163     if (callerPackage.equals(classPackage))
164       return true;
165     if ((modifiers & Access.PROTECTED) != 0
166         && this.isSubclass(declaring))
167       return true;
168     return false;
169   }
170
171   /** Sets the name of the class being defined in this classfile.
172    * @param name the name to give to the class
173    */

174   public void setName (String JavaDoc name)
175   {
176     this_name = name;
177     setSignature("L"+name.replace('.', '/')+";");
178   }
179
180   SourceDebugExtAttr sourceDbgExt;
181
182   /** Create a <code>SourceDebugExtAttr</code>, if needed, and
183    * set the "stratum". The stratum is typically a programming language
184    * such as "JSP", "Scheme", or "Java" (the default). */

185   public void setStratum (String JavaDoc stratum)
186   {
187     if (sourceDbgExt == null)
188       sourceDbgExt = new SourceDebugExtAttr(this);
189     sourceDbgExt.addStratum(stratum);
190   }
191
192   /** Set the name of the SourceFile associated with this class. */
193   public void setSourceFile (String JavaDoc name)
194   {
195     if (sourceDbgExt != null)
196       {
197     sourceDbgExt.addFile(name);
198     if (sourceDbgExt.fileCount > 1)
199       return;
200       }
201
202     name = SourceFileAttr.fixSourceFile(name);
203     int slash = name.lastIndexOf('/');
204     if (slash >= 0)
205       name = name.substring(slash+1);
206     SourceFileAttr.setSourceFile(this, name);
207   }
208
209   /**
210    * Set the superclass of the is class.
211    * @param name name of super class, or null if this is "Object".
212    */

213   public void setSuper (String JavaDoc name)
214   {
215     setSuper(name == null ? Type.pointer_type : ClassType.make(name));
216   }
217
218   public void setSuper (ClassType superClass)
219   {
220     this.superClass = superClass;
221   }
222
223   public ClassType getSuperclass ()
224   {
225     if (superClass == null
226     && ! isInterface()
227     && ! ("java.lang.Object".equals(getName()))
228     && (flags & EXISTING_CLASS) != 0 && getReflectClass() != null)
229       {
230     superClass = (ClassType) make(reflectClass.getSuperclass());
231       }
232     return superClass;
233   }
234
235   public String JavaDoc getPackageName()
236   {
237     String JavaDoc name = getName();
238     int index = name.lastIndexOf('.');
239     return index < 0 ? "" : name.substring(0, index);
240   }
241
242   /**
243    * @return the interfaces this class is declared to implement
244    * (not those inherited from its superclass/superinterfaces).
245    */

246   public synchronized ClassType[] getInterfaces()
247   {
248     if (interfaces == null
249     && (flags & EXISTING_CLASS) != 0 && getReflectClass() != null)
250       {
251     Class JavaDoc[] reflectInterfaces = reflectClass.getInterfaces();
252     int numInterfaces = reflectInterfaces.length;
253     interfaces
254       = numInterfaces == 0 ? noClasses : new ClassType[numInterfaces];
255
256     for (int i = 0; i < numInterfaces; i++)
257       interfaces[i] = (ClassType) Type.make(reflectInterfaces[i]);
258       }
259     return interfaces;
260   }
261
262   public void setInterfaces (ClassType[] interfaces)
263   { this.interfaces = interfaces; }
264
265   /** Add an interface to the list of implemented interfaces. */
266   public void addInterface (ClassType newInterface)
267   {
268     int oldCount;
269     if (interfaces == null || interfaces.length == 0)
270       {
271     oldCount = 0;
272     interfaces = new ClassType[1];
273       }
274     else
275       {
276     oldCount = interfaces.length;
277     for (int i = oldCount; --i >= 0; )
278       if (interfaces[i] == newInterface)
279         return;
280     ClassType[] newInterfaces = new ClassType[oldCount+1];
281     System.arraycopy(interfaces, 0, newInterfaces, 0, oldCount);
282     interfaces = newInterfaces;
283       }
284     interfaces[oldCount] = newInterface;
285   }
286
287   public final boolean isInterface()
288   { return (getModifiers() & Access.INTERFACE) != 0; }
289
290   public final void setInterface(boolean val)
291   {
292     if (val) access_flags |= Access.INTERFACE|Access.ABSTRACT;
293     else access_flags &= ~Access.INTERFACE|Access.ABSTRACT;
294   }
295
296   public ClassType () { }
297
298   public ClassType (String JavaDoc class_name)
299   {
300     super();
301     setName(class_name);
302   }
303
304   Field fields;
305   int fields_count;
306   Field last_field;
307   /** Constant pool index of "ConstantValue". */
308   int ConstantValue_name_index;
309
310   /** Constant pool index of "Code". */
311   int Code_name_index;
312
313   /** Constant pool index of "LocalVariableTable". */
314   int LocalVariableTable_name_index;
315
316   /** Constant pool index of "LineNumberTable". */
317   int LineNumberTable_name_index;
318
319   /** Get the fields of this class. */
320   public final synchronized Field getFields()
321   {
322     if ((flags & (ADD_FIELDS_DONE|EXISTING_CLASS)) == EXISTING_CLASS)
323       addFields();
324     return fields;
325   }
326
327   public final int getFieldCount()
328   {
329     return fields_count;
330   }
331
332   /** Find a field with the given name declared in this class.
333    * @return the matching field, or null if there is no such field.
334    */

335   public Field getDeclaredField(String JavaDoc name)
336   {
337     for (Field field = getFields(); field != null; field = field.next)
338       {
339     if (name.equals(field.name))
340       return field;
341       }
342     return null;
343   }
344
345   /** Find a field with the given name declared in this class or its ancestors.
346    * @param name the name of the field.
347    * @param mask of match a field whose modifiers has one of these bits set.
348    * Howeve, if mask is -1, ignore the access flags.
349    * @return the matching field, or null if there is no such field.
350    */

351   public Field getField(String JavaDoc name, int mask)
352   {
353     ClassType cl = this;
354     for (;;)
355       {
356         Field field = cl.getDeclaredField(name);
357         if (field != null
358             && (mask == -1 || (field.getModifiers() & mask) != 0))
359           return field;
360         ClassType[] interfaces = cl.getInterfaces();
361         if (interfaces != null)
362           {
363             for (int i = 0; i < interfaces.length; i++)
364               {
365                 field = interfaces[i].getField(name, mask);
366                 if (field != null)
367                   return field;
368               }
369           }
370         cl = cl.getSuperclass();
371         if (cl == null)
372           return null;
373       }
374   }
375
376   /** Find a field with the given name declared in this class or its ancestors.
377    * @return the matching field, or null if there is no such field.
378    */

379   public Field getField(String JavaDoc name)
380   {
381     return getField(name, Access.PUBLIC);
382   }
383
384   /**
385    * Add a new field to this class.
386    */

387   public Field addField () { return new Field (this); }
388
389   /**
390    * Add a new field to this class, and name the field.
391    * @param name the name of the new field
392    */

393   public Field addField (String JavaDoc name) {
394     Field field = new Field (this);
395     field.setName(name);
396     return field;
397   }
398
399   public final Field addField (String JavaDoc name, Type type) {
400     Field field = new Field (this);
401     field.setName(name);
402     field.setType(type);
403     return field;
404   }
405
406   public final Field addField (String JavaDoc name, Type type, int flags)
407   {
408     Field field = addField (name, type);
409     field.flags = flags;
410     return field;
411   }
412
413   /** Use reflection to add all the declared fields of this class.
414    * Does not add private or package-private fields.
415    * Does not check for duplicate (already-known) fields.
416    * Is not thread-safe if another thread may access this ClassType. */

417   public void addFields()
418   {
419     Class JavaDoc clas = getReflectClass();
420     java.lang.reflect.Field JavaDoc[] fields;
421     try
422       {
423         fields = clas.getDeclaredFields();
424       }
425     catch (SecurityException JavaDoc ex)
426       {
427         fields = clas.getFields();
428       }
429     int count = fields.length;
430     for (int i = 0; i < count; i++)
431       {
432         java.lang.reflect.Field JavaDoc field = fields[i];
433         if ("this$0".equals(field.getName()))
434           flags |= HAS_OUTER_LINK;
435         addField(field.getName(), Type.make(field.getType()),
436                  field.getModifiers());
437       }
438     flags |= ADD_FIELDS_DONE;
439   }
440
441   Method methods;
442   int methods_count;
443   Method last_method;
444   public Method constructor;
445
446   /** Get the methods of this class. */
447   public final Method getMethods()
448   {
449     return methods;
450   }
451
452   public final int getMethodCount() {
453     return methods_count;
454   }
455  
456   Method addMethod () {
457     return new Method (this, 0);
458   }
459
460   public Method addMethod (String JavaDoc name) {
461     return addMethod(name, 0);
462   }
463
464   public Method addMethod (String JavaDoc name, int flags) {
465     Method method = new Method (this, flags);
466     method.setName(name);
467     return method;
468   }
469
470   // deprecated:
471
public Method addMethod (String JavaDoc name,
472                Type[] arg_types, Type return_type,
473                int flags) {
474     return addMethod(name, flags, arg_types, return_type);
475   }
476
477   /** Add a method to this ClassType.
478     * If an existing method matches, return that. Otherwise, create
479     * a new one.
480     * In contrast, the other addMethod methods always create new Methods. */

481   public Method addMethod (String JavaDoc name, int flags,
482                Type[] arg_types, Type return_type)
483   {
484     Method method = getDeclaredMethod(name, arg_types);
485     if (method != null
486         && return_type.equals(method.getReturnType())
487         && (flags & method.access_flags) == flags)
488       return method;
489     method = addMethod(name, flags);
490     method.arg_types = arg_types;
491     method.return_type = return_type;
492     return method;
493   }
494
495   public Method addMethod (String JavaDoc name, String JavaDoc signature, int flags)
496   {
497     Method meth = addMethod(name, flags);
498     meth.setSignature(signature);
499     return meth;
500   }
501
502   /** Add a method to this ClassType.
503     * If an existing method matches, return that. Otherwise, create
504     * a new one. */

505   public Method getMethod (java.lang.reflect.Method JavaDoc method)
506   {
507     String JavaDoc name = method.getName();
508     Class JavaDoc[] parameterClasses = method.getParameterTypes();
509     Type[] parameterTypes = new Type[parameterClasses.length];
510     for (int i = parameterClasses.length; --i >= 0; )
511       parameterTypes[i] = Type.make(parameterClasses[i]);
512     return addMethod(name, method.getModifiers(),
513                      parameterTypes, Type.make(method.getReturnType()));
514   }
515
516   public final synchronized Method getDeclaredMethods()
517   {
518     if ((flags & (ADD_METHODS_DONE|EXISTING_CLASS)) == EXISTING_CLASS)
519       addMethods(getReflectClass());
520     return methods;
521   }
522
523   /** Count methods matching a given filter.
524    * @param filter to select methods to return
525    * @param searchSupers 0 if only current class should be searched,
526    * 1 if superclasses should also be searched,
527    * 2 if super-interfaces should also be search
528    * @return number of methods that match
529    */

530   public final int countMethods (Filter filter, int searchSupers)
531   {
532     return getMethods(filter, searchSupers, null, 0);
533   }
534
535   public Method[] getMethods (Filter filter, boolean searchSupers)
536   {
537     return getMethods(filter, searchSupers ? 1 : 0);
538   }
539
540   /** Get methods matching a given filter.
541    * @param filter to select methods to return
542    * @param searchSupers 0 if only current class should be searched,
543    * 1 if superclasses should also be searched,
544    * 2 if super-interfaces should also be searched
545    * @return a fresh array containing the methods satisfying the filter
546    */

547   public Method[] getMethods (Filter filter, int searchSupers)
548   {
549     int count = getMethods(filter, searchSupers, null, 0);
550     Method[] result = new Method[count];
551     getMethods(filter, searchSupers, result, 0);
552     return result;
553   }
554
555   /** Helper to get methods satisfying a filtering predicate.
556    * @param filter to select methods to return
557    * @param searchSupers 0 if only current class should be searched,
558    * 1 if superclasses should also be searched,
559    * 2 if super-interfaces should also be searched
560    * @param result array to place selected methods in
561    * @param offset start of where in result to place result
562    * @return number of methods placed in result array
563    * @deprecated
564    */

565   public int getMethods (Filter filter, int searchSupers,
566              Method[] result, int offset)
567   {
568     int count = 0;
569     for (ClassType ctype = this; ctype != null;
570      ctype = ctype.getSuperclass())
571     {
572       for (Method meth = ctype.getDeclaredMethods();
573        meth != null; meth = meth.getNext())
574     if (filter.select(meth))
575       {
576         if (result != null)
577           result[offset + count] = meth;
578         count++;
579       }
580       if (searchSupers == 0)
581     break;
582
583       if (searchSupers > 1)
584     {
585       ClassType[] interfaces = ctype.getInterfaces();
586       if (interfaces != null)
587         {
588           for (int i = 0; i < interfaces.length; i++)
589         count += interfaces[i].getMethods(filter, searchSupers,
590                           result, offset+count);
591         }
592     }
593     }
594     return count;
595   }
596
597   /** Helper to get methods satisfying a filtering predicate.
598    * @param filter to select methods to return
599    * @param searchSupers 0 if only current class should be searched,
600    * 1 if superclasses should also be searched,
601    * 2 if super-interfaces should also be searched
602    * @param result Vector to add selected methods in
603    * @param context If non-null, skip if class not visible in named package.
604    * @return number of methods placed in result array
605    */

606   public int getMethods (Filter filter, int searchSupers, Vector JavaDoc result,
607              String JavaDoc context)
608   {
609     int count = 0;
610     for (ClassType ctype = this; ctype != null;
611      ctype = ctype.getSuperclass())
612     {
613       if (context == null
614       || (ctype.getModifiers() & Access.PUBLIC) != 0
615       || context.equals(ctype.getPackageName()))
616     {
617       for (Method meth = ctype.getDeclaredMethods();
618            meth != null; meth = meth.getNext())
619         if (filter.select(meth))
620           {
621         if (result != null)
622           result.addElement(meth);
623         count++;
624           }
625     }
626       if (searchSupers == 0)
627     break;
628
629       if (searchSupers > 1)
630     {
631       ClassType[] interfaces = ctype.getInterfaces();
632       if (interfaces != null)
633         {
634           for (int i = 0; i < interfaces.length; i++)
635         count += interfaces[i].getMethods(filter, searchSupers,
636                           result, context);
637         }
638     }
639     }
640     return count;
641   }
642
643   /** Look for a matching method.
644    * @param name method name
645    * @param arg_types parameter types that must match.
646    * Can also be null, to match any parameter type list.
647    * Otherwise, an element of arg_types must be the same type (equals),
648    * though a null element of arg_types is a wildcard that matches any type.
649    */

650   public Method getDeclaredMethod(String JavaDoc name, Type[] arg_types)
651   {
652     int needOuterLinkArg = "<init>".equals(name) && hasOuterLink() ? 1 : 0;
653     for (Method method = getDeclaredMethods();
654      method != null; method = method.next)
655       {
656     if (! name.equals(method.getName()))
657       continue;
658     Type[] method_args = method.getParameterTypes();
659     if (arg_types == null
660             || (arg_types == method_args && needOuterLinkArg==0))
661       return method;
662     int i = arg_types.length;
663     if (i != method_args.length-needOuterLinkArg)
664       continue;
665     while (-- i >= 0)
666       {
667         Type meth_type = method_args[i+needOuterLinkArg];
668         Type need_type = arg_types[i];
669         if (meth_type == need_type || need_type == null)
670           continue;
671         String JavaDoc meth_sig = meth_type.getSignature();
672         String JavaDoc need_sig = need_type.getSignature();
673         if (! meth_sig.equals(need_sig))
674           break;
675       }
676     if (i < 0)
677       return method;
678       }
679     return null;
680   }
681
682   /** Get a method with matching name and number of arguments. */
683   public Method getDeclaredMethod(String JavaDoc name, int argCount)
684   {
685     Method result = null;
686     int needOuterLinkArg = "<init>".equals(name) && hasOuterLink() ? 1 : 0;
687     for (Method method = getDeclaredMethods();
688      method != null; method = method.next)
689       {
690     if (name.equals(method.getName())
691         && argCount + needOuterLinkArg == method.getParameterTypes().length)
692       {
693         if (result != null)
694           throw new Error JavaDoc("ambiguous call to getDeclaredMethod(\""
695                   + name + "\", " + argCount+
696                   ")\n - " + result + "\n - " + method);
697         result = method;
698       }
699       }
700     return result;
701   }
702
703   public Method getMethod(String JavaDoc name, Type[] arg_types)
704   {
705     ClassType cl = this;
706     for (;;)
707       {
708         Method method = cl.getDeclaredMethod(name, arg_types);
709     if (method != null)
710           return method;
711         cl = cl.getSuperclass();
712         if (cl == null)
713           break;
714       }
715     cl = this;
716     for (;;)
717       {
718         ClassType[] interfaces = cl.getInterfaces();
719         if (interfaces != null)
720           {
721             for (int i = 0; i < interfaces.length; i++)
722               {
723                 Method method
724                   = interfaces[i].getDeclaredMethod(name, arg_types);
725                 if (method != null)
726                   return method;
727               }
728           }
729         cl = cl.getSuperclass();
730         if (cl == null)
731           break;
732       }
733     return null;
734   }
735
736   /** Use reflection to add all the declared methods of this class.
737    * Does not add constructors nor private or package-private methods.
738    * Does not check for duplicate (already-known) methods.
739    * @param clas should be the same as getReflectClass(). */

740   public void addMethods(Class JavaDoc clas)
741   {
742     // Set this flag BEFORE the actual addition.
743
// This prevents this method to be called indirectly for the same class
744
// while it is executed, which would result in methods being listed
745
// twice in this class.
746
flags |= ADD_METHODS_DONE;
747
748     java.lang.reflect.Method JavaDoc[] methods;
749     try
750       {
751         methods = clas.getDeclaredMethods();
752       }
753     catch (SecurityException JavaDoc ex)
754       {
755         methods = clas.getMethods();
756       }
757     int count = methods.length;
758     for (int i = 0; i < count; i++)
759       {
760         java.lang.reflect.Method JavaDoc method = methods[i];
761         if (! method.getDeclaringClass().equals(clas))
762           continue;
763         int modifiers = method.getModifiers();
764         Class JavaDoc[] paramTypes = method.getParameterTypes();
765         int j = paramTypes.length;
766         Type[] args = new Type[j];
767         while (--j >= 0)
768           args[j] = Type.make(paramTypes[j]);
769         Method meth = addMethod(method.getName(), modifiers);
770         meth.arg_types = args;
771         meth.return_type = Type.make(method.getReturnType());
772       }
773
774     java.lang.reflect.Constructor JavaDoc[] cmethods;
775     try
776       {
777         cmethods = clas.getDeclaredConstructors();
778       }
779     catch (SecurityException JavaDoc ex)
780       {
781         cmethods = clas.getConstructors();
782       }
783     count = cmethods.length;
784     for (int i = 0; i < count; i++)
785       {
786         java.lang.reflect.Constructor JavaDoc method = cmethods[i];
787         if (! method.getDeclaringClass().equals(clas))
788           continue;
789         int modifiers = method.getModifiers();
790         if ((modifiers & (Access.PUBLIC|Access.PROTECTED)) == 0)
791           continue;
792         Class JavaDoc[] paramTypes = method.getParameterTypes();
793         int j = paramTypes.length;
794         Type[] args = new Type[j];
795         while (--j >= 0)
796           args[j] = Type.make(paramTypes[j]);
797         Method meth = addMethod("<init>", modifiers);
798         meth.arg_types = args;
799         meth.return_type = Type.void_type;
800       }
801   }
802
803   public Method[] getMatchingMethods(String JavaDoc name, Type[] paramTypes, int flags)
804   {
805     int nMatches = 0;
806     java.util.Vector JavaDoc matches = new java.util.Vector JavaDoc(10);
807     for (Method method = methods; method != null; method = method.getNext())
808     {
809       if (! name.equals(method.getName()))
810         continue;
811       if ((flags & Access.STATIC) != (method.access_flags & Access.STATIC))
812         continue;
813       if ((flags & Access.PUBLIC) > (method.access_flags & Access.PUBLIC))
814         continue;
815       Type[] mtypes = method.arg_types;
816       if (mtypes.length != paramTypes.length)
817         continue;
818       nMatches++;
819       matches.addElement(method);
820     }
821     Method[] result = new Method[nMatches];
822     matches.copyInto(result);
823     return result;
824   }
825
826   /** Do various fixups after generating code but before we can write it out.
827    * This includes assigning constant pool indexes where needed,
828    * finalizing labels, etc. */

829   public void doFixups ()
830   {
831     if (constants == null)
832       constants = new ConstantPool();
833     if (thisClassIndex == 0)
834       thisClassIndex = constants.addClass(this).index;
835     if (superClass == this)
836       setSuper((ClassType) null);
837     if (superClassIndex < 0)
838       superClassIndex = superClass == null ? 0
839     : constants.addClass(superClass).index;
840     if (interfaces != null && interfaceIndexes == null)
841       {
842     int n = interfaces.length;
843     interfaceIndexes = new int [n];
844     for (int i = 0; i < n; i++)
845       interfaceIndexes[i] = constants.addClass(interfaces[i]).index;
846       }
847     for (Field field = fields; field != null; field = field.next) {
848       field.assign_constants (this);
849     }
850     for (Method method = methods; method != null; method = method.next)
851       method.assignConstants();
852     Attribute.assignConstants(this, this);
853   }
854
855   public void writeToStream (OutputStream stream)
856     throws java.io.IOException JavaDoc
857   {
858     java.io.DataOutputStream JavaDoc dstr = new java.io.DataOutputStream JavaDoc (stream);
859     int i;
860
861     doFixups ();
862
863     dstr.writeInt (0xcafebabe); // magic
864
dstr.writeShort(getClassfileMinorVersion());
865     dstr.writeShort(getClassfileMajorVersion());
866
867     // Write out the constant pool.
868
if (constants == null)
869       dstr.writeShort (1);
870     else
871       constants.write(dstr);
872
873     dstr.writeShort (access_flags);
874     dstr.writeShort (thisClassIndex);
875     dstr.writeShort (superClassIndex);
876     if (interfaceIndexes == null)
877       dstr.writeShort (0); // interfaces_count
878
else
879       {
880     int interfaces_count = interfaceIndexes.length;
881     dstr.writeShort (interfaces_count);
882     for (i = 0; i < interfaces_count; i++)
883       dstr.writeShort (interfaceIndexes[i]);
884       }
885
886     dstr.writeShort (fields_count);
887     for (Field field = fields; field != null; field = field.next)
888       field.write (dstr, this);
889
890     dstr.writeShort (methods_count);
891     for (Method method = methods; method != null; method = method.next)
892       method.write (dstr, this);
893
894     Attribute.writeAll (this, dstr);
895
896     flags |= ADD_FIELDS_DONE | ADD_METHODS_DONE;
897   }
898
899   public void writeToFile (String JavaDoc filename)
900     throws java.io.IOException JavaDoc
901  {
902     OutputStream stream
903       = new BufferedOutputStream(new FileOutputStream (filename));
904     writeToStream (stream);
905     stream.close ();
906   }
907
908   public void writeToFile ()
909     throws java.io.IOException JavaDoc
910   {
911     writeToFile (this_name.replace ('.', File.separatorChar) + ".class");
912   }
913
914   public byte[] writeToArray ()
915   {
916     ByteArrayOutputStream stream = new ByteArrayOutputStream (500);
917     try
918       {
919     writeToStream(stream);
920       }
921     catch (java.io.IOException JavaDoc ex)
922       {
923     throw new InternalError JavaDoc(ex.toString());
924       }
925     return stream.toByteArray ();
926   }
927
928   /**
929    * Convert a String to a Utf8 byte array.
930    * @param str the input String.
931    * @return the input encoded as a utf8 byte array.
932    */

933   public static byte[] to_utf8 (String JavaDoc str)
934   {
935     if (str == null)
936       return null;
937     int str_len = str.length ();
938     int utf_len = 0;
939     for (int i = 0; i < str_len; i++) {
940       int c = str.charAt(i);
941       if ((c > 0) && (c <= 0x7F))
942     utf_len++;
943       else if (c <= 0x7FF)
944     utf_len += 2;
945       else
946     utf_len += 3;
947     }
948     byte[] buffer = new byte[utf_len];
949     int j = 0;
950     for (int i = 0; i < str_len; i++) {
951       int c = str.charAt(i);
952       if ((c > 0) && (c <= 0x7F))
953     buffer[j++] = (byte) c;
954       else if (c <= 0x7FF) {
955     buffer[j++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
956     buffer[j++] = (byte) (0x80 | ((c >> 0) & 0x3F));
957       } else {
958     buffer[j++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
959     buffer[j++] = (byte) (0x80 | ((c >> 6) & 0x3F));
960     buffer[j++] = (byte) (0x80 | ((c >> 0) & 0x3F));
961       }
962     }
963     return buffer;
964   }
965
966   /** True if this class/interface implements the interface iface. */
967   public final boolean implementsInterface(ClassType iface)
968   {
969     if (this == iface)
970       return true;
971     ClassType baseClass = this.getSuperclass();
972     if (baseClass != null && baseClass.implementsInterface(iface))
973       return true;
974     ClassType[] interfaces = getInterfaces();
975     if (interfaces != null)
976       {
977     for (int i = interfaces.length; --i >= 0; )
978       {
979         if (interfaces[i].implementsInterface(iface))
980           return true;
981       }
982       }
983     return false;
984   }
985
986   /** A more efficient version of isSubclass(ClassType.make(cname)).
987    * Does not cause the named class be loaded if it hasn't been.
988    * @param cname a class name - cannot be an interface name
989    */

990   public final boolean isSubclass (String JavaDoc cname)
991   {
992     ClassType ctype = this;
993     for (;;)
994       {
995         if (cname.equals(ctype.getName()))
996           return true;
997         ctype = ctype.getSuperclass();
998         if (ctype == null)
999           return false;
1000      }
1001  }
1002
1003  public final boolean isSubclass(ClassType other)
1004  {
1005    if (other.isInterface())
1006      return implementsInterface(other);
1007    if ((this == tostring_type && other == string_type)
1008    || (this == string_type && other == tostring_type))
1009      return true;
1010    ClassType baseClass = this;
1011    while (baseClass != null)
1012      {
1013        if (baseClass == other)
1014          return true;
1015        baseClass = baseClass.getSuperclass();
1016      }
1017    return false;
1018  }
1019
1020  public int compare(Type other)
1021  {
1022    if (other == nullType)
1023      return 1;
1024    if (! (other instanceof ClassType))
1025      return swappedCompareResult(other.compare(this));
1026    String JavaDoc name = getName();
1027    if (name != null && name.equals(other.getName()))
1028      return 0;
1029    ClassType cother = (ClassType) other;
1030    if (isSubclass(cother))
1031      return -1;
1032    if (cother.isSubclass(this))
1033      return 1;
1034    if (this == tostring_type)
1035      return cother == Type.pointer_type ? -1 : 1;
1036    if (cother == tostring_type)
1037      return this == Type.pointer_type ? 1 : -1;
1038    if (this.isInterface() || cother.isInterface())
1039      return -2;
1040    return -3;
1041  }
1042
1043  public String JavaDoc toString()
1044  {
1045    return "ClassType " + getName();
1046  }
1047
1048  /**
1049   * @serialData Write the class name (as given by getName()) using writeUTF.
1050   */

1051  public void writeExternal(ObjectOutput out) throws IOException
1052  {
1053    out.writeUTF(getName());
1054  }
1055
1056  public void readExternal(ObjectInput in)
1057    throws IOException, ClassNotFoundException JavaDoc
1058  {
1059    setName(in.readUTF());
1060    flags |= ClassType.EXISTING_CLASS;
1061  }
1062
1063  public Object JavaDoc readResolve() throws ObjectStreamException
1064  {
1065    String JavaDoc name = getName();
1066    /* #ifdef JAVA5 */
1067    // java.util.HashMap<String,Type> map = mapNameToType;
1068
/* #else */
1069    java.util.Hashtable JavaDoc map = mapNameToType;
1070    /* #endif */
1071    synchronized (map)
1072      {
1073        Type found = (Type) map.get(name);
1074        if (found != null)
1075          return found;
1076        map.put(name, this);
1077      }
1078    return this;
1079  }
1080
1081  /** Clear various object references, to help garbage collection. */
1082  public void cleanupAfterCompilation ()
1083  {
1084    for (Method meth = methods; meth != null; meth = meth.getNext())
1085      meth.cleanupAfterCompilation();
1086
1087    constants = null;
1088    attributes = null;
1089    sourceDbgExt = null;
1090  }
1091}
1092
Popular Tags