KickJava   Java API By Example, From Geeks To Geeks.

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


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 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 package org.objectweb.asm;
31
32 /**
33  * A {@link ClassVisitor} that generates classes in bytecode form. More
34  * precisely this visitor generates a byte array conforming to the Java class
35  * file format. It can be used alone, to generate a Java class "from scratch",
36  * or with one or more {@link ClassReader ClassReader} and adapter class visitor
37  * to generate a modified class from one or more existing Java classes.
38  *
39  * @author Eric Bruneton
40  */

41 public class ClassWriter implements ClassVisitor {
42
43     /**
44      * The type of instructions without any argument.
45      */

46     final static int NOARG_INSN = 0;
47
48     /**
49      * The type of instructions with an signed byte argument.
50      */

51     final static int SBYTE_INSN = 1;
52
53     /**
54      * The type of instructions with an signed short argument.
55      */

56     final static int SHORT_INSN = 2;
57
58     /**
59      * The type of instructions with a local variable index argument.
60      */

61     final static int VAR_INSN = 3;
62
63     /**
64      * The type of instructions with an implicit local variable index argument.
65      */

66     final static int IMPLVAR_INSN = 4;
67
68     /**
69      * The type of instructions with a type descriptor argument.
70      */

71     final static int TYPE_INSN = 5;
72
73     /**
74      * The type of field and method invocations instructions.
75      */

76     final static int FIELDORMETH_INSN = 6;
77
78     /**
79      * The type of the INVOKEINTERFACE instruction.
80      */

81     final static int ITFMETH_INSN = 7;
82
83     /**
84      * The type of instructions with a 2 bytes bytecode offset label.
85      */

86     final static int LABEL_INSN = 8;
87
88     /**
89      * The type of instructions with a 4 bytes bytecode offset label.
90      */

91     final static int LABELW_INSN = 9;
92
93     /**
94      * The type of the LDC instruction.
95      */

96     final static int LDC_INSN = 10;
97
98     /**
99      * The type of the LDC_W and LDC2_W instructions.
100      */

101     final static int LDCW_INSN = 11;
102
103     /**
104      * The type of the IINC instruction.
105      */

106     final static int IINC_INSN = 12;
107
108     /**
109      * The type of the TABLESWITCH instruction.
110      */

111     final static int TABL_INSN = 13;
112
113     /**
114      * The type of the LOOKUPSWITCH instruction.
115      */

116     final static int LOOK_INSN = 14;
117
118     /**
119      * The type of the MULTIANEWARRAY instruction.
120      */

121     final static int MANA_INSN = 15;
122
123     /**
124      * The type of the WIDE instruction.
125      */

126     final static int WIDE_INSN = 16;
127
128     /**
129      * The instruction types of all JVM opcodes.
130      */

131     static byte[] TYPE;
132
133     /**
134      * The type of CONSTANT_Class constant pool items.
135      */

136     final static int CLASS = 7;
137
138     /**
139      * The type of CONSTANT_Fieldref constant pool items.
140      */

141     final static int FIELD = 9;
142
143     /**
144      * The type of CONSTANT_Methodref constant pool items.
145      */

146     final static int METH = 10;
147
148     /**
149      * The type of CONSTANT_InterfaceMethodref constant pool items.
150      */

151     final static int IMETH = 11;
152
153     /**
154      * The type of CONSTANT_String constant pool items.
155      */

156     final static int STR = 8;
157
158     /**
159      * The type of CONSTANT_Integer constant pool items.
160      */

161     final static int INT = 3;
162
163     /**
164      * The type of CONSTANT_Float constant pool items.
165      */

166     final static int FLOAT = 4;
167
168     /**
169      * The type of CONSTANT_Long constant pool items.
170      */

171     final static int LONG = 5;
172
173     /**
174      * The type of CONSTANT_Double constant pool items.
175      */

176     final static int DOUBLE = 6;
177
178     /**
179      * The type of CONSTANT_NameAndType constant pool items.
180      */

181     final static int NAME_TYPE = 12;
182
183     /**
184      * The type of CONSTANT_Utf8 constant pool items.
185      */

186     final static int UTF8 = 1;
187
188     /**
189      * Minor and major version numbers of the class to be generated.
190      */

191     int version;
192
193     /**
194      * Index of the next item to be added in the constant pool.
195      */

196     private short index;
197
198     /**
199      * The constant pool of this class.
200      */

201     private ByteVector pool;
202
203     /**
204      * The constant pool's hash table data.
205      */

206     private Item[] items;
207
208     /**
209      * The threshold of the constant pool's hash table.
210      */

211     private int threshold;
212
213     /**
214      * A reusable key used to look for items in the hash {@link #items items}.
215      */

216     Item key;
217
218     /**
219      * A reusable key used to look for items in the hash {@link #items items}.
220      */

221     Item key2;
222
223     /**
224      * A reusable key used to look for items in the hash {@link #items items}.
225      */

226     Item key3;
227
228     /**
229      * The access flags of this class.
230      */

231     private int access;
232
233     /**
234      * The constant pool item that contains the internal name of this class.
235      */

236     private int name;
237
238     /**
239      * The constant pool item that contains the signature of this class.
240      */

241     private int signature;
242
243     /**
244      * The constant pool item that contains the internal name of the super class
245      * of this class.
246      */

247     private int superName;
248
249     /**
250      * Number of interfaces implemented or extended by this class or interface.
251      */

252     private int interfaceCount;
253
254     /**
255      * The interfaces implemented or extended by this class or interface. More
256      * precisely, this array contains the indexes of the constant pool items
257      * that contain the internal names of these interfaces.
258      */

259     private int[] interfaces;
260
261     /**
262      * The index of the constant pool item that contains the name of the source
263      * file from which this class was compiled.
264      */

265     private int sourceFile;
266
267     /**
268      * The SourceDebug attribute of this class.
269      */

270     private ByteVector sourceDebug;
271
272     /**
273      * The constant pool item that contains the name of the enclosing class of
274      * this class.
275      */

276     private int enclosingMethodOwner;
277
278     /**
279      * The constant pool item that contains the name and descriptor of the
280      * enclosing method of this class.
281      */

282     private int enclosingMethod;
283
284     /**
285      * The runtime visible annotations of this class.
286      */

287     private AnnotationWriter anns;
288
289     /**
290      * The runtime invisible annotations of this class.
291      */

292     private AnnotationWriter ianns;
293
294     /**
295      * The non standard attributes of this class.
296      */

297     private Attribute attrs;
298
299     /**
300      * The number of entries in the InnerClasses attribute.
301      */

302     private int innerClassesCount;
303
304     /**
305      * The InnerClasses attribute.
306      */

307     private ByteVector innerClasses;
308
309     /**
310      * The fields of this class. These fields are stored in a linked list of
311      * {@link FieldWriter} objects, linked to each other by their
312      * {@link FieldWriter#next} field. This field stores the first element of
313      * this list.
314      */

315     FieldWriter firstField;
316
317     /**
318      * The fields of this class. These fields are stored in a linked list of
319      * {@link FieldWriter} objects, linked to each other by their
320      * {@link FieldWriter#next} field. This field stores the last element of
321      * this list.
322      */

323     FieldWriter lastField;
324
325     /**
326      * The methods of this class. These methods are stored in a linked list of
327      * {@link MethodWriter} objects, linked to each other by their
328      * {@link MethodWriter#next} field. This field stores the first element of
329      * this list.
330      */

331     MethodWriter firstMethod;
332
333     /**
334      * The methods of this class. These methods are stored in a linked list of
335      * {@link MethodWriter} objects, linked to each other by their
336      * {@link MethodWriter#next} field. This field stores the last element of
337      * this list.
338      */

339     MethodWriter lastMethod;
340
341     /**
342      * <tt>true</tt> if the maximum stack size and number of local variables
343      * must be automatically computed.
344      */

345     private boolean computeMaxs;
346
347     /**
348      * <tt>true</tt> to test that all attributes are known.
349      */

350     boolean checkAttributes;
351
352     // ------------------------------------------------------------------------
353
// Static initializer
354
// ------------------------------------------------------------------------
355

356     /**
357      * Computes the instruction types of JVM opcodes.
358      */

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

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

455     public ClassWriter(final boolean computeMaxs) {
456         this(computeMaxs, false);
457     }
458
459     /**
460      * Constructs a new {@link ClassWriter} object.
461      *
462      * @param computeMaxs <tt>true</tt> if the maximum stack size and the
463      * maximum number of local variables must be automatically computed.
464      * If this flag is <tt>true</tt>, then the arguments of the
465      * {@link MethodVisitor#visitMaxs visitMaxs} method of the
466      * {@link MethodVisitor} returned by the
467      * {@link #visitMethod visitMethod} method will be ignored, and
468      * computed automatically from the signature and the bytecode of each
469      * method.
470      * @param skipUnknownAttributes <tt>true</tt> to silently ignore unknown
471      * attributes, or <tt>false</tt> to throw an exception if an
472      * unknown attribute is found.
473      */

474     public ClassWriter(
475         final boolean computeMaxs,
476         final boolean skipUnknownAttributes)
477     {
478         index = 1;
479         pool = new ByteVector();
480         items = new Item[256];
481         threshold = (int) (0.75d * items.length);
482         key = new Item();
483         key2 = new Item();
484         key3 = new Item();
485         this.computeMaxs = computeMaxs;
486         this.checkAttributes = !skipUnknownAttributes;
487     }
488
489     // ------------------------------------------------------------------------
490
// Implementation of the ClassVisitor interface
491
// ------------------------------------------------------------------------
492

493     public void visit(
494         final int version,
495         final int access,
496         final String JavaDoc name,
497         final String JavaDoc signature,
498         final String JavaDoc superName,
499         final String JavaDoc[] interfaces)
500     {
501         this.version = version;
502         this.access = access;
503         this.name = newClass(name);
504         if (signature != null) {
505             this.signature = newUTF8(signature);
506         }
507         this.superName = superName == null ? 0 : newClass(superName);
508         if (interfaces != null && interfaces.length > 0) {
509             interfaceCount = interfaces.length;
510             this.interfaces = new int[interfaceCount];
511             for (int i = 0; i < interfaceCount; ++i) {
512                 this.interfaces[i] = newClass(interfaces[i]);
513             }
514         }
515     }
516
517     public void visitSource(final String JavaDoc file, final String JavaDoc debug) {
518         if (file != null) {
519             sourceFile = newUTF8(file);
520         }
521         if (debug != null) {
522             sourceDebug = new ByteVector();
523             sourceDebug.putUTF8(debug);
524         }
525     }
526
527     public void visitOuterClass(
528         final String JavaDoc owner,
529         final String JavaDoc name,
530         final String JavaDoc desc)
531     {
532         enclosingMethodOwner = newClass(owner);
533         if (name != null && desc != null) {
534             enclosingMethod = newNameType(name, desc);
535         }
536     }
537
538     public AnnotationVisitor visitAnnotation(String JavaDoc desc, boolean visible) {
539         ByteVector bv = new ByteVector();
540         // write type, and reserve space for values count
541
bv.putShort(newUTF8(desc)).putShort(0);
542         AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
543         if (visible) {
544             aw.next = anns;
545             anns = aw;
546         } else {
547             aw.next = ianns;
548             ianns = aw;
549         }
550         return aw;
551     }
552
553     public void visitAttribute(final Attribute attr) {
554         attr.next = attrs;
555         attrs = attr;
556     }
557
558     public void visitInnerClass(
559         final String JavaDoc name,
560         final String JavaDoc outerName,
561         final String JavaDoc innerName,
562         final int access)
563     {
564         if (innerClasses == null) {
565             innerClasses = new ByteVector();
566         }
567         ++innerClassesCount;
568         innerClasses.putShort(name == null ? 0 : newClass(name));
569         innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
570         innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
571         innerClasses.putShort(access);
572     }
573
574     public FieldVisitor visitField(
575         final int access,
576         final String JavaDoc name,
577         final String JavaDoc desc,
578         final String JavaDoc signature,
579         final Object JavaDoc value)
580     {
581         return new FieldWriter(this, access, name, desc, signature, value);
582     }
583
584     public MethodVisitor visitMethod(
585         final int access,
586         final String JavaDoc name,
587         final String JavaDoc desc,
588         final String JavaDoc signature,
589         final String JavaDoc[] exceptions)
590     {
591         return new MethodWriter(this,
592                 access,
593                 name,
594                 desc,
595                 signature,
596                 exceptions,
597                 computeMaxs);
598     }
599
600     public void visitEnd() {
601     }
602
603     // ------------------------------------------------------------------------
604
// Other public methods
605
// ------------------------------------------------------------------------
606

607     /**
608      * Returns the bytecode of the class that was build with this class writer.
609      *
610      * @return the bytecode of the class that was build with this class writer.
611      */

612     public byte[] toByteArray() {
613         // computes the real size of the bytecode of this class
614
int size = 24 + 2 * interfaceCount;
615         int nbFields = 0;
616         FieldWriter fb = firstField;
617         while (fb != null) {
618             ++nbFields;
619             size += fb.getSize();
620             fb = fb.next;
621         }
622         int nbMethods = 0;
623         MethodWriter mb = firstMethod;
624         while (mb != null) {
625             ++nbMethods;
626             size += mb.getSize();
627             mb = mb.next;
628         }
629         int attributeCount = 0;
630         if (signature != 0) {
631             ++attributeCount;
632             size += 8;
633             newUTF8("Signature");
634         }
635         if (sourceFile != 0) {
636             ++attributeCount;
637             size += 8;
638             newUTF8("SourceFile");
639         }
640         if (sourceDebug != null) {
641             ++attributeCount;
642             size += sourceDebug.length;
643             newUTF8("SourceDebugExtension");
644         }
645         if (enclosingMethodOwner != 0) {
646             ++attributeCount;
647             size += 10;
648             newUTF8("EnclosingMethod");
649         }
650         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
651             ++attributeCount;
652             size += 6;
653             newUTF8("Deprecated");
654         }
655         if ((access & Opcodes.ACC_SYNTHETIC) != 0
656                 && (version & 0xffff) < Opcodes.V1_5)
657         {
658             ++attributeCount;
659             size += 6;
660             newUTF8("Synthetic");
661         }
662         if (version == Opcodes.V1_4) {
663             if ((access & Opcodes.ACC_ANNOTATION) != 0) {
664                 ++attributeCount;
665                 size += 6;
666                 newUTF8("Annotation");
667             }
668             if ((access & Opcodes.ACC_ENUM) != 0) {
669                 ++attributeCount;
670                 size += 6;
671                 newUTF8("Enum");
672             }
673         }
674         if (innerClasses != null) {
675             ++attributeCount;
676             size += 8 + innerClasses.length;
677             newUTF8("InnerClasses");
678         }
679         if (anns != null) {
680             ++attributeCount;
681             size += 8 + anns.getSize();
682             newUTF8("RuntimeVisibleAnnotations");
683         }
684         if (ianns != null) {
685             ++attributeCount;
686             size += 8 + ianns.getSize();
687             newUTF8("RuntimeInvisibleAnnotations");
688         }
689         if (attrs != null) {
690             attributeCount += attrs.getCount();
691             size += attrs.getSize(this, null, 0, -1, -1);
692         }
693         size += pool.length;
694         // allocates a byte vector of this size, in order to avoid unnecessary
695
// arraycopy operations in the ByteVector.enlarge() method
696
ByteVector out = new ByteVector(size);
697         out.putInt(0xCAFEBABE).putInt(version);
698         out.putShort(index).putByteArray(pool.data, 0, pool.length);
699         out.putShort(access).putShort(name).putShort(superName);
700         out.putShort(interfaceCount);
701         for (int i = 0; i < interfaceCount; ++i) {
702             out.putShort(interfaces[i]);
703         }
704         out.putShort(nbFields);
705         fb = firstField;
706         while (fb != null) {
707             fb.put(out);
708             fb = fb.next;
709         }
710         out.putShort(nbMethods);
711         mb = firstMethod;
712         while (mb != null) {
713             mb.put(out);
714             mb = mb.next;
715         }
716         out.putShort(attributeCount);
717         if (signature != 0) {
718             out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
719         }
720         if (sourceFile != 0) {
721             out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
722         }
723         if (sourceDebug != null) {
724             int len = sourceDebug.length;
725             out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
726             out.putByteArray(sourceDebug.data, 0, len);
727         }
728         if (enclosingMethodOwner != 0) {
729             out.putShort(newUTF8("EnclosingMethod")).putInt(4);
730             out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
731         }
732         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
733             out.putShort(newUTF8("Deprecated")).putInt(0);
734         }
735         if ((access & Opcodes.ACC_SYNTHETIC) != 0
736                 && (version & 0xffff) < Opcodes.V1_5)
737         {
738             out.putShort(newUTF8("Synthetic")).putInt(0);
739         }
740         if (version == Opcodes.V1_4) {
741             if ((access & Opcodes.ACC_ANNOTATION) != 0) {
742                 out.putShort(newUTF8("Annotation")).putInt(0);
743             }
744             if ((access & Opcodes.ACC_ENUM) != 0) {
745                 out.putShort(newUTF8("Enum")).putInt(0);
746             }
747         }
748         if (innerClasses != null) {
749             out.putShort(newUTF8("InnerClasses"));
750             out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
751             out.putByteArray(innerClasses.data, 0, innerClasses.length);
752         }
753         if (anns != null) {
754             out.putShort(newUTF8("RuntimeVisibleAnnotations"));
755             anns.put(out);
756         }
757         if (ianns != null) {
758             out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
759             ianns.put(out);
760         }
761         if (attrs != null) {
762             attrs.put(this, null, 0, -1, -1, out);
763         }
764         return out.data;
765     }
766
767     // ------------------------------------------------------------------------
768
// Utility methods: constant pool management
769
// ------------------------------------------------------------------------
770

