< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java

Print this page


   1 /*
   2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.bcel.internal.classfile;
  21 
  22 import java.io.ByteArrayOutputStream;
  23 import java.io.DataOutputStream;
  24 import java.io.File;
  25 import java.io.FileOutputStream;
  26 import java.io.IOException;
  27 import java.io.OutputStream;
  28 import java.util.ArrayList;
  29 import java.util.Objects;
  30 import java.util.StringTokenizer;
  31 import java.util.List;
  32 import java.util.Set;
  33 import java.util.TreeSet;
  34 
  35 import com.sun.org.apache.bcel.internal.Const;
  36 import com.sun.org.apache.bcel.internal.generic.Type;
  37 import com.sun.org.apache.bcel.internal.util.BCELComparator;
  38 import com.sun.org.apache.bcel.internal.util.ClassQueue;
  39 import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
  40 
  41 /**
  42  * Represents a Java class, i.e., the data structures, constant pool, fields,
  43  * methods and commands contained in a Java .class file. See <a
  44  * href="http://docs.oracle.com/javase/specs/">JVM specification</a> for
  45  * details. The intent of this class is to represent a parsed or otherwise
  46  * existing class file. Those interested in programatically generating classes
  47  * should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
  48 
  49  * @version $Id$
  50  * @see com.sun.org.apache.bcel.internal.generic.ClassGen
  51  * @LastModified: Jun 2019
  52  */
  53 public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable<JavaClass> {
  54 
  55     private String file_name;
  56     private String package_name;
  57     private String source_file_name = "<Unknown>";
  58     private int class_name_index;
  59     private int superclass_name_index;
  60     private String class_name;
  61     private String superclass_name;
  62     private int major;
  63     private int minor; // Compiler version
  64     private ConstantPool constant_pool; // Constant pool
  65     private int[] interfaces; // implemented interfaces
  66     private String[] interface_names;
  67     private Field[] fields; // Fields, i.e., variables of class
  68     private Method[] methods; // methods defined in the class
  69     private Attribute[] attributes; // attributes defined in the class
  70     private AnnotationEntry[] annotations;   // annotations defined on the class
  71     private byte source = HEAP; // Generated in memory
  72     private boolean isAnonymous = false;
  73     private boolean isNested = false;
  74     private boolean computedNestedTypeStatus = false;
  75     public static final byte HEAP = 1;
  76     public static final byte FILE = 2;
  77     public static final byte ZIP = 3;

  78 
  79     private static BCELComparator bcelComparator = new BCELComparator() {
  80 
  81         @Override
  82         public boolean equals( final Object o1, final Object o2 ) {
  83             final JavaClass THIS = (JavaClass) o1;
  84             final JavaClass THAT = (JavaClass) o2;
  85             return Objects.equals(THIS.getClassName(), THAT.getClassName());
  86         }
  87 
  88 
  89         @Override
  90         public int hashCode( final Object o ) {
  91             final JavaClass THIS = (JavaClass) o;
  92             return THIS.getClassName().hashCode();
  93         }
  94     };
  95     /**
  96      * In cases where we go ahead and create something,
  97      * use the default SyntheticRepository, because we


 201             final String file_name, final int major, final int minor, final int access_flags,
 202             final ConstantPool constant_pool, final int[] interfaces, final Field[] fields,
 203             final Method[] methods, final Attribute[] attributes) {
 204         this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
 205                 constant_pool, interfaces, fields, methods, attributes, HEAP);
 206     }
 207 
 208 
 209     /**
 210      * Called by objects that are traversing the nodes of the tree implicitely
 211      * defined by the contents of a Java class. I.e., the hierarchy of methods,
 212      * fields, attributes, etc. spawns a tree of objects.
 213      *
 214      * @param v Visitor object
 215      */
 216     @Override
 217     public void accept( final Visitor v ) {
 218         v.visitJavaClass(this);
 219     }
 220 










 221     /**
 222      * Dump class to a file.
 223      *
 224      * @param file Output file
 225      * @throws IOException
 226      */
 227     public void dump(final File file) throws IOException {
 228         final String parent = file.getParent();
 229         if (parent != null) {
 230             final File dir = new File(parent);
 231             if (!dir.mkdirs()) { // either was not created or already existed
 232                 if (!dir.isDirectory()) {
 233                     throw new IOException("Could not create the directory " + dir);
 234                 }
 235             }
 236         }
 237         try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
 238             dump(dos);
 239         }
 240     }


 589      */
 590     @Override
 591     public String toString() {
 592         String access = Utility.accessToString(super.getAccessFlags(), true);
 593         access = access.isEmpty() ? "" : (access + " ");
 594         final StringBuilder buf = new StringBuilder(128);
 595         buf.append(access).append(Utility.classOrInterface(super.getAccessFlags())).append(" ").append(
 596                 class_name).append(" extends ").append(
 597                 Utility.compactClassName(superclass_name, false)).append('\n');
 598         final int size = interfaces.length;
 599         if (size > 0) {
 600             buf.append("implements\t\t");
 601             for (int i = 0; i < size; i++) {
 602                 buf.append(interface_names[i]);
 603                 if (i < size - 1) {
 604                     buf.append(", ");
 605                 }
 606             }
 607             buf.append('\n');
 608         }
 609         buf.append("filename\t\t").append(file_name).append('\n');
 610         buf.append("compiled from\t\t").append(source_file_name).append('\n');
 611         buf.append("compiler version\t").append(major).append(".").append(minor).append('\n');
 612         buf.append("access flags\t\t").append(super.getAccessFlags()).append('\n');
 613         buf.append("constant pool\t\t").append(constant_pool.getLength()).append(" entries\n");
 614         buf.append("ACC_SUPER flag\t\t").append(isSuper()).append("\n");
 615         if (attributes.length > 0) {
 616             buf.append("\nAttribute(s):\n");
 617             for (final Attribute attribute : attributes) {
 618                 buf.append(indent(attribute));
 619             }
 620         }
 621         final AnnotationEntry[] annotations = getAnnotationEntries();
 622         if (annotations!=null && annotations.length>0) {
 623             buf.append("\nAnnotation(s):\n");
 624             for (final AnnotationEntry annotation : annotations) {
 625                 buf.append(indent(annotation));
 626             }
 627         }
 628         if (fields.length > 0) {
 629             buf.append("\n").append(fields.length).append(" fields:\n");


 699 
 700     /**
 701      * @since 6.0
 702      */
 703     public final boolean isNested() {
 704         computeNestedTypeStatus();
 705         return this.isNested;
 706     }
 707 
 708     private void computeNestedTypeStatus() {
 709         if (computedNestedTypeStatus) {
 710             return;
 711         }
 712         for (final Attribute attribute : this.attributes) {
 713               if (attribute instanceof InnerClasses) {
 714                   final InnerClass[] innerClasses = ((InnerClasses) attribute).getInnerClasses();
 715                   for (final InnerClass innerClasse : innerClasses) {
 716                       boolean innerClassAttributeRefersToMe = false;
 717                       String inner_class_name = constant_pool.getConstantString(innerClasse.getInnerClassIndex(),
 718                                  Const.CONSTANT_Class);
 719                       inner_class_name = Utility.compactClassName(inner_class_name);
 720                       if (inner_class_name.equals(getClassName())) {
 721                           innerClassAttributeRefersToMe = true;
 722                       }
 723                       if (innerClassAttributeRefersToMe) {
 724                           this.isNested = true;
 725                           if (innerClasse.getInnerNameIndex() == 0) {
 726                               this.isAnonymous = true;
 727                           }
 728                       }
 729                   }
 730               }
 731         }
 732         this.computedNestedTypeStatus = true;
 733     }
 734 
 735 
 736     /** @return returns either HEAP (generated), FILE, or ZIP
 737      */
 738     public final byte getSource() {
 739         return source;
 740     }
 741 
 742 
 743     /********************* New repository functionality *********************/
 744     /**
 745      * Gets the ClassRepository which holds its definition. By default
 746      * this is the same as SyntheticRepository.getInstance();
 747      */
 748     public com.sun.org.apache.bcel.internal.util.Repository getRepository() {
 749         return repository;
 750     }
 751 
 752 
 753     /**
 754      * Sets the ClassRepository which loaded the JavaClass.
 755      * Should be called immediately after parsing is done.
 756      */
 757     public void setRepository(final com.sun.org.apache.bcel.internal.util.Repository repository) {
 758         this.repository = repository;
 759     }
 760 
 761 
 762     /** Equivalent to runtime "instanceof" operator.
 763      *
 764      * @return true if this JavaClass is derived from the super class
 765      * @throws ClassNotFoundException if superclasses or superinterfaces
 766      *   of this object can't be found
 767      */
 768     public final boolean instanceOf( final JavaClass super_class ) throws ClassNotFoundException {
 769         if (this.equals(super_class)) {
 770             return true;
 771         }
 772         final JavaClass[] super_classes = getSuperClasses();
 773         for (final JavaClass super_classe : super_classes) {
 774             if (super_classe.equals(super_class)) {
 775                 return true;
 776             }
 777         }


   1 /*
   2  * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.bcel.internal.classfile;
  21 
  22 import java.io.ByteArrayOutputStream;
  23 import java.io.DataOutputStream;
  24 import java.io.File;
  25 import java.io.FileOutputStream;
  26 import java.io.IOException;
  27 import java.io.OutputStream;
  28 import java.util.ArrayList;
  29 import java.util.Objects;
  30 import java.util.StringTokenizer;
  31 import java.util.List;
  32 import java.util.Set;
  33 import java.util.TreeSet;
  34 
  35 import com.sun.org.apache.bcel.internal.Const;
  36 import com.sun.org.apache.bcel.internal.generic.Type;
  37 import com.sun.org.apache.bcel.internal.util.BCELComparator;
  38 import com.sun.org.apache.bcel.internal.util.ClassQueue;
  39 import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
  40 
  41 /**
  42  * Represents a Java class, i.e., the data structures, constant pool,
  43  * fields, methods and commands contained in a Java .class file.
  44  * See <a href="http://docs.oracle.com/javase/specs/">JVM specification</a> for details.
  45  * The intent of this class is to represent a parsed or otherwise existing
  46  * class file.  Those interested in programatically generating classes
  47  * should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
  48 

  49  * @see com.sun.org.apache.bcel.internal.generic.ClassGen
  50  * @LastModified: Jan 2020
  51  */
  52 public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable<JavaClass> {
  53 
  54     private String file_name;
  55     private String package_name;
  56     private String source_file_name = "<Unknown>";
  57     private int class_name_index;
  58     private int superclass_name_index;
  59     private String class_name;
  60     private String superclass_name;
  61     private int major;
  62     private int minor; // Compiler version
  63     private ConstantPool constant_pool; // Constant pool
  64     private int[] interfaces; // implemented interfaces
  65     private String[] interface_names;
  66     private Field[] fields; // Fields, i.e., variables of class
  67     private Method[] methods; // methods defined in the class
  68     private Attribute[] attributes; // attributes defined in the class
  69     private AnnotationEntry[] annotations;   // annotations defined on the class
  70     private byte source = HEAP; // Generated in memory
  71     private boolean isAnonymous = false;
  72     private boolean isNested = false;
  73     private boolean computedNestedTypeStatus = false;
  74     public static final byte HEAP = 1;
  75     public static final byte FILE = 2;
  76     public static final byte ZIP = 3;
  77     private static final boolean debug = false;
  78 
  79     private static BCELComparator bcelComparator = new BCELComparator() {
  80 
  81         @Override
  82         public boolean equals( final Object o1, final Object o2 ) {
  83             final JavaClass THIS = (JavaClass) o1;
  84             final JavaClass THAT = (JavaClass) o2;
  85             return Objects.equals(THIS.getClassName(), THAT.getClassName());
  86         }
  87 
  88 
  89         @Override
  90         public int hashCode( final Object o ) {
  91             final JavaClass THIS = (JavaClass) o;
  92             return THIS.getClassName().hashCode();
  93         }
  94     };
  95     /**
  96      * In cases where we go ahead and create something,
  97      * use the default SyntheticRepository, because we


 201             final String file_name, final int major, final int minor, final int access_flags,
 202             final ConstantPool constant_pool, final int[] interfaces, final Field[] fields,
 203             final Method[] methods, final Attribute[] attributes) {
 204         this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
 205                 constant_pool, interfaces, fields, methods, attributes, HEAP);
 206     }
 207 
 208 
 209     /**
 210      * Called by objects that are traversing the nodes of the tree implicitely
 211      * defined by the contents of a Java class. I.e., the hierarchy of methods,
 212      * fields, attributes, etc. spawns a tree of objects.
 213      *
 214      * @param v Visitor object
 215      */
 216     @Override
 217     public void accept( final Visitor v ) {
 218         v.visitJavaClass(this);
 219     }
 220 
 221 
 222     /* Print debug information depending on `JavaClass.debug'
 223      */
 224     static void Debug( final String str ) {
 225         if (debug) {
 226             System.out.println(str);
 227         }
 228     }
 229 
 230 
 231     /**
 232      * Dump class to a file.
 233      *
 234      * @param file Output file
 235      * @throws IOException
 236      */
 237     public void dump(final File file) throws IOException {
 238         final String parent = file.getParent();
 239         if (parent != null) {
 240             final File dir = new File(parent);
 241             if (!dir.mkdirs()) { // either was not created or already existed
 242                 if (!dir.isDirectory()) {
 243                     throw new IOException("Could not create the directory " + dir);
 244                 }
 245             }
 246         }
 247         try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
 248             dump(dos);
 249         }
 250     }


 599      */
 600     @Override
 601     public String toString() {
 602         String access = Utility.accessToString(super.getAccessFlags(), true);
 603         access = access.isEmpty() ? "" : (access + " ");
 604         final StringBuilder buf = new StringBuilder(128);
 605         buf.append(access).append(Utility.classOrInterface(super.getAccessFlags())).append(" ").append(
 606                 class_name).append(" extends ").append(
 607                 Utility.compactClassName(superclass_name, false)).append('\n');
 608         final int size = interfaces.length;
 609         if (size > 0) {
 610             buf.append("implements\t\t");
 611             for (int i = 0; i < size; i++) {
 612                 buf.append(interface_names[i]);
 613                 if (i < size - 1) {
 614                     buf.append(", ");
 615                 }
 616             }
 617             buf.append('\n');
 618         }
 619         buf.append("file name\t\t").append(file_name).append('\n');
 620         buf.append("compiled from\t\t").append(source_file_name).append('\n');
 621         buf.append("compiler version\t").append(major).append(".").append(minor).append('\n');
 622         buf.append("access flags\t\t").append(super.getAccessFlags()).append('\n');
 623         buf.append("constant pool\t\t").append(constant_pool.getLength()).append(" entries\n");
 624         buf.append("ACC_SUPER flag\t\t").append(isSuper()).append("\n");
 625         if (attributes.length > 0) {
 626             buf.append("\nAttribute(s):\n");
 627             for (final Attribute attribute : attributes) {
 628                 buf.append(indent(attribute));
 629             }
 630         }
 631         final AnnotationEntry[] annotations = getAnnotationEntries();
 632         if (annotations!=null && annotations.length>0) {
 633             buf.append("\nAnnotation(s):\n");
 634             for (final AnnotationEntry annotation : annotations) {
 635                 buf.append(indent(annotation));
 636             }
 637         }
 638         if (fields.length > 0) {
 639             buf.append("\n").append(fields.length).append(" fields:\n");


 709 
 710     /**
 711      * @since 6.0
 712      */
 713     public final boolean isNested() {
 714         computeNestedTypeStatus();
 715         return this.isNested;
 716     }
 717 
 718     private void computeNestedTypeStatus() {
 719         if (computedNestedTypeStatus) {
 720             return;
 721         }
 722         for (final Attribute attribute : this.attributes) {
 723               if (attribute instanceof InnerClasses) {
 724                   final InnerClass[] innerClasses = ((InnerClasses) attribute).getInnerClasses();
 725                   for (final InnerClass innerClasse : innerClasses) {
 726                       boolean innerClassAttributeRefersToMe = false;
 727                       String inner_class_name = constant_pool.getConstantString(innerClasse.getInnerClassIndex(),
 728                                  Const.CONSTANT_Class);
 729                       inner_class_name = Utility.compactClassName(inner_class_name, false);
 730                       if (inner_class_name.equals(getClassName())) {
 731                           innerClassAttributeRefersToMe = true;
 732                       }
 733                       if (innerClassAttributeRefersToMe) {
 734                           this.isNested = true;
 735                           if (innerClasse.getInnerNameIndex() == 0) {
 736                               this.isAnonymous = true;
 737                           }
 738                       }
 739                   }
 740               }
 741         }
 742         this.computedNestedTypeStatus = true;
 743     }
 744 
 745 
 746     /** @return returns either HEAP (generated), FILE, or ZIP
 747      */
 748     public final byte getSource() {
 749         return source;
 750     }
 751 
 752 
 753     /********************* New repository functionality *********************/
 754     /**
 755      * Gets the ClassRepository which holds its definition. By default
 756      * this is the same as SyntheticRepository.getInstance();
 757      */
 758     public com.sun.org.apache.bcel.internal.util.Repository getRepository() {
 759         return repository;
 760     }
 761 
 762 
 763     /**
 764      * Sets the ClassRepository which loaded the JavaClass.
 765      * Should be called immediately after parsing is done.
 766      */
 767     public void setRepository( final com.sun.org.apache.bcel.internal.util.Repository repository ) { // TODO make protected?
 768         this.repository = repository;
 769     }
 770 
 771 
 772     /** Equivalent to runtime "instanceof" operator.
 773      *
 774      * @return true if this JavaClass is derived from the super class
 775      * @throws ClassNotFoundException if superclasses or superinterfaces
 776      *   of this object can't be found
 777      */
 778     public final boolean instanceOf( final JavaClass super_class ) throws ClassNotFoundException {
 779         if (this.equals(super_class)) {
 780             return true;
 781         }
 782         final JavaClass[] super_classes = getSuperClasses();
 783         for (final JavaClass super_classe : super_classes) {
 784             if (super_classe.equals(super_class)) {
 785                 return true;
 786             }
 787         }


< prev index next >