1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * ASM: a very small and fast Java bytecode manipulation framework
32  * Copyright (c) 2000-2011 INRIA, France Telecom
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. Neither the name of the copyright holders nor the names of its
44  *    contributors may be used to endorse or promote products derived from
45  *    this software without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57  * THE POSSIBILITY OF SUCH DAMAGE.
58  */
59 package jdk.internal.org.objectweb.asm;
60 
61 /**
62  * An {@link FieldVisitor} that generates Java fields in bytecode form.
63  *
64  * @author Eric Bruneton
65  */
66 final class FieldWriter extends FieldVisitor {
67 
68     /**
69      * The class writer to which this field must be added.
70      */
71     private final ClassWriter cw;
72 
73     /**
74      * Access flags of this field.
75      */
76     private final int access;
77 
78     /**
79      * The index of the constant pool item that contains the name of this
80      * method.
81      */
82     private final int name;
83 
84     /**
85      * The index of the constant pool item that contains the descriptor of this
86      * field.
87      */
88     private final int desc;
89 
90     /**
91      * The index of the constant pool item that contains the signature of this
92      * field.
93      */
94     private int signature;
95 
96     /**
97      * The index of the constant pool item that contains the constant value of
98      * this field.
99      */
100     private int value;
101 
102     /**
103      * The runtime visible annotations of this field. May be <tt>null</tt>.
104      */
105     private AnnotationWriter anns;
106 
107     /**
108      * The runtime invisible annotations of this field. May be <tt>null</tt>.
109      */
110     private AnnotationWriter ianns;
111 
112     /**
113      * The runtime visible type annotations of this field. May be <tt>null</tt>.
114      */
115     private AnnotationWriter tanns;
116 
117     /**
118      * The runtime invisible type annotations of this field. May be
119      * <tt>null</tt>.
120      */
121     private AnnotationWriter itanns;
122 
123     /**
124      * The non standard attributes of this field. May be <tt>null</tt>.
125      */
126     private Attribute attrs;
127 
128     // ------------------------------------------------------------------------
129     // Constructor
130     // ------------------------------------------------------------------------
131 
132     /**
133      * Constructs a new {@link FieldWriter}.
134      *
135      * @param cw
136      *            the class writer to which this field must be added.
137      * @param access
138      *            the field's access flags (see {@link Opcodes}).
139      * @param name
140      *            the field's name.
141      * @param desc
142      *            the field's descriptor (see {@link Type}).
143      * @param signature
144      *            the field's signature. May be <tt>null</tt>.
145      * @param value
146      *            the field's constant value. May be <tt>null</tt>.
147      */
FieldWriter(final ClassWriter cw, final int access, final String name, final String desc, final String signature, final Object value)148     FieldWriter(final ClassWriter cw, final int access, final String name,
149             final String desc, final String signature, final Object value) {
150         super(Opcodes.ASM6);
151         if (cw.firstField == null) {
152             cw.firstField = this;
153         } else {
154             cw.lastField.fv = this;
155         }
156         cw.lastField = this;
157         this.cw = cw;
158         this.access = access;
159         this.name = cw.newUTF8(name);
160         this.desc = cw.newUTF8(desc);
161         if (signature != null) {
162             this.signature = cw.newUTF8(signature);
163         }
164         if (value != null) {
165             this.value = cw.newConstItem(value).index;
166         }
167     }
168 
169     // ------------------------------------------------------------------------
170     // Implementation of the FieldVisitor abstract class
171     // ------------------------------------------------------------------------
172 
173     @Override
visitAnnotation(final String desc, final boolean visible)174     public AnnotationVisitor visitAnnotation(final String desc,
175             final boolean visible) {
176         ByteVector bv = new ByteVector();
177         // write type, and reserve space for values count
178         bv.putShort(cw.newUTF8(desc)).putShort(0);
179         AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
180         if (visible) {
181             aw.next = anns;
182             anns = aw;
183         } else {
184             aw.next = ianns;
185             ianns = aw;
186         }
187         return aw;
188     }
189 
190     @Override
visitTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)191     public AnnotationVisitor visitTypeAnnotation(final int typeRef,
192             final TypePath typePath, final String desc, final boolean visible) {
193         ByteVector bv = new ByteVector();
194         // write target_type and target_info
195         AnnotationWriter.putTarget(typeRef, typePath, bv);
196         // write type, and reserve space for values count
197         bv.putShort(cw.newUTF8(desc)).putShort(0);
198         AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
199                 bv.length - 2);
200         if (visible) {
201             aw.next = tanns;
202             tanns = aw;
203         } else {
204             aw.next = itanns;
205             itanns = aw;
206         }
207         return aw;
208     }
209 
210     @Override
visitAttribute(final Attribute attr)211     public void visitAttribute(final Attribute attr) {
212         attr.next = attrs;
213         attrs = attr;
214     }
215 
216     @Override
visitEnd()217     public void visitEnd() {
218     }
219 
220     // ------------------------------------------------------------------------
221     // Utility methods
222     // ------------------------------------------------------------------------
223 
224     /**
225      * Returns the size of this field.
226      *
227      * @return the size of this field.
228      */
getSize()229     int getSize() {
230         int size = 8;
231         if (value != 0) {
232             cw.newUTF8("ConstantValue");
233             size += 8;
234         }
235         if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
236             if ((cw.version & 0xFFFF) < Opcodes.V1_5
237                     || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
238                 cw.newUTF8("Synthetic");
239                 size += 6;
240             }
241         }
242         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
243             cw.newUTF8("Deprecated");
244             size += 6;
245         }
246         if (signature != 0) {
247             cw.newUTF8("Signature");
248             size += 8;
249         }
250         if (anns != null) {
251             cw.newUTF8("RuntimeVisibleAnnotations");
252             size += 8 + anns.getSize();
253         }
254         if (ianns != null) {
255             cw.newUTF8("RuntimeInvisibleAnnotations");
256             size += 8 + ianns.getSize();
257         }
258         if (tanns != null) {
259             cw.newUTF8("RuntimeVisibleTypeAnnotations");
260             size += 8 + tanns.getSize();
261         }
262         if (itanns != null) {
263             cw.newUTF8("RuntimeInvisibleTypeAnnotations");
264             size += 8 + itanns.getSize();
265         }
266         if (attrs != null) {
267             size += attrs.getSize(cw, null, 0, -1, -1);
268         }
269         return size;
270     }
271 
272     /**
273      * Puts the content of this field into the given byte vector.
274      *
275      * @param out
276      *            where the content of this field must be put.
277      */
put(final ByteVector out)278     void put(final ByteVector out) {
279         final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
280         int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
281                 | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
282         out.putShort(access & ~mask).putShort(name).putShort(desc);
283         int attributeCount = 0;
284         if (value != 0) {
285             ++attributeCount;
286         }
287         if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
288             if ((cw.version & 0xFFFF) < Opcodes.V1_5
289                     || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
290                 ++attributeCount;
291             }
292         }
293         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
294             ++attributeCount;
295         }
296         if (signature != 0) {
297             ++attributeCount;
298         }
299         if (anns != null) {
300             ++attributeCount;
301         }
302         if (ianns != null) {
303             ++attributeCount;
304         }
305         if (tanns != null) {
306             ++attributeCount;
307         }
308         if (itanns != null) {
309             ++attributeCount;
310         }
311         if (attrs != null) {
312             attributeCount += attrs.getCount();
313         }
314         out.putShort(attributeCount);
315         if (value != 0) {
316             out.putShort(cw.newUTF8("ConstantValue"));
317             out.putInt(2).putShort(value);
318         }
319         if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
320             if ((cw.version & 0xFFFF) < Opcodes.V1_5
321                     || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
322                 out.putShort(cw.newUTF8("Synthetic")).putInt(0);
323             }
324         }
325         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
326             out.putShort(cw.newUTF8("Deprecated")).putInt(0);
327         }
328         if (signature != 0) {
329             out.putShort(cw.newUTF8("Signature"));
330             out.putInt(2).putShort(signature);
331         }
332         if (anns != null) {
333             out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
334             anns.put(out);
335         }
336         if (ianns != null) {
337             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
338             ianns.put(out);
339         }
340         if (tanns != null) {
341             out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
342             tanns.put(out);
343         }
344         if (itanns != null) {
345             out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
346             itanns.put(out);
347         }
348         if (attrs != null) {
349             attrs.put(cw, null, 0, -1, -1, out);
350         }
351     }
352 }
353