771     /**
772      * Adds a number or string constant to the constant pool of the class being
773      * build. Does nothing if the constant pool already contains a similar item.
774      *
775      * @param cst the value of the constant to be added to the constant pool.
776      * This parameter must be an {@link Integer}, a {@link Float}, a
777      * {@link Long}, a {@link Double}, a {@link String} or a
778      * {@link Type}.
779      * @return a new or already existing constant item with the given value.
780      */

781     Item newConstItem(final Object JavaDoc cst) {
782         if (cst instanceof Integer JavaDoc) {
783             int val = ((Integer JavaDoc) cst).intValue();
784             return newInteger(val);
785         } else if (cst instanceof Byte JavaDoc) {
786             int val = ((Byte JavaDoc) cst).intValue();
787             return newInteger(val);
788         } else if (cst instanceof Character JavaDoc) {
789             int val = ((Character JavaDoc) cst).charValue();
790             return newInteger(val);
791         } else if (cst instanceof Short JavaDoc) {
792             int val = ((Short JavaDoc) cst).intValue();
793             return newInteger(val);
794         } else if (cst instanceof Boolean JavaDoc) {
795             int val = ((Boolean JavaDoc) cst).booleanValue() ? 1 : 0;
796             return newInteger(val);
797         } else if (cst instanceof Float JavaDoc) {
798             float val = ((Float JavaDoc) cst).floatValue();
799             return newFloat(val);
800         } else if (cst instanceof Long JavaDoc) {
801             long val = ((Long JavaDoc) cst).longValue();
802             return newLong(val);
803         } else if (cst instanceof Double JavaDoc) {
804             double val = ((Double JavaDoc) cst).doubleValue();
805             return newDouble(val);
806         } else if (cst instanceof String JavaDoc) {
807             return newString((String JavaDoc) cst);
808         } else if (cst instanceof Type) {
809             Type t = (Type) cst;
810             return newClassItem(t.getSort() == Type.OBJECT
811                     ? t.getInternalName()
812                     : t.getDescriptor());
813         } else {
814             throw new IllegalArgumentException JavaDoc("value " + cst);
815         }
816     }
817
818     /**
819      * Adds a number or string constant to the constant pool of the class being
820      * build. Does nothing if the constant pool already contains a similar item.
821      * <i>This method is intended for {@link Attribute} sub classes, and is
822      * normally not needed by class generators or adapters.</i>
823      *
824      * @param cst the value of the constant to be added to the constant pool.
825      * This parameter must be an {@link Integer}, a {@link Float}, a
826      * {@link Long}, a {@link Double} or a {@link String}.
827      * @return the index of a new or already existing constant item with the
828      * given value.
829      */

