Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/chaoswg/xtc4y/classdesc/ClassDescriptor.java


1   //$Header: /cvsroot/xtc4y/xtc4y/src/com/chaoswg/xtc4y/classdesc/ClassDescriptor.java,v 1.2 2003/08/25 10:50:14 toggm Exp $
2   /******************************************************************************
3    * XTC4y - eXtreme Testing Collection 4 you                                   *
4    * -------------------------------------------------------------------------- *
5    * URL: http://www.chaoswg.com/xtc4y                                          *
6    * Author: Mike Toggweiler (2.dog@gmx.ch)                                     *
7    *                                                                            *
8    * Last Updated: $Date: 2003/08/25 10:50:14 $, by $Author: toggm $            *
9    * Version: $Revision: 1.2 $                                                  *
10   * -------------------------------------------------------------------------- *
11   * COPYRIGHT:   (c) 2003 by Mike Toggweiler                                   *
12   *                                                                            *
13   * This program is free software; you can redistribute it and/or modify       *
14   * it under the terms of the GNU General Public License as published by       *
15   * the Free Software Foundation; either version 2 of the License, or          *
16   * (at your option) any later version.                                        *
17   *****************************************************************************/
18  package com.chaoswg.xtc4y.classdesc;
19  
20  import java.util.Vector;
21  
22  import java.io.ByteArrayOutputStream;
23  import java.io.DataInputStream;
24  import java.io.DataOutputStream;
25  import java.io.IOException;
26  
27  /**
28   * This container class represents the content of a class file in a readable 
29   * and reditable way.
30   * For further informations about the java class fiel format, see the 
31   * <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html">Java Virtual Machine Specification</a> §4. All mentioned references 
32   * refere to the chapters and subchapters in this book.
33   * @author Mike Toggweiler
34   **/
35  public class ClassDescriptor {
36      /**
37       * Every class has to begin with this magic number
38       **/
39      public final static int MAGIC_NUMBER = 0xCAFEBABE;
40  
41      private short minorVersion;
42      private short majorVersion;
43      private ClassAccessFlags classAccess;
44      private ClassCPEntry thisClass; 
45      private ClassCPEntry superClass; 
46      private Vector interfaces; 
47      private Vector fields;
48      private Vector methods;
49      private Vector attributes;
50  
51      /**
52       * Construct a new initial classDescriptor
53       **/
54      public ClassDescriptor() {
55    reset();  
56      }
57  
58      /**
59       * Construct a new ClassDescriptor and intialize it reading from a 
60       * DataInputstream
61       * @param dis the DataInputStream to read from
62       **/
63      public ClassDescriptor(DataInputStream dis) throws IOException {
64    initialize(dis);
65      }
66  
67      /**
68       * reset all variables to default values
69       **/
70      protected void reset() {
71    //initialise default values
72    minorVersion = 0;
73    majorVersion = 46;  
74    classAccess = new ClassAccessFlags((short)0);
75    thisClass = null;
76    superClass = null;
77    interfaces = new Vector();
78    fields = new Vector();
79    methods = new Vector();
80    attributes = new Vector();
81      }
82  
83      /**
84       * Initialize a ClassDescriptor by reading from a DataInputStream
85       * @param dis DataInputStream to read from
86       **/
87      public void initialize(DataInputStream dis) throws IOException {
88    reset();
89    //read the magic number
90    int magic = dis.readInt();
91    if (magic != MAGIC_NUMBER) {
92        throw new ClassFormatError("Magic number mismatch");
93    }
94    
95    //minor
96    minorVersion = (short)dis.readUnsignedShort();
97    //major
98    majorVersion = (short)dis.readUnsignedShort();
99  
100   //initialize constant pool
101   ConstantPool constantPool = new ConstantPool(dis);  
102   
103   //access_flags
104   classAccess = new ClassAccessFlags(dis);
105   
106   //this_class
107   short classIndex = (short)dis.readUnsignedShort();
108   thisClass = (ClassCPEntry)constantPool.getCPEntryAt(classIndex);
109   constantPool.setThisClass(thisClass);
110   //super_class
111   short superIndex = (short)dis.readUnsignedShort(); 
112   if (superIndex != 0) {
113       superClass = 
114     (ClassCPEntry)constantPool.getCPEntryAt(superIndex);
115   }
116   else {
117       superClass = null;
118   }
119   
120   //interface_count
121   int ifCount = dis.readUnsignedShort();
122   //interfaces[interface_count]      
123   interfaces.clear();
124   for (int i=0; i<ifCount; ++i) {      
125       //interface
126       interfaces.add(new InterfaceInfo(dis, constantPool));
127   }
128   
129   //fields_count
130   int fCount = dis.readUnsignedShort();
131   fields.clear();
132   //field_info[fields_count]
133   for (int i=0; i<fCount; ++i) {
134       //field_info
135       fields.add(new FieldInfo(dis, constantPool));
136   }  
137   
138   //methods_count
139   int mCount = dis.readUnsignedShort();
140   methods.clear();
141   //methods[methods_count]
142   for (int i=0; i<mCount; ++i) {
143       //method
144       methods.add(new MethodInfo(dis, constantPool));
145   }
146 
147   //attributes_count
148   int aCount = dis.readUnsignedShort();
149   attributes.clear();
150   //attributes[attributes_count]
151   for (int i=0; i<aCount; ++i) {
152       attributes.add(new AttributeInfo(dis, constantPool));
153   }  
154     }
155 
156     /**
157      * Print the class onto a DataOutputStream
158      * @param dos the DataOutputStream to write on
159      **/
160     public void writeClass(DataOutputStream dos) throws IOException {
161   //magic_number
162   dos.writeInt(MAGIC_NUMBER);  
163   //minor
164   dos.writeShort(minorVersion);
165   //major
166   dos.writeShort(majorVersion);
167 
168   ConstantPool cp = new ConstantPool();
169   ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
170   DataOutputStream dos2 = new DataOutputStream(baos2);
171   ByteArrayOutputStream baos3 = new ByteArrayOutputStream();
172   DataOutputStream dos3 = new DataOutputStream(baos3);
173   cp.setThisClass(thisClass);
174 
175   //let all register their variables and print on a dummy stream
176   //access_flags
177   classAccess.write(dos2);
178   
179   //this_class
180   dos2.writeShort(cp.addCPEntry(thisClass));
181   //super_class
182   if (superClass != null) {
183       dos2.writeShort(cp.addCPEntry(superClass));
184   }
185   else {
186       dos2.writeShort((short)0);
187   }
188   
189   //interface_count
190   dos2.writeShort(interfaces.size());
191   //interfaces[interface_count]      
192   for (int i=0; i<interfaces.size(); ++i) {      
193       //interface
194       ((InterfaceInfo)interfaces.elementAt(i)).write(dos2, cp);
195   }
196   
197   //fields_count       
198   dos2.writeShort(fields.size());
199   //field_info[fields_count]
200   for (int i=0; i<fields.size(); ++i) {
201       //field_info
202       ((FieldInfo)fields.elementAt(i)).write(dos2, cp);
203   }
204   //methods_count
205   dos2.writeShort(methods.size());
206   //methods[methods_count]
207   for (int i=0; i<methods.size(); ++i) {
208       //method
209       ((MethodInfo)methods.elementAt(i)).write(dos2, cp);
210   }
211 
212   //attributes_count
213   dos2.writeShort(attributes.size());
214   //attributes[attributes_count]
215   for (int i=0; i<attributes.size(); ++i) {
216       ((AttributeInfo)attributes.elementAt(i)).write(dos2, cp);
217   }
218   
219   //print out constant pool
220   cp.write(dos3);
221   //print out size of constant pool + 1
222   dos.writeShort(cp.getSize()+1);
223   
224   //print out constant pool
225   byte[] constantPool = baos3.toByteArray();
226   dos.write(constantPool);  
227   //print out previously created code  
228   dos.write(baos2.toByteArray());  
229     
230   dos2.close();
231   baos2.close();
232   dos3.close();
233   baos3.close();
234     }
235 
236     /**
237      * Set the minor version
238      * @param minor version to set
239      **/
240     public void setMinorVersion(short minor) {
241   minorVersion = minor;
242     }
243 
244     /**
245      * @return the minor version
246      **/
247     public short getMinorVersion() {
248   return minorVersion;
249     }
250 
251     /**
252      * Set the major version
253      * @param major version to set
254      **/
255     public void setMajorVersion(short major) {
256   majorVersion = major;
257     }
258 
259     /**
260      * @return the major version
261      **/
262     public short getMajorVersion() {
263   return majorVersion;
264     }
265     
266     /**
267      * set the classAccessFlag
268      **/
269     public void setClassAccess(ClassAccessFlags flags) {
270   classAccess = flags;
271     }
272 
273     /**
274      * @return the classAccessFlag
275      **/
276     public ClassAccessFlags getClassAccessFlags() {
277   return classAccess;
278     }
279 
280     /**
281      * Set the class
282      * @param cl the class cp entry representing this class
283      **/
284     public void setThisClass(ClassCPEntry cl) {
285   thisClass = cl;
286     }
287 
288     /**
289      * @return the classCP Entry for this class
290      **/
291     public ClassCPEntry getThisClass() {
292   return thisClass;
293     }
294 
295     /**
296      * Set the super class, null if no super class is present
297      * @param cl a class cp entry representing the super class
298      **/
299     public void setSuperClass(ClassCPEntry cl) {
300   superClass = cl;
301     }
302 
303     /**
304      * @return the super class or null if no class is present
305      **/
306     public ClassCPEntry getSuperClass() {
307   return superClass;
308     }
309 
310     /**
311      * Add an interface
312      * @param ifc an InterfaceInfo describing the direct super interface 
313      **/
314     public void addInterface(InterfaceInfo ifc) {
315   interfaces.add(ifc);
316     }
317     /**
318      * @return an array of InterfaceInfos representing the direct super 
319      * interfaces
320      **/
321     public InterfaceInfo[] getInterfaces() {
322   return ((InterfaceInfo[])
323     interfaces.toArray(new InterfaceInfo[interfaces.size()]));
324     }
325 
326     /**
327      * Remove an interface 
328      * @param ifc the interface to remove
329      **/
330     public void removeInterface(InterfaceInfo ifc) {
331   interfaces.remove(ifc);
332     }
333 
334     /**
335      * Add a field to this class
336      * @param field the field to add
337      **/
338     public void addField(FieldInfo field) {
339   //TBD: check if field is not already defined (define equals method
340   //in the FieldInfo class and check against contains)
341   fields.add(field);
342     }
343 
344     /**
345      * @return an array of Fields currently defined in this class
346      **/
347     public FieldInfo[] getFields() {
348   return ((FieldInfo[])fields.toArray(new FieldInfo[fields.size()]));
349     }
350 
351     /**
352      * Remove a Field from the current class
353      * @param field the FieldInfo to remove
354      **/
355     public void removeField(FieldInfo field) {
356   fields.remove(field);
357     }
358 
359     /**
360      * Add a method to this class
361      * @param method the method to add
362      **/
363     public void addMethod(MethodInfo method) {
364   methods.add(method);
365     }
366 
367     /**
368      * @return an array of Methods currently defined in this class
369      **/
370     public MethodInfo[] getMethods() {
371   return ((MethodInfo[])methods.toArray(new MethodInfo[methods.size()]));
372     }
373 
374     /**
375      * Remove a Method from the current class
376      * @param method the MethodInfo to remove
377      **/
378     public void removeMethod(MethodInfo method) {
379   methods.remove(method);
380     }
381 
382     /**
383      * Add an attribute to this class
384      * @param attribute the attribute to add
385      **/
386     public void addAttribute(AttributeInfo attribute) {
387   attributes.add(attribute);
388     }
389 
390     /**
391      * @return an array of Attributes currently defined in this class
392      **/
393     public AttributeInfo[] getAttributes() {
394   return 
395       ((AttributeInfo[])
396        attributes.toArray(new AttributeInfo[attributes.size()]));
397     }
398 
399     /**
400      * Remove an attribute from the current class
401      * @param attribute the AttributeInfo to remove
402      **/
403     public void removeAttribute(AttributeInfo attribute) {
404   attributes.remove(attribute);
405     }
406 
407     /**
408      * Print the class descriptor in a readable way
409      **/
410     public String toString() {
411   String ret = "";
412   ret += "Minor: " + minorVersion + "\n";
413   ret += "Major: " + majorVersion + "\n";
414   ret += "ClassAccessFlag: " + classAccess + "\n";
415   ret += "ThisClass:" + thisClass + "\n";  
416   ret += "SuperClass:" + superClass + "\n"; 
417   ret += "Interfaces:\n";
418   for (int i=0; i<interfaces.size(); ++i) {
419       ret += "    " + i + " " + interfaces.elementAt(i) + "\n";
420   }
421   ret += "Fields:\n";
422   for (int i=0; i<fields.size(); ++i) {
423       ret += "    " + i + " " + fields.elementAt(i) + "\n";
424   }
425   ret += "Methods:\n";
426   for (int i=0; i<methods.size(); ++i) {
427       ret += "    " + i + " " + methods.elementAt(i) + "\n";
428   }
429   ret += "Attributes:\n";
430   for (int i=0; i<attributes.size(); ++i) {
431       ret += "    " + i + " " + attributes.elementAt(i) + "\n";
432   }
433   return ret;
434     }
435 }