KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > classfile > ClassFile


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24
25 package com.sun.jdo.api.persistence.enhancer.classfile;
26
27 import java.util.ArrayList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Vector JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.io.*;
32 import java.io.DataOutputStream JavaDoc;
33
34
35 /**
36  * ClassFile models the structure of a class as represented within
37  * a class file.
38  */

39
40 final public class ClassFile implements VMConstants, Serializable {
41
42   /* Class file constants */
43   public static final int magic = 0xcafebabe;
44
45   //@olsen: added more flexible version checking.
46
public static final short[][] jdkMajorMinorVersions = new short[][]{
47     new short[]{45, 3}, // jdk 1.1
48
new short[]{46, 0}, // jdk 1.2
49
new short[]{47, 0}, // jdk 1.3
50
new short[]{48, 0}, // jdk 1.4
51
new short[]{49, 0} // jdk 1.5
52
};
53   public static final List JavaDoc jdkVersions =
54     convertMajorMinorVersions(jdkMajorMinorVersions);
55   public static final String JavaDoc supportedVersions = printSupportedVersions();
56
57   private int majorVersion = 0;
58   private int minorVersion = 0;
59
60   /* The constant pool for the class file */
61   private ConstantPool constantPool = new ConstantPool();
62
63   /* access flag bit mask - see VMConstants */
64   private int accessFlags = 0;
65
66   /* The name of the class */
67   private ConstClass thisClassName;
68
69   /* The name of the super class */
70   private ConstClass superClassName;
71
72   /* A list of the interfaces which the class implements
73    * The contents are ConstClass objects
74    */

75   private Vector JavaDoc classInterfaces = new Vector JavaDoc();
76
77   /* A list of the fields which the class contains
78    * The contents are ClassField objects
79    */

80   private Vector JavaDoc classFields = new Vector JavaDoc();
81
82   /* A list of the methods which the class defines
83    * The contents are ClassMethod objects
84    */

85   private Vector JavaDoc classMethods = new Vector JavaDoc();
86
87   /* A list of the attributes associated with the class */
88   private AttributeVector classAttributes = new AttributeVector();
89
90
91
92   /* public accessors */
93
94
95
96   /**
97    * Return the constant pool for the class file
98    */

99   public ConstantPool pool() {
100     return constantPool;
101   }
102
103   /**
104    * Return the access flags for the class - see VMConstants
105    */

106   public int access() {
107     return accessFlags;
108   }
109
110   /**
111    * Is the class final?
112    */

113   final public boolean isFinal() {
114     return (accessFlags & ACCFinal) != 0;
115   }
116
117   /**
118    * Is the class an interface?
119    */

120   final public boolean isInterface() {
121     return (accessFlags & ACCInterface) != 0;
122   }
123
124   /**
125    * Is the class public?
126    */

127   final public boolean isPublic() {
128     return (accessFlags & ACCPublic) != 0;
129   }
130
131   /**
132    * Is the class abstract?
133    */

134   final public boolean isAbstract() {
135     return (accessFlags & ACCAbstract) != 0;
136   }
137
138
139   /**
140    * Set the access flags for the class - see VMConstants
141    */

142   public void setAccessFlags (int flags) {
143     accessFlags = flags;
144   }
145
146   /**
147    * Return the name of the class
148    */

149   public ConstClass className() {
150     return thisClassName;
151   }
152
153   /**
154    * Return the name of the super class
155    */

156   public ConstClass superName() {
157     return superClassName;
158   }
159
160   /**
161    * Return the name of the super class as a string
162    */

163   public String JavaDoc superNameString() {
164     return (superClassName == null) ? null : superClassName.asString();
165   }
166
167   /**
168    * Set the name of the super class
169    */

170   public void setSuperName(ConstClass superCl) {
171     superClassName = superCl;
172   }
173
174   /**
175    * Return the list of the interfaces which the class implements
176    * The contents are ConstClass objects
177    */

178   public Vector JavaDoc interfaces() {
179     return classInterfaces;
180   }
181
182   /**
183    * Add an interface to the list of the interfaces which the class implements
184    */

185   public void addInterface (ConstClass iface) {
186     classInterfaces.addElement(iface);
187   }
188
189   /**
190    * Return the list of the fields which the class contains
191    * The contents are ClassField objects
192    */

193   public Vector JavaDoc fields() {
194     return classFields;
195   }
196
197   /**
198    * Add a field to the list of the fields which the class contains
199    */

200   public void addField (ClassField field) {
201     classFields.addElement(field);
202   }
203
204   /**
205    * Add a field to the list of the fields which the class contains,
206    * at the index'th position.
207    */

208   public void addField(ClassField field, int index) {
209     classFields.insertElementAt(field, index);
210   }
211
212   /**
213    * Return the list of the methods which the class defines
214    * The contents are ClassMethod objects
215    */

216   public Vector JavaDoc methods() {
217     return classMethods;
218   }
219
220   /**
221    * Look for a method with the specified name and type signature
222    */

223   public ClassMethod findMethod(String JavaDoc methodName, String JavaDoc methodSig) {
224     for (Enumeration JavaDoc e = methods().elements(); e.hasMoreElements();) {
225       ClassMethod method = (ClassMethod) e.nextElement();
226       if (method.name().asString().equals(methodName) &&
227       method.signature().asString().equals(methodSig))
228     return method;
229     }
230     return null;
231   }
232
233   /**
234    * Add a method to the list of the methods which the class defines
235    */

236   public void addMethod(ClassMethod method) {
237     classMethods.addElement(method);
238   }
239
240   /**
241    * Look for a field with the specified name
242    */

243   public ClassField findField(String JavaDoc fieldName) {
244     for (Enumeration JavaDoc e = fields().elements(); e.hasMoreElements();) {
245       ClassField field = (ClassField) e.nextElement();
246       if (field.name().asString().equals(fieldName))
247     return field;
248     }
249     return null;
250   }
251
252   /**
253    * Return the list of the attributes associated with the class
254    */

255   public AttributeVector attributes() {
256     return classAttributes;
257   }
258
259   /**
260    * Construct a ClassFile from an input stream
261    */

262   public ClassFile(DataInputStream data) throws ClassFormatError JavaDoc {
263     try {
264       int thisMagic = data.readInt();
265       if (thisMagic != magic)
266         throw new ClassFormatError JavaDoc("Bad magic value for input");//NOI18N
267

268       short thisMinorVersion = data.readShort();
269       short thisMajorVersion = data.readShort();
270       //@olsen: changed checking only target 1.1 and 1.2 to more
271
//general check for a list of versions.
272

273       if (isSupportedVersion(thisMajorVersion, thisMinorVersion)) {
274          minorVersion = thisMinorVersion;
275          majorVersion = thisMajorVersion;
276       } else {
277         throw new ClassFormatError JavaDoc("Bad version number: {" + //NOI18N
278
thisMajorVersion + "," + //NOI18N
279
thisMinorVersion +
280                   "} expected one of: " + //NOI18N
281
supportedVersions);
282       }
283       readConstants(data);
284       accessFlags = data.readUnsignedShort();
285       thisClassName = (ConstClass)
286       constantPool.constantAt(data.readUnsignedShort());
287       superClassName = (ConstClass)
288       constantPool.constantAt(data.readUnsignedShort());
289       readInterfaces(data);
290       readFields(data);
291       readMethods(data);
292       classAttributes = AttributeVector.readAttributes(data, constantPool);
293     } catch (IOException e) {
294       ClassFormatError JavaDoc cfe = new ClassFormatError JavaDoc("IOException during reading");//NOI18N
295
cfe.initCause(e);
296       throw cfe;
297     }
298     //@olsen: added println() for debugging
299
//System.out.println("ClassFile(): new class = " + thisClassName.asString());
300
}
301
302   /**
303    * Construct a bare bones class, ready for additions
304    */

305   public ClassFile(String JavaDoc cname, String JavaDoc supername) {
306     thisClassName = constantPool.addClass(cname);
307     superClassName = constantPool.addClass(supername);
308     //@olsen: added println() for debugging
309
//System.out.println("ClassFile(): new bare class file = " + thisClassName);
310
}
311
312   /**
313    * Write the Class file to the data output stream
314    */

315   public
316   void write (DataOutputStream JavaDoc buff) throws IOException {
317     buff.writeInt(magic);
318     buff.writeShort(minorVersion);
319     buff.writeShort(majorVersion);
320     constantPool.write(buff);
321     buff.writeShort(accessFlags);
322     buff.writeShort(thisClassName.getIndex());
323     //@lars: superclass may be null (java.lang.Object); VMSpec 2nd ed., section 4.1
324
buff.writeShort(superClassName == null ? 0 : superClassName.getIndex());
325 // buff.writeShort(superClassName.getIndex());
326
writeInterfaces(buff);
327     writeFields(buff);
328     writeMethods(buff);
329     classAttributes.write(buff);
330   }
331
332   /**
333    * Returns a byte array representation of this class.
334    */

335   public byte[] getBytes() throws java.io.IOException JavaDoc {
336     /* Write the class bytes to a file, for debugging. */
337
338     String JavaDoc writeClassToDirectory =
339       System.getProperty("filter.writeClassToDirectory");
340     if (writeClassToDirectory != null) {
341       String JavaDoc filename = writeClassToDirectory + java.io.File.separator +
342           thisClassName.asString() + ".class";//NOI18N
343
System.err.println("Writing class to file " + filename);
344       DataOutputStream JavaDoc stream = new DataOutputStream JavaDoc(
345       new java.io.FileOutputStream JavaDoc(filename));
346       write(stream);
347       stream.close();
348     }
349
350     /* Get the class bytes and return them. */
351
352     ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
353     write(new DataOutputStream JavaDoc(byteStream));
354
355     return byteStream.toByteArray();
356   }
357
358
359
360   /* package local methods */
361
362   public void print (PrintStream out) {
363     constantPool.print(out);
364     out.println();
365
366     out.println("majorVersion = " + Integer.toString(majorVersion));//NOI18N
367
out.println("minorVersion = " + Integer.toString(minorVersion));//NOI18N
368
out.println("accessFlags = " + Integer.toString(accessFlags));//NOI18N
369
out.println("className = " + thisClassName.asString());//NOI18N
370
out.println("superClassName = " + superClassName.asString());//NOI18N
371
out.print("Interfaces =");//NOI18N
372
for (int i=0; i<classInterfaces.size(); i++) {
373         out.print(" " + ((ConstClass) classInterfaces.elementAt(i)).asString());//NOI18N
374
}
375     out.println();
376
377     out.println("fields =");//NOI18N
378
for (int i=0; i<classFields.size(); i++) {
379       ((ClassField) classFields.elementAt(i)).print(out, 3);
380     }
381
382     out.println("methods =");//NOI18N
383
for (int i=0; i<classMethods.size(); i++) {
384       ((ClassMethod) classMethods.elementAt(i)).print(out, 3);
385     }
386
387     out.println("attributes =");//NOI18N
388
classAttributes.print(out, 3);
389
390   }
391
392   public void summarize () {
393     PrintStream os = System.out;
394
395     constantPool.summarize();
396     int codeSize = 0;
397     for (int i=0; i<classMethods.size(); i++) {
398       codeSize += ((ClassMethod) classMethods.elementAt(i)).codeSize();
399     }
400     System.out.println(classMethods.size() + " methods in " + codeSize + " bytes");//NOI18N
401
}
402
403   /*
404    * class file reading helpers
405    */

406   private void readConstants (DataInputStream data) throws IOException {
407     constantPool = new ConstantPool(data);
408   }
409
410   private void readInterfaces(DataInputStream data) throws IOException {
411     int nInterfaces = data.readUnsignedShort();
412     while (nInterfaces-- > 0) {
413       int interfaceIndex = data.readUnsignedShort();
414       ConstClass ci = null;
415       if (interfaceIndex != 0)
416     ci = (ConstClass) constantPool.constantAt(interfaceIndex);
417       classInterfaces.addElement(ci);
418     }
419   }
420
421   private void writeInterfaces(DataOutputStream JavaDoc data) throws IOException {
422     data.writeShort(classInterfaces.size());
423     for (int i=0; i<classInterfaces.size(); i++) {
424       ConstClass ci = (ConstClass) classInterfaces.elementAt(i);
425       int interfaceIndex = 0;
426       if (ci != null)
427     interfaceIndex = ci.getIndex();
428       data.writeShort(interfaceIndex);
429     }
430   }
431
432   private void readFields(DataInputStream data) throws IOException {
433     int nFields = data.readUnsignedShort();
434     while (nFields-- > 0) {
435       classFields.addElement (ClassField.read(data, constantPool));
436     }
437   }
438
439   private void writeFields (DataOutputStream JavaDoc data) throws IOException {
440     data.writeShort(classFields.size());
441     for (int i=0; i<classFields.size(); i++)
442       ((ClassField)classFields.elementAt(i)).write(data);
443   }
444
445   private void readMethods (DataInputStream data) throws IOException {
446     int nMethods = data.readUnsignedShort();
447     while (nMethods-- > 0) {
448       classMethods.addElement (ClassMethod.read(data, constantPool));
449     }
450   }
451
452   private void writeMethods (DataOutputStream JavaDoc data) throws IOException {
453     data.writeShort(classMethods.size());
454     for (int i=0; i<classMethods.size(); i++)
455       ((ClassMethod)classMethods.elementAt(i)).write(data);
456   }
457
458
459     //@olsen: Static methods added for major.minor compatibility checking
460
private static List JavaDoc convertMajorMinorVersions(short[][] majorMinor) {
461       int length = majorMinor.length;
462       List JavaDoc result = new ArrayList JavaDoc(length);
463       for (int i = 0; i < length; i++) {
464         result.add(getVersionInt(majorMinor[i][0], majorMinor[i][1]));
465       }
466       return result;
467     }
468
469     private static boolean isSupportedVersion(short major, short minor) {
470       Integer JavaDoc version = getVersionInt(major, minor);
471       return jdkVersions.contains(version);
472     }
473
474     private static Integer JavaDoc getVersionInt(short major, short minor) {
475         return new Integer JavaDoc(major * 65536 + minor);
476     }
477
478     public static final String JavaDoc printSupportedVersions() {
479       StringBuffer JavaDoc buf = new StringBuffer JavaDoc("{"); //NOI18N
480
int length = jdkMajorMinorVersions.length;
481       for (int i = 0; i < length; i++) {
482         int major = jdkMajorMinorVersions[i][0];
483         int minor = jdkMajorMinorVersions[i][1];
484         buf.append("{"); //NOI18N
485
buf.append(major);
486         buf.append(","); //NOI18N
487
buf.append(minor);
488         buf.append("}"); //NOI18N
489
}
490         buf.append("}"); //NOI18N
491
return buf.toString();
492     }
493
494 }
495
496 abstract class ArraySorter {
497   protected ArraySorter() {}
498
499   /* return the size of the array being sorted */
500   abstract int size();
501
502   /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
503   abstract int compare(int o1Index, int o2Index);
504
505   /* Swap the elements at index o1Index and o2Index */
506   abstract void swap(int o1Index, int o2Index);
507
508   void sortArray() {
509     sortArray(0, size()-1);
510   }
511
512   private void sortArray(int start, int end) {
513     if (end > start) {
514       swap(start, (start+end)/2);
515       int last = start;
516       for (int i = start+1; i<=end; i++) {
517     if (compare(i, start) < 0)
518       swap (++last, i);
519       }
520       swap(start, last);
521       sortArray(start, last-1);
522       sortArray(last+1, end);
523     }
524   }
525 }
526
527 class InterfaceArraySorter extends ArraySorter {
528   private ConstClass theArray[];
529
530   InterfaceArraySorter(ConstClass[] interfaces) {
531     theArray = interfaces;
532   }
533
534   /* return the size of the array being sorted */
535   int size() { return theArray.length; }
536
537   /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
538   int compare(int o1Index, int o2Index) {
539     return theArray[o1Index].asString().compareTo(
540     theArray[o2Index].asString());
541   }
542
543   /* Swap the elements at index o1Index and o2Index */
544   void swap(int o1Index, int o2Index) {
545     ConstClass tmp = theArray[o1Index];
546     theArray[o1Index] = theArray[o2Index];
547     theArray[o2Index] = tmp;
548   }
549 }
550
551 class FieldArraySorter extends ArraySorter {
552   private ClassField theArray[];
553
554   FieldArraySorter(ClassField[] fields) {
555     theArray = fields;
556   }
557
558   /* return the size of the array being sorted */
559   int size() { return theArray.length; }
560
561   /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
562   int compare(int o1Index, int o2Index) {
563     return theArray[o1Index].name().asString().compareTo(
564     theArray[o2Index].name().asString());
565   }
566
567   /* Swap the elements at index o1Index and o2Index */
568   void swap(int o1Index, int o2Index) {
569     ClassField tmp = theArray[o1Index];
570     theArray[o1Index] = theArray[o2Index];
571     theArray[o2Index] = tmp;
572   }
573 }
574
575 class MethodArraySorter extends ArraySorter {
576   private ClassMethod theArray[];
577
578   MethodArraySorter(ClassMethod[] methods) {
579     theArray = methods;
580   }
581
582   /* return the size of the array being sorted */
583   int size() { return theArray.length; }
584
585   /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
586   int compare(int o1Index, int o2Index) {
587     int cmp = theArray[o1Index].name().asString().compareTo(
588     theArray[o2Index].name().asString());
589     if (cmp == 0) {
590       cmp = theArray[o1Index].signature().asString().compareTo(
591     theArray[o2Index].signature().asString());
592     }
593     return cmp;
594   }
595
596   /* Swap the elements at index o1Index and o2Index */
597   void swap(int o1Index, int o2Index) {
598     ClassMethod tmp = theArray[o1Index];
599     theArray[o1Index] = theArray[o2Index];
600     theArray[o2Index] = tmp;
601   }
602
603
604 }
605
606
Popular Tags