830     public int newConst(final Object JavaDoc cst) {
831         return newConstItem(cst).index;
832     }
833
834     /**
835      * Adds an UTF8 string to the constant pool of the class being build. Does
836      * nothing if the constant pool already contains a similar item. <i>This
837      * method is intended for {@link Attribute} sub classes, and is normally not
838      * needed by class generators or adapters.</i>
839      *
840      * @param value the String value.
841      * @return the index of a new or already existing UTF8 item.
842      */

843     public int newUTF8(final String JavaDoc value) {
844         key.set('s', value, null, null);
845         Item result = get(key);
846         if (result == null) {
847             pool.putByte(UTF8).putUTF8(value);
848             result = new Item(index++, key);
849             put(result);
850         }
851         return result.index;
852     }
853
854     /**
855      * Adds a class reference to the constant pool of the class being build.
856      * Does nothing if the constant pool already contains a similar item.
857      * <i>This method is intended for {@link Attribute} sub classes, and is
858      * normally not needed by class generators or adapters.</i>
859      *
860      * @param value the internal name of the class.
861      * @return the index of a new or already existing class reference item.
862      */

863     public int newClass(final String JavaDoc value) {
864         return newClassItem(value).index;
865     }
866
867     /**
868      * Adds a class reference to the constant pool of the class being build.
869      * Does nothing if the constant pool already contains a similar item.
870      * <i>This method is intended for {@link Attribute} sub classes, and is
871      * normally not needed by class generators or adapters.</i>
872      *
873      * @param value the internal name of the class.
874      * @return a new or already existing class reference item.
875      */

