1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2011 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 com.sleepycat.asm;
31 
32 /**
33  * An {@link FieldVisitor} that generates Java fields in bytecode form.
34  *
35  * @author Eric Bruneton
36  */
37 final class FieldWriter extends FieldVisitor {
38 
39     /**
40      * The class writer to which this field must be added.
41      */
42     private final ClassWriter cw;
43 
44     /**
45      * Access flags of this field.
46      */
47     private final int access;
48 
49     /**
50      * The index of the constant pool item that contains the name of this
51      * method.
52      */
53     private final int name;
54 
55     /**
56      * The index of the constant pool item that contains the descriptor of this
57      * field.
58      */
59     private final int desc;
60 
61     /**
62      * The index of the constant pool item that contains the signature of this
63      * field.
64      */
65     private int signature;
66 
67     /**
68      * The index of the constant pool item that contains the constant value of
69      * this field.
70      */
71     private int value;
72 
73     /**
74      * The runtime visible annotations of this field. May be <tt>null</tt>.
75      */
76     private AnnotationWriter anns;
77 
78     /**
79      * The runtime invisible annotations of this field. May be <tt>null</tt>.
80      */
81     private AnnotationWriter ianns;
82 
83     /**
84      * The non standard attributes of this field. May be <tt>null</tt>.
85      */
86     private Attribute attrs;
87 
88     // ------------------------------------------------------------------------
89     // Constructor
90     // ------------------------------------------------------------------------
91 
92     /**
93      * Constructs a new {@link FieldWriter}.
94      *
95      * @param cw the class writer to which this field must be added.
96      * @param access the field's access flags (see {@link Opcodes}).
97      * @param name the field's name.
98      * @param desc the field's descriptor (see {@link Type}).
99      * @param signature the field's signature. May be <tt>null</tt>.
100      * @param value the field's constant value. May be <tt>null</tt>.
101      */
FieldWriter( final ClassWriter cw, final int access, final String name, final String desc, final String signature, final Object value)102     FieldWriter(
103         final ClassWriter cw,
104         final int access,
105         final String name,
106         final String desc,
107         final String signature,
108         final Object value)
109     {
110         super(Opcodes.ASM4);
111         if (cw.firstField == null) {
112             cw.firstField = this;
113         } else {
114             cw.lastField.fv = this;
115         }
116         cw.lastField = this;
117         this.cw = cw;
118         this.access = access;
119         this.name = cw.newUTF8(name);
120         this.desc = cw.newUTF8(desc);
121         if (ClassReader.SIGNATURES && signature != null) {
122             this.signature = cw.newUTF8(signature);
123         }
124         if (value != null) {
125             this.value = cw.newConstItem(value).index;
126         }
127     }
128 
129     // ------------------------------------------------------------------------
130     // Implementation of the FieldVisitor abstract class
131     // ------------------------------------------------------------------------
132 
133     @Override
visitAnnotation( final String desc, final boolean visible)134     public AnnotationVisitor visitAnnotation(
135         final String desc,
136         final boolean visible)
137     {
138         if (!ClassReader.ANNOTATIONS) {
139             return null;
140         }
141         ByteVector bv = new ByteVector();
142         // write type, and reserve space for values count
143         bv.putShort(cw.newUTF8(desc)).putShort(0);
144         AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
145         if (visible) {
146             aw.next = anns;
147             anns = aw;
148         } else {
149             aw.next = ianns;
150             ianns = aw;
151         }
152         return aw;
153     }
154 
155     @Override
visitAttribute(final Attribute attr)156     public void visitAttribute(final Attribute attr) {
157         attr.next = attrs;
158         attrs = attr;
159     }
160 
161     @Override
visitEnd()162     public void visitEnd() {
163     }
164 
165     // ------------------------------------------------------------------------
166     // Utility methods
167     // ------------------------------------------------------------------------
168 
169     /**
170      * Returns the size of this field.
171      *
172      * @return the size of this field.
173      */
getSize()174     int getSize() {
175         int size = 8;
176         if (value != 0) {
177             cw.newUTF8("ConstantValue");
178             size += 8;
179         }
180         if ((access & Opcodes.ACC_SYNTHETIC) != 0
181                 && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
182         {
183             cw.newUTF8("Synthetic");
184             size += 6;
185         }
186         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
187             cw.newUTF8("Deprecated");
188             size += 6;
189         }
190         if (ClassReader.SIGNATURES && signature != 0) {
191             cw.newUTF8("Signature");
192             size += 8;
193         }
194         if (ClassReader.ANNOTATIONS && anns != null) {
195             cw.newUTF8("RuntimeVisibleAnnotations");
196             size += 8 + anns.getSize();
197         }
198         if (ClassReader.ANNOTATIONS && ianns != null) {
199             cw.newUTF8("RuntimeInvisibleAnnotations");
200             size += 8 + ianns.getSize();
201         }
202         if (attrs != null) {
203             size += attrs.getSize(cw, null, 0, -1, -1);
204         }
205         return size;
206     }
207 
208     /**
209      * Puts the content of this field into the given byte vector.
210      *
211      * @param out where the content of this field must be put.
212      */
put(final ByteVector out)213     void put(final ByteVector out) {
214         int mask = Opcodes.ACC_DEPRECATED
215                 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
216                 | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
217         out.putShort(access & ~mask).putShort(name).putShort(desc);
218         int attributeCount = 0;
219         if (value != 0) {
220             ++attributeCount;
221         }
222         if ((access & Opcodes.ACC_SYNTHETIC) != 0
223                 && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
224         {
225             ++attributeCount;
226         }
227         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
228             ++attributeCount;
229         }
230         if (ClassReader.SIGNATURES && signature != 0) {
231             ++attributeCount;
232         }
233         if (ClassReader.ANNOTATIONS && anns != null) {
234             ++attributeCount;
235         }
236         if (ClassReader.ANNOTATIONS && ianns != null) {
237             ++attributeCount;
238         }
239         if (attrs != null) {
240             attributeCount += attrs.getCount();
241         }
242         out.putShort(attributeCount);
243         if (value != 0) {
244             out.putShort(cw.newUTF8("ConstantValue"));
245             out.putInt(2).putShort(value);
246         }
247         if ((access & Opcodes.ACC_SYNTHETIC) != 0
248                 && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
249         {
250             out.putShort(cw.newUTF8("Synthetic")).putInt(0);
251         }
252         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
253             out.putShort(cw.newUTF8("Deprecated")).putInt(0);
254         }
255         if (ClassReader.SIGNATURES && signature != 0) {
256             out.putShort(cw.newUTF8("Signature"));
257             out.putInt(2).putShort(signature);
258         }
259         if (ClassReader.ANNOTATIONS && anns != null) {
260             out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
261             anns.put(out);
262         }
263         if (ClassReader.ANNOTATIONS && ianns != null) {
264             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
265             ianns.put(out);
266         }
267         if (attrs != null) {
268             attrs.put(cw, null, 0, -1, -1, out);
269         }
270     }
271 }
272