rlm@10: /***
rlm@10: * ASM: a very small and fast Java bytecode manipulation framework
rlm@10: * Copyright (c) 2000-2005 INRIA, France Telecom
rlm@10: * All rights reserved.
rlm@10: *
rlm@10: * Redistribution and use in source and binary forms, with or without
rlm@10: * modification, are permitted provided that the following conditions
rlm@10: * are met:
rlm@10: * 1. Redistributions of source code must retain the above copyright
rlm@10: * notice, this list of conditions and the following disclaimer.
rlm@10: * 2. Redistributions in binary form must reproduce the above copyright
rlm@10: * notice, this list of conditions and the following disclaimer in the
rlm@10: * documentation and/or other materials provided with the distribution.
rlm@10: * 3. Neither the name of the copyright holders nor the names of its
rlm@10: * contributors may be used to endorse or promote products derived from
rlm@10: * this software without specific prior written permission.
rlm@10: *
rlm@10: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
rlm@10: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
rlm@10: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
rlm@10: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
rlm@10: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
rlm@10: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
rlm@10: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
rlm@10: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
rlm@10: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
rlm@10: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
rlm@10: * THE POSSIBILITY OF SUCH DAMAGE.
rlm@10: */
rlm@10: package clojure.asm;
rlm@10:
rlm@10: /**
rlm@10: * An {@link FieldVisitor} that generates Java fields in bytecode form.
rlm@10: *
rlm@10: * @author Eric Bruneton
rlm@10: */
rlm@10: final class FieldWriter implements FieldVisitor{
rlm@10:
rlm@10: /**
rlm@10: * Next field writer (see {@link ClassWriter#firstField firstField}).
rlm@10: */
rlm@10: FieldWriter next;
rlm@10:
rlm@10: /**
rlm@10: * The class writer to which this field must be added.
rlm@10: */
rlm@10: private ClassWriter cw;
rlm@10:
rlm@10: /**
rlm@10: * Access flags of this field.
rlm@10: */
rlm@10: private int access;
rlm@10:
rlm@10: /**
rlm@10: * The index of the constant pool item that contains the name of this
rlm@10: * method.
rlm@10: */
rlm@10: private int name;
rlm@10:
rlm@10: /**
rlm@10: * The index of the constant pool item that contains the descriptor of this
rlm@10: * field.
rlm@10: */
rlm@10: private int desc;
rlm@10:
rlm@10: /**
rlm@10: * The index of the constant pool item that contains the signature of this
rlm@10: * field.
rlm@10: */
rlm@10: private int signature;
rlm@10:
rlm@10: /**
rlm@10: * The index of the constant pool item that contains the constant value of
rlm@10: * this field.
rlm@10: */
rlm@10: private int value;
rlm@10:
rlm@10: /**
rlm@10: * The runtime visible annotations of this field. May be null.
rlm@10: */
rlm@10: private AnnotationWriter anns;
rlm@10:
rlm@10: /**
rlm@10: * The runtime invisible annotations of this field. May be null.
rlm@10: */
rlm@10: private AnnotationWriter ianns;
rlm@10:
rlm@10: /**
rlm@10: * The non standard attributes of this field. May be null.
rlm@10: */
rlm@10: private Attribute attrs;
rlm@10:
rlm@10: // ------------------------------------------------------------------------
rlm@10: // Constructor
rlm@10: // ------------------------------------------------------------------------
rlm@10:
rlm@10: /**
rlm@10: * Constructs a new {@link FieldWriter}.
rlm@10: *
rlm@10: * @param cw the class writer to which this field must be added.
rlm@10: * @param access the field's access flags (see {@link Opcodes}).
rlm@10: * @param name the field's name.
rlm@10: * @param desc the field's descriptor (see {@link Type}).
rlm@10: * @param signature the field's signature. May be null.
rlm@10: * @param value the field's constant value. May be null.
rlm@10: */
rlm@10: protected FieldWriter(
rlm@10: final ClassWriter cw,
rlm@10: final int access,
rlm@10: final String name,
rlm@10: final String desc,
rlm@10: final String signature,
rlm@10: final Object value){
rlm@10: if(cw.firstField == null)
rlm@10: {
rlm@10: cw.firstField = this;
rlm@10: }
rlm@10: else
rlm@10: {
rlm@10: cw.lastField.next = this;
rlm@10: }
rlm@10: cw.lastField = this;
rlm@10: this.cw = cw;
rlm@10: this.access = access;
rlm@10: this.name = cw.newUTF8(name);
rlm@10: this.desc = cw.newUTF8(desc);
rlm@10: if(signature != null)
rlm@10: {
rlm@10: this.signature = cw.newUTF8(signature);
rlm@10: }
rlm@10: if(value != null)
rlm@10: {
rlm@10: this.value = cw.newConstItem(value).index;
rlm@10: }
rlm@10: }
rlm@10:
rlm@10: // ------------------------------------------------------------------------
rlm@10: // Implementation of the FieldVisitor interface
rlm@10: // ------------------------------------------------------------------------
rlm@10:
rlm@10: public AnnotationVisitor visitAnnotation(
rlm@10: final String desc,
rlm@10: final boolean visible){
rlm@10: ByteVector bv = new ByteVector();
rlm@10: // write type, and reserve space for values count
rlm@10: bv.putShort(cw.newUTF8(desc)).putShort(0);
rlm@10: AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
rlm@10: if(visible)
rlm@10: {
rlm@10: aw.next = anns;
rlm@10: anns = aw;
rlm@10: }
rlm@10: else
rlm@10: {
rlm@10: aw.next = ianns;
rlm@10: ianns = aw;
rlm@10: }
rlm@10: return aw;
rlm@10: }
rlm@10:
rlm@10: public void visitAttribute(final Attribute attr){
rlm@10: attr.next = attrs;
rlm@10: attrs = attr;
rlm@10: }
rlm@10:
rlm@10: public void visitEnd(){
rlm@10: }
rlm@10:
rlm@10: // ------------------------------------------------------------------------
rlm@10: // Utility methods
rlm@10: // ------------------------------------------------------------------------
rlm@10:
rlm@10: /**
rlm@10: * Returns the size of this field.
rlm@10: *
rlm@10: * @return the size of this field.
rlm@10: */
rlm@10: int getSize(){
rlm@10: int size = 8;
rlm@10: if(value != 0)
rlm@10: {
rlm@10: cw.newUTF8("ConstantValue");
rlm@10: size += 8;
rlm@10: }
rlm@10: if((access & Opcodes.ACC_SYNTHETIC) != 0
rlm@10: && (cw.version & 0xffff) < Opcodes.V1_5)
rlm@10: {
rlm@10: cw.newUTF8("Synthetic");
rlm@10: size += 6;
rlm@10: }
rlm@10: if((access & Opcodes.ACC_DEPRECATED) != 0)
rlm@10: {
rlm@10: cw.newUTF8("Deprecated");
rlm@10: size += 6;
rlm@10: }
rlm@10: if(signature != 0)
rlm@10: {
rlm@10: cw.newUTF8("Signature");
rlm@10: size += 8;
rlm@10: }
rlm@10: if(anns != null)
rlm@10: {
rlm@10: cw.newUTF8("RuntimeVisibleAnnotations");
rlm@10: size += 8 + anns.getSize();
rlm@10: }
rlm@10: if(ianns != null)
rlm@10: {
rlm@10: cw.newUTF8("RuntimeInvisibleAnnotations");
rlm@10: size += 8 + ianns.getSize();
rlm@10: }
rlm@10: if(attrs != null)
rlm@10: {
rlm@10: size += attrs.getSize(cw, null, 0, -1, -1);
rlm@10: }
rlm@10: return size;
rlm@10: }
rlm@10:
rlm@10: /**
rlm@10: * Puts the content of this field into the given byte vector.
rlm@10: *
rlm@10: * @param out where the content of this field must be put.
rlm@10: */
rlm@10: void put(final ByteVector out){
rlm@10: out.putShort(access).putShort(name).putShort(desc);
rlm@10: int attributeCount = 0;
rlm@10: if(value != 0)
rlm@10: {
rlm@10: ++attributeCount;
rlm@10: }
rlm@10: if((access & Opcodes.ACC_SYNTHETIC) != 0
rlm@10: && (cw.version & 0xffff) < Opcodes.V1_5)
rlm@10: {
rlm@10: ++attributeCount;
rlm@10: }
rlm@10: if((access & Opcodes.ACC_DEPRECATED) != 0)
rlm@10: {
rlm@10: ++attributeCount;
rlm@10: }
rlm@10: if(signature != 0)
rlm@10: {
rlm@10: ++attributeCount;
rlm@10: }
rlm@10: if(anns != null)
rlm@10: {
rlm@10: ++attributeCount;
rlm@10: }
rlm@10: if(ianns != null)
rlm@10: {
rlm@10: ++attributeCount;
rlm@10: }
rlm@10: if(attrs != null)
rlm@10: {
rlm@10: attributeCount += attrs.getCount();
rlm@10: }
rlm@10: out.putShort(attributeCount);
rlm@10: if(value != 0)
rlm@10: {
rlm@10: out.putShort(cw.newUTF8("ConstantValue"));
rlm@10: out.putInt(2).putShort(value);
rlm@10: }
rlm@10: if((access & Opcodes.ACC_SYNTHETIC) != 0
rlm@10: && (cw.version & 0xffff) < Opcodes.V1_5)
rlm@10: {
rlm@10: out.putShort(cw.newUTF8("Synthetic")).putInt(0);
rlm@10: }
rlm@10: if((access & Opcodes.ACC_DEPRECATED) != 0)
rlm@10: {
rlm@10: out.putShort(cw.newUTF8("Deprecated")).putInt(0);
rlm@10: }
rlm@10: if(signature != 0)
rlm@10: {
rlm@10: out.putShort(cw.newUTF8("Signature"));
rlm@10: out.putInt(2).putShort(signature);
rlm@10: }
rlm@10: if(anns != null)
rlm@10: {
rlm@10: out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
rlm@10: anns.put(out);
rlm@10: }
rlm@10: if(ianns != null)
rlm@10: {
rlm@10: out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
rlm@10: ianns.put(out);
rlm@10: }
rlm@10: if(attrs != null)
rlm@10: {
rlm@10: attrs.put(cw, null, 0, -1, -1, out);
rlm@10: }
rlm@10: }
rlm@10: }