1/*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2007 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 */ 30package org.mockito.asm; 31 32/** 33 * An {@link FieldVisitor} that generates Java fields in bytecode form. 34 * 35 * @author Eric Bruneton 36 */ 37final class FieldWriter implements FieldVisitor { 38 39 /** 40 * Next field writer (see {@link ClassWriter#firstField firstField}). 41 */ 42 FieldWriter next; 43 44 /** 45 * The class writer to which this field must be added. 46 */ 47 private final ClassWriter cw; 48 49 /** 50 * Access flags of this field. 51 */ 52 private final int access; 53 54 /** 55 * The index of the constant pool item that contains the name of this 56 * method. 57 */ 58 private final int name; 59 60 /** 61 * The index of the constant pool item that contains the descriptor of this 62 * field. 63 */ 64 private final int desc; 65 66 /** 67 * The index of the constant pool item that contains the signature of this 68 * field. 69 */ 70 private int signature; 71 72 /** 73 * The index of the constant pool item that contains the constant value of 74 * this field. 75 */ 76 private int value; 77 78 /** 79 * The runtime visible annotations of this field. May be <tt>null</tt>. 80 */ 81 private AnnotationWriter anns; 82 83 /** 84 * The runtime invisible annotations of this field. May be <tt>null</tt>. 85 */ 86 private AnnotationWriter ianns; 87 88 /** 89 * The non standard attributes of this field. May be <tt>null</tt>. 90 */ 91 private Attribute attrs; 92 93 // ------------------------------------------------------------------------ 94 // Constructor 95 // ------------------------------------------------------------------------ 96 97 /** 98 * Constructs a new {@link FieldWriter}. 99 * 100 * @param cw the class writer to which this field must be added. 101 * @param access the field's access flags (see {@link Opcodes}). 102 * @param name the field's name. 103 * @param desc the field's descriptor (see {@link Type}). 104 * @param signature the field's signature. May be <tt>null</tt>. 105 * @param value the field's constant value. May be <tt>null</tt>. 106 */ 107 FieldWriter( 108 final ClassWriter cw, 109 final int access, 110 final String name, 111 final String desc, 112 final String signature, 113 final Object value) 114 { 115 if (cw.firstField == null) { 116 cw.firstField = this; 117 } else { 118 cw.lastField.next = this; 119 } 120 cw.lastField = this; 121 this.cw = cw; 122 this.access = access; 123 this.name = cw.newUTF8(name); 124 this.desc = cw.newUTF8(desc); 125 if (ClassReader.SIGNATURES && signature != null) { 126 this.signature = cw.newUTF8(signature); 127 } 128 if (value != null) { 129 this.value = cw.newConstItem(value).index; 130 } 131 } 132 133 // ------------------------------------------------------------------------ 134 // Implementation of the FieldVisitor interface 135 // ------------------------------------------------------------------------ 136 137 public AnnotationVisitor visitAnnotation( 138 final String desc, 139 final boolean visible) 140 { 141 if (!ClassReader.ANNOTATIONS) { 142 return null; 143 } 144 ByteVector bv = new ByteVector(); 145 // write type, and reserve space for values count 146 bv.putShort(cw.newUTF8(desc)).putShort(0); 147 AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 148 if (visible) { 149 aw.next = anns; 150 anns = aw; 151 } else { 152 aw.next = ianns; 153 ianns = aw; 154 } 155 return aw; 156 } 157 158 public void visitAttribute(final Attribute attr) { 159 attr.next = attrs; 160 attrs = attr; 161 } 162 163 public void visitEnd() { 164 } 165 166 // ------------------------------------------------------------------------ 167 // Utility methods 168 // ------------------------------------------------------------------------ 169 170 /** 171 * Returns the size of this field. 172 * 173 * @return the size of this field. 174 */ 175 int getSize() { 176 int size = 8; 177 if (value != 0) { 178 cw.newUTF8("ConstantValue"); 179 size += 8; 180 } 181 if ((access & Opcodes.ACC_SYNTHETIC) != 0 182 && (cw.version & 0xffff) < Opcodes.V1_5) 183 { 184 cw.newUTF8("Synthetic"); 185 size += 6; 186 } 187 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 188 cw.newUTF8("Deprecated"); 189 size += 6; 190 } 191 if (ClassReader.SIGNATURES && signature != 0) { 192 cw.newUTF8("Signature"); 193 size += 8; 194 } 195 if (ClassReader.ANNOTATIONS && anns != null) { 196 cw.newUTF8("RuntimeVisibleAnnotations"); 197 size += 8 + anns.getSize(); 198 } 199 if (ClassReader.ANNOTATIONS && ianns != null) { 200 cw.newUTF8("RuntimeInvisibleAnnotations"); 201 size += 8 + ianns.getSize(); 202 } 203 if (attrs != null) { 204 size += attrs.getSize(cw, null, 0, -1, -1); 205 } 206 return size; 207 } 208 209 /** 210 * Puts the content of this field into the given byte vector. 211 * 212 * @param out where the content of this field must be put. 213 */ 214 void put(final ByteVector out) { 215 out.putShort(access).putShort(name).putShort(desc); 216 int attributeCount = 0; 217 if (value != 0) { 218 ++attributeCount; 219 } 220 if ((access & Opcodes.ACC_SYNTHETIC) != 0 221 && (cw.version & 0xffff) < Opcodes.V1_5) 222 { 223 ++attributeCount; 224 } 225 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 226 ++attributeCount; 227 } 228 if (ClassReader.SIGNATURES && signature != 0) { 229 ++attributeCount; 230 } 231 if (ClassReader.ANNOTATIONS && anns != null) { 232 ++attributeCount; 233 } 234 if (ClassReader.ANNOTATIONS && ianns != null) { 235 ++attributeCount; 236 } 237 if (attrs != null) { 238 attributeCount += attrs.getCount(); 239 } 240 out.putShort(attributeCount); 241 if (value != 0) { 242 out.putShort(cw.newUTF8("ConstantValue")); 243 out.putInt(2).putShort(value); 244 } 245 if ((access & Opcodes.ACC_SYNTHETIC) != 0 246 && (cw.version & 0xffff) < Opcodes.V1_5) 247 { 248 out.putShort(cw.newUTF8("Synthetic")).putInt(0); 249 } 250 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 251 out.putShort(cw.newUTF8("Deprecated")).putInt(0); 252 } 253 if (ClassReader.SIGNATURES && signature != 0) { 254 out.putShort(cw.newUTF8("Signature")); 255 out.putInt(2).putShort(signature); 256 } 257 if (ClassReader.ANNOTATIONS && anns != null) { 258 out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); 259 anns.put(out); 260 } 261 if (ClassReader.ANNOTATIONS && ianns != null) { 262 out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); 263 ianns.put(out); 264 } 265 if (attrs != null) { 266 attrs.put(cw, null, 0, -1, -1, out); 267 } 268 } 269} 270