876     private Item newClassItem(final String JavaDoc value) {
877         key2.set('C', value, null, null);
878         Item result = get(key2);
879         if (result == null) {
880             pool.put12(CLASS, newUTF8(value));
881             result = new Item(index++, key2);
882             put(result);
883         }
884         return result;
885     }
886
887     /**
888      * Adds a field reference to the constant pool of the class being build.
889      * Does nothing if the constant pool already contains a similar item.
890      * <i>This method is intended for {@link Attribute} sub classes, and is
891      * normally not needed by class generators or adapters.</i>
892      *
893      * @param owner the internal name of the field's owner class.
894      * @param name the field's name.
895      * @param desc the field's descriptor.
896      * @return the index of a new or already existing field reference item.
897      */

898     public int newField(final String JavaDoc owner, final String JavaDoc name, final String JavaDoc desc)
899     {
900         key3.set('G', owner, name, desc);
901         Item result = get(key3);
902         if (result == null) {
903             put122(FIELD, newClass(owner), newNameType(name, desc));
904             result = new Item(index++, key3);
905             put(result);
906         }
907         return result.index;
908     }
909
910     /**
911      * Adds a method reference to the constant pool of the class being build.
912      * Does nothing if the constant pool already contains a similar item.
913      *
914      * @param owner the internal name of the method's owner class.
915      * @param name the method's name.
916      * @param desc the method's descriptor.
917      * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
918      * @return a new or already existing method reference item.
919      */

