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 */
59package jdk.internal.org.objectweb.asm;
60
61/**
62 * An {@link FieldVisitor} that generates Java fields in bytecode form.
63 *
64 * @author Eric Bruneton
65 */
66final 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     */
148    FieldWriter(final ClassWriter cw, final int access, final String name,
149            final String desc, final String signature, final Object value) {
150        super(Opcodes.ASM5);
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 (ClassReader.SIGNATURES && 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
174    public AnnotationVisitor visitAnnotation(final String desc,
175            final boolean visible) {
176        if (!ClassReader.ANNOTATIONS) {
177            return null;
178        }
179        ByteVector bv = new ByteVector();
180        // write type, and reserve space for values count
181        bv.putShort(cw.newUTF8(desc)).putShort(0);
182        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
183        if (visible) {
184            aw.next = anns;
185            anns = aw;
186        } else {
187            aw.next = ianns;
188            ianns = aw;
189        }
190        return aw;
191    }
192
193    @Override
194    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
195            final TypePath typePath, final String desc, final boolean visible) {
196        if (!ClassReader.ANNOTATIONS) {
197            return null;
198        }
199        ByteVector bv = new ByteVector();
200        // write target_type and target_info
201        AnnotationWriter.putTarget(typeRef, typePath, bv);
202        // write type, and reserve space for values count
203        bv.putShort(cw.newUTF8(desc)).putShort(0);
204        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
205                bv.length - 2);
206        if (visible) {
207            aw.next = tanns;
208            tanns = aw;
209        } else {
210            aw.next = itanns;
211            itanns = aw;
212        }
213        return aw;
214    }
215
216    @Override
217    public void visitAttribute(final Attribute attr) {
218        attr.next = attrs;
219        attrs = attr;
220    }
221
222    @Override
223    public void visitEnd() {
224    }
225
226    // ------------------------------------------------------------------------
227    // Utility methods
228    // ------------------------------------------------------------------------
229
230    /**
231     * Returns the size of this field.
232     *
233     * @return the size of this field.
234     */
235    int getSize() {
236        int size = 8;
237        if (value != 0) {
238            cw.newUTF8("ConstantValue");
239            size += 8;
240        }
241        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
242            if ((cw.version & 0xFFFF) < Opcodes.V1_5
243                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
244                cw.newUTF8("Synthetic");
245                size += 6;
246            }
247        }
248        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
249            cw.newUTF8("Deprecated");
250            size += 6;
251        }
252        if (ClassReader.SIGNATURES && signature != 0) {
253            cw.newUTF8("Signature");
254            size += 8;
255        }
256        if (ClassReader.ANNOTATIONS && anns != null) {
257            cw.newUTF8("RuntimeVisibleAnnotations");
258            size += 8 + anns.getSize();
259        }
260        if (ClassReader.ANNOTATIONS && ianns != null) {
261            cw.newUTF8("RuntimeInvisibleAnnotations");
262            size += 8 + ianns.getSize();
263        }
264        if (ClassReader.ANNOTATIONS && tanns != null) {
265            cw.newUTF8("RuntimeVisibleTypeAnnotations");
266            size += 8 + tanns.getSize();
267        }
268        if (ClassReader.ANNOTATIONS && itanns != null) {
269            cw.newUTF8("RuntimeInvisibleTypeAnnotations");
270            size += 8 + itanns.getSize();
271        }
272        if (attrs != null) {
273            size += attrs.getSize(cw, null, 0, -1, -1);
274        }
275        return size;
276    }
277
278    /**
279     * Puts the content of this field into the given byte vector.
280     *
281     * @param out
282     *            where the content of this field must be put.
283     */
284    void put(final ByteVector out) {
285        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
286        int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
287                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
288        out.putShort(access & ~mask).putShort(name).putShort(desc);
289        int attributeCount = 0;
290        if (value != 0) {
291            ++attributeCount;
292        }
293        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
294            if ((cw.version & 0xFFFF) < Opcodes.V1_5
295                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
296                ++attributeCount;
297            }
298        }
299        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
300            ++attributeCount;
301        }
302        if (ClassReader.SIGNATURES && signature != 0) {
303            ++attributeCount;
304        }
305        if (ClassReader.ANNOTATIONS && anns != null) {
306            ++attributeCount;
307        }
308        if (ClassReader.ANNOTATIONS && ianns != null) {
309            ++attributeCount;
310        }
311        if (ClassReader.ANNOTATIONS && tanns != null) {
312            ++attributeCount;
313        }
314        if (ClassReader.ANNOTATIONS && itanns != null) {
315            ++attributeCount;
316        }
317        if (attrs != null) {
318            attributeCount += attrs.getCount();
319        }
320        out.putShort(attributeCount);
321        if (value != 0) {
322            out.putShort(cw.newUTF8("ConstantValue"));
323            out.putInt(2).putShort(value);
324        }
325        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
326            if ((cw.version & 0xFFFF) < Opcodes.V1_5
327                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
328                out.putShort(cw.newUTF8("Synthetic")).putInt(0);
329            }
330        }
331        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
332            out.putShort(cw.newUTF8("Deprecated")).putInt(0);
333        }
334        if (ClassReader.SIGNATURES && signature != 0) {
335            out.putShort(cw.newUTF8("Signature"));
336            out.putInt(2).putShort(signature);
337        }
338        if (ClassReader.ANNOTATIONS && anns != null) {
339            out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
340            anns.put(out);
341        }
342        if (ClassReader.ANNOTATIONS && ianns != null) {
343            out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
344            ianns.put(out);
345        }
346        if (ClassReader.ANNOTATIONS && tanns != null) {
347            out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
348            tanns.put(out);
349        }
350        if (ClassReader.ANNOTATIONS && itanns != null) {
351            out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
352            itanns.put(out);
353        }
354        if (attrs != null) {
355            attrs.put(cw, null, 0, -1, -1, out);
356        }
357    }
358}
359