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.uwyn.rife.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 (cw.version == Opcodes.V1_4
180: && (access & Opcodes.ACC_ENUM) != 0) {
181: cw.newUTF8("Enum");
182: size += 6;
183: }
184: if (signature != 0) {
185: cw.newUTF8("Signature");
186: size += 8;
187: }
188: if (anns != null) {
189: cw.newUTF8("RuntimeVisibleAnnotations");
190: size += 8 + anns.getSize();
191: }
192: if (ianns != null) {
193: cw.newUTF8("RuntimeInvisibleAnnotations");
194: size += 8 + ianns.getSize();
195: }
196: if (attrs != null) {
197: size += attrs.getSize(cw, null, 0, -1, -1);
198: }
199: return size;
200: }
201:
202: /**
203: * Puts the content of this field into the given byte vector.
204: *
205: * @param out where the content of this field must be put.
206: */
207: void put(final ByteVector out) {
208: out.putShort(access).putShort(name).putShort(desc);
209: int attributeCount = 0;
210: if (value != 0) {
211: ++attributeCount;
212: }
213: if ((access & Opcodes.ACC_SYNTHETIC) != 0
214: && (cw.version & 0xffff) < Opcodes.V1_5) {
215: ++attributeCount;
216: }
217: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
218: ++attributeCount;
219: }
220: if (cw.version == Opcodes.V1_4
221: && (access & Opcodes.ACC_ENUM) != 0) {
222: ++attributeCount;
223: }
224: if (signature != 0) {
225: ++attributeCount;
226: }
227: if (anns != null) {
228: ++attributeCount;
229: }
230: if (ianns != null) {
231: ++attributeCount;
232: }
233: if (attrs != null) {
234: attributeCount += attrs.getCount();
235: }
236: out.putShort(attributeCount);
237: if (value != 0) {
238: out.putShort(cw.newUTF8("ConstantValue"));
239: out.putInt(2).putShort(value);
240: }
241: if ((access & Opcodes.ACC_SYNTHETIC) != 0
242: && (cw.version & 0xffff) < Opcodes.V1_5) {
243: out.putShort(cw.newUTF8("Synthetic")).putInt(0);
244: }
245: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
246: out.putShort(cw.newUTF8("Deprecated")).putInt(0);
247: }
248: if (cw.version == Opcodes.V1_4
249: && (access & Opcodes.ACC_ENUM) != 0) {
250: out.putShort(cw.newUTF8("Enum")).putInt(0);
251: }
252: if (signature != 0) {
253: out.putShort(cw.newUTF8("Signature"));
254: out.putInt(2).putShort(signature);
255: }
256: if (anns != null) {
257: out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
258: anns.put(out);
259: }
260: if (ianns != null) {
261: out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
262: ianns.put(out);
263: }
264: if (attrs != null) {
265: attrs.put(cw, null, 0, -1, -1, out);
266: }
267: }
268: }
|