920     Item newMethodItem(
921         final String JavaDoc owner,
922         final String JavaDoc name,
923         final String JavaDoc desc,
924         final boolean itf)
925     {
926         key3.set(itf ? 'N' : 'M', owner, name, desc);
927         Item result = get(key3);
928         if (result == null) {
929             put122(itf ? IMETH : METH, newClass(owner), newNameType(name, desc));
930             result = new Item(index++, key3);
931             put(result);
932         }
933         return result;
934     }
935
936     /**
937      * Adds a method reference to the constant pool of the class being build.
938      * Does nothing if the constant pool already contains a similar item.
939      * <i>This method is intended for {@link Attribute} sub classes, and is
940      * normally not needed by class generators or adapters.</i>
941      *
942      * @param owner the internal name of the method's owner class.
943      * @param name the method's name.
944      * @param desc the method's descriptor.
945      * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
946      * @return the index of a new or already existing method reference item.
947      */

948     public int newMethod(
949         final String JavaDoc owner,
950         final String JavaDoc name,
951         final String JavaDoc desc,
952         final boolean itf)
953     {
954         return newMethodItem(owner, name, desc, itf).index;
955     }
956
957     /**
958      * Adds an integer to the constant pool of the class being build. Does
959      * nothing if the constant pool already contains a similar item.
960      *
961      * @param value the int value.
962      * @return a new or already existing int item.
963      */

