001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package io.ebean.enhance.asm.tree; 031 032import io.ebean.enhance.asm.AnnotationVisitor; 033import io.ebean.enhance.asm.Attribute; 034import io.ebean.enhance.asm.ClassVisitor; 035import io.ebean.enhance.asm.FieldVisitor; 036import io.ebean.enhance.asm.Opcodes; 037import io.ebean.enhance.asm.Type; 038import io.ebean.enhance.asm.TypePath; 039 040import java.util.ArrayList; 041import java.util.List; 042 043/** 044 * A node that represents a field. 045 * 046 * @author Eric Bruneton 047 */ 048public class FieldNode extends FieldVisitor { 049 050 /** 051 * The field's access flags (see {@link Opcodes}). This 052 * field also indicates if the field is synthetic and/or deprecated. 053 */ 054 public int access; 055 056 /** 057 * The field's name. 058 */ 059 public String name; 060 061 /** 062 * The field's descriptor (see {@link Type}). 063 */ 064 public String desc; 065 066 /** 067 * The field's signature. May be <tt>null</tt>. 068 */ 069 public String signature; 070 071 /** 072 * The field's initial value. This field, which may be <tt>null</tt> if the 073 * field does not have an initial value, must be an {@link Integer}, a 074 * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. 075 */ 076 public Object value; 077 078 /** 079 * The runtime visible annotations of this field. This list is a list of 080 * {@link AnnotationNode} objects. May be <tt>null</tt>. 081 * 082 * @associates org.objectweb.asm.tree.AnnotationNode 083 * @label visible 084 */ 085 public List<AnnotationNode> visibleAnnotations; 086 087 /** 088 * The runtime invisible annotations of this field. This list is a list of 089 * {@link AnnotationNode} objects. May be <tt>null</tt>. 090 * 091 * @associates org.objectweb.asm.tree.AnnotationNode 092 * @label invisible 093 */ 094 public List<AnnotationNode> invisibleAnnotations; 095 096 /** 097 * The runtime visible type annotations of this field. This list is a list 098 * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. 099 * 100 * @associates org.objectweb.asm.tree.TypeAnnotationNode 101 * @label visible 102 */ 103 public List<TypeAnnotationNode> visibleTypeAnnotations; 104 105 /** 106 * The runtime invisible type annotations of this field. This list is a list 107 * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. 108 * 109 * @associates org.objectweb.asm.tree.TypeAnnotationNode 110 * @label invisible 111 */ 112 public List<TypeAnnotationNode> invisibleTypeAnnotations; 113 114 /** 115 * The non standard attributes of this field. This list is a list of 116 * {@link Attribute} objects. May be <tt>null</tt>. 117 * 118 * @associates org.objectweb.asm.Attribute 119 */ 120 public List<Attribute> attrs; 121 122 /** 123 * Constructs a new {@link FieldNode}. <i>Subclasses must not use this 124 * constructor</i>. Instead, they must use the 125 * {@link #FieldNode(int, int, String, String, String, Object)} version. 126 * 127 * @param access 128 * the field's access flags (see 129 * {@link Opcodes}). This parameter also 130 * indicates if the field is synthetic and/or deprecated. 131 * @param name 132 * the field's name. 133 * @param desc 134 * the field's descriptor (see {@link Type 135 * Type}). 136 * @param signature 137 * the field's signature. 138 * @param value 139 * the field's initial value. This parameter, which may be 140 * <tt>null</tt> if the field does not have an initial value, 141 * must be an {@link Integer}, a {@link Float}, a {@link Long}, a 142 * {@link Double} or a {@link String}. 143 * @throws IllegalStateException 144 * If a subclass calls this constructor. 145 */ 146 public FieldNode(final int access, final String name, final String desc, 147 final String signature, final Object value) { 148 this(Opcodes.ASM6, access, name, desc, signature, value); 149 if (getClass() != FieldNode.class) { 150 throw new IllegalStateException(); 151 } 152 } 153 154 /** 155 * Constructs a new {@link FieldNode}. <i>Subclasses must not use this 156 * constructor</i>. 157 * 158 * @param api 159 * the ASM API version implemented by this visitor. Must be one 160 * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. 161 * @param access 162 * the field's access flags (see 163 * {@link Opcodes}). This parameter also 164 * indicates if the field is synthetic and/or deprecated. 165 * @param name 166 * the field's name. 167 * @param desc 168 * the field's descriptor (see {@link Type 169 * Type}). 170 * @param signature 171 * the field's signature. 172 * @param value 173 * the field's initial value. This parameter, which may be 174 * <tt>null</tt> if the field does not have an initial value, 175 * must be an {@link Integer}, a {@link Float}, a {@link Long}, a 176 * {@link Double} or a {@link String}. 177 */ 178 public FieldNode(final int api, final int access, final String name, 179 final String desc, final String signature, final Object value) { 180 super(api); 181 this.access = access; 182 this.name = name; 183 this.desc = desc; 184 this.signature = signature; 185 this.value = value; 186 } 187 188 // ------------------------------------------------------------------------ 189 // Implementation of the FieldVisitor abstract class 190 // ------------------------------------------------------------------------ 191 192 @Override 193 public AnnotationVisitor visitAnnotation(final String desc, 194 final boolean visible) { 195 AnnotationNode an = new AnnotationNode(desc); 196 if (visible) { 197 if (visibleAnnotations == null) { 198 visibleAnnotations = new ArrayList<AnnotationNode>(1); 199 } 200 visibleAnnotations.add(an); 201 } else { 202 if (invisibleAnnotations == null) { 203 invisibleAnnotations = new ArrayList<AnnotationNode>(1); 204 } 205 invisibleAnnotations.add(an); 206 } 207 return an; 208 } 209 210 @Override 211 public AnnotationVisitor visitTypeAnnotation(int typeRef, 212 TypePath typePath, String desc, boolean visible) { 213 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 214 if (visible) { 215 if (visibleTypeAnnotations == null) { 216 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); 217 } 218 visibleTypeAnnotations.add(an); 219 } else { 220 if (invisibleTypeAnnotations == null) { 221 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); 222 } 223 invisibleTypeAnnotations.add(an); 224 } 225 return an; 226 } 227 228 @Override 229 public void visitAttribute(final Attribute attr) { 230 if (attrs == null) { 231 attrs = new ArrayList<Attribute>(1); 232 } 233 attrs.add(attr); 234 } 235 236 @Override 237 public void visitEnd() { 238 } 239 240 // ------------------------------------------------------------------------ 241 // Accept methods 242 // ------------------------------------------------------------------------ 243 244 /** 245 * Checks that this field node is compatible with the given ASM API version. 246 * This methods checks that this node, and all its nodes recursively, do not 247 * contain elements that were introduced in more recent versions of the ASM 248 * API than the given version. 249 * 250 * @param api 251 * an ASM API version. Must be one of {@link Opcodes#ASM4}, 252 * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. 253 */ 254 public void check(final int api) { 255 if (api == Opcodes.ASM4) { 256 if (visibleTypeAnnotations != null 257 && visibleTypeAnnotations.size() > 0) { 258 throw new RuntimeException(); 259 } 260 if (invisibleTypeAnnotations != null 261 && invisibleTypeAnnotations.size() > 0) { 262 throw new RuntimeException(); 263 } 264 } 265 } 266 267 /** 268 * Makes the given class visitor visit this field. 269 * 270 * @param cv 271 * a class visitor. 272 */ 273 public void accept(final ClassVisitor cv) { 274 FieldVisitor fv = cv.visitField(access, name, desc, signature, value); 275 if (fv == null) { 276 return; 277 } 278 int i, n; 279 n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); 280 for (i = 0; i < n; ++i) { 281 AnnotationNode an = visibleAnnotations.get(i); 282 an.accept(fv.visitAnnotation(an.desc, true)); 283 } 284 n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); 285 for (i = 0; i < n; ++i) { 286 AnnotationNode an = invisibleAnnotations.get(i); 287 an.accept(fv.visitAnnotation(an.desc, false)); 288 } 289 n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); 290 for (i = 0; i < n; ++i) { 291 TypeAnnotationNode an = visibleTypeAnnotations.get(i); 292 an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, 293 true)); 294 } 295 n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations 296 .size(); 297 for (i = 0; i < n; ++i) { 298 TypeAnnotationNode an = invisibleTypeAnnotations.get(i); 299 an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, 300 false)); 301 } 302 n = attrs == null ? 0 : attrs.size(); 303 for (i = 0; i < n; ++i) { 304 fv.visitAttribute(attrs.get(i)); 305 } 306 fv.visitEnd(); 307 } 308}