InnerClass.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.bcel.classfile;

  18. import java.io.DataInput;
  19. import java.io.DataOutputStream;
  20. import java.io.IOException;

  21. import org.apache.bcel.Const;

  22. /**
  23.  * This class represents a inner class attribute, i.e., the class indices of the inner and outer classes, the name and
  24.  * the attributes of the inner class.
  25.  *
  26.  * @see InnerClasses
  27.  */
  28. public final class InnerClass implements Cloneable, Node {

  29.     private int innerClassIndex;
  30.     private int outerClassIndex;
  31.     private int innerNameIndex;
  32.     private int innerAccessFlags;

  33.     /**
  34.      * Constructs object from file stream.
  35.      *
  36.      * @param file Input stream
  37.      * @throws IOException if an I/O error occurs.
  38.      */
  39.     InnerClass(final DataInput file) throws IOException {
  40.         this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort());
  41.     }

  42.     /**
  43.      * Initialize from another object.
  44.      *
  45.      * @param c Source to copy.
  46.      */
  47.     public InnerClass(final InnerClass c) {
  48.         this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c.getInnerAccessFlags());
  49.     }

  50.     /**
  51.      * @param innerClassIndex Class index in constant pool of inner class
  52.      * @param outerClassIndex Class index in constant pool of outer class
  53.      * @param innerNameIndex Name index in constant pool of inner class
  54.      * @param innerAccessFlags Access flags of inner class
  55.      */
  56.     public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex, final int innerAccessFlags) {
  57.         this.innerClassIndex = innerClassIndex;
  58.         this.outerClassIndex = outerClassIndex;
  59.         this.innerNameIndex = innerNameIndex;
  60.         this.innerAccessFlags = innerAccessFlags;
  61.     }

  62.     /**
  63.      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
  64.      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
  65.      *
  66.      * @param v Visitor object
  67.      */
  68.     @Override
  69.     public void accept(final Visitor v) {
  70.         v.visitInnerClass(this);
  71.     }

  72.     /**
  73.      * @return deep copy of this object
  74.      */
  75.     public InnerClass copy() {
  76.         try {
  77.             return (InnerClass) clone();
  78.         } catch (final CloneNotSupportedException e) {
  79.             // TODO should this throw?
  80.         }
  81.         return null;
  82.     }

  83.     /**
  84.      * Dump inner class attribute to file stream in binary format.
  85.      *
  86.      * @param file Output file stream
  87.      * @throws IOException if an I/O error occurs.
  88.      */
  89.     public void dump(final DataOutputStream file) throws IOException {
  90.         file.writeShort(innerClassIndex);
  91.         file.writeShort(outerClassIndex);
  92.         file.writeShort(innerNameIndex);
  93.         file.writeShort(innerAccessFlags);
  94.     }

  95.     /**
  96.      * @return access flags of inner class.
  97.      */
  98.     public int getInnerAccessFlags() {
  99.         return innerAccessFlags;
  100.     }

  101.     /**
  102.      * @return class index of inner class.
  103.      */
  104.     public int getInnerClassIndex() {
  105.         return innerClassIndex;
  106.     }

  107.     /**
  108.      * @return name index of inner class.
  109.      */
  110.     public int getInnerNameIndex() {
  111.         return innerNameIndex;
  112.     }

  113.     /**
  114.      * @return class index of outer class.
  115.      */
  116.     public int getOuterClassIndex() {
  117.         return outerClassIndex;
  118.     }

  119.     /**
  120.      * @param innerAccessFlags access flags for this inner class
  121.      */
  122.     public void setInnerAccessFlags(final int innerAccessFlags) {
  123.         this.innerAccessFlags = innerAccessFlags;
  124.     }

  125.     /**
  126.      * @param innerClassIndex index into the constant pool for this class
  127.      */
  128.     public void setInnerClassIndex(final int innerClassIndex) {
  129.         this.innerClassIndex = innerClassIndex;
  130.     }

  131.     /**
  132.      * @param innerNameIndex index into the constant pool for this class's name
  133.      */
  134.     public void setInnerNameIndex(final int innerNameIndex) { // TODO unused
  135.         this.innerNameIndex = innerNameIndex;
  136.     }

  137.     /**
  138.      * @param outerClassIndex index into the constant pool for the owning class
  139.      */
  140.     public void setOuterClassIndex(final int outerClassIndex) { // TODO unused
  141.         this.outerClassIndex = outerClassIndex;
  142.     }

  143.     /**
  144.      * @return String representation.
  145.      */
  146.     @Override
  147.     public String toString() {
  148.         return "InnerClass(" + innerClassIndex + ", " + outerClassIndex + ", " + innerNameIndex + ", " + innerAccessFlags + ")";
  149.     }

  150.     /**
  151.      * @return Resolved string representation
  152.      */
  153.     public String toString(final ConstantPool constantPool) {
  154.         String outerClassName;
  155.         String innerName;
  156.         String innerClassName = constantPool.getConstantString(innerClassIndex, Const.CONSTANT_Class);
  157.         innerClassName = Utility.compactClassName(innerClassName, false);
  158.         if (outerClassIndex != 0) {
  159.             outerClassName = constantPool.getConstantString(outerClassIndex, Const.CONSTANT_Class);
  160.             outerClassName = " of class " + Utility.compactClassName(outerClassName, false);
  161.         } else {
  162.             outerClassName = "";
  163.         }
  164.         if (innerNameIndex != 0) {
  165.             innerName = constantPool.getConstantUtf8(innerNameIndex).getBytes();
  166.         } else {
  167.             innerName = "(anonymous)";
  168.         }
  169.         String access = Utility.accessToString(innerAccessFlags, true);
  170.         access = access.isEmpty() ? "" : access + " ";
  171.         return "  " + access + innerName + "=class " + innerClassName + outerClassName;
  172.     }
  173. }