964     Item newInteger(final int value) {
965         key.set(value);
966         Item result = get(key);
967         if (result == null) {
968             pool.putByte(INT).putInt(value);
969             result = new Item(index++, key);
970             put(result);
971         }
972         return result;
973     }
974
975     /**
976      * Adds a float to the constant pool of the class being build. Does nothing
977      * if the constant pool already contains a similar item.
978      *
979      * @param value the float value.
980      * @return a new or already existing float item.
981      */

982     Item newFloat(final float value) {
983         key.set(value);
984         Item result = get(key);
985         if (result == null) {
986             pool.putByte(FLOAT).putInt(Float.floatToIntBits(value));
987             result = new Item(index++, key);
988             put(result);
989         }
990         return result;
991     }
992
993     /**
994      * Adds a long to the constant pool of the class being build. Does nothing
995      * if the constant pool already contains a similar item.
996      *
997      * @param value the long value.
998      * @return a new or already existing long item.
999      */

1000    Item newLong(final long value) {
1001        key.set(value);
1002        Item result = get(key);
1003        if (result == null) {
1004            pool.putByte(LONG).putLong(value);
1005            result = new Item(index, key);
1006            put(result);
1007            index += 2;
1008        }
1009        return result;
1010    }
1011
1012    /**
1013     * Adds a double to the constant pool of the class being build. Does nothing
1014     * if the constant pool already contains a similar item.
1015     *
1016     * @param value the double value.
1017     * @return a new or already existing double item.
1018     */

