KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > bytecode > JavaClass


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.bytecode;
31
32 import com.caucho.vfs.ReadStream;
33 import com.caucho.vfs.Vfs;
34 import com.caucho.vfs.WriteStream;
35
36 import java.io.ByteArrayInputStream JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.InputStream JavaDoc;
39 import java.lang.reflect.Modifier JavaDoc;
40 import java.net.URL JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.logging.Level JavaDoc;
43 import java.util.logging.Logger JavaDoc;
44
45 /**
46  * Represents a java class.
47  */

48 public class JavaClass extends JClass {
49   static private final Logger JavaDoc log
50     = Logger.getLogger(JavaClass.class.getName());
51
52   public static final int MAGIC = 0xcafebabe;
53
54   public static final int ACC_PUBLIC = 0x0001;
55   public static final int ACC_PRIVATE = 0x0002;
56   public static final int ACC_PROTECTED = 0x0004;
57   public static final int ACC_STATIC = 0x0008;
58   public static final int ACC_FINAL = 0x0010;
59   public static final int ACC_SUPER = 0x0020;
60
61   private JavaClassLoader _loader;
62
63   private URL JavaDoc _url;
64
65   private int _major;
66   private int _minor;
67
68   private ConstantPool _constantPool = new ConstantPool();
69   
70   private int _accessFlags;
71
72   private String JavaDoc _thisClass;
73   private String JavaDoc _superClass;
74
75   private ArrayList JavaDoc<String JavaDoc> _interfaces = new ArrayList JavaDoc<String JavaDoc>();
76   
77   private ArrayList JavaDoc<JavaField> _fields = new ArrayList JavaDoc<JavaField>();
78   
79   private ArrayList JavaDoc<JavaMethod> _methods = new ArrayList JavaDoc<JavaMethod>();
80   
81   private ArrayList JavaDoc<Attribute> _attributes = new ArrayList JavaDoc<Attribute>();
82   
83   private JavaAnnotation []_annotations;
84
85   public JavaClass(JavaClassLoader loader)
86   {
87     if (loader == null)
88       throw new NullPointerException JavaDoc();
89     
90     _loader = loader;
91   }
92
93   /**
94    * Returns the loader.
95    */

96   public JavaClassLoader getClassLoader()
97   {
98     return _loader;
99   }
100
101   /**
102    * Sets the URL.
103    */

104   public void setURL(URL JavaDoc url)
105   {
106     _url = url;
107   }
108
109   /**
110    * Sets the major identifier of the class file.
111    */

112   public void setMajor(int major)
113   {
114     _major = major;
115   }
116
117   /**
118    * Gets the major identifier of the class file.
119    */

120   public int getMajor()
121   {
122     return _major;
123   }
124
125   /**
126    * Sets the minor identifier of the class file.
127    */

128   public void setMinor(int minor)
129   {
130     _minor = minor;
131   }
132
133   /**
134    * Gets the minor identifier of the class file.
135    */

136   public int getMinor()
137   {
138     return _minor;
139   }
140
141   /**
142    * Returns the class's constant pool.
143    */

144   public ConstantPool getConstantPool()
145   {
146     return _constantPool;
147   }
148
149   /**
150    * Sets the access flags.
151    */

152   public void setAccessFlags(int flags)
153   {
154     _accessFlags = flags;
155   }
156
157   /**
158    * Gets the access flags.
159    */

160   public int getAccessFlags()
161   {
162     lazyLoad();
163     
164     return _accessFlags;
165   }
166
167   /**
168    * Sets this class.
169    */

170   public void setThisClass(String JavaDoc className)
171   {
172     _thisClass = className;
173   }
174
175   /**
176    * Gets this class name.
177    */

178   public String JavaDoc getThisClass()
179   {
180     return _thisClass;
181   }
182
183   /**
184    * Sets the super class.
185    */

186   public void setSuperClass(String JavaDoc className)
187   {
188     _superClass = className;
189
190     getConstantPool().addClass(className);
191   }
192
193   /**
194    * Gets the super class name.
195    */

196   public String JavaDoc getSuperClassName()
197   {
198     lazyLoad();
199     
200     return _superClass;
201   }
202
203   /**
204    * Gets the super class name.
205    */

206   public JClass getSuperClass()
207   {
208     lazyLoad();
209     
210     if (_superClass == null)
211       return null;
212     else
213       return getClassLoader().forName(_superClass.replace('/', '.'));
214   }
215
216   /**
217    * Returns true for a final class.
218    */

219   public boolean isFinal()
220   {
221     return Modifier.isFinal(getAccessFlags());
222   }
223
224   /**
225    * Returns true for an abstract class.
226    */

227   public boolean isAbstract()
228   {
229     return Modifier.isAbstract(getAccessFlags());
230   }
231
232   /**
233    * Returns true for a public class.
234    */

235   public boolean isPublic()
236   {
237     return Modifier.isPublic(getAccessFlags());
238   }
239
240   /**
241    * Returns true for a primitive class.
242    */

243   public boolean isPrimitive()
244   {
245     return false;
246   }
247
248   /**
249    * Adds an interface.
250    */

251   public void addInterface(String JavaDoc className)
252   {
253     _interfaces.add(className);
254   }
255
256   /**
257    * Adds an interface.
258    */

259   public ArrayList JavaDoc<String JavaDoc> getInterfaceNames()
260   {
261     return _interfaces;
262   }
263
264   /**
265    * Gets the interfaces.
266    */

267   public JClass []getInterfaces()
268   {
269     lazyLoad();
270     
271     JClass []interfaces = new JClass[_interfaces.size()];
272
273     for (int i = 0; i < _interfaces.size(); i++) {
274       String JavaDoc name = _interfaces.get(i);
275       name = name.replace('/', '.');
276       
277       interfaces[i] = getClassLoader().forName(name);
278     }
279     
280     return interfaces;
281   }
282
283   /**
284    * Adds a field
285    */

286   public void addField(JavaField field)
287   {
288     _fields.add(field);
289   }
290
291   /**
292    * Returns the fields.
293    */

294   public ArrayList JavaDoc<JavaField> getFieldList()
295   {
296     lazyLoad();
297     
298     return _fields;
299   }
300
301   /**
302    * Returns a fields.
303    */

304   public JavaField getField(String JavaDoc name)
305   {
306     ArrayList JavaDoc<JavaField> fieldList = getFieldList();
307     
308     for (int i = 0; i < fieldList.size(); i++) {
309       JavaField field = fieldList.get(i);
310
311       if (field.getName().equals(name))
312     return field;
313     }
314
315     return null;
316   }
317
318   /**
319    * Adds a method
320    */

321   public void addMethod(JavaMethod method)
322   {
323     _methods.add(method);
324   }
325
326   /**
327    * Returns the methods.
328    */

329   public ArrayList JavaDoc<JavaMethod> getMethodList()
330   {
331     lazyLoad();
332     
333     return _methods;
334   }
335
336   /**
337    * Returns true for an array.
338    */

339   public boolean isArray()
340   {
341     return false;
342   }
343
344   /**
345    * Returns true for an interface.
346    */

347   public boolean isInterface()
348   {
349     lazyLoad();
350     
351     return Modifier.isInterface(_accessFlags);
352   }
353
354   /**
355    * Returns a method.
356    */

357   public JavaMethod getMethod(String JavaDoc name)
358   {
359     ArrayList JavaDoc<JavaMethod> methodList = getMethodList();
360     
361     for (int i = 0; i < methodList.size(); i++) {
362       JavaMethod method = methodList.get(i);
363
364       if (method.getName().equals(name))
365     return method;
366     }
367
368     return null;
369   }
370
371   /**
372    * Finds a method.
373    */

374   public JavaMethod findMethod(String JavaDoc name, String JavaDoc descriptor)
375   {
376     ArrayList JavaDoc<JavaMethod> methodList = getMethodList();
377     
378     for (int i = 0; i < methodList.size(); i++) {
379       JavaMethod method = methodList.get(i);
380
381       if (method.getName().equals(name) &&
382       method.getDescriptor().equals(descriptor))
383     return method;
384     }
385
386     return null;
387   }
388
389   /**
390    * Adds an attribute
391    */

392   public void addAttribute(Attribute attr)
393   {
394     _attributes.add(attr);
395
396     attr.addConstants(this);
397   }
398
399   /**
400    * Returns the methods.
401    */

402   public ArrayList JavaDoc<Attribute> getAttributeList()
403   {
404     lazyLoad();
405     
406     return _attributes;
407   }
408
409   /**
410    * Returns the attribute.
411    */

412   public Attribute getAttribute(String JavaDoc name)
413   {
414     ArrayList JavaDoc<Attribute> attributeList = getAttributeList();
415     
416     for (int i = attributeList.size() - 1; i >= 0; i--) {
417       Attribute attr = attributeList.get(i);
418
419       if (attr.getName().equals(name))
420     return attr;
421     }
422
423     return null;
424   }
425
426   //
427
// JClass methods.
428
//
429

430   /**
431    * Returns the class-equivalent name.
432    */

433   public String JavaDoc getName()
434   {
435     return getThisClass().replace('/', '.');
436   }
437   
438   /**
439    * Returns true if the class is assignable from the argument.
440    */

441   public boolean isAssignableFrom(JClass cl)
442   {
443     if (getName().equals(cl.getName()))
444       return true;
445
446     JClass []ifc = cl.getInterfaces();
447
448     for (int i = 0; i < ifc.length; i++) {
449       if (isAssignableFrom(ifc[i]))
450     return true;
451     }
452
453     if (cl.getSuperClass() != null)
454       return isAssignableFrom(cl.getSuperClass());
455     else
456       return false;
457   }
458   
459   /**
460    * Returns true if the class is assignable from the argument.
461    */

462   public boolean isAssignableFrom(Class JavaDoc cl)
463   {
464     if (getName().equals(cl.getName()))
465       return true;
466
467     Class JavaDoc []ifc = cl.getInterfaces();
468
469     for (int i = 0; i < ifc.length; i++) {
470       if (isAssignableFrom(ifc[i]))
471     return true;
472     }
473
474     if (cl.getSuperclass() != null)
475       return isAssignableFrom(cl.getSuperclass());
476     else
477       return false;
478   }
479   
480   /**
481    * Returns true if the class is assignable from the argument.
482    */

483   public boolean isAssignableTo(Class JavaDoc cl)
484   {
485     if (getName().equals(cl.getName()))
486       return true;
487
488     JClass []ifc = getInterfaces();
489
490     for (int i = 0; i < ifc.length; i++) {
491       if (ifc[i].isAssignableTo(cl))
492     return true;
493     }
494
495     if (getSuperClass() != null)
496       return getSuperClass().isAssignableTo(cl);
497     else
498       return false;
499   }
500   
501   /**
502    * Returns the array of declared methods.
503    */

504   public JMethod []getDeclaredMethods()
505   {
506     ArrayList JavaDoc<JavaMethod> methodList = getMethodList();
507     
508     JMethod[] methods = new JMethod[methodList.size()];
509
510     methodList.toArray(methods);
511
512     return methods;
513   }
514   
515   /**
516    * Returns the array of declared methods.
517    */

518   public JMethod []getConstructors()
519   {
520     ArrayList JavaDoc<JavaMethod> ctorList = new ArrayList JavaDoc<JavaMethod>();
521     
522     for (JavaMethod method : getMethodList()) {
523       if (method.getName().equals("<init>"))
524     ctorList.add(method);
525     }
526     
527     JMethod[] methods = new JMethod[ctorList.size()];
528
529     ctorList.toArray(methods);
530
531     return methods;
532   }
533   
534   /**
535    * Returns the matching method
536    */

537   public JMethod getMethod(String JavaDoc name, JClass []paramTypes)
538   {
539     loop:
540     for (JMethod method : getMethods()) {
541       if (! method.getName().equals(name))
542     continue;
543
544       JClass []mParamTypes = method.getParameterTypes();
545       if (mParamTypes.length != paramTypes.length)
546     continue;
547
548       for (int i = 0; i < paramTypes.length; i++) {
549     if (! paramTypes[i].getName().equals(mParamTypes[i].getName()))
550       continue loop;
551       }
552
553
554       return method;
555     }
556
557     return null;
558   }
559   
560   /**
561    * Returns the matching method
562    */

563   public JMethod []getMethods()
564   {
565     ArrayList JavaDoc<JMethod> methodList = new ArrayList JavaDoc<JMethod>();
566
567     getMethods(methodList);
568
569     JMethod []methods = new JMethod[methodList.size()];
570     methodList.toArray(methods);
571
572     return methods;
573   }
574   
575   /**
576    * Returns the matching method
577    */

578   private void getMethods(ArrayList JavaDoc<JMethod> methodList)
579   {
580     for (JMethod method : getDeclaredMethods()) {
581       if (! methodList.contains(method))
582     methodList.add(method);
583     }
584
585     if (getSuperClass() != null) {
586       for (JMethod method : getSuperClass().getMethods()) {
587     if (! methodList.contains(method))
588       methodList.add(method);
589       }
590     }
591   }
592   
593   /**
594    * Returns the array of declared fields.
595    */

596   public JField []getDeclaredFields()
597   {
598     ArrayList JavaDoc<JavaField> fieldList = getFieldList();
599     
600     JField[] fields = new JField[fieldList.size()];
601
602     fieldList.toArray(fields);
603
604     return fields;
605   }
606   
607   /**
608    * Returns the array of fields.
609    */

610   public JField []getFields()
611   {
612     ArrayList JavaDoc<JField> fieldList = new ArrayList JavaDoc<JField>();
613
614     getFields(fieldList);
615
616     JField []fields = new JField[fieldList.size()];
617     fieldList.toArray(fields);
618
619     return fields;
620   }
621   
622   /**
623    * Returns all the fields
624    */

625   private void getFields(ArrayList JavaDoc<JField> fieldList)
626   {
627     for (JField field : getDeclaredFields()) {
628       if (! fieldList.contains(field))
629     fieldList.add(field);
630     }
631
632     if (getSuperClass() != null) {
633       for (JField field : getSuperClass().getFields()) {
634     if (! fieldList.contains(field))
635       fieldList.add(field);
636       }
637     }
638   }
639
640   /**
641    * Returns the declared annotations.
642    */

643   public JAnnotation []getDeclaredAnnotations()
644   {
645     if (_annotations == null) {
646       Attribute attr = getAttribute("RuntimeVisibleAnnotations");
647
648       if (attr instanceof OpaqueAttribute) {
649     byte []buffer = ((OpaqueAttribute) attr).getValue();
650     
651     try {
652       ByteArrayInputStream JavaDoc is = new ByteArrayInputStream JavaDoc(buffer);
653
654       ConstantPool cp = getConstantPool();
655
656       _annotations = JavaAnnotation.parseAnnotations(is, cp,
657                              getClassLoader());
658     } catch (IOException JavaDoc e) {
659       log.log(Level.FINER, e.toString(), e);
660     }
661       }
662
663       if (_annotations == null) {
664     _annotations = new JavaAnnotation[0];
665       }
666     }
667     
668     return _annotations;
669   }
670   
671   /**
672    * Returns the annotation.
673    */

674   public JAnnotation getAnnotation(String JavaDoc className)
675   {
676     JAnnotation []annList = getDeclaredAnnotations();
677
678     for (int i = 0; i < annList.length; i++) {
679       if (annList[i].getType().equals(className))
680     return annList[i];
681     }
682     
683     return null;
684   }
685
686   /**
687    * Lazily load the class.
688    */

689   private void lazyLoad()
690   {
691     if (_major > 0)
692       return;
693
694     try {
695       if (_url == null)
696     throw new IllegalStateException JavaDoc();
697       
698       InputStream JavaDoc is = _url.openStream();
699       ReadStream rs = Vfs.openRead(is);
700       try {
701     _major = 1;
702     
703     ByteCodeParser parser = new ByteCodeParser();
704     parser.setClassLoader(_loader);
705     parser.setJavaClass(this);
706
707     parser.parse(rs);
708       } finally {
709     rs.close();
710     is.close();
711       }
712     } catch (RuntimeException JavaDoc e) {
713       throw e;
714     } catch (Exception JavaDoc e) {
715       throw new RuntimeException JavaDoc(e);
716     }
717   }
718
719   /**
720    * Writes the class to the output.
721    */

722   public void write(WriteStream os)
723     throws IOException JavaDoc
724   {
725     ByteCodeWriter out = new ByteCodeWriter(os, this);
726
727     out.writeInt(MAGIC);
728     out.writeShort(_minor);
729     out.writeShort(_major);
730
731     _constantPool.write(out);
732
733     out.writeShort(_accessFlags);
734     out.writeClass(_thisClass);
735     out.writeClass(_superClass);
736
737     out.writeShort(_interfaces.size());
738     for (int i = 0; i < _interfaces.size(); i++) {
739       String JavaDoc className = _interfaces.get(i);
740
741       out.writeClass(className);
742     }
743
744     out.writeShort(_fields.size());
745     for (int i = 0; i < _fields.size(); i++) {
746       JavaField field = _fields.get(i);
747
748       field.write(out);
749     }
750
751     out.writeShort(_methods.size());
752     for (int i = 0; i < _methods.size(); i++) {
753       JavaMethod method = _methods.get(i);
754
755       method.write(out);
756     }
757
758     out.writeShort(_attributes.size());
759     for (int i = 0; i < _attributes.size(); i++) {
760       Attribute attr = _attributes.get(i);
761
762       attr.write(out);
763     }
764   }
765
766   public String JavaDoc toString()
767   {
768     return "JavaClass[" + _thisClass + "]";
769   }
770 }
771
Popular Tags