1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * ASM: a very small and fast Java bytecode manipulation framework
  32  * Copyright (c) 2000-2011 INRIA, France Telecom
  33  * All rights reserved.
  34  *
  35  * Redistribution and use in source and binary forms, with or without
  36  * modification, are permitted provided that the following conditions
  37  * are met:
  38  * 1. Redistributions of source code must retain the above copyright
  39  *    notice, this list of conditions and the following disclaimer.
  40  * 2. Redistributions in binary form must reproduce the above copyright
  41  *    notice, this list of conditions and the following disclaimer in the
  42  *    documentation and/or other materials provided with the distribution.
  43  * 3. Neither the name of the copyright holders nor the names of its
  44  *    contributors may be used to endorse or promote products derived from
  45  *    this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 package jdk.internal.org.objectweb.asm.tree;
  60 
  61 import java.util.ArrayList;
  62 import java.util.Arrays;
  63 import java.util.List;
  64 
  65 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  66 import jdk.internal.org.objectweb.asm.Attribute;
  67 import jdk.internal.org.objectweb.asm.ClassVisitor;
  68 import jdk.internal.org.objectweb.asm.FieldVisitor;
  69 import jdk.internal.org.objectweb.asm.MethodVisitor;
  70 import jdk.internal.org.objectweb.asm.Opcodes;
  71 import jdk.internal.org.objectweb.asm.TypePath;
  72 
  73 /**
  74  * A node that represents a class.
  75  *
  76  * @author Eric Bruneton
  77  */
  78 public class ClassNode extends ClassVisitor {
  79 
  80     /**
  81      * The class version.
  82      */
  83     public int version;
  84 
  85     /**
  86      * The class's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This
  87      * field also indicates if the class is deprecated.
  88      */
  89     public int access;
  90 
  91     /**
  92      * The internal name of the class (see
  93      * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}).
  94      */
  95     public String name;
  96 
  97     /**
  98      * The signature of the class. May be <tt>null</tt>.
  99      */
 100     public String signature;
 101 
 102     /**
 103      * The internal of name of the super class (see
 104      * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). For
 105      * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
 106      * only for the {@link Object} class.
 107      */
 108     public String superName;
 109 
 110     /**
 111      * The internal names of the class's interfaces (see
 112      * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). This
 113      * list is a list of {@link String} objects.
 114      */
 115     public List<String> interfaces;
 116 
 117     /**
 118      * The name of the source file from which this class was compiled. May be
 119      * <tt>null</tt>.
 120      */
 121     public String sourceFile;
 122 
 123     /**
 124      * Debug information to compute the correspondence between source and
 125      * compiled elements of the class. May be <tt>null</tt>.
 126      */
 127     public String sourceDebug;
 128 
 129     /**
 130      * The internal name of the enclosing class of the class. May be
 131      * <tt>null</tt>.
 132      */
 133     public String outerClass;
 134 
 135     /**
 136      * The name of the method that contains the class, or <tt>null</tt> if the
 137      * class is not enclosed in a method.
 138      */
 139     public String outerMethod;
 140 
 141     /**
 142      * The descriptor of the method that contains the class, or <tt>null</tt> if
 143      * the class is not enclosed in a method.
 144      */
 145     public String outerMethodDesc;
 146 
 147     /**
 148      * The runtime visible annotations of this class. This list is a list of
 149      * {@link AnnotationNode} objects. May be <tt>null</tt>.
 150      *
 151      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
 152      * @label visible
 153      */
 154     public List<AnnotationNode> visibleAnnotations;
 155 
 156     /**
 157      * The runtime invisible annotations of this class. This list is a list of
 158      * {@link AnnotationNode} objects. May be <tt>null</tt>.
 159      *
 160      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
 161      * @label invisible
 162      */
 163     public List<AnnotationNode> invisibleAnnotations;
 164 
 165     /**
 166      * The runtime visible type annotations of this class. This list is a list
 167      * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
 168      *
 169      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
 170      * @label visible
 171      */
 172     public List<TypeAnnotationNode> visibleTypeAnnotations;
 173 
 174     /**
 175      * The runtime invisible type annotations of this class. This list is a list
 176      * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
 177      *
 178      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
 179      * @label invisible
 180      */
 181     public List<TypeAnnotationNode> invisibleTypeAnnotations;
 182 
 183     /**
 184      * The non standard attributes of this class. This list is a list of
 185      * {@link Attribute} objects. May be <tt>null</tt>.
 186      *
 187      * @associates jdk.internal.org.objectweb.asm.Attribute
 188      */
 189     public List<Attribute> attrs;
 190 
 191     /**
 192      * Informations about the inner classes of this class. This list is a list
 193      * of {@link InnerClassNode} objects.
 194      *
 195      * @associates jdk.internal.org.objectweb.asm.tree.InnerClassNode
 196      */
 197     public List<InnerClassNode> innerClasses;
 198 
 199     /**
 200      * The fields of this class. This list is a list of {@link FieldNode}
 201      * objects.
 202      *
 203      * @associates jdk.internal.org.objectweb.asm.tree.FieldNode
 204      */
 205     public List<FieldNode> fields;
 206 
 207     /**
 208      * The methods of this class. This list is a list of {@link MethodNode}
 209      * objects.
 210      *
 211      * @associates jdk.internal.org.objectweb.asm.tree.MethodNode
 212      */
 213     public List<MethodNode> methods;
 214 
 215     /**
 216      * Constructs a new {@link ClassNode}. <i>Subclasses must not use this
 217      * constructor</i>. Instead, they must use the {@link #ClassNode(int)}
 218      * version.
 219      */
 220     public ClassNode() {
 221         this(Opcodes.ASM5);
 222     }
 223 
 224     /**
 225      * Constructs a new {@link ClassNode}.
 226      *
 227      * @param api
 228      *            the ASM API version implemented by this visitor. Must be one
 229      *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
 230      */
 231     public ClassNode(final int api) {
 232         super(api);
 233         this.interfaces = new ArrayList<String>();
 234         this.innerClasses = new ArrayList<InnerClassNode>();
 235         this.fields = new ArrayList<FieldNode>();
 236         this.methods = new ArrayList<MethodNode>();
 237     }
 238 
 239     // ------------------------------------------------------------------------
 240     // Implementation of the ClassVisitor abstract class
 241     // ------------------------------------------------------------------------
 242 
 243     @Override
 244     public void visit(final int version, final int access, final String name,
 245             final String signature, final String superName,
 246             final String[] interfaces) {
 247         this.version = version;
 248         this.access = access;
 249         this.name = name;
 250         this.signature = signature;
 251         this.superName = superName;
 252         if (interfaces != null) {
 253             this.interfaces.addAll(Arrays.asList(interfaces));
 254         }
 255     }
 256 
 257     @Override
 258     public void visitSource(final String file, final String debug) {
 259         sourceFile = file;
 260         sourceDebug = debug;
 261     }
 262 
 263     @Override
 264     public void visitOuterClass(final String owner, final String name,
 265             final String desc) {
 266         outerClass = owner;
 267         outerMethod = name;
 268         outerMethodDesc = desc;
 269     }
 270 
 271     @Override
 272     public AnnotationVisitor visitAnnotation(final String desc,
 273             final boolean visible) {
 274         AnnotationNode an = new AnnotationNode(desc);
 275         if (visible) {
 276             if (visibleAnnotations == null) {
 277                 visibleAnnotations = new ArrayList<AnnotationNode>(1);
 278             }
 279             visibleAnnotations.add(an);
 280         } else {
 281             if (invisibleAnnotations == null) {
 282                 invisibleAnnotations = new ArrayList<AnnotationNode>(1);
 283             }
 284             invisibleAnnotations.add(an);
 285         }
 286         return an;
 287     }
 288 
 289     @Override
 290     public AnnotationVisitor visitTypeAnnotation(int typeRef,
 291             TypePath typePath, String desc, boolean visible) {
 292         TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
 293         if (visible) {
 294             if (visibleTypeAnnotations == null) {
 295                 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
 296             }
 297             visibleTypeAnnotations.add(an);
 298         } else {
 299             if (invisibleTypeAnnotations == null) {
 300                 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
 301             }
 302             invisibleTypeAnnotations.add(an);
 303         }
 304         return an;
 305     }
 306 
 307     @Override
 308     public void visitAttribute(final Attribute attr) {
 309         if (attrs == null) {
 310             attrs = new ArrayList<Attribute>(1);
 311         }
 312         attrs.add(attr);
 313     }
 314 
 315     @Override
 316     public void visitInnerClass(final String name, final String outerName,
 317             final String innerName, final int access) {
 318         InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
 319                 access);
 320         innerClasses.add(icn);
 321     }
 322 
 323     @Override
 324     public FieldVisitor visitField(final int access, final String name,
 325             final String desc, final String signature, final Object value) {
 326         FieldNode fn = new FieldNode(access, name, desc, signature, value);
 327         fields.add(fn);
 328         return fn;
 329     }
 330 
 331     @Override
 332     public MethodVisitor visitMethod(final int access, final String name,
 333             final String desc, final String signature, final String[] exceptions) {
 334         MethodNode mn = new MethodNode(access, name, desc, signature,
 335                 exceptions);
 336         methods.add(mn);
 337         return mn;
 338     }
 339 
 340     @Override
 341     public void visitEnd() {
 342     }
 343 
 344     // ------------------------------------------------------------------------
 345     // Accept method
 346     // ------------------------------------------------------------------------
 347 
 348     /**
 349      * Checks that this class node is compatible with the given ASM API version.
 350      * This methods checks that this node, and all its nodes recursively, do not
 351      * contain elements that were introduced in more recent versions of the ASM
 352      * API than the given version.
 353      *
 354      * @param api
 355      *            an ASM API version. Must be one of {@link Opcodes#ASM4} or
 356      *            {@link Opcodes#ASM5}.
 357      */
 358     public void check(final int api) {
 359         if (api == Opcodes.ASM4) {
 360             if (visibleTypeAnnotations != null
 361                     && visibleTypeAnnotations.size() > 0) {
 362                 throw new RuntimeException();
 363             }
 364             if (invisibleTypeAnnotations != null
 365                     && invisibleTypeAnnotations.size() > 0) {
 366                 throw new RuntimeException();
 367             }
 368             for (FieldNode f : fields) {
 369                 f.check(api);
 370             }
 371             for (MethodNode m : methods) {
 372                 m.check(api);
 373             }
 374         }
 375     }
 376 
 377     /**
 378      * Makes the given class visitor visit this class.
 379      *
 380      * @param cv
 381      *            a class visitor.
 382      */
 383     public void accept(final ClassVisitor cv) {
 384         // visits header
 385         String[] interfaces = new String[this.interfaces.size()];
 386         this.interfaces.toArray(interfaces);
 387         cv.visit(version, access, name, signature, superName, interfaces);
 388         // visits source
 389         if (sourceFile != null || sourceDebug != null) {
 390             cv.visitSource(sourceFile, sourceDebug);
 391         }
 392         // visits outer class
 393         if (outerClass != null) {
 394             cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
 395         }
 396         // visits attributes
 397         int i, n;
 398         n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
 399         for (i = 0; i < n; ++i) {
 400             AnnotationNode an = visibleAnnotations.get(i);
 401             an.accept(cv.visitAnnotation(an.desc, true));
 402         }
 403         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
 404         for (i = 0; i < n; ++i) {
 405             AnnotationNode an = invisibleAnnotations.get(i);
 406             an.accept(cv.visitAnnotation(an.desc, false));
 407         }
 408         n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
 409         for (i = 0; i < n; ++i) {
 410             TypeAnnotationNode an = visibleTypeAnnotations.get(i);
 411             an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
 412                     true));
 413         }
 414         n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
 415                 .size();
 416         for (i = 0; i < n; ++i) {
 417             TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
 418             an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
 419                     false));
 420         }
 421         n = attrs == null ? 0 : attrs.size();
 422         for (i = 0; i < n; ++i) {
 423             cv.visitAttribute(attrs.get(i));
 424         }
 425         // visits inner classes
 426         for (i = 0; i < innerClasses.size(); ++i) {
 427             innerClasses.get(i).accept(cv);
 428         }
 429         // visits fields
 430         for (i = 0; i < fields.size(); ++i) {
 431             fields.get(i).accept(cv);
 432         }
 433         // visits methods
 434         for (i = 0; i < methods.size(); ++i) {
 435             methods.get(i).accept(cv);
 436         }
 437         // visits end
 438         cv.visitEnd();
 439     }
 440 }