1019    Item newDouble(final double value) {
1020        key.set(value);
1021        Item result = get(key);
1022        if (result == null) {
1023            pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value));
1024            result = new Item(index, key);
1025            put(result);
1026            index += 2;
1027        }
1028        return result;
1029    }
1030
1031    /**
1032     * Adds a string to the constant pool of the class being build. Does nothing
1033     * if the constant pool already contains a similar item.
1034     *
1035     * @param value the String value.
1036     * @return a new or already existing string item.
1037     */

1038    private Item newString(final String JavaDoc value) {
1039        key2.set('S', value, null, null);
1040        Item result = get(key2);
1041        if (result == null) {
1042            pool.put12(STR, newUTF8(value));
1043            result = new Item(index++, key2);
1044            put(result);
1045        }
1046        return result;
1047    }
1048
1049    /**
1050     * Adds a name and type to the constant pool of the class being build. Does
1051     * nothing if the constant pool already contains a similar item. <i>This
1052     * method is intended for {@link Attribute} sub classes, and is normally not
1053     * needed by class generators or adapters.</i>
1054     *
1055     * @param name a name.
1056     * @param desc a type descriptor.
1057     * @return the index of a new or already existing name and type item.
1058     */

1059    public int newNameType(final String JavaDoc name, final String JavaDoc desc) {
1060        key2.set('T', name, desc, null);
1061        Item result = get(key2);
1062        if (result == null) {
1063            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
1064            result = new Item(index++, key2);
1065            put(result);
1066        }
1067        return result.index;
1068    }
1069
1070    /**
1071     * Returns the constant pool's hash table item which is equal to the given
1072     * item.
1073     *
1074     * @param key a constant pool item.
1075     * @return the constant pool's hash table item which is equal to the given
1076     * item, or <tt>null</tt> if there is no such item.
1077     */

1078    private Item get(final Item key) {
1079        int h = key.hashCode;
1080        Item i = items[h % items.length];
1081        while (i != null) {
1082            if (i.hashCode == h && key.isEqualTo(i)) {
1083                return i;
1084            }
1085            i = i.next;
1086        }
1087        return null;
1088    }
1089
1090    /**
1091     * Puts the given item in the constant pool's hash table. The hash table
1092     * <i>must</i> not already contains this item.
1093     *
1094     * @param i the item to be added to the constant pool's hash table.
1095     */

1096    private void put(final Item i) {
1097        if (index > threshold) {
1098            Item[] newItems = new Item[items.length * 2 + 1];
1099            for (int l = items.length - 1; l >= 0; --l) {
1100                Item j = items[l];
1101                while (j != null) {
1102                    int index = j.hashCode % newItems.length;
1103                    Item k = j.next;
1104                    j.next = newItems[index];
1105                    newItems[index] = j;
1106                    j = k;
1107                }
1108            }
1109            items = newItems;
1110            threshold = (int) (items.length * 0.75);
1111        }
1112        int index = i.hashCode % items.length;
1113        i.next = items[index];
1114        items[index] = i;
1115    }
1116
1117    /**
1118     * Puts one byte and two shorts into the constant pool.
1119     *
1120     * @param b a byte.
1121     * @param s1 a short.
1122     * @param s2 another short.
1123     */

1124    private void put122(final int b, final int s1, final int s2) {
1125        pool.put12(b, s1).putShort(s2);
1126    }
1127}
1128
Popular Tags