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.ModuleVisitor;
  71 import jdk.internal.org.objectweb.asm.Opcodes;
  72 import jdk.internal.org.objectweb.asm.TypePath;
  73 
  74 /**
  75  * A node that represents a class.
  76  *
  77  * @author Eric Bruneton
  78  */
  79 public class ClassNode extends ClassVisitor {
  80 
  81     /**
  82      * The class version.
  83      */
  84     public int version;
  85 
  86     /**
  87      * The class's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This
  88      * field also indicates if the class is deprecated.
  89      */
  90     public int access;
  91 
  92     /**
  93      * The internal name of the class (see
  94      * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}).
  95      */
  96     public String name;
  97 
  98     /**
  99      * The signature of the class. May be <tt>null</tt>.
 100      */
 101     public String signature;
 102 
 103     /**
 104      * The internal of name of the super class (see
 105      * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). For
 106      * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
 107      * only for the {@link Object} class.
 108      */
 109     public String superName;
 110 
 111     /**
 112      * The internal names of the class's interfaces (see
 113      * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). This
 114      * list is a list of {@link String} objects.
 115      */
 116     public List<String> interfaces;
 117 
 118     /**
 119      * The name of the source file from which this class was compiled. May be
 120      * <tt>null</tt>.
 121      */
 122     public String sourceFile;
 123 
 124     /**
 125      * Debug information to compute the correspondence between source and
 126      * compiled elements of the class. May be <tt>null</tt>.
 127      */
 128     public String sourceDebug;
 129 
 130     /**
 131      * Module information. May be <tt>null</tt>.
 132      */
 133     public ModuleNode module;
 134 
 135     /**
 136      * The internal name of the enclosing class of the class. May be
 137      * <tt>null</tt>.
 138      */
 139     public String outerClass;
 140 
 141     /**
 142      * The name of the method that contains the class, or <tt>null</tt> if the
 143      * class is not enclosed in a method.
 144      */
 145     public String outerMethod;
 146 
 147     /**
 148      * The descriptor of the method that contains the class, or <tt>null</tt> if
 149      * the class is not enclosed in a method.
 150      */
 151     public String outerMethodDesc;
 152 
 153     /**
 154      * The runtime visible annotations of this class. This list is a list of
 155      * {@link AnnotationNode} objects. May be <tt>null</tt>.
 156      *
 157      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
 158      * @label visible
 159      */
 160     public List<AnnotationNode> visibleAnnotations;
 161 
 162     /**
 163      * The runtime invisible annotations of this class. This list is a list of
 164      * {@link AnnotationNode} objects. May be <tt>null</tt>.
 165      *
 166      * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
 167      * @label invisible
 168      */
 169     public List<AnnotationNode> invisibleAnnotations;
 170 
 171     /**
 172      * The runtime visible type annotations of this class. This list is a list
 173      * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
 174      *
 175      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
 176      * @label visible
 177      */
 178     public List<TypeAnnotationNode> visibleTypeAnnotations;
 179 
 180     /**
 181      * The runtime invisible type annotations of this class. This list is a list
 182      * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
 183      *
 184      * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
 185      * @label invisible
 186      */
 187     public List<TypeAnnotationNode> invisibleTypeAnnotations;
 188 
 189     /**
 190      * The non standard attributes of this class. This list is a list of
 191      * {@link Attribute} objects. May be <tt>null</tt>.
 192      *
 193      * @associates jdk.internal.org.objectweb.asm.Attribute
 194      */
 195     public List<Attribute> attrs;
 196 
 197     /**
 198      * Informations about the inner classes of this class. This list is a list
 199      * of {@link InnerClassNode} objects.
 200      *
 201      * @associates jdk.internal.org.objectweb.asm.tree.InnerClassNode
 202      */
 203     public List<InnerClassNode> innerClasses;
 204 
 205     /**
 206      * The fields of this class. This list is a list of {@link FieldNode}
 207      * objects.
 208      *
 209      * @associates jdk.internal.org.objectweb.asm.tree.FieldNode
 210      */
 211     public List<FieldNode> fields;
 212 
 213     /**
 214      * The methods of this class. This list is a list of {@link MethodNode}
 215      * objects.
 216      *
 217      * @associates jdk.internal.org.objectweb.asm.tree.MethodNode
 218      */
 219     public List<MethodNode> methods;
 220 
 221     /**
 222      * Constructs a new {@link ClassNode}. <i>Subclasses must not use this
 223      * constructor</i>. Instead, they must use the {@link #ClassNode(int)}
 224      * version.
 225      *
 226      * @throws IllegalStateException
 227      *             If a subclass calls this constructor.
 228      */
 229     public ClassNode() {
 230         this(Opcodes.ASM6);
 231         if (getClass() != ClassNode.class) {
 232             throw new IllegalStateException();
 233         }
 234     }
 235 
 236     /**
 237      * Constructs a new {@link ClassNode}.
 238      *
 239      * @param api
 240      *            the ASM API version implemented by this visitor. Must be one
 241      *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
 242      */
 243     public ClassNode(final int api) {
 244         super(api);
 245         this.interfaces = new ArrayList<String>();
 246         this.innerClasses = new ArrayList<InnerClassNode>();
 247         this.fields = new ArrayList<FieldNode>();
 248         this.methods = new ArrayList<MethodNode>();
 249     }
 250 
 251     // ------------------------------------------------------------------------
 252     // Implementation of the ClassVisitor abstract class
 253     // ------------------------------------------------------------------------
 254 
 255     @Override
 256     public void visit(final int version, final int access, final String name,
 257             final String signature, final String superName,
 258             final String[] interfaces) {
 259         this.version = version;
 260         this.access = access;
 261         this.name = name;
 262         this.signature = signature;
 263         this.superName = superName;
 264         if (interfaces != null) {
 265             this.interfaces.addAll(Arrays.asList(interfaces));
 266         }
 267     }
 268 
 269     @Override
 270     public void visitSource(final String file, final String debug) {
 271         sourceFile = file;
 272         sourceDebug = debug;
 273     }
 274 
 275     @Override
 276     public ModuleVisitor visitModule(final String name, final int access,
 277             final String version) {
 278         return module = new ModuleNode(name, access, version);
 279     }
 280 
 281     @Override
 282     public void visitOuterClass(final String owner, final String name,
 283             final String desc) {
 284         outerClass = owner;
 285         outerMethod = name;
 286         outerMethodDesc = desc;
 287     }
 288 
 289     @Override
 290     public AnnotationVisitor visitAnnotation(final String desc,
 291             final boolean visible) {
 292         AnnotationNode an = new AnnotationNode(desc);
 293         if (visible) {
 294             if (visibleAnnotations == null) {
 295                 visibleAnnotations = new ArrayList<AnnotationNode>(1);
 296             }
 297             visibleAnnotations.add(an);
 298         } else {
 299             if (invisibleAnnotations == null) {
 300                 invisibleAnnotations = new ArrayList<AnnotationNode>(1);
 301             }
 302             invisibleAnnotations.add(an);
 303         }
 304         return an;
 305     }
 306 
 307     @Override
 308     public AnnotationVisitor visitTypeAnnotation(int typeRef,
 309             TypePath typePath, String desc, boolean visible) {
 310         TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
 311         if (visible) {
 312             if (visibleTypeAnnotations == null) {
 313                 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
 314             }
 315             visibleTypeAnnotations.add(an);
 316         } else {
 317             if (invisibleTypeAnnotations == null) {
 318                 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
 319             }
 320             invisibleTypeAnnotations.add(an);
 321         }
 322         return an;
 323     }
 324 
 325     @Override
 326     public void visitAttribute(final Attribute attr) {
 327         if (attrs == null) {
 328             attrs = new ArrayList<Attribute>(1);
 329         }
 330         attrs.add(attr);
 331     }
 332 
 333     @Override
 334     public void visitInnerClass(final String name, final String outerName,
 335             final String innerName, final int access) {
 336         InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
 337                 access);
 338         innerClasses.add(icn);
 339     }
 340 
 341     @Override
 342     public FieldVisitor visitField(final int access, final String name,
 343             final String desc, final String signature, final Object value) {
 344         FieldNode fn = new FieldNode(access, name, desc, signature, value);
 345         fields.add(fn);
 346         return fn;
 347     }
 348 
 349     @Override
 350     public MethodVisitor visitMethod(final int access, final String name,
 351             final String desc, final String signature, final String[] exceptions) {
 352         MethodNode mn = new MethodNode(access, name, desc, signature,
 353                 exceptions);
 354         methods.add(mn);
 355         return mn;
 356     }
 357 
 358     @Override
 359     public void visitEnd() {
 360     }
 361 
 362     // ------------------------------------------------------------------------
 363     // Accept method
 364     // ------------------------------------------------------------------------
 365 
 366     /**
 367      * Checks that this class node is compatible with the given ASM API version.
 368      * This methods checks that this node, and all its nodes recursively, do not
 369      * contain elements that were introduced in more recent versions of the ASM
 370      * API than the given version.
 371      *
 372      * @param api
 373      *            an ASM API version. Must be one of {@link Opcodes#ASM4},
 374      *            {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
 375      */
 376     public void check(final int api) {
 377         if (api < Opcodes.ASM6) {
 378             if (module != null) {
 379                 throw new RuntimeException();
 380             }
 381         }
 382         if (api < Opcodes.ASM5) {
 383             if (visibleTypeAnnotations != null
 384                     && visibleTypeAnnotations.size() > 0) {
 385                 throw new RuntimeException();
 386             }
 387             if (invisibleTypeAnnotations != null
 388                     && invisibleTypeAnnotations.size() > 0) {
 389                 throw new RuntimeException();
 390             }
 391         }
 392         // checks attributes
 393         int i, n;
 394         n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
 395         for (i = 0; i < n; ++i) {
 396             visibleAnnotations.get(i).check(api);
 397         }
 398         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
 399         for (i = 0; i < n; ++i) {
 400             invisibleAnnotations.get(i).check(api);
 401         }
 402         n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
 403         for (i = 0; i < n; ++i) {
 404             visibleTypeAnnotations.get(i).check(api);
 405         }
 406         n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
 407                 .size();
 408         for (i = 0; i < n; ++i) {
 409             invisibleTypeAnnotations.get(i).check(api);
 410         }
 411         for (FieldNode f : fields) {
 412             f.check(api);
 413         }
 414         for (MethodNode m : methods) {
 415             m.check(api);
 416         }
 417     }
 418 
 419     /**
 420      * Makes the given class visitor visit this class.
 421      *
 422      * @param cv
 423      *            a class visitor.
 424      */
 425     public void accept(final ClassVisitor cv) {
 426         // visits header
 427         String[] interfaces = new String[this.interfaces.size()];
 428         this.interfaces.toArray(interfaces);
 429         cv.visit(version, access, name, signature, superName, interfaces);
 430         // visits source
 431         if (sourceFile != null || sourceDebug != null) {
 432             cv.visitSource(sourceFile, sourceDebug);
 433         }
 434         // visits module
 435         if (module != null) {
 436             module.accept(cv);
 437         }
 438         // visits outer class
 439         if (outerClass != null) {
 440             cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
 441         }
 442         // visits attributes
 443         int i, n;
 444         n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
 445         for (i = 0; i < n; ++i) {
 446             AnnotationNode an = visibleAnnotations.get(i);
 447             an.accept(cv.visitAnnotation(an.desc, true));
 448         }
 449         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
 450         for (i = 0; i < n; ++i) {
 451             AnnotationNode an = invisibleAnnotations.get(i);
 452             an.accept(cv.visitAnnotation(an.desc, false));
 453         }
 454         n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
 455         for (i = 0; i < n; ++i) {
 456             TypeAnnotationNode an = visibleTypeAnnotations.get(i);
 457             an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
 458                     true));
 459         }
 460         n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
 461                 .size();
 462         for (i = 0; i < n; ++i) {
 463             TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
 464             an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
 465                     false));
 466         }
 467         n = attrs == null ? 0 : attrs.size();
 468         for (i = 0; i < n; ++i) {
 469             cv.visitAttribute(attrs.get(i));
 470         }
 471         // visits inner classes
 472         for (i = 0; i < innerClasses.size(); ++i) {
 473             innerClasses.get(i).accept(cv);
 474         }
 475         // visits fields
 476         for (i = 0; i < fields.size(); ++i) {
 477             fields.get(i).accept(cv);
 478         }
 479         // visits methods
 480         for (i = 0; i < methods.size(); ++i) {
 481             methods.get(i).accept(cv);
 482         }
 483         // visits end
 484         cv.visitEnd();
 485     }
 486 }