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      * @throws IllegalStateException
 221      *             If a subclass calls this constructor.
 222      */
 223     public ClassNode() {
 224         this(Opcodes.ASM5);
 225         if (getClass() != ClassNode.class) {
 226             throw new IllegalStateException();
 227         }
 228     }
 229 
 230     /**
 231      * Constructs a new {@link ClassNode}.
 232      *
 233      * @param api
 234      *            the ASM API version implemented by this visitor. Must be one
 235      *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
 236      */
 237     public ClassNode(final int api) {
 238         super(api);
 239         this.interfaces = new ArrayList<String>();
 240         this.innerClasses = new ArrayList<InnerClassNode>();
 241         this.fields = new ArrayList<FieldNode>();
 242         this.methods = new ArrayList<MethodNode>();
 243     }
 244 
 245     // ------------------------------------------------------------------------
 246     // Implementation of the ClassVisitor abstract class
 247     // ------------------------------------------------------------------------
 248 
 249     @Override
 250     public void visit(final int version, final int access, final String name,
 251             final String signature, final String superName,
 252             final String[] interfaces) {
 253         this.version = version;
 254         this.access = access;
 255         this.name = name;
 256         this.signature = signature;
 257         this.superName = superName;
 258         if (interfaces != null) {
 259             this.interfaces.addAll(Arrays.asList(interfaces));
 260         }
 261     }
 262 
 263     @Override
 264     public void visitSource(final String file, final String debug) {
 265         sourceFile = file;
 266         sourceDebug = debug;
 267     }
 268 
 269     @Override
 270     public void visitOuterClass(final String owner, final String name,
 271             final String desc) {
 272         outerClass = owner;
 273         outerMethod = name;
 274         outerMethodDesc = desc;
 275     }
 276 
 277     @Override
 278     public AnnotationVisitor visitAnnotation(final String desc,
 279             final boolean visible) {
 280         AnnotationNode an = new AnnotationNode(desc);
 281         if (visible) {
 282             if (visibleAnnotations == null) {
 283                 visibleAnnotations = new ArrayList<AnnotationNode>(1);
 284             }
 285             visibleAnnotations.add(an);
 286         } else {
 287             if (invisibleAnnotations == null) {
 288                 invisibleAnnotations = new ArrayList<AnnotationNode>(1);
 289             }
 290             invisibleAnnotations.add(an);
 291         }
 292         return an;
 293     }
 294 
 295     @Override
 296     public AnnotationVisitor visitTypeAnnotation(int typeRef,
 297             TypePath typePath, String desc, boolean visible) {
 298         TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
 299         if (visible) {
 300             if (visibleTypeAnnotations == null) {
 301                 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
 302             }
 303             visibleTypeAnnotations.add(an);
 304         } else {
 305             if (invisibleTypeAnnotations == null) {
 306                 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
 307             }
 308             invisibleTypeAnnotations.add(an);
 309         }
 310         return an;
 311     }
 312 
 313     @Override
 314     public void visitAttribute(final Attribute attr) {
 315         if (attrs == null) {
 316             attrs = new ArrayList<Attribute>(1);
 317         }
 318         attrs.add(attr);
 319     }
 320 
 321     @Override
 322     public void visitInnerClass(final String name, final String outerName,
 323             final String innerName, final int access) {
 324         InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
 325                 access);
 326         innerClasses.add(icn);
 327     }
 328 
 329     @Override
 330     public FieldVisitor visitField(final int access, final String name,
 331             final String desc, final String signature, final Object value) {
 332         FieldNode fn = new FieldNode(access, name, desc, signature, value);
 333         fields.add(fn);
 334         return fn;
 335     }
 336 
 337     @Override
 338     public MethodVisitor visitMethod(final int access, final String name,
 339             final String desc, final String signature, final String[] exceptions) {
 340         MethodNode mn = new MethodNode(access, name, desc, signature,
 341                 exceptions);
 342         methods.add(mn);
 343         return mn;
 344     }
 345 
 346     @Override
 347     public void visitEnd() {
 348     }
 349 
 350     // ------------------------------------------------------------------------
 351     // Accept method
 352     // ------------------------------------------------------------------------
 353 
 354     /**
 355      * Checks that this class node is compatible with the given ASM API version.
 356      * This methods checks that this node, and all its nodes recursively, do not
 357      * contain elements that were introduced in more recent versions of the ASM
 358      * API than the given version.
 359      *
 360      * @param api
 361      *            an ASM API version. Must be one of {@link Opcodes#ASM4} or
 362      *            {@link Opcodes#ASM5}.
 363      */
 364     public void check(final int api) {
 365         if (api == Opcodes.ASM4) {
 366             if (visibleTypeAnnotations != null
 367                     && visibleTypeAnnotations.size() > 0) {
 368                 throw new RuntimeException();
 369             }
 370             if (invisibleTypeAnnotations != null
 371                     && invisibleTypeAnnotations.size() > 0) {
 372                 throw new RuntimeException();
 373             }
 374             for (FieldNode f : fields) {
 375                 f.check(api);
 376             }
 377             for (MethodNode m : methods) {
 378                 m.check(api);
 379             }
 380         }
 381     }
 382 
 383     /**
 384      * Makes the given class visitor visit this class.
 385      *
 386      * @param cv
 387      *            a class visitor.
 388      */
 389     public void accept(final ClassVisitor cv) {
 390         // visits header
 391         String[] interfaces = new String[this.interfaces.size()];
 392         this.interfaces.toArray(interfaces);
 393         cv.visit(version, access, name, signature, superName, interfaces);
 394         // visits source
 395         if (sourceFile != null || sourceDebug != null) {
 396             cv.visitSource(sourceFile, sourceDebug);
 397         }
 398         // visits outer class
 399         if (outerClass != null) {
 400             cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
 401         }
 402         // visits attributes
 403         int i, n;
 404         n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
 405         for (i = 0; i < n; ++i) {
 406             AnnotationNode an = visibleAnnotations.get(i);
 407             an.accept(cv.visitAnnotation(an.desc, true));
 408         }
 409         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
 410         for (i = 0; i < n; ++i) {
 411             AnnotationNode an = invisibleAnnotations.get(i);
 412             an.accept(cv.visitAnnotation(an.desc, false));
 413         }
 414         n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
 415         for (i = 0; i < n; ++i) {
 416             TypeAnnotationNode an = visibleTypeAnnotations.get(i);
 417             an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
 418                     true));
 419         }
 420         n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
 421                 .size();
 422         for (i = 0; i < n; ++i) {
 423             TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
 424             an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
 425                     false));
 426         }
 427         n = attrs == null ? 0 : attrs.size();
 428         for (i = 0; i < n; ++i) {
 429             cv.visitAttribute(attrs.get(i));
 430         }
 431         // visits inner classes
 432         for (i = 0; i < innerClasses.size(); ++i) {
 433             innerClasses.get(i).accept(cv);
 434         }
 435         // visits fields
 436         for (i = 0; i < fields.size(); ++i) {
 437             fields.get(i).accept(cv);
 438         }
 439         // visits methods
 440         for (i = 0; i < methods.size(); ++i) {
 441             methods.get(i).accept(cv);
 442         }
 443         // visits end
 444         cv.visitEnd();
 445     }
 446 }