View Javadoc
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   */
18  package org.apache.bcel.classfile;
19  
20  import java.io.DataInput;
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  
24  import org.apache.bcel.Const;
25  
26  /**
27   * This class is derived from <em>Attribute</em> and denotes that this class
28   * is an Inner class of another.
29   * to the source file of this class.
30   * It is instantiated from the <em>Attribute.readAttribute()</em> method.
31   *
32   * @see     Attribute
33   */
34  public final class InnerClasses extends Attribute {
35  
36      private InnerClass[] innerClasses;
37  
38  
39      /**
40       * Initialize from another object. Note that both objects use the same
41       * references (shallow copy). Use clone() for a physical copy.
42       */
43      public InnerClassesnnerClasses.html#InnerClasses">InnerClasses(final InnerClasses c) {
44          this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), c.getConstantPool());
45      }
46  
47  
48      /**
49       * @param name_index Index in constant pool to CONSTANT_Utf8
50       * @param length Content length in bytes
51       * @param innerClasses array of inner classes attributes
52       * @param constant_pool Array of constants
53       */
54      public InnerClasses(final int name_index, final int length, final InnerClass[] innerClasses,
55              final ConstantPool constant_pool) {
56          super(Const.ATTR_INNER_CLASSES, name_index, length, constant_pool);
57          this.innerClasses = innerClasses != null ? innerClasses : new InnerClass[0];
58      }
59  
60  
61      /**
62       * Construct object from input stream.
63       *
64       * @param name_index Index in constant pool to CONSTANT_Utf8
65       * @param length Content length in bytes
66       * @param input Input stream
67       * @param constant_pool Array of constants
68       * @throws IOException
69       */
70      InnerClasses(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
71              throws IOException {
72          this(name_index, length, (InnerClass[]) null, constant_pool);
73          final int number_of_classes = input.readUnsignedShort();
74          innerClasses = new InnerClass[number_of_classes];
75          for (int i = 0; i < number_of_classes; i++) {
76              innerClasses[i] = new InnerClass(input);
77          }
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.visitInnerClasses(this);
91      }
92  
93  
94      /**
95       * Dump source file attribute to file stream in binary format.
96       *
97       * @param file Output file stream
98       * @throws IOException
99       */
100     @Override
101     public void dump( final DataOutputStream file ) throws IOException {
102         super.dump(file);
103         file.writeShort(innerClasses.length);
104         for (final InnerClass inner_class : innerClasses) {
105             inner_class.dump(file);
106         }
107     }
108 
109 
110     /**
111      * @return array of inner class "records"
112      */
113     public InnerClass[] getInnerClasses() {
114         return innerClasses;
115     }
116 
117 
118     /**
119      * @param innerClasses the array of inner classes
120      */
121     public void setInnerClasses( final InnerClass[] innerClasses ) {
122         this.innerClasses = innerClasses != null ? innerClasses : new InnerClass[0];
123     }
124 
125 
126     /**
127      * @return String representation.
128      */
129     @Override
130     public String toString() {
131         final StringBuilder buf = new StringBuilder();
132         buf.append("InnerClasses(");
133         buf.append(innerClasses.length);
134         buf.append("):\n");
135         for (final InnerClass inner_class : innerClasses) {
136             buf.append(inner_class.toString(super.getConstantPool())).append("\n");
137         }
138         return buf.substring(0, buf.length()-1); // remove the last newline
139     }
140 
141 
142     /**
143      * @return deep copy of this attribute
144      */
145     @Override
146     public Attribute copy( final ConstantPool _constant_pool ) {
147         // TODO this could be recoded to use a lower level constructor after creating a copy of the inner classes
148         final InnerClasses./../../../org/apache/bcel/classfile/InnerClasses.html#InnerClasses">InnerClasses c = (InnerClasses) clone();
149         c.innerClasses = new InnerClass[innerClasses.length];
150         for (int i = 0; i < innerClasses.length; i++) {
151             c.innerClasses[i] = innerClasses[i].copy();
152         }
153         c.setConstantPool(_constant_pool);
154         return c;
155     }
156 }