1    
2    /*
3    
4      The author of this software is Ian Kaplan
5      Bear Products International
6      www.bearcave.com
7      iank@bearcave.com
8    
9      Copyright (c) Ian Kaplan, 1999, 2000
10   
11     See copyright file for usage and licensing
12   
13   */
14   
15   package attr;
16   
17   import java.io.*;
18   import util.*;
19   import jconst.*;
20   
21   /**
22   
23   <p>
24      This object represents the Java class file inner class
25      information.
26   
27   <p>
28      Inner classes were added to Java 1.1 and are described by
29      Sun's Inner Class Specification, 2/10/97.
30   
31   <p>
32      An inner class is a class that is nested inside another class.  The
33      inner class exists in the local scope of its enclosing class.  So
34      an inner class may access any class variables or member functions
35      of the parent class.  It may also reference any visible methods
36      from the parent classes super class.
37   
38   <p>
39      Although the inner class shares scoping with its parent class, it
40      is compiled into a separate class file.  This class has a name that
41      is created from the inner class and its parent class.  To quote the
42      Inner class specification (Class Name Transformations):
43   
44   <blockquote>
45        Names of nested classes are transformed as necessary by the
46        compiler to avoid conflicts with identical names in other
47        scopes.  Names are encoded to the virtual machine by taking their
48        source form, qualified with dots, and changing each dot after a
49        class name into a dollar sign.
50   </blockquote>
51   
52   <p>
53      The JVM has no special support for inner classes.  They are
54      supported in the compiler by allowing inner class methods to
55      reference class variables and methods that might not normally be in
56      scope for an external class.  To quote Sun's inner class
57      specification "This complicates the compiler's job."
58   
59   <p>
60      The format for the inner classes attribute is:
61   
62   <pre>
63        innerClasses_attribute {
64          u2 attribute_name_index;
65          u4 attribute_name_length;
66          u2 number_of_classes
67          innerClassInfo classes[ number_of_classes];
68        }
69   </pre>
70   
71   <p>
72      The attribute_name_index and attribute length are read by the
73      attrFactory.allocAttr method.  These values are passed into the class
74      constructor.
75   
76   <p>
77      Here innerClassInfo is
78   
79   <pre>
80      innerClassInfo {
81        u2 inner_class_info_index;
82        u2 outer_class_info_index;
83        u2 inner_name_index;
84        u2 inner_class_access_flags;
85      }
86   </pre>
87   
88   <p>
89      Sun's JVM Specification and inner class specification is difficult
90      to understand when it comes to inner classes.
91   
92   <p>
93      The inner_class_info_index is either zero or an index into the 
94      constant table for a constClass_or_String representing the 
95      inner class.
96   
97   <p>
98      The outer_class_info_index is zero if the inner_class is not a
99      member.  Otherwise the value of outer_class_info_index is an index
100     into the constant table for a constClass_or_String representing the
101     class or interface of which the inner_class is a member.
102  
103  <p>
104     If the inner_class is anonymous, the inner_name_index will be
105     zero.  Otherwise this is an index into the constant table for
106     a constUtf8 object which contains the class name.
107  
108  <p>
109     The inner_class_access_flags are the access mask for the inner
110     class or interface.
111  
112   */
113  public class inninnerClassAttrtends attrInfo {
114  
115  
116    class innerClassInfo {
117      constClass_or_String innerClass = null;
118      constClass_or_String outerClass = null;
119      constUtf8 className = null;
120      int accessFlags;
121  
122  
123      innerClassInfo( DataInputStream dStream, constPool constPoolSec ) {
124  
125        int inner_class_info_index = readU2( dStream );
126        int outer_class_info_index = readU2( dStream );
127        int inner_name_index = readU2( dStream );
128        accessFlags = readU2( dStream );
129        constBase obj;
130  
131        if (inner_class_info_index > 0) {
132  	obj = constPoolSec.constPoolElem( inner_class_info_index );
133  	if (obj != null && obj instanceof constClass_or_String) {
134  	  innerClass = (constClass_or_String)obj;
135  	}
136        }
137  
138        if (outer_class_info_index > 0) {
139  	obj = constPoolSec.constPoolElem( outer_class_info_index );
140  	if (obj != null && obj instanceof constClass_or_String) {
141  	  outerClass = (constClass_or_String)obj;
142  	}
143        }
144  
145        if (inner_name_index > 0) {
146  	obj = constPoolSec.constPoolElem( inner_name_index );
147  	if (obj != null && obj instanceof constUtf8) {
148  	  className = (constUtf8)obj;
149  	}
150        }
151        
152      } // innerClassInfo constructor
153  
154  
155      void pr() {
156        System.out.print("innerClass: ");
157        innerClass.pr();
158        System.out.print("outerClass: ");
159        outerClass.pr();
160      } // pr
161  
162    } // class innderClassInfo
163  
164  
165    innerClassInfo classInfoTab[] = null;
166  
167  
168    public innerClassAttr( String name, int length, 
169  		   DataInputStream dStream, constPool constPoolSec ) {
170  
171      int numInnerClasses = readU2( dStream );
172      if (numInnerClasses > 0) {
173        
174        classInfoTab = new innerClassInfo[ numInnerClasses ];
175  
176        for (int i = 0; i < numInnerClasses; i++) {
177  	classInfoTab[i] = new innerClassInfo( dStream, constPoolSec );
178        }
179      }
180    } // innerClassAttr constructor
181  
182  } // innerClassAttr
183