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