KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > bytecode > ClassFileInput


1 // Copyright (c) 1997, 2004 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.bytecode;
5 import java.io.InputStream JavaDoc;
6 import java.io.DataInputStream JavaDoc;
7 import java.io.IOException JavaDoc;
8
9 /** Class to read a ClassType from a DataInputStream (.class file).
10  * @author Per Bothner
11  */

12
13 public class ClassFileInput extends DataInputStream JavaDoc
14 {
15   ClassType ctype;
16   InputStream JavaDoc str;
17
18   public ClassFileInput (InputStream JavaDoc str)
19        throws IOException JavaDoc
20   {
21     super(str);
22   }
23
24   public ClassFileInput (ClassType ctype, InputStream JavaDoc str)
25        throws IOException JavaDoc, ClassFormatError JavaDoc
26   {
27     super(str);
28     this.ctype = ctype;
29     if (!readHeader())
30       throw new ClassFormatError JavaDoc("invalid magic number");
31     ctype.constants = readConstants();
32     readClassInfo();
33     readFields();
34     readMethods();
35     readAttributes(ctype);
36   }
37  
38   /** Read a class (in .class format) from an InputStream.
39     * @return A new ClassType object representing the class that was read.
40     */

41   public static ClassType readClassType (InputStream JavaDoc str)
42        throws IOException JavaDoc, ClassFormatError JavaDoc
43   {
44     ClassType ctype = new ClassType();
45     new ClassFileInput(ctype, str);
46     return ctype;
47   }
48
49   public boolean readHeader () throws IOException JavaDoc
50   {
51     int magic = readInt();
52     if (magic != 0xcafebabe)
53       return false;
54     int minor = readUnsignedShort();
55     int major = readUnsignedShort();
56     ctype.classfileFormatVersion = major * 0x10000 + minor;
57     return true;
58   }
59
60   public ConstantPool readConstants () throws IOException JavaDoc
61   {
62     return new ConstantPool(this);
63   }
64
65   public void readClassInfo () throws IOException JavaDoc
66   {
67     ctype.access_flags = readUnsignedShort();
68     CpoolClass clas;
69     String JavaDoc name;
70
71     ctype.thisClassIndex = readUnsignedShort();
72     clas = (CpoolClass) ctype.constants.getForced(ctype.thisClassIndex,
73                           ConstantPool.CLASS);
74     name = clas.name.string;
75     ctype.this_name = name.replace('/', '.');
76     ctype.setSignature("L"+name+";");
77
78     ctype.superClassIndex = readUnsignedShort();
79     if (ctype.superClassIndex == 0)
80       ctype.setSuper((ClassType) null);
81     else
82       {
83     clas = (CpoolClass) ctype.constants.getForced(ctype.superClassIndex,
84                               ConstantPool.CLASS);
85     name = clas.name.string;
86     ctype.setSuper(name.replace('/', '.'));
87       }
88
89     int nInterfaces = readUnsignedShort();
90     if (nInterfaces > 0)
91       {
92     ctype.interfaces = new ClassType[nInterfaces];
93     ctype.interfaceIndexes = new int[nInterfaces];
94     for (int i = 0; i < nInterfaces; i++)
95       {
96         int index = readUnsignedShort();
97         ctype.interfaceIndexes[i] = index;
98         clas = (CpoolClass) ctype.constants.getForced(index,
99                               ConstantPool.CLASS);
100         name = clas.name.string.replace('/', '.');
101         ctype.interfaces[i] = ClassType.make(name);
102       }
103       }
104   }
105
106   public int readAttributes (AttrContainer container) throws IOException JavaDoc
107   {
108     int count = readUnsignedShort();
109     Attribute last = container.getAttributes();
110     for (int i = 0; i < count; i++)
111       {
112     if (last != null)
113       {
114         for (;;)
115           {
116         Attribute next = last.getNext();
117         if (next == null)
118           break;
119         last = next;
120           }
121       }
122     
123     int index = readUnsignedShort();
124     CpoolUtf8 nameConstant = (CpoolUtf8)
125       ctype.constants.getForced(index, ConstantPool.UTF8);
126     int length = readInt();
127     nameConstant.intern();
128     Attribute attr = readAttribute(nameConstant.string, length, container);
129     if (attr != null)
130       {
131         if (attr.getNameIndex() == 0)
132           attr.setNameIndex(index);
133         if (last == null)
134           container.setAttributes(attr);
135         else
136           {
137         if (container.getAttributes()==attr)
138           { /* Move to end. */
139             container.setAttributes(attr.getNext());
140             attr.setNext(null);
141           }
142         last.setNext(attr);
143           }
144         last = attr;
145       }
146       }
147     return count;
148   }
149
150   public final void skipAttribute (int length)
151     throws IOException JavaDoc
152   {
153     int read = 0;
154     while (read < length)
155       {
156     int skipped = (int) skip(length - read);
157     if (skipped == 0)
158       {
159         if (read() < 0)
160           throw new java.io.EOFException JavaDoc
161         ("EOF while reading class files attributes");
162         skipped = 1;
163       }
164     read += skipped;
165       }
166   }
167
168   public Attribute readAttribute (String JavaDoc name, int length, AttrContainer container)
169     throws IOException JavaDoc
170   {
171     if (name == "SourceFile" && container instanceof ClassType)
172       {
173     return new SourceFileAttr(readUnsignedShort(), (ClassType) container);
174       }
175     else if (name == "Code" && container instanceof Method)
176       {
177         CodeAttr code = new CodeAttr((Method) container);
178     code.setMaxStack(readUnsignedShort());
179     code.setMaxLocals(readUnsignedShort());
180     int code_len = readInt();
181     byte[] insns = new byte[code_len];
182     readFully(insns);
183     code.setCode(insns);
184     int exception_table_length = readUnsignedShort();
185     for (int i = 0; i < exception_table_length; i++)
186       {
187         int start_pc = readUnsignedShort();
188         int end_pc = readUnsignedShort();
189         int handler_pc = readUnsignedShort();
190         int catch_type = readUnsignedShort();
191         code.addHandler(start_pc, end_pc, handler_pc, catch_type);
192       }
193     readAttributes(code);
194     return code;
195       }
196     else if (name == "LineNumberTable" && container instanceof CodeAttr)
197       {
198         int count = 2 * readUnsignedShort();
199     short[] numbers = new short[count];
200     for (int i = 0; i < count; i++)
201       {
202         numbers[i] = readShort();
203       }
204     return new LineNumbersAttr(numbers, (CodeAttr) container);
205       }
206     else if (name == "LocalVariableTable" && container instanceof CodeAttr)
207       {
208     CodeAttr code = (CodeAttr) container;
209     LocalVarsAttr attr = new LocalVarsAttr(code);
210     Method method = attr.getMethod();
211     if (attr.parameter_scope == null)
212       attr.parameter_scope = method.pushScope();
213     Scope scope = attr.parameter_scope;
214     if (scope.end == null)
215       scope.end = new Label(code.PC);
216     ConstantPool constants = method.getConstants();
217         int count = readUnsignedShort();
218     int prev_start = scope.start.position;
219     int prev_end = scope.end.position;
220     for (int i = 0; i < count; i++)
221       {
222         Variable var = new Variable();
223         int start_pc = readUnsignedShort();
224         int end_pc = start_pc + readUnsignedShort();
225
226         if (start_pc != prev_start || end_pc != prev_end)
227           {
228         while (scope.parent != null
229                && (start_pc < scope.start.position
230                || end_pc > scope.end.position))
231           scope = scope.parent;
232         Scope parent = scope;
233         scope = new Scope(new Label(start_pc), new Label(end_pc));
234         scope.linkChild(parent);
235         prev_start = start_pc;
236         prev_end = end_pc;
237           }
238         scope.addVariable(var);
239         var.setName(readUnsignedShort(), constants);
240         var.setSignature(readUnsignedShort(), constants);
241         var.offset = readUnsignedShort();
242       }
243     return attr;
244       }
245     else if (name == "ConstantValue" && container instanceof Field)
246       {
247     return new ConstantValueAttr(readUnsignedShort());
248       }
249     else if (name == "InnerClasses" && container instanceof ClassType)
250       {
251         int count = 4 * readUnsignedShort();
252     short[] data = new short[count];
253     for (int i = 0; i < count; i++)
254       {
255         data[i] = readShort();
256       }
257     return new InnerClassesAttr(data, (ClassType) container);
258      }
259     else if (name == "Exceptions" && container instanceof Method)
260       {
261     Method meth = (Method)container;
262     int count = readUnsignedShort();
263         short[] exn_indices = new short[count];
264     for (int i = 0; i < count; ++i)
265       exn_indices[i] = readShort();
266         meth.setExceptions(exn_indices);
267     return meth.getExceptionAttr();
268       }
269     else if (name == "SourceDebugExtension" && container instanceof ClassType)
270       {
271     SourceDebugExtAttr attr
272       = new SourceDebugExtAttr((ClassType) container);
273     byte[] data = new byte[length];
274     readFully(data, 0, length);
275     attr.data = data;
276     attr.dlength = length;
277     return attr;
278       }
279     else
280       {
281     byte[] data = new byte[length];
282     readFully(data, 0, length);
283     return new MiscAttr(name, data);
284       }
285   }
286
287   public void readFields () throws IOException JavaDoc
288   {
289     int nFields = readUnsignedShort();
290     ConstantPool constants = ctype.constants;
291     for (int i = 0; i < nFields; i++)
292       {
293     int flags = readUnsignedShort();
294     int nameIndex = readUnsignedShort();
295     int descriptorIndex = readUnsignedShort();
296     Field fld = ctype.addField();
297     fld.setName(nameIndex, constants);
298     fld.setSignature(descriptorIndex, constants);
299     fld.flags = flags;
300     readAttributes(fld);
301       }
302   }
303
304   public void readMethods () throws IOException JavaDoc
305   {
306     int nMethods = readUnsignedShort();
307     for (int i = 0; i < nMethods; i++)
308       {
309     int flags = readUnsignedShort();
310     int nameIndex = readUnsignedShort();
311     int descriptorIndex = readUnsignedShort();
312     Method meth = ctype.addMethod(null, flags);
313     meth.setName(nameIndex);
314     meth.setSignature(descriptorIndex);
315     readAttributes(meth);
316       }
317   }
318 }
319
Popular Tags