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 org.drools.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: final ByteVector bv = new ByteVector();
134: // write type, and reserve space for values count
135: bv.putShort(this .cw.newUTF8(desc)).putShort(0);
136: final AnnotationWriter aw = new AnnotationWriter(this .cw, true,
137: bv, bv, 2);
138: if (visible) {
139: aw.next = this .anns;
140: this .anns = aw;
141: } else {
142: aw.next = this .ianns;
143: this .ianns = aw;
144: }
145: return aw;
146: }
147:
148: public void visitAttribute(final Attribute attr) {
149: attr.next = this .attrs;
150: this .attrs = attr;
151: }
152:
153: public void visitEnd() {
154: }
155:
156: // ------------------------------------------------------------------------
157: // Utility methods
158: // ------------------------------------------------------------------------
159:
160: /**
161: * Returns the size of this field.
162: *
163: * @return the size of this field.
164: */
165: int getSize() {
166: int size = 8;
167: if (this .value != 0) {
168: this .cw.newUTF8("ConstantValue");
169: size += 8;
170: }
171: if ((this .access & Opcodes.ACC_SYNTHETIC) != 0
172: && (this .cw.version & 0xffff) < Opcodes.V1_5) {
173: this .cw.newUTF8("Synthetic");
174: size += 6;
175: }
176: if ((this .access & Opcodes.ACC_DEPRECATED) != 0) {
177: this .cw.newUTF8("Deprecated");
178: size += 6;
179: }
180: if (this .cw.version == Opcodes.V1_4
181: && (this .access & Opcodes.ACC_ENUM) != 0) {
182: this .cw.newUTF8("Enum");
183: size += 6;
184: }
185: if (this .signature != 0) {
186: this .cw.newUTF8("Signature");
187: size += 8;
188: }
189: if (this .anns != null) {
190: this .cw.newUTF8("RuntimeVisibleAnnotations");
191: size += 8 + this .anns.getSize();
192: }
193: if (this .ianns != null) {
194: this .cw.newUTF8("RuntimeInvisibleAnnotations");
195: size += 8 + this .ianns.getSize();
196: }
197: if (this .attrs != null) {
198: size += this .attrs.getSize(this .cw, null, 0, -1, -1);
199: }
200: return size;
201: }
202:
203: /**
204: * Puts the content of this field into the given byte vector.
205: *
206: * @param out where the content of this field must be put.
207: */
208: void put(final ByteVector out) {
209: out.putShort(this .access).putShort(this .name).putShort(
210: this .desc);
211: int attributeCount = 0;
212: if (this .value != 0) {
213: ++attributeCount;
214: }
215: if ((this .access & Opcodes.ACC_SYNTHETIC) != 0
216: && (this .cw.version & 0xffff) < Opcodes.V1_5) {
217: ++attributeCount;
218: }
219: if ((this .access & Opcodes.ACC_DEPRECATED) != 0) {
220: ++attributeCount;
221: }
222: if (this .cw.version == Opcodes.V1_4
223: && (this .access & Opcodes.ACC_ENUM) != 0) {
224: ++attributeCount;
225: }
226: if (this .signature != 0) {
227: ++attributeCount;
228: }
229: if (this .anns != null) {
230: ++attributeCount;
231: }
232: if (this .ianns != null) {
233: ++attributeCount;
234: }
235: if (this .attrs != null) {
236: attributeCount += this .attrs.getCount();
237: }
238: out.putShort(attributeCount);
239: if (this .value != 0) {
240: out.putShort(this .cw.newUTF8("ConstantValue"));
241: out.putInt(2).putShort(this .value);
242: }
243: if ((this .access & Opcodes.ACC_SYNTHETIC) != 0
244: && (this .cw.version & 0xffff) < Opcodes.V1_5) {
245: out.putShort(this .cw.newUTF8("Synthetic")).putInt(0);
246: }
247: if ((this .access & Opcodes.ACC_DEPRECATED) != 0) {
248: out.putShort(this .cw.newUTF8("Deprecated")).putInt(0);
249: }
250: if (this .cw.version == Opcodes.V1_4
251: && (this .access & Opcodes.ACC_ENUM) != 0) {
252: out.putShort(this .cw.newUTF8("Enum")).putInt(0);
253: }
254: if (this .signature != 0) {
255: out.putShort(this .cw.newUTF8("Signature"));
256: out.putInt(2).putShort(this .signature);
257: }
258: if (this .anns != null) {
259: out.putShort(this .cw.newUTF8("RuntimeVisibleAnnotations"));
260: this .anns.put(out);
261: }
262: if (this .ianns != null) {
263: out
264: .putShort(this .cw
265: .newUTF8("RuntimeInvisibleAnnotations"));
266: this .ianns.put(out);
267: }
268: if (this .attrs != null) {
269: this .attrs.put(this .cw, null, 0, -1, -1, out);
270: }
271: }
272: }
|