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 * @see InnerClasses 36 */ 37 public final class InnerClass implements Cloneable, Node { 38 39 private int inner_class_index; 40 private int outer_class_index; 41 private int inner_name_index; 42 private int inner_access_flags; 43 44 45 /** 46 * Initialize from another object. 47 */ 48 public InnerClass(final InnerClass c) { 49 this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c 50 .getInnerAccessFlags()); 51 } 52 53 54 /** 55 * Construct object from file stream. 56 * @param file Input stream 57 * @throws IOException 58 */ 59 InnerClass(final DataInput file) throws IOException { 60 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file 61 .readUnsignedShort()); 62 } 63 64 65 /** 66 * @param inner_class_index Class index in constant pool of inner class 67 * @param outer_class_index Class index in constant pool of outer class 68 * @param inner_name_index Name index in constant pool of inner class 69 * @param inner_access_flags Access flags of inner class 70 */ 71 public InnerClass(final int inner_class_index, final int outer_class_index, final int inner_name_index, 72 final int inner_access_flags) { 73 this.inner_class_index = inner_class_index; 74 this.outer_class_index = outer_class_index; 75 this.inner_name_index = inner_name_index; 76 this.inner_access_flags = inner_access_flags; 77 } 78 79 80 /** 81 * Called by objects that are traversing the nodes of the tree implicitely 82 * defined by the contents of a Java class. I.e., the hierarchy of methods, 83 * fields, attributes, etc. spawns a tree of objects. 84 * 85 * @param v Visitor object 86 */ 87 @Override 88 public void accept( final Visitor v ) { 89 v.visitInnerClass(this); 90 } 91 92 93 /** 94 * Dump inner class attribute to file stream in binary format. 95 * 96 * @param file Output file stream 97 * @throws IOException 98 */ 99 public void dump( final DataOutputStream file ) throws IOException { 100 file.writeShort(inner_class_index); 101 file.writeShort(outer_class_index); 102 file.writeShort(inner_name_index); 103 file.writeShort(inner_access_flags); 104 } 105 106 107 /** 108 * @return access flags of inner class. 109 */ 110 public int getInnerAccessFlags() { 111 return inner_access_flags; 112 } 113 114 115 /** 116 * @return class index of inner class. 117 */ 118 public int getInnerClassIndex() { 119 return inner_class_index; 120 } 121 122 123 /** 124 * @return name index of inner class. 125 */ 126 public int getInnerNameIndex() { 127 return inner_name_index; 128 } 129 130 131 /** 132 * @return class index of outer class. 133 */ 134 public int getOuterClassIndex() { 135 return outer_class_index; 136 } 137 138 139 /** 140 * @param inner_access_flags access flags for this inner class 141 */ 142 public void setInnerAccessFlags( final int inner_access_flags ) { 143 this.inner_access_flags = inner_access_flags; 144 } 145 146 147 /** 148 * @param inner_class_index index into the constant pool for this class 149 */ 150 public void setInnerClassIndex( final int inner_class_index ) { 151 this.inner_class_index = inner_class_index; 152 } 153 154 155 /** 156 * @param inner_name_index index into the constant pool for this class's name 157 */ 158 public void setInnerNameIndex( final int inner_name_index ) { // TODO unused 159 this.inner_name_index = inner_name_index; 160 } 161 162 163 /** 164 * @param outer_class_index index into the constant pool for the owning class 165 */ 166 public void setOuterClassIndex( final int outer_class_index ) { // TODO unused 167 this.outer_class_index = outer_class_index; 168 } 169 170 171 /** 172 * @return String representation. 173 */ 174 @Override 175 public String toString() { 176 return "InnerClass(" + inner_class_index + ", " + outer_class_index + ", " 177 + inner_name_index + ", " + inner_access_flags + ")"; 178 } 179 180 181 /** 182 * @return Resolved string representation 183 */ 184 public String toString( final ConstantPool constant_pool ) { 185 String outer_class_name; 186 String inner_name; 187 String inner_class_name = constant_pool.getConstantString(inner_class_index, 188 Const.CONSTANT_Class); 189 inner_class_name = Utility.compactClassName(inner_class_name, false); 190 if (outer_class_index != 0) { 191 outer_class_name = constant_pool.getConstantString(outer_class_index, 192 Const.CONSTANT_Class); 193 outer_class_name = " of class " + Utility.compactClassName(outer_class_name, false); 194 } else { 195 outer_class_name = ""; 196 } 197 if (inner_name_index != 0) { 198 inner_name = ((ConstantUtf8) constant_pool.getConstant(inner_name_index, 199 Const.CONSTANT_Utf8)).getBytes(); 200 } else { 201 inner_name = "(anonymous)"; 202 } 203 String access = Utility.accessToString(inner_access_flags, true); 204 access = access.isEmpty() ? "" : (access + " "); 205 return " " + access + inner_name + "=class " + inner_class_name + outer_class_name; 206 } 207 208 209 /** 210 * @return deep copy of this object 211 */ 212 public InnerClass copy() { 213 try { 214 return (InnerClass) clone(); 215 } catch (final CloneNotSupportedException e) { 216 // TODO should this throw? 217 } 218 return null; 219 } 220 }