1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.bcel.internal.classfile; 23 24 import java.io.DataInput; 25 import java.io.DataOutputStream; 26 import java.io.IOException; 27 28 import com.sun.org.apache.bcel.internal.Const; 29 30 /** 31 * This class represents a inner class attribute, i.e., the class 32 * indices of the inner and outer classes, the name and the attributes 33 * of the inner class. 34 * 35 * @version $Id: InnerClass.java 1749603 2016-06-21 20:50:19Z ggregory $ 36 * @see InnerClasses 37 */ 38 public final class InnerClass implements Cloneable, Node { 39 40 private int inner_class_index; 41 private int outer_class_index; 42 private int inner_name_index; 43 private int inner_access_flags; 44 45 46 /** 47 * Initialize from another object. 48 */ 49 public InnerClass(final InnerClass c) { 50 this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c 51 .getInnerAccessFlags()); 52 } 53 54 55 /** 56 * Construct object from file stream. 57 * @param file Input stream 58 * @throws IOException 59 */ 60 InnerClass(final DataInput file) throws IOException { 61 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file 62 .readUnsignedShort()); 63 } 64 65 66 /** 67 * @param inner_class_index Class index in constant pool of inner class 68 * @param outer_class_index Class index in constant pool of outer class 69 * @param inner_name_index Name index in constant pool of inner class 70 * @param inner_access_flags Access flags of inner class 71 */ 72 public InnerClass(final int inner_class_index, final int outer_class_index, final int inner_name_index, 73 final int inner_access_flags) { 74 this.inner_class_index = inner_class_index; 75 this.outer_class_index = outer_class_index; 76 this.inner_name_index = inner_name_index; 77 this.inner_access_flags = inner_access_flags; 78 } 79 80 81 /** 82 * Called by objects that are traversing the nodes of the tree implicitely 83 * defined by the contents of a Java class. I.e., the hierarchy of methods, 84 * fields, attributes, etc. spawns a tree of objects. 85 * 86 * @param v Visitor object 87 */ 88 @Override 89 public void accept( final Visitor v ) { 90 v.visitInnerClass(this); 91 } 92 93 94 /** 95 * Dump inner class attribute to file stream in binary format. 96 * 97 * @param file Output file stream 98 * @throws IOException 99 */ 100 public final void dump( final DataOutputStream file ) throws IOException { 101 file.writeShort(inner_class_index); 102 file.writeShort(outer_class_index); 103 file.writeShort(inner_name_index); 104 file.writeShort(inner_access_flags); 105 } 106 107 108 /** 109 * @return access flags of inner class. 110 */ 111 public final int getInnerAccessFlags() { 112 return inner_access_flags; 113 } 114 115 116 /** 117 * @return class index of inner class. 118 */ 119 public final int getInnerClassIndex() { 120 return inner_class_index; 121 } 122 123 124 /** 125 * @return name index of inner class. 126 */ 127 public final int getInnerNameIndex() { 128 return inner_name_index; 129 } 130 131 132 /** 133 * @return class index of outer class. 134 */ 135 public final int getOuterClassIndex() { 136 return outer_class_index; 137 } 138 139 140 /** 141 * @param inner_access_flags access flags for this inner class 142 */ 143 public final void setInnerAccessFlags( final int inner_access_flags ) { 144 this.inner_access_flags = inner_access_flags; 145 } 146 147 148 /** 149 * @param inner_class_index index into the constant pool for this class 150 */ 151 public final void setInnerClassIndex( final int inner_class_index ) { 152 this.inner_class_index = inner_class_index; 153 } 154 155 156 /** 157 * @param inner_name_index index into the constant pool for this class's name 158 */ 159 public final void setInnerNameIndex( final int inner_name_index ) { // TODO unused 160 this.inner_name_index = inner_name_index; 161 } 162 163 164 /** 165 * @param outer_class_index index into the constant pool for the owning class 166 */ 167 public final void setOuterClassIndex( final int outer_class_index ) { // TODO unused 168 this.outer_class_index = outer_class_index; 169 } 170 171 172 /** 173 * @return String representation. 174 */ 175 @Override 176 public final String toString() { 177 return "InnerClass(" + inner_class_index + ", " + outer_class_index + ", " 178 + inner_name_index + ", " + inner_access_flags + ")"; 179 } 180 181 182 /** 183 * @return Resolved string representation 184 */ 185 public final String toString( final ConstantPool constant_pool ) { 186 String outer_class_name; 187 String inner_name; 188 String inner_class_name = constant_pool.getConstantString(inner_class_index, 189 Const.CONSTANT_Class); 190 inner_class_name = Utility.compactClassName(inner_class_name); 191 if (outer_class_index != 0) { 192 outer_class_name = constant_pool.getConstantString(outer_class_index, 193 Const.CONSTANT_Class); 194 outer_class_name = " of class " + Utility.compactClassName(outer_class_name); 195 } else { 196 outer_class_name = ""; 197 } 198 if (inner_name_index != 0) { 199 inner_name = ((ConstantUtf8) constant_pool.getConstant(inner_name_index, 200 Const.CONSTANT_Utf8)).getBytes(); 201 } else { 202 inner_name = "(anonymous)"; 203 } 204 String access = Utility.accessToString(inner_access_flags, true); 205 access = access.isEmpty() ? "" : (access + " "); 206 return " " + access + inner_name + "=class " + inner_class_name + outer_class_name; 207 } 208 209 210 /** 211 * @return deep copy of this object 212 */ 213 public InnerClass copy() { 214 try { 215 return (InnerClass) clone(); 216 } catch (final CloneNotSupportedException e) { 217 // TODO should this throw? 218 } 219 return null; 220 } 221 }