KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > asm > ClassWriter


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000,2002,2003 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Contact: Eric.Bruneton@rd.francetelecom.com
31  *
32  * Author: Eric Bruneton
33  */

34
35 package org.logicalcobwebs.asm;
36
37 /**
38  * A {@link ClassVisitor ClassVisitor} that generates Java class files. More
39  * precisely this visitor generates a byte array conforming to the Java class
40  * file format. It can be used alone, to generate a Java class "from scratch",
41  * or with one or more {@link ClassReader ClassReader} and adapter class
42  * visitor to generate a modified class from one or more existing Java classes.
43  */

44
45 public class ClassWriter implements ClassVisitor {
46
47   /**
48    * The type of CONSTANT_Class constant pool items.
49    */

50
51   final static int CLASS = 7;
52
53   /**
54    * The type of CONSTANT_Fieldref constant pool items.
55    */

56
57   final static int FIELD = 9;
58
59   /**
60    * The type of CONSTANT_Methodref constant pool items.
61    */

62
63   final static int METH = 10;
64
65   /**
66    * The type of CONSTANT_InterfaceMethodref constant pool items.
67    */

68
69   final static int IMETH = 11;
70
71   /**
72    * The type of CONSTANT_String constant pool items.
73    */

74
75   final static int STR = 8;
76
77   /**
78    * The type of CONSTANT_Integer constant pool items.
79    */

80
81   final static int INT = 3;
82
83   /**
84    * The type of CONSTANT_Float constant pool items.
85    */

86
87   final static int FLOAT = 4;
88
89   /**
90    * The type of CONSTANT_Long constant pool items.
91    */

92
93   final static int LONG = 5;
94
95   /**
96    * The type of CONSTANT_Double constant pool items.
97    */

98
99   final static int DOUBLE = 6;
100
101   /**
102    * The type of CONSTANT_NameAndType constant pool items.
103    */

104
105   final static int NAME_TYPE = 12;
106
107   /**
108    * The type of CONSTANT_Utf8 constant pool items.
109    */

110
111   final static int UTF8 = 1;
112
113   /**
114    * Index of the next item to be added in the constant pool.
115    */

116
117   private short index;
118
119   /**
120    * The constant pool of this class.
121    */

122
123   private ByteVector pool;
124
125   /**
126    * The constant pool's hash table data.
127    */

128
129   private Item[] table;
130
131   /**
132    * The threshold of the constant pool's hash table.
133    */

134
135   private int threshold;
136
137   /**
138    * The access flags of this class.
139    */

140
141   private int access;
142
143   /**
144    * The constant pool item that contains the internal name of this class.
145    */

146
147   private int name;
148
149   /**
150    * The constant pool item that contains the internal name of the super class
151    * of this class.
152    */

153
154   private int superName;
155
156   /**
157    * Number of interfaces implemented or extended by this class or interface.
158    */

159
160   private int interfaceCount;
161
162   /**
163    * The interfaces implemented or extended by this class or interface. More
164    * precisely, this array contains the indexes of the constant pool items
165    * that contain the internal names of these interfaces.
166    */

167
168   private int[] interfaces;
169
170   /**
171    * The index of the constant pool item that contains the name of the source
172    * file from which this class was compiled.
173    */

174
175   private int sourceFile;
176
177   /**
178    * Number of fields of this class.
179    */

180
181   private int fieldCount;
182
183   /**
184    * The fields of this class.
185    */

186
187   private ByteVector fields;
188
189   /**
190    * <tt>true</tt> if the maximum stack size and number of local variables must
191    * be automatically computed.
192    */

193
194   private boolean computeMaxs;
195
196   /**
197    * The methods of this class. These methods are stored in a linked list of
198    * {@link CodeWriter CodeWriter} objects, linked to each other by their {@link
199    * CodeWriter#next} field. This field stores the first element of this list.
200    */

201
202   CodeWriter firstMethod;
203
204   /**
205    * The methods of this class. These methods are stored in a linked list of
206    * {@link CodeWriter CodeWriter} objects, linked to each other by their {@link
207    * CodeWriter#next} field. This field stores the last element of this list.
208    */

209
210   CodeWriter lastMethod;
211
212   /**
213    * The number of entries in the InnerClasses attribute.
214    */

215
216   private int innerClassesCount;
217
218   /**
219    * The InnerClasses attribute.
220    */

221
222   private ByteVector innerClasses;
223
224   /**
225    * The non standard attributes of the class.
226    */

227
228   private Attribute attrs;
229
230   /**
231    * A reusable key used to look for items in the hash {@link #table table}.
232    */

233
234   Item key;
235
236   /**
237    * A reusable key used to look for items in the hash {@link #table table}.
238    */

239
240   Item key2;
241
242   /**
243    * A reusable key used to look for items in the hash {@link #table table}.
244    */

245
246   Item key3;
247
248   /**
249    * The type of instructions without any label.
250    */

251
252   final static int NOARG_INSN = 0;
253
254   /**
255    * The type of instructions with an signed byte label.
256    */

257
258   final static int SBYTE_INSN = 1;
259
260   /**
261    * The type of instructions with an signed short label.
262    */

263
264   final static int SHORT_INSN = 2;
265
266   /**
267    * The type of instructions with a local variable index label.
268    */

269
270   final static int VAR_INSN = 3;
271
272   /**
273    * The type of instructions with an implicit local variable index label.
274    */

275
276   final static int IMPLVAR_INSN = 4;
277
278   /**
279    * The type of instructions with a type descriptor argument.
280    */

281
282   final static int TYPE_INSN = 5;
283
284   /**
285    * The type of field and method invocations instructions.
286    */

287
288   final static int FIELDORMETH_INSN = 6;
289
290   /**
291    * The type of the INVOKEINTERFACE instruction.
292    */

293
294   final static int ITFMETH_INSN = 7;
295
296   /**
297    * The type of instructions with a 2 bytes bytecode offset label.
298    */

299
300   final static int LABEL_INSN = 8;
301
302   /**
303    * The type of instructions with a 4 bytes bytecode offset label.
304    */

305
306   final static int LABELW_INSN = 9;
307
308   /**
309    * The type of the LDC instruction.
310    */

311
312   final static int LDC_INSN = 10;
313
314   /**
315    * The type of the LDC_W and LDC2_W instructions.
316    */

317
318   final static int LDCW_INSN = 11;
319
320   /**
321    * The type of the IINC instruction.
322    */

323
324   final static int IINC_INSN = 12;
325
326   /**
327    * The type of the TABLESWITCH instruction.
328    */

329
330   final static int TABL_INSN = 13;
331
332   /**
333    * The type of the LOOKUPSWITCH instruction.
334    */

335
336   final static int LOOK_INSN = 14;
337
338   /**
339    * The type of the MULTIANEWARRAY instruction.
340    */

341
342   final static int MANA_INSN = 15;
343
344   /**
345    * The type of the WIDE instruction.
346    */

347
348   final static int WIDE_INSN = 16;
349
350   /**
351    * The instruction types of all JVM opcodes.
352    */

353
354   static byte[] TYPE;
355
356   // --------------------------------------------------------------------------
357
// Static initializer
358
// --------------------------------------------------------------------------
359

360   /**
361    * Computes the instruction types of JVM opcodes.
362    */

363
364   static {
365     int i;
366     byte[] b = new byte[220];
367     String JavaDoc s =
368       "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADDDDDEEEEEEEEE" +
369       "EEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA" +
370       "AAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAAAAAAGGGGGGGHAFBFAAFFAAQPIIJJII" +
371       "IIIIIIIIIIIIIIII";
372     for (i = 0; i < b.length; ++i) {
373       b[i] = (byte)(s.charAt(i) - 'A');
374     }
375     TYPE = b;
376
377     /* code to generate the above string
378
379     // SBYTE_INSN instructions
380     b[Constants.NEWARRAY] = SBYTE_INSN;
381     b[Constants.BIPUSH] = SBYTE_INSN;
382
383     // SHORT_INSN instructions
384     b[Constants.SIPUSH] = SHORT_INSN;
385
386     // (IMPL)VAR_INSN instructions
387     b[Constants.RET] = VAR_INSN;
388     for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
389       b[i] = VAR_INSN;
390     }
391     for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
392       b[i] = VAR_INSN;
393     }
394     for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
395       b[i] = IMPLVAR_INSN;
396     }
397     for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
398       b[i] = IMPLVAR_INSN;
399     }
400
401     // TYPE_INSN instructions
402     b[Constants.NEW] = TYPE_INSN;
403     b[Constants.ANEWARRAY] = TYPE_INSN;
404     b[Constants.CHECKCAST] = TYPE_INSN;
405     b[Constants.INSTANCEOF] = TYPE_INSN;
406
407     // (Set)FIELDORMETH_INSN instructions
408     for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
409       b[i] = FIELDORMETH_INSN;
410     }
411     b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
412
413     // LABEL(W)_INSN instructions
414     for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
415       b[i] = LABEL_INSN;
416     }
417     b[Constants.IFNULL] = LABEL_INSN;
418     b[Constants.IFNONNULL] = LABEL_INSN;
419     b[200] = LABELW_INSN; // GOTO_W
420     b[201] = LABELW_INSN; // JSR_W
421     // temporary opcodes used internally by ASM - see Label and CodeWriter
422     for (i = 202; i < 220; ++i) {
423       b[i] = LABEL_INSN;
424     }
425
426     // LDC(_W) instructions
427     b[Constants.LDC] = LDC_INSN;
428     b[19] = LDCW_INSN; // LDC_W
429     b[20] = LDCW_INSN; // LDC2_W
430
431     // special instructions
432     b[Constants.IINC] = IINC_INSN;
433     b[Constants.TABLESWITCH] = TABL_INSN;
434     b[Constants.LOOKUPSWITCH] = LOOK_INSN;
435     b[Constants.MULTIANEWARRAY] = MANA_INSN;
436     b[196] = WIDE_INSN; // WIDE
437
438     for (i = 0; i < b.length; ++i) {
439       System.err.print((char)('A' + b[i]));
440     }
441     System.err.println();
442     */

443   }
444
445   // --------------------------------------------------------------------------
446
// Constructor
447
// --------------------------------------------------------------------------
448

449   /**
450    * Constructs a new {@link ClassWriter ClassWriter} object.
451    *
452    * @param computeMaxs <tt>true</tt> if the maximum stack size and the maximum
453    * number of local variables must be automatically computed. If this flag
454    * is <tt>true</tt>, then the arguments of the {@link
455    * CodeVisitor#visitMaxs visitMaxs} method of the {@link CodeVisitor
456    * CodeVisitor} returned by the {@link #visitMethod visitMethod} method
457    * will be ignored, and computed automatically from the signature and
458    * the bytecode of each method.
459    */

460
461   public ClassWriter (final boolean computeMaxs) {
462     index = 1;
463     pool = new ByteVector();
464     table = new Item[64];
465     threshold = (int)(0.75d*table.length);
466     key = new Item();
467     key2 = new Item();
468     key3 = new Item();
469     this.computeMaxs = computeMaxs;
470   }
471
472   // --------------------------------------------------------------------------
473
// Implementation of the ClassVisitor interface
474
// --------------------------------------------------------------------------
475

476   public void visit (
477     final int access,
478     final String JavaDoc name,
479     final String JavaDoc superName,
480     final String JavaDoc[] interfaces,
481     final String JavaDoc sourceFile)
482   {
483     this.access = access;
484     this.name = newClass(name);
485     this.superName = superName == null ? 0 : newClass(superName);
486     if (interfaces != null && interfaces.length > 0) {
487       interfaceCount = interfaces.length;
488       this.interfaces = new int[interfaceCount];
489       for (int i = 0; i < interfaceCount; ++i) {
490         this.interfaces[i] = newClass(interfaces[i]);
491       }
492     }
493     if (sourceFile != null) {
494       newUTF8("SourceFile");
495       this.sourceFile = newUTF8(sourceFile);
496     }
497     if ((access & Constants.ACC_DEPRECATED) != 0) {
498       newUTF8("Deprecated");
499     }
500   }
501
502   public void visitInnerClass (
503     final String JavaDoc name,
504     final String JavaDoc outerName,
505     final String JavaDoc innerName,
506     final int access)
507   {
508     if (innerClasses == null) {
509       newUTF8("InnerClasses");
510       innerClasses = new ByteVector();
511     }
512     ++innerClassesCount;
513     innerClasses.put2(name == null ? 0 : newClass(name));
514     innerClasses.put2(outerName == null ? 0 : newClass(outerName));
515     innerClasses.put2(innerName == null ? 0 : newUTF8(innerName));
516     innerClasses.put2(access);
517   }
518
519   public void visitField (
520     final int access,
521     final String JavaDoc name,
522     final String JavaDoc desc,
523     final Object JavaDoc value,
524     final Attribute attrs)
525   {
526     ++fieldCount;
527     if (fields == null) {
528       fields = new ByteVector();
529     }
530     fields.put2(access).put2(newUTF8(name)).put2(newUTF8(desc));
531     int attributeCount = 0;
532     if (value != null) {
533       ++attributeCount;
534     }
535     if ((access & Constants.ACC_SYNTHETIC) != 0) {
536       ++attributeCount;
537     }
538     if ((access & Constants.ACC_DEPRECATED) != 0) {
539       ++attributeCount;
540     }
541     if (attrs != null) {
542       attributeCount += attrs.getCount();
543     }
544     fields.put2(attributeCount);
545     if (value != null) {
546       fields.put2(newUTF8("ConstantValue"));
547       fields.put4(2).put2(newConst(value).index);
548     }
549     if ((access & Constants.ACC_SYNTHETIC) != 0) {
550       fields.put2(newUTF8("Synthetic")).put4(0);
551     }
552     if ((access & Constants.ACC_DEPRECATED) != 0) {
553       fields.put2(newUTF8("Deprecated")).put4(0);
554     }
555     if (attrs != null) {
556       attrs.getSize(this);
557       attrs.put(this, fields);
558     }
559   }
560
561   public CodeVisitor visitMethod (
562     final int access,
563     final String JavaDoc name,
564     final String JavaDoc desc,
565     final String JavaDoc[] exceptions,
566     final Attribute attrs)
567   {
568     CodeWriter cw = new CodeWriter(this, computeMaxs);
569     cw.init(access, name, desc, exceptions, attrs);
570     return cw;
571   }
572
573   public void visitAttribute (final Attribute attr) {
574     attr.next = attrs;
575     attrs = attr;
576   }
577
578   public void visitEnd () {
579   }
580
581   // --------------------------------------------------------------------------
582
// Other public methods
583
// --------------------------------------------------------------------------
584

585   /**
586    * Returns the bytecode of the class that was build with this class writer.
587    *
588    * @return the bytecode of the class that was build with this class writer.
589    */

590
591   public byte[] toByteArray () {
592     // computes the real size of the bytecode of this class
593
int size = 24 + 2*interfaceCount;
594     if (fields != null) {
595       size += fields.length;
596     }
597     int nbMethods = 0;
598     CodeWriter cb = firstMethod;
599     while (cb != null) {
600       ++nbMethods;
601       size += cb.getSize();
602       cb = cb.next;
603     }
604     int attributeCount = 0;
605     if (sourceFile != 0) {
606       ++attributeCount;
607       size += 8;
608     }
609     if ((access & Constants.ACC_DEPRECATED) != 0) {
610       ++attributeCount;
611       size += 6;
612     }
613     if (innerClasses != null) {
614       ++attributeCount;
615       size += 8 + innerClasses.length;
616     }
617     if (attrs != null) {
618       attributeCount += attrs.getCount();
619       size += attrs.getSize(this);
620     }
621     size += pool.length;
622     // allocates a byte vector of this size, in order to avoid unnecessary
623
// arraycopy operations in the ByteVector.enlarge() method
624
ByteVector out = new ByteVector(size);
625     out.put4(0xCAFEBABE).put2(3).put2(45);
626     out.put2(index).putByteArray(pool.data, 0, pool.length);
627     out.put2(access).put2(name).put2(superName);
628     out.put2(interfaceCount);
629     for (int i = 0; i < interfaceCount; ++i) {
630       out.put2(interfaces[i]);
631     }
632     out.put2(fieldCount);
633     if (fields != null) {
634       out.putByteArray(fields.data, 0, fields.length);
635     }
636     out.put2(nbMethods);
637     cb = firstMethod;
638     while (cb != null) {
639       cb.put(out);
640       cb = cb.next;
641     }
642     out.put2(attributeCount);
643     if (sourceFile != 0) {
644       out.put2(newUTF8("SourceFile")).put4(2).put2(sourceFile);
645     }
646     if ((access & Constants.ACC_DEPRECATED) != 0) {
647       out.put2(newUTF8("Deprecated")).put4(0);
648     }
649     if (innerClasses != null) {
650       out.put2(newUTF8("InnerClasses"));
651       out.put4(innerClasses.length + 2).put2(innerClassesCount);
652       out.putByteArray(innerClasses.data, 0, innerClasses.length);
653     }
654     if (attrs != null) {
655       attrs.put(this, out);
656     }
657     return out.data;
658   }
659
660   // --------------------------------------------------------------------------
661
// Utility methods: constant pool management
662
// --------------------------------------------------------------------------
663

664   /**
665    * Adds a number or string constant to the constant pool of the class being
666    * build. Does nothing if the constant pool already contains a similar item.
667    *
668    * @param cst the value of the constant to be added to the constant pool. This
669    * parameter must be an {@link java.lang.Integer Integer}, a {@link
670    * java.lang.Float Float}, a {@link java.lang.Long Long}, a {@link
671           java.lang.Double Double} or a {@link String String}.
672    * @return a new or already existing constant item with the given value.
673    */

674
675   Item newConst (final Object JavaDoc cst) {
676     if (cst instanceof Integer JavaDoc) {
677       int val = ((Integer JavaDoc)cst).intValue();
678       return newInteger(val);
679     } else if (cst instanceof Float JavaDoc) {
680       float val = ((Float JavaDoc)cst).floatValue();
681       return newFloat(val);
682     } else if (cst instanceof Long JavaDoc) {
683       long val = ((Long JavaDoc)cst).longValue();
684       return newLong(val);
685     } else if (cst instanceof Double JavaDoc) {
686       double val = ((Double JavaDoc)cst).doubleValue();
687       return newDouble(val);
688     } else if (cst instanceof String JavaDoc) {
689       return newString((String JavaDoc)cst);
690     } else {
691       throw new IllegalArgumentException JavaDoc("value " + cst);
692     }
693   }
694
695   /**
696    * Adds a number or string constant to the constant pool of the class being
697    * build. Does nothing if the constant pool already contains a similar item.
698    *
699    * @param cst the value of the constant to be added to the constant pool. This
700    * parameter must be an {@link java.lang.Integer Integer}, a {@link
701    * java.lang.Float Float}, a {@link java.lang.Long Long}, a {@link
702           java.lang.Double Double} or a {@link String String}.
703    * @return the index of a new or already existing constant item with the given
704    * value.
705    */

706
707   protected int newCst (final Object JavaDoc cst) {
708     return newConst(cst).index;
709   }
710
711   /**
712    * Adds an UTF8 string to the constant pool of the class being build. Does
713    * nothing if the constant pool already contains a similar item.
714    *
715    * @param value the String value.
716    * @return the index of a new or already existing UTF8 item.
717    */

718
719   protected int newUTF8 (final String JavaDoc value) {
720     key.set(UTF8, value, null, null);
721     Item result = get(key);
722     if (result == null) {
723       pool.put1(UTF8).putUTF(value);
724       result = new Item(index++, key);
725       put(result);
726     }
727     return result.index;
728   }
729
730   /**
731    * Adds a class reference to the constant pool of the class being build. Does
732    * nothing if the constant pool already contains a similar item.
733    *
734    * @param value the internal name of the class.
735    * @return the index of a new or already existing class reference item.
736    */

737
738   protected int newClass (final String JavaDoc value) {
739     key2.set(CLASS, value, null, null);
740     Item result = get(key2);
741     if (result == null) {
742       pool.put12(CLASS, newUTF8(value));
743       result = new Item(index++, key2);
744       put(result);
745     }
746     return result.index;
747   }
748
749   /**
750    * Adds a field reference to the constant pool of the class being build. Does
751    * nothing if the constant pool already contains a similar item.
752    *
753    * @param owner the internal name of the field's owner class.
754    * @param name the field's name.
755    * @param desc the field's descriptor.
756    * @return the index of a new or already existing field reference item.
757    */

758
759   protected int newField (
760     final String JavaDoc owner,
761     final String JavaDoc name,
762     final String JavaDoc desc)
763   {
764     key3.set(FIELD, owner, name, desc);
765     Item result = get(key3);
766     if (result == null) {
767       put122(FIELD, newClass(owner), newNameType(name, desc));
768       result = new Item(index++, key3);
769       put(result);
770     }
771     return result.index;
772   }
773
774   /**
775    * Adds a method reference to the constant pool of the class being build. Does
776    * nothing if the constant pool already contains a similar item.
777    *
778    * @param owner the internal name of the method's owner class.
779    * @param name the method's name.
780    * @param desc the method's descriptor.
781    * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
782    * @return a new or already existing method reference item.
783    */

784
785   Item newMethodItem (
786     final String JavaDoc owner,
787     final String JavaDoc name,
788     final String JavaDoc desc,
789     final boolean itf)
790   {
791     key3.set(itf ? IMETH : METH, owner, name, desc);
792     Item result = get(key3);
793     if (result == null) {
794       put122(itf ? IMETH : METH, newClass(owner), newNameType(name, desc));
795       result = new Item(index++, key3);
796       put(result);
797     }
798     return result;
799   }
800
801   /**
802    * Adds a method reference to the constant pool of the class being build. Does
803    * nothing if the constant pool already contains a similar item.
804    *
805    * @param owner the internal name of the method's owner class.
806    * @param name the method's name.
807    * @param desc the method's descriptor.
808    * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
809    * @return the index of a new or already existing method reference item.
810    */

811
812   protected int newMethod (
813     final String JavaDoc owner,
814     final String JavaDoc name,
815     final String JavaDoc desc,
816     final boolean itf)
817   {
818     return newMethodItem(owner, name, desc, itf).index;
819   }
820
821   /**
822    * Adds an integer to the constant pool of the class being build. Does nothing
823    * if the constant pool already contains a similar item.
824    *
825    * @param value the int value.
826    * @return a new or already existing int item.
827    */

828
829   private Item newInteger (final int value) {
830     key.set(value);
831     Item result = get(key);
832     if (result == null) {
833       pool.put1(INT).put4(value);
834       result = new Item(index++, key);
835       put(result);
836     }
837     return result;
838   }
839
840   /**
841    * Adds a float to the constant pool of the class being build. Does nothing if
842    * the constant pool already contains a similar item.
843    *
844    * @param value the float value.
845    * @return a new or already existing float item.
846    */

847
848   private Item newFloat (final float value) {
849     key.set(value);
850     Item result = get(key);
851     if (result == null) {
852       pool.put1(FLOAT).put4(Float.floatToIntBits(value));
853       result = new Item(index++, key);
854       put(result);
855     }
856     return result;
857   }
858
859   /**
860    * Adds a long to the constant pool of the class being build. Does nothing if
861    * the constant pool already contains a similar item.
862    *
863    * @param value the long value.
864    * @return a new or already existing long item.
865    */

866
867   private Item newLong (final long value) {
868     key.set(value);
869     Item result = get(key);
870     if (result == null) {
871       pool.put1(LONG).put8(value);
872       result = new Item(index, key);
873       put(result);
874       index += 2;
875     }
876     return result;
877   }
878
879   /**
880    * Adds a double to the constant pool of the class being build. Does nothing
881    * if the constant pool already contains a similar item.
882    *
883    * @param value the double value.
884    * @return a new or already existing double item.
885    */

886
887   private Item newDouble (final double value) {
888     key.set(value);
889     Item result = get(key);
890     if (result == null) {
891       pool.put1(DOUBLE).put8(Double.doubleToLongBits(value));
892       result = new Item(index, key);
893       put(result);
894       index += 2;
895     }
896     return result;
897   }
898
899   /**
900    * Adds a string to the constant pool of the class being build. Does nothing
901    * if the constant pool already contains a similar item.
902    *
903    * @param value the String value.
904    * @return a new or already existing string item.
905    */

906
907   private Item newString (final String JavaDoc value) {
908     key2.set(STR, value, null, null);
909     Item result = get(key2);
910     if (result == null) {
911       pool.put12(STR, newUTF8(value));
912       result = new Item(index++, key2);
913       put(result);
914     }
915     return result;
916   }
917
918   /**
919    * Adds a name and type to the constant pool of the class being build. Does
920    * nothing if the constant pool already contains a similar item.
921    *
922    * @param name a name.
923    * @param desc a type descriptor.
924    * @return the index of a new or already existing name and type item.
925    */

926
927   protected int newNameType (final String JavaDoc name, final String JavaDoc desc) {
928     key2.set(NAME_TYPE, name, desc, null);
929     Item result = get(key2);
930     if (result == null) {
931       put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
932       result = new Item(index++, key2);
933       put(result);
934     }
935     return result.index;
936   }
937
938   /**
939    * Returns the constant pool's hash table item which is equal to the given
940    * item.
941    *
942    * @param key a constant pool item.
943    * @return the constant pool's hash table item which is equal to the given
944    * item, or <tt>null</tt> if there is no such item.
945    */

946
947   private Item get (final Item key) {
948     Item tab[] = table;
949     int hashCode = key.hashCode;
950     int index = (hashCode & 0x7FFFFFFF) % tab.length;
951     for (Item i = tab[index]; i != null; i = i.next) {
952       if (i.hashCode == hashCode && key.isEqualTo(i)) {
953         return i;
954       }
955     }
956     return null;
957   }
958
959   /**
960    * Puts the given item in the constant pool's hash table. The hash table
961    * <i>must</i> not already contains this item.
962    *
963    * @param i the item to be added to the constant pool's hash table.
964    */

965
966   private void put (final Item i) {
967     if (index > threshold) {
968       int oldCapacity = table.length;
969       Item oldMap[] = table;
970       int newCapacity = oldCapacity * 2 + 1;
971       Item newMap[] = new Item[newCapacity];
972       threshold = (int)(newCapacity * 0.75);
973       table = newMap;
974       for (int j = oldCapacity; j-- > 0; ) {
975         for (Item old = oldMap[j]; old != null; ) {
976           Item e = old;
977           old = old.next;
978           int index = (e.hashCode & 0x7FFFFFFF) % newCapacity;
979           e.next = newMap[index];
980           newMap[index] = e;
981         }
982       }
983     }
984     int index = (i.hashCode & 0x7FFFFFFF) % table.length;
985     i.next = table[index];
986     table[index] = i;
987   }
988
989   /**
990    * Puts one byte and two shorts into the constant pool.
991    *
992    * @param b a byte.
993    * @param s1 a short.
994    * @param s2 another short.
995    */

996
997   private void put122 (final int b, final int s1, final int s2) {
998     pool.put12(b, s1).put2(s2);
999   }
1000
1001  // --------------------------------------------------------------------------
1002
// Attributes support
1003
// --------------------------------------------------------------------------
1004

1005  /**
1006   * Converts the content of the given attribute to a byte array.
1007   *
1008   * @param attr the attribute that must be converted to a byte array.
1009   * @return a byte array containing the content of the given attribute (and
1010   * this content only, i.e. the 6 attribute header bytes must not be
1011   * included in the returned array).
1012   */

1013
1014  protected byte[] writeAttribute (final Attribute attr) {
1015    if (attr.b == null) {
1016      throw new IllegalArgumentException JavaDoc(
1017        "Unsupported attribute type: " + attr.type);
1018    } else {
1019      byte[] b = new byte[attr.len];
1020      System.arraycopy(attr.b, attr.off, b, 0, attr.len);
1021      return b;
1022    }
1023  }
1024}
1025
Popular Tags