Source code: com/techtrader/modules/tools/bytecode/BCClass.java
1 package com.techtrader.modules.tools.bytecode;
2
3
4 import java.io.IOException;
5 import java.io.File;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.io.DataInput;
9 import java.io.DataOutput;
10 import java.io.DataInputStream;
11 import java.io.DataOutputStream;
12 import java.io.FileInputStream;
13 import java.io.FileOutputStream;
14 import java.io.ByteArrayOutputStream;
15 import java.io.ByteArrayInputStream;
16 import java.util.List;
17 import java.util.LinkedList;
18 import java.util.Iterator;
19
20 import com.techtrader.modules.tools.bytecode.lowlevel.ConstantPool;
21 import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
22
23
24 /**
25 * Start here to understand this package.
26 * A BCClass is a representation of a bytecode class. It contains
27 * methods to manipulate the class object itself as well as methods to
28 * manage the fields and methods of the class. As with most entities in the
29 * bytecode framework, there are methods to manipulate the low-level state
30 * of the class (constant pool indexes, etc), but these methods can safely
31 * be ignored in favor of the available high-level methods.
32 *
33 * @author Abe White
34 */
35 public class BCClass
36 extends BCEntity
37 implements Constants
38 {
39 private int _magic = VALID_MAGIC;
40 private int _minorVersion = 3;
41 private int _majorVersion = 45;
42 private int _access = ACCESS_PUBLIC | ACCESS_SUPER;
43 private int _classIndex = 0;
44 private int _superclassIndex = 0;
45
46 private ConstantPool _pool = new ConstantPool (this);
47 private List _interfaceIndexes = new LinkedList ();
48 private List _methods = new LinkedList ();
49 private List _fields = new LinkedList ();
50
51
52 /**
53 * Default constructor. Creates a new empty class.
54 */
55 public BCClass ()
56 {
57 }
58
59
60 /**
61 * Create a BCClass that is an exact copy of the given one.
62 */
63 public BCClass (BCClass orig)
64 {
65 copy (orig);
66 }
67
68
69 /**
70 * Create a BCClass for the given Class type.
71 */
72 public BCClass (Class type)
73 throws IOException
74 {
75 read (type);
76 }
77
78
79 /**
80 * Create a new BCClass with the given name.
81 */
82 public BCClass (String name)
83 {
84 setName (name);
85 setSuperclassName (Object.class.getName ());
86 }
87
88
89 /**
90 * Create a BCClass from the given .class file.
91 */
92 public BCClass (File classFile)
93 throws IOException
94 {
95 read (classFile);
96 }
97
98
99 /**
100 * Create a BCClass from the given stream representing a .class file.
101 */
102 public BCClass (InputStream in)
103 throws IOException
104 {
105 read (in);
106 }
107
108
109 /**
110 * Read the class definition from the given file.
111 * This method resets all information in this instance.
112 */
113 public void read (File classFile)
114 throws IOException
115 {
116 InputStream in = new FileInputStream (classFile);
117 try { read (in); } finally { in.close (); }
118 }
119
120
121 /**
122 * Read the class definition from the given stream.
123 * This method resets all information in this instance.
124 */
125 public void read (InputStream instream)
126 throws IOException
127 {
128 DataInput in = new DataInputStream (instream);
129
130 // header information
131 setMagic (in.readInt ());
132 setMinorVersion (in.readUnsignedShort ());
133 setMajorVersion (in.readUnsignedShort ());
134
135 // constant pool
136 _pool.readData (in);
137
138 // access flags
139 setAccessFlags (in.readUnsignedShort ());
140
141 // class, super class, interfaces
142 setIndex (in.readUnsignedShort ());
143 setSuperclassIndex (in.readUnsignedShort ());
144
145 _interfaceIndexes.clear ();
146 int interfaceCount = in.readUnsignedShort ();
147 int interfaceIndex;
148 for (int i = 0; i < interfaceCount; i++)
149 _interfaceIndexes.add (new Integer (in.readUnsignedShort ()));
150
151 // fields
152 _fields.clear ();
153 int fieldCount = in.readUnsignedShort ();
154 BCField field;
155 for (int i = 0; i < fieldCount; i++)
156 {
157 field = addField ();
158 field.readData (in);
159 }
160
161 // methods
162 _methods.clear ();
163 int methodCount = in.readUnsignedShort ();
164 BCMethod method;
165 for (int i = 0; i < methodCount; i++)
166 {
167 method = addMethod ();
168 method.readData (in);
169 }
170
171 readAttributes (in);
172 }
173
174
175 /**
176 * Read the definition of the given class.
177 * This method resets all information in this instance.
178 */
179 public void read (Class type)
180 throws IOException
181 {
182 // find out the length of the package name
183 int dotIndex = type.getName ().lastIndexOf ('.') + 1;
184
185 // strip the package off of the class name
186 String className = type.getName ().substring (dotIndex);
187
188 // attempt to get the class file for the class as a stream
189 InputStream in = type.getResourceAsStream (className + ".class");
190 try { read (in); } finally { in.close (); }
191 }
192
193
194 /**
195 * For existing classes, write the new bytecode to the same .class file
196 * the class was laoded from.
197 */
198 public void write ()
199 throws IOException
200 {
201 String name = getName ();
202 int dotIndex = name.lastIndexOf ('.') + 1;
203 name = name.substring (dotIndex);
204
205 Class type = null;
206 try
207 {
208 type = getType ();
209 }
210 catch (ClassNotFoundException cnfe)
211 {
212 throw new IOException (cnfe.getMessage ());
213 }
214
215 // attempt to get the class file for the class as a stream
216 OutputStream out = new FileOutputStream (type.getResource
217 (name + ".class").getFile ());
218 try { write (out); } finally { out.close (); }
219 }
220
221
222 /**
223 * Write the class to the specified file.
224 */
225 public void write (File classFile)
226 throws IOException
227 {
228 OutputStream out = new FileOutputStream (classFile);
229 try { write (out); } finally { out.close (); }
230 }
231
232
233 /**
234 * Write the class to the specified stream.
235 */
236 public void write (OutputStream outstream)
237 throws IOException
238 {
239 DataOutput out = new DataOutputStream (outstream);
240
241 // header information
242 out.writeInt (getMagic ());
243 out.writeShort (getMinorVersion ());
244 out.writeShort (getMajorVersion ());
245
246 // constant pool
247 _pool.writeData (out);
248
249 // access flags
250 out.writeShort (getAccessFlags ());
251
252 // class, super class, interfaces
253 out.writeShort (getIndex ());
254 out.writeShort (getSuperclassIndex ());
255 out.writeShort (_interfaceIndexes.size ());
256 for (Iterator i = _interfaceIndexes.iterator (); i.hasNext ();)
257 out.writeShort (((Number) i.next ()).intValue ());
258
259 // fields
260 out.writeShort (_fields.size ());
261 for (Iterator i = _fields.iterator (); i.hasNext ();)
262 ((BCField) i.next ()).writeData (out);
263
264 // methods
265 out.writeShort (_methods.size ());
266 for (Iterator i = _methods.iterator (); i.hasNext ();)
267 ((BCMethod) i.next ()).writeData (out);
268
269 // attributes
270 writeAttributes (out);
271 }
272
273
274 /**
275 * Get the contents of this class as a byte array, possibly for use
276 * in a custom ClassLoader.
277 */
278 public byte[] toByteArray ()
279 throws IOException
280 {
281 ByteArrayOutputStream out = new ByteArrayOutputStream ();
282 try
283 {
284 write (out);
285 out.flush ();
286
287 return out.toByteArray ();
288 }
289 finally
290 {
291 out.close ();
292 }
293 }
294
295
296 /**
297 * Copy all of the data from the given original BCClass to this one,
298 * recursing into fields, methods, code, the constant pool, etc.
299 */
300 public void copy (BCClass orig)
301 {
302 try
303 {
304 ByteArrayInputStream in = new ByteArrayInputStream
305 (orig.toByteArray ());
306 read (in);
307 in.close ();
308 }
309 catch (IOException ioe)
310 {
311 throw new RuntimeException (ioe.getMessage ());
312 }
313 }
314
315
316 /**
317 * Get the magic number for this .class; if this is a valid class, this
318 * should be equal to the VALID_MAGIC constant.
319 */
320 public int getMagic ()
321 {
322 return _magic;
323 }
324
325
326 /**
327 * Set the magic number for this .class; if this is a valid class, this
328 * should be equal to the VALID_MAGIC constant (the default value).
329 */
330 public void setMagic (int magic)
331 {
332 _magic = magic;
333 }
334
335
336 /**
337 * Get the major version of the bytecode spec used for this class;
338 * JVMs are only required to operate with versions that they understand;
339 * leaving the default value (45) is safe.
340 */
341 public int getMajorVersion ()
342 {
343 return _majorVersion;
344 }
345
346
347 /**
348 * Set the major version of the bytecode spec used for this class;
349 * JVMs are only required to operate with versions that they understand;
350 * leaving the default value (45) is safe.
351 */
352 public void setMajorVersion (int majorVersion)
353 {
354 _majorVersion = majorVersion;
355 }
356
357
358 /**
359 * Get the minor version of the bytecode spec used for this class;
360 * JVMs are only required to operate with versions that they understand;
361 * leaving the default value (3) is safe.
362 */
363 public int getMinorVersion ()
364 {
365 return _minorVersion;
366 }
367
368
369 /**
370 * Set the minor version of the bytecode spec used for this class;
371 * JVMs are only required to operate with versions that they understand;
372 * leaving the default value (3) is safe.
373 */
374 public void setMinorVersion (int minorVersion)
375 {
376 _minorVersion = minorVersion;
377 }
378
379
380 /**
381 * Return the access flags for this class as a bit array of
382 * ACCESS_XXX constants. This can be used to transfer access flags
383 * between classes without getting/setting each possible access flag.
384 */
385 public int getAccessFlags ()
386 {
387 return _access;
388 }
389
390
391 /**
392 * Set the access flags for this class as a bit array of
393 * ACCESS_XXX constants. This can be used to transfer access flags
394 * between classes without getting/setting each possible access flag.
395 */
396 public void setAccessFlags (int access)
397 {
398 _access = access;
399 }
400
401
402 /**
403 * Manipulate the class access flags.
404 */
405 public boolean isPublic ()
406 {
407 return BCHelper.hasFlag (_access, ACCESS_PUBLIC);
408 }
409
410
411 /**
412 * Manipulate the class access flags.
413 */
414 public void makePublic ()
415 {
416 _access = BCHelper.setFlag (_access, ACCESS_PUBLIC, true);
417 }
418
419
420 /**
421 * Manipulate the class access flags.
422 */
423 public boolean isPackage ()
424 {
425 return !isPublic ();
426 }
427
428
429 /**
430 * Manipulate the class access flags.
431 */
432 public void makePackage ()
433 {
434 _access = BCHelper.setFlag (_access, ACCESS_PUBLIC, false);
435 }
436
437
438 /**
439 * Manipulate the class access flags.
440 */
441 public boolean isFinal ()
442 {
443 return BCHelper.hasFlag (_access, ACCESS_FINAL);
444 }
445
446
447 /**
448 * Manipulate the class access flags.
449 */
450 public void setFinal (boolean on)
451 {
452 _access = BCHelper.setFlag (_access, ACCESS_FINAL, on);
453 }
454
455
456 /**
457 * Manipulate the class access flags.
458 */
459 public boolean isInterface ()
460 {
461 return BCHelper.hasFlag (_access, ACCESS_INTERFACE);
462 }
463
464
465 /**
466 * Manipulate the class access flags.
467 */
468 public void setInterface (boolean on)
469 {
470 _access = BCHelper.setFlag (_access, ACCESS_INTERFACE, on);
471 if (on)
472 setAbstract (true);
473 }
474
475
476 /**
477 * Manipulate the class access flags.
478 */
479 public boolean isAbstract ()
480 {
481 return BCHelper.hasFlag (_access, ACCESS_ABSTRACT);
482 }
483
484
485 /**
486 * Manipulate the class access flags.
487 */
488 public void setAbstract (boolean on)
489 {
490 _access = BCHelper.setFlag (_access, ACCESS_INTERFACE, on);
491 }
492
493
494 /**
495 * Get the index in the constant pool of the ClassEntry for this class.
496 */
497 public int getIndex ()
498 {
499 return _classIndex;
500 }
501
502
503 /**
504 * Set the constant pool index of the ClassEntry for this class.
505 */
506 public void setIndex (int index)
507 {
508 _classIndex = index;
509 }
510
511
512 /**
513 * Get the name of this class, including package name.
514 */
515 public String getName ()
516 {
517 return BCHelper.getExternalForm
518 (_pool.getClassName (_classIndex), true);
519 }
520
521
522 /**
523 * Set the name of this class.
524 */
525 public void setName (String name)
526 {
527 _classIndex = _pool.setClassName (_classIndex,
528 BCHelper.getInternalForm (name, false));
529 }
530
531
532 /**
533 * Get the Class object for this class.
534 */
535 public Class getType ()
536 throws ClassNotFoundException
537 {
538 return BCHelper.classForName (_pool.getClassName (_classIndex));
539 }
540
541
542 /**
543 * Get the index in the constant pool of the ClassEntry for the
544 * superclass.
545 */
546 public int getSuperclassIndex ()
547 {
548 return _superclassIndex;
549 }
550
551
552 /**
553 * Set the constant pool index of the ClassEntry for the superclass.
554 */
555 public void setSuperclassIndex (int index)
556 {
557 _superclassIndex = index;
558 }
559
560
561 /**
562 * Get the name of the superclass for this class, including package name.
563 */
564 public String getSuperclassName ()
565 {
566 return BCHelper.getExternalForm
567 (_pool.getClassName (_superclassIndex), true);
568 }
569
570
571 /**
572 * Set the name of the superclass to this class.
573 */
574 public void setSuperclassName (String name)
575 {
576 _superclassIndex = _pool.setClassName (_superclassIndex,
577 BCHelper.getInternalForm (name, false));
578 }
579
580
581 /**
582 * Get the Class object for the superclass of this class.
583 */
584 public Class getSuperclassType ()
585 throws ClassNotFoundException
586 {
587 return BCHelper.classForName (_pool.getClassName (_superclassIndex));
588 }
589
590
591 /**
592 * Set the Class object for the superclass of this class.
593 */
594 public void setSuperclassType (Class type)
595 {
596 if (type == null)
597 setSuperclassName (Object.class.getName ());
598 else
599 setSuperclassName (type.getName ());
600 }
601
602
603 /**
604 * Get the list of indexes into the constant pool of the ClassEntrys
605 * describing all the interfaces this class implements/extends.
606 *
607 * @return the implmented interfaces, or empty array if none
608 */
609 public int[] getInterfaceIndexes ()
610 {
611 int[] indexes = new int[_interfaceIndexes.size ()];
612
613 Iterator intItr = _interfaceIndexes.iterator ();
614 for (int i = 0, max = _interfaceIndexes.size (); i < max; i++)
615 indexes[i] = ((Integer) intItr.next ()).intValue ();
616
617 return indexes;
618 }
619
620
621 /**
622 * Set the list of indexes into the constant pool of the ClassEntrys
623 * describing all the interfaces this class implements/extends; set to
624 * null if none.
625 */
626 public void setInterfaceIndexes (int[] interfaceIndexes)
627 {
628 _interfaceIndexes.clear ();
629
630 if (interfaceIndexes != null)
631 for (int i = 0; i < interfaceIndexes.length; i++)
632 _interfaceIndexes.add (new Integer (interfaceIndexes[i]));
633 }
634
635
636 /**
637 * Get the names of the interfaces for this class, including package names.
638 */
639 public String[] getInterfaceNames ()
640 {
641 String[] names = new String[_interfaceIndexes.size ()];
642
643 Iterator interfaces = _interfaceIndexes.iterator ();
644 for (int i = 0; i < names.length; i++)
645 names[i] = BCHelper.getExternalForm (_pool.getClassName
646 (((Integer) interfaces.next ()).intValue ()), true);
647
648 return names;
649 }
650
651
652 /**
653 * Get the Class objects for the interfaces of this class.
654 */
655 public Class[] getInterfaceTypes ()
656 throws ClassNotFoundException
657 {
658 Class[] types = new Class[_interfaceIndexes.size ()];
659
660 Iterator interfaces = _interfaceIndexes.iterator ();
661 for (int i = 0; i < types.length; i++)
662 types[i] = BCHelper.classForName (_pool.getClassName
663 (((Integer) interfaces.next ()).intValue ()));
664
665 return types;
666 }
667
668
669 /**
670 * Set the interfaces implemented by this class.
671 */
672 public void setInterfaceNames (String[] interfaces)
673 {
674 _interfaceIndexes.clear ();
675 if (interfaces != null)
676 for (int i = 0; i < interfaces.length; i++)
677 addInterfaceName (interfaces[i]);
678 }
679
680
681 /**
682 * Set the interfaces implemented by this class.
683 */
684 public void setInterfaceTypes (Class[] interfaces)
685 {
686 String[] names = null;
687 if (interfaces != null)
688 {
689 names = new String[interfaces.length];
690 for (int i = 0; i < interfaces.length; i++)
691 names[i] = interfaces[i].getName ();
692 }
693
694 setInterfaceNames (names);
695 }
696
697
698 /**
699 * Clear this class of all interface declarations.
700 */
701 public void clearInterfaces ()
702 {
703 _interfaceIndexes.clear ();
704 }
705
706
707 /**
708 * Remove an interface implmented by this class.
709 */
710 public boolean removeInterfaceName (String name)
711 {
712 if (name == null)
713 return false;
714
715 String internalForm = BCHelper.getInternalForm (name, false);
716 for (Iterator i = _interfaceIndexes.iterator (); i.hasNext ();)
717 {
718 if (_pool.getClassName (((Integer) i.next ()).intValue ()).
719 equals (internalForm))
720 {
721 i.remove ();
722 return true;
723 }
724 }
725 return false;
726 }
727
728
729 /**
730 * Remove an interface implemented by this class.
731 */
732 public boolean removeInterfaceType (Class type)
733 {
734 return removeInterfaceName (type.getName ());
735 }
736
737
738 /**
739 * Add an interface to those implemented by this class.
740 */
741 public void addInterfaceName (String name)
742 {
743 int index = _pool.setClassName (0,
744 BCHelper.getInternalForm (name, false));
745
746 _interfaceIndexes.add (new Integer (index));
747 }
748
749
750 /**
751 * Add a Class to those implemented by this interface.
752 */
753 public void addInterfaceType (Class type)
754 {
755 addInterfaceName (type.getName ());
756 }
757
758
759 /**
760 * Return true if the class declares that it implements the given
761 * interface.
762 */
763 public boolean implementsInterface (String name)
764 {
765 String[] interfaces = getInterfaceNames ();
766 for (int i = 0; i < interfaces.length; i++)
767 if (interfaces[i].equals (name))
768 return true;
769
770 return false;
771 }
772
773
774 /**
775 * Return true if the class declares that it implements the given
776 * interface.
777 */
778 public boolean implementsInterface (Class type)
779 {
780 return implementsInterface (type.getName ());
781 }
782
783
784 /**
785 * Get all the fields of this class.
786 */
787 public BCField[] getFields ()
788 {
789 return (BCField[]) _fields.toArray (new BCField[_fields.size ()]);
790 }
791
792
793 /**
794 * Get the field with the given name.
795 */
796 public BCField getField (String name)
797 {
798 BCField next;
799 for (Iterator i = _fields.iterator (); i.hasNext ();)
800 {
801 next = (BCField) i.next ();
802 if (next.getName ().equals (name))
803 return next;
804 }
805
806 return null;
807 }
808
809
810 /**
811 * Import the given field from another class, or, if the field belongs
812 * to this class, add a duplicate of it (in this case, it is an error
813 * not to change the field name).
814 */
815 public BCField importField (BCField field)
816 {
817 BCField newField = addField (field.getName (), field.getTypeName ());
818 newField.setAccessFlags (field.getAccessFlags ());
819 newField.importAttributes (field);
820
821 return newField;
822 }
823
824
825 /**
826 * Import all fields from another class.
827 */
828 public void importFields (BCClass other)
829 {
830 BCField[] fields = other.getFields ();
831 for (int i = 0; i < fields.length; i++)
832 importField (fields[i]);
833 }
834
835
836 /**
837 * Add a field to this class.
838 */
839 public BCField addField ()
840 {
841 BCField field = new BCField (this);
842 _fields.add (field);
843
844 return field;
845 }
846
847
848 /**
849 * Add a field to this class.
850 */
851 public BCField addField (String name, String type)
852 {
853 BCField field = addField ();
854 field.setName (name);
855 field.setTypeName (type);
856
857 return field;
858 }
859
860
861 /**
862 * Add a field to this class.
863 */
864 public BCField addField (String name, Class type)
865 {
866 return addField (name, type.getName ());
867 }
868
869
870 /**
871 * Clear all fields from this class.
872 */
873 public void clearFields ()
874 {
875 _fields.clear ();
876 }
877
878
879 /**
880 * Removes the field with the given name from this class.
881 */
882 public boolean removeField (String name)
883 {
884 return removeField (getField (name));
885 }
886
887
888 /**
889 * Removes a field from this class. After this method, the field
890 * will be invalid, and the result of any operations on it is undefined.
891 */
892 public boolean removeField (BCField field)
893 {
894 if (field == null || !_fields.remove (field))
895 return false;
896
897 field.invalidate ();
898 return true;
899 }
900
901
902 /**
903 * Get all the methods of this class.
904 */
905 public BCMethod[] getMethods ()
906 {
907 return (BCMethod[]) _methods.toArray (new BCMethod[_methods.size ()]);
908 }
909
910
911 /**
912 * Get the method with the given name. If multiple methods in this class
913 * have this name, which is returned is not defined.
914 */
915 public BCMethod getMethod (String name)
916 {
917 BCMethod next;
918 for (Iterator i = _methods.iterator (); i.hasNext ();)
919 {
920 next = (BCMethod) i.next ();
921 if (next.getName ().equals (name))
922 return next;
923 }
924
925 return null;
926 }
927
928
929 /**
930 * Get all methods with the given name.
931 *
932 * @return the matching methods, or empty array if none
933 */
934 public BCMethod[] getMethods (String name)
935 {
936 List matches = new LinkedList ();
937 BCMethod next;
938 for (Iterator i = _methods.iterator (); i.hasNext ();)
939 {
940 next = (BCMethod) i.next ();
941 if (next.getName ().equals (name))
942 matches.add (next);
943 }
944
945 return (BCMethod[]) matches.toArray (new BCMethod[matches.size ()]);
946 }
947
948
949 /**
950 * Get the method with the given name and param types.
951 */
952 public BCMethod getMethod (String name, String[] params)
953 {
954 if (params == null)
955 params = new String[0];
956
957 String[] curParams;
958 boolean match;
959 BCMethod next;
960 for (Iterator i = _methods.iterator (); i.hasNext ();)
961 {
962 next = (BCMethod) i.next ();
963 if (next.getName ().equals (name))
964 {
965 curParams = next.getParamTypeNames ();
966 if (curParams.length != params.length)
967 continue;
968
969 match = true;
970 for (int j = 0; j < params.length; j++)
971 {
972 if (!curParams[j].equals (BCHelper.getExternalForm
973 (params[j], true)))
974 {
975 match = false;
976 break;
977 }
978 }
979
980 if (match)
981 return next;
982 }
983 }
984
985 return null;
986 }
987
988
989 /**
990 * Get the method with the given name and param types.
991 */
992 public BCMethod getMethod (String name, Class[] params)
993 {
994 String[] paramTypeNames;
995 if (params == null)
996 paramTypeNames = new String[0];
997 else
998 {
999 paramTypeNames = new String[params.length];
1000 for (int i = 0; i < params.length; i++)
1001 paramTypeNames[i] = params[i].getName ();
1002 }
1003
1004 return getMethod (name, paramTypeNames);
1005 }
1006
1007
1008 /**
1009 * Import the given method from another class, or, if the method belongs
1010 * to this class, add a duplicate of it (in this case, it is an error
1011 * not to change the method name or parameter types).
1012 */
1013 public BCMethod importMethod (BCMethod method)
1014 {
1015 BCMethod newMethod = addMethod (method.getName (),
1016 method.getReturnTypeName (), method.getParamTypeNames ());
1017 newMethod.setAccessFlags (method.getAccessFlags ());
1018 newMethod.importAttributes (method);
1019
1020 return newMethod;
1021 }
1022
1023
1024 /**
1025 * Import all methods from the given class; note that this includes
1026 * constructors, static initializers, etc.
1027 */
1028 public void importMethods (BCClass other)
1029 {
1030 BCMethod[] methods = other.getMethods ();
1031 for (int i = 0; i < methods.length; i++)
1032 importMethod (methods[i]);
1033 }
1034
1035
1036 /**
1037 * Add a method to this class.
1038 */
1039 public BCMethod addMethod ()
1040 {
1041 BCMethod method = new BCMethod (this);
1042 _methods.add (method);
1043
1044 return method;
1045 }
1046
1047
1048 /**
1049 * Add a method to this class.
1050 */
1051 public BCMethod addMethod (String name, String returnType,
1052 String[] paramTypes)
1053 {
1054 BCMethod method = addMethod ();
1055 method.setName (name);
1056 method.setDescriptor (returnType, paramTypes);
1057
1058 return method;
1059 }
1060
1061
1062 /**
1063 * Add a method to this class.
1064 */
1065 public BCMethod addMethod (String name, Class returnType,
1066 Class[] paramTypes)
1067 {
1068 BCMethod method = addMethod ();
1069 method.setName (name);
1070 method.setDescriptor (returnType, paramTypes);
1071
1072 return method;
1073 }
1074
1075
1076 /**
1077 * Remove all methods from this class; note that this includes
1078 * constructors, static initializers, etc.
1079 */
1080 public void clearMethods ()
1081 {
1082 _methods.clear ();
1083 }
1084
1085
1086 /**
1087 * Removes a method from this class. After this method, the method
1088 * will be invalid, and the result of any operations on it is undefined.
1089 */
1090 public boolean removeMethod (BCMethod method)
1091 {
1092 if (method == null || !_methods.remove (method))
1093 return false;
1094
1095 method.invalidate ();
1096 return true;
1097 }
1098
1099
1100 /**
1101 * Removes the method with the given name from the class. If multiple
1102 * methods have the name, they will all be removed.
1103 */
1104 public boolean removeMethod (String name)
1105 {
1106 BCMethod[] matches = getMethods (name);
1107 for (int i = 0; i < matches.length; i++)
1108 removeMethod (matches[i]);
1109
1110 return (matches.length > 0);
1111 }
1112
1113
1114 /**
1115 * Removes the method with the given signature.
1116 */
1117 public boolean removeMethod (String name, String[] params)
1118 {
1119 return removeMethod (getMethod (name, params));
1120 }
1121
1122
1123 /**
1124 * Removes the method with the given signature.
1125 */
1126 public boolean removeMethod (String name, Class[] params)
1127 {
1128 return removeMethod (getMethod (name, params));
1129 }
1130
1131
1132 /**
1133 * Return the constant pool for this class.
1134 */
1135 public ConstantPool getPool ()
1136 {
1137 return _pool;
1138 }
1139
1140
1141 /**
1142 * Add a default constructor to this class. This method can only be
1143 * called if the superclass has been set.
1144 */
1145 public BCMethod addDefaultConstructor ()
1146 {
1147 BCMethod method = addMethod ("<init>", void.class, null);
1148 Code code = method.addCode ();
1149 code.setMaxStack (1);
1150 code.setMaxLocals (1);
1151
1152 code.aload_0 ();
1153 code.invokespecial ().setMethod
1154 ("<init>", void.class, null, getSuperclassName ());
1155 code.vreturn ();
1156
1157 return method;
1158 }
1159
1160
1161 public void acceptVisit (BCVisitor visit)
1162 {
1163 visit.enterBCClass (this);
1164
1165 _pool.acceptVisit (visit);
1166 for (Iterator i = _fields.iterator (); i.hasNext ();)
1167 ((BCField) i.next ()).acceptVisit (visit);
1168 for (Iterator i = _methods.iterator (); i.hasNext ();)
1169 ((BCMethod) i.next ()).acceptVisit (visit);
1170 visitAttributes (visit);
1171
1172 visit.exitBCClass (this);
1173 }
1174}