001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 */
018 package org.apache.bcel.classfile;
019
020 import java.io.DataInput;
021 import java.io.DataOutputStream;
022 import java.io.IOException;
023 import java.io.Serializable;
024
025 import org.apache.bcel.Constants;
026
027 /**
028 * This class represents a inner class attribute, i.e., the class
029 * indices of the inner and outer classes, the name and the attributes
030 * of the inner class.
031 *
032 * @version $Id: InnerClass.java 1152072 2011-07-29 01:54:05Z dbrosius $
033 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
034 * @see InnerClasses
035 */
036 public final class InnerClass implements Cloneable, Node, Serializable {
037
038 private static final long serialVersionUID = -7200195918166127614L;
039 private int inner_class_index;
040 private int outer_class_index;
041 private int inner_name_index;
042 private int inner_access_flags;
043
044
045 /**
046 * Initialize from another object.
047 */
048 public InnerClass(InnerClass c) {
049 this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c
050 .getInnerAccessFlags());
051 }
052
053
054 /**
055 * Construct object from file stream.
056 * @param file Input stream
057 * @throws IOException
058 */
059 InnerClass(DataInput file) throws IOException {
060 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
061 .readUnsignedShort());
062 }
063
064
065 /**
066 * @param inner_class_index Class index in constant pool of inner class
067 * @param outer_class_index Class index in constant pool of outer class
068 * @param inner_name_index Name index in constant pool of inner class
069 * @param inner_access_flags Access flags of inner class
070 */
071 public InnerClass(int inner_class_index, int outer_class_index, int inner_name_index,
072 int inner_access_flags) {
073 this.inner_class_index = inner_class_index;
074 this.outer_class_index = outer_class_index;
075 this.inner_name_index = inner_name_index;
076 this.inner_access_flags = inner_access_flags;
077 }
078
079
080 /**
081 * Called by objects that are traversing the nodes of the tree implicitely
082 * defined by the contents of a Java class. I.e., the hierarchy of methods,
083 * fields, attributes, etc. spawns a tree of objects.
084 *
085 * @param v Visitor object
086 */
087 public void accept( Visitor v ) {
088 v.visitInnerClass(this);
089 }
090
091
092 /**
093 * Dump inner class attribute to file stream in binary format.
094 *
095 * @param file Output file stream
096 * @throws IOException
097 */
098 public final void dump( DataOutputStream file ) throws IOException {
099 file.writeShort(inner_class_index);
100 file.writeShort(outer_class_index);
101 file.writeShort(inner_name_index);
102 file.writeShort(inner_access_flags);
103 }
104
105
106 /**
107 * @return access flags of inner class.
108 */
109 public final int getInnerAccessFlags() {
110 return inner_access_flags;
111 }
112
113
114 /**
115 * @return class index of inner class.
116 */
117 public final int getInnerClassIndex() {
118 return inner_class_index;
119 }
120
121
122 /**
123 * @return name index of inner class.
124 */
125 public final int getInnerNameIndex() {
126 return inner_name_index;
127 }
128
129
130 /**
131 * @return class index of outer class.
132 */
133 public final int getOuterClassIndex() {
134 return outer_class_index;
135 }
136
137
138 /**
139 * @param inner_access_flags access flags for this inner class
140 */
141 public final void setInnerAccessFlags( int inner_access_flags ) {
142 this.inner_access_flags = inner_access_flags;
143 }
144
145
146 /**
147 * @param inner_class_index index into the constant pool for this class
148 */
149 public final void setInnerClassIndex( int inner_class_index ) {
150 this.inner_class_index = inner_class_index;
151 }
152
153
154 /**
155 * @param inner_name_index index into the constant pool for this class's name
156 */
157 public final void setInnerNameIndex( int inner_name_index ) {
158 this.inner_name_index = inner_name_index;
159 }
160
161
162 /**
163 * @param outer_class_index index into the constant pool for the owning class
164 */
165 public final void setOuterClassIndex( int outer_class_index ) {
166 this.outer_class_index = outer_class_index;
167 }
168
169
170 /**
171 * @return String representation.
172 */
173 @Override
174 public final String toString() {
175 return "InnerClass(" + inner_class_index + ", " + outer_class_index + ", "
176 + inner_name_index + ", " + inner_access_flags + ")";
177 }
178
179
180 /**
181 * @return Resolved string representation
182 */
183 public final String toString( ConstantPool constant_pool ) {
184 String inner_class_name, outer_class_name, inner_name, access;
185 inner_class_name = constant_pool.getConstantString(inner_class_index,
186 Constants.CONSTANT_Class);
187 inner_class_name = Utility.compactClassName(inner_class_name);
188 if (outer_class_index != 0) {
189 outer_class_name = constant_pool.getConstantString(outer_class_index,
190 Constants.CONSTANT_Class);
191 outer_class_name = Utility.compactClassName(outer_class_name);
192 } else {
193 outer_class_name = "<not a member>";
194 }
195 if (inner_name_index != 0) {
196 inner_name = ((ConstantUtf8) constant_pool.getConstant(inner_name_index,
197 Constants.CONSTANT_Utf8)).getBytes();
198 } else {
199 inner_name = "<anonymous>";
200 }
201 access = Utility.accessToString(inner_access_flags, true);
202 access = access.equals("") ? "" : (access + " ");
203 return "InnerClass:" + access + inner_class_name + "(\"" + outer_class_name + "\", \""
204 + inner_name + "\")";
205 }
206
207
208 /**
209 * @return deep copy of this object
210 */
211 public InnerClass copy() {
212 try {
213 return (InnerClass) clone();
214 } catch (CloneNotSupportedException e) {
215 }
216 return null;
217 }
218 }