001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2007 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 org.objectweb.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 final ClassWriter cw;
047:
048: /**
049: * Access flags of this field.
050: */
051: private final int access;
052:
053: /**
054: * The index of the constant pool item that contains the name of this
055: * method.
056: */
057: private final int name;
058:
059: /**
060: * The index of the constant pool item that contains the descriptor of this
061: * field.
062: */
063: private final 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: 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 (ClassReader.SIGNATURES && 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: if (!ClassReader.ANNOTATIONS) {
134: return null;
135: }
136: ByteVector bv = new ByteVector();
137: // write type, and reserve space for values count
138: bv.putShort(cw.newUTF8(desc)).putShort(0);
139: AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
140: if (visible) {
141: aw.next = anns;
142: anns = aw;
143: } else {
144: aw.next = ianns;
145: ianns = aw;
146: }
147: return aw;
148: }
149:
150: public void visitAttribute(final Attribute attr) {
151: attr.next = attrs;
152: attrs = attr;
153: }
154:
155: public void visitEnd() {
156: }
157:
158: // ------------------------------------------------------------------------
159: // Utility methods
160: // ------------------------------------------------------------------------
161:
162: /**
163: * Returns the size of this field.
164: *
165: * @return the size of this field.
166: */
167: int getSize() {
168: int size = 8;
169: if (value != 0) {
170: cw.newUTF8("ConstantValue");
171: size += 8;
172: }
173: if ((access & Opcodes.ACC_SYNTHETIC) != 0
174: && (cw.version & 0xffff) < Opcodes.V1_5) {
175: cw.newUTF8("Synthetic");
176: size += 6;
177: }
178: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
179: cw.newUTF8("Deprecated");
180: size += 6;
181: }
182: if (ClassReader.SIGNATURES && signature != 0) {
183: cw.newUTF8("Signature");
184: size += 8;
185: }
186: if (ClassReader.ANNOTATIONS && anns != null) {
187: cw.newUTF8("RuntimeVisibleAnnotations");
188: size += 8 + anns.getSize();
189: }
190: if (ClassReader.ANNOTATIONS && ianns != null) {
191: cw.newUTF8("RuntimeInvisibleAnnotations");
192: size += 8 + ianns.getSize();
193: }
194: if (attrs != null) {
195: size += attrs.getSize(cw, null, 0, -1, -1);
196: }
197: return size;
198: }
199:
200: /**
201: * Puts the content of this field into the given byte vector.
202: *
203: * @param out where the content of this field must be put.
204: */
205: void put(final ByteVector out) {
206: out.putShort(access).putShort(name).putShort(desc);
207: int attributeCount = 0;
208: if (value != 0) {
209: ++attributeCount;
210: }
211: if ((access & Opcodes.ACC_SYNTHETIC) != 0
212: && (cw.version & 0xffff) < Opcodes.V1_5) {
213: ++attributeCount;
214: }
215: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
216: ++attributeCount;
217: }
218: if (ClassReader.SIGNATURES && signature != 0) {
219: ++attributeCount;
220: }
221: if (ClassReader.ANNOTATIONS && anns != null) {
222: ++attributeCount;
223: }
224: if (ClassReader.ANNOTATIONS && ianns != null) {
225: ++attributeCount;
226: }
227: if (attrs != null) {
228: attributeCount += attrs.getCount();
229: }
230: out.putShort(attributeCount);
231: if (value != 0) {
232: out.putShort(cw.newUTF8("ConstantValue"));
233: out.putInt(2).putShort(value);
234: }
235: if ((access & Opcodes.ACC_SYNTHETIC) != 0
236: && (cw.version & 0xffff) < Opcodes.V1_5) {
237: out.putShort(cw.newUTF8("Synthetic")).putInt(0);
238: }
239: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
240: out.putShort(cw.newUTF8("Deprecated")).putInt(0);
241: }
242: if (ClassReader.SIGNATURES && signature != 0) {
243: out.putShort(cw.newUTF8("Signature"));
244: out.putInt(2).putShort(signature);
245: }
246: if (ClassReader.ANNOTATIONS && anns != null) {
247: out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
248: anns.put(out);
249: }
250: if (ClassReader.ANNOTATIONS && ianns != null) {
251: out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
252: ianns.put(out);
253: }
254: if (attrs != null) {
255: attrs.put(cw, null, 0, -1, -1, out);
256: }
257: }
258: }
|