001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package com.tc.asm;
030:
031: /**
032: * An {@link FieldVisitor} that generates Java fields in bytecode form.
033: *
034: * @author Eric Bruneton
035: */
036: final class FieldWriter implements FieldVisitor {
037:
038: /**
039: * Next field writer (see {@link ClassWriter#firstField firstField}).
040: */
041: FieldWriter next;
042:
043: /**
044: * The class writer to which this field must be added.
045: */
046: private ClassWriter cw;
047:
048: /**
049: * Access flags of this field.
050: */
051: private int access;
052:
053: /**
054: * The index of the constant pool item that contains the name of this
055: * method.
056: */
057: private int name;
058:
059: /**
060: * The index of the constant pool item that contains the descriptor of this
061: * field.
062: */
063: private int desc;
064:
065: /**
066: * The index of the constant pool item that contains the signature of this
067: * field.
068: */
069: private int signature;
070:
071: /**
072: * The index of the constant pool item that contains the constant value of
073: * this field.
074: */
075: private int value;
076:
077: /**
078: * The runtime visible annotations of this field. May be <tt>null</tt>.
079: */
080: private AnnotationWriter anns;
081:
082: /**
083: * The runtime invisible annotations of this field. May be <tt>null</tt>.
084: */
085: private AnnotationWriter ianns;
086:
087: /**
088: * The non standard attributes of this field. May be <tt>null</tt>.
089: */
090: private Attribute attrs;
091:
092: // ------------------------------------------------------------------------
093: // Constructor
094: // ------------------------------------------------------------------------
095:
096: /**
097: * Constructs a new {@link FieldWriter}.
098: *
099: * @param cw the class writer to which this field must be added.
100: * @param access the field's access flags (see {@link Opcodes}).
101: * @param name the field's name.
102: * @param desc the field's descriptor (see {@link Type}).
103: * @param signature the field's signature. May be <tt>null</tt>.
104: * @param value the field's constant value. May be <tt>null</tt>.
105: */
106: protected FieldWriter(final ClassWriter cw, final int access,
107: final String name, final String desc,
108: final String signature, final Object value) {
109: if (cw.firstField == null) {
110: cw.firstField = this ;
111: } else {
112: cw.lastField.next = this ;
113: }
114: cw.lastField = this ;
115: this .cw = cw;
116: this .access = access;
117: this .name = cw.newUTF8(name);
118: this .desc = cw.newUTF8(desc);
119: if (signature != null) {
120: this .signature = cw.newUTF8(signature);
121: }
122: if (value != null) {
123: this .value = cw.newConstItem(value).index;
124: }
125: }
126:
127: // ------------------------------------------------------------------------
128: // Implementation of the FieldVisitor interface
129: // ------------------------------------------------------------------------
130:
131: public AnnotationVisitor visitAnnotation(final String desc,
132: final boolean visible) {
133: ByteVector bv = new ByteVector();
134: // write type, and reserve space for values count
135: bv.putShort(cw.newUTF8(desc)).putShort(0);
136: AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
137: if (visible) {
138: aw.next = anns;
139: anns = aw;
140: } else {
141: aw.next = ianns;
142: ianns = aw;
143: }
144: return aw;
145: }
146:
147: public void visitAttribute(final Attribute attr) {
148: attr.next = attrs;
149: attrs = attr;
150: }
151:
152: public void visitEnd() {
153: }
154:
155: // ------------------------------------------------------------------------
156: // Utility methods
157: // ------------------------------------------------------------------------
158:
159: /**
160: * Returns the size of this field.
161: *
162: * @return the size of this field.
163: */
164: int getSize() {
165: int size = 8;
166: if (value != 0) {
167: cw.newUTF8("ConstantValue");
168: size += 8;
169: }
170: if ((access & Opcodes.ACC_SYNTHETIC) != 0
171: && (cw.version & 0xffff) < Opcodes.V1_5) {
172: cw.newUTF8("Synthetic");
173: size += 6;
174: }
175: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
176: cw.newUTF8("Deprecated");
177: size += 6;
178: }
179: if (signature != 0) {
180: cw.newUTF8("Signature");
181: size += 8;
182: }
183: if (anns != null) {
184: cw.newUTF8("RuntimeVisibleAnnotations");
185: size += 8 + anns.getSize();
186: }
187: if (ianns != null) {
188: cw.newUTF8("RuntimeInvisibleAnnotations");
189: size += 8 + ianns.getSize();
190: }
191: if (attrs != null) {
192: size += attrs.getSize(cw, null, 0, -1, -1);
193: }
194: return size;
195: }
196:
197: /**
198: * Puts the content of this field into the given byte vector.
199: *
200: * @param out where the content of this field must be put.
201: */
202: void put(final ByteVector out) {
203: out.putShort(access).putShort(name).putShort(desc);
204: int attributeCount = 0;
205: if (value != 0) {
206: ++attributeCount;
207: }
208: if ((access & Opcodes.ACC_SYNTHETIC) != 0
209: && (cw.version & 0xffff) < Opcodes.V1_5) {
210: ++attributeCount;
211: }
212: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
213: ++attributeCount;
214: }
215: if (signature != 0) {
216: ++attributeCount;
217: }
218: if (anns != null) {
219: ++attributeCount;
220: }
221: if (ianns != null) {
222: ++attributeCount;
223: }
224: if (attrs != null) {
225: attributeCount += attrs.getCount();
226: }
227: out.putShort(attributeCount);
228: if (value != 0) {
229: out.putShort(cw.newUTF8("ConstantValue"));
230: out.putInt(2).putShort(value);
231: }
232: if ((access & Opcodes.ACC_SYNTHETIC) != 0
233: && (cw.version & 0xffff) < Opcodes.V1_5) {
234: out.putShort(cw.newUTF8("Synthetic")).putInt(0);
235: }
236: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
237: out.putShort(cw.newUTF8("Deprecated")).putInt(0);
238: }
239: if (signature != 0) {
240: out.putShort(cw.newUTF8("Signature"));
241: out.putInt(2).putShort(signature);
242: }
243: if (anns != null) {
244: out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
245: anns.put(out);
246: }
247: if (ianns != null) {
248: out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
249: ianns.put(out);
250: }
251: if (attrs != null) {
252: attrs.put(cw, null, 0, -1, -1, out);
253: }
254: }
255: }
|