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: }