KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quilt > cl > ClassTransformer


1 /* ClassTransformer.java */
2 package org.quilt.cl;
3
4 import java.util.Hashtable JavaDoc;
5 import java.util.List JavaDoc;
6
7 import org.apache.bcel.classfile.JavaClass;
8 import org.apache.bcel.classfile.Method;
9 import org.apache.bcel.generic.ClassGen;
10 import org.apache.bcel.generic.InstructionList;
11 import org.apache.bcel.generic.MethodGen;
12
13 /**
14  * Transform a JavaClass, if there are any class, method, or graph
15  * transformers. Methods whose names begin with "q$$q" are not
16  * transformed.
17  *
18  * @author <a HREF="jddixon@users.sourceforge.net">Jim Dixon</a>
19  */

20 public class ClassTransformer {
21
22     /** For passing application-specific data. */
23     private Hashtable JavaDoc classHash = new Hashtable JavaDoc();
24
25     /** Class pre- and post-processors. */
26     private List JavaDoc cxf;
27     /** Method pre- and post-processors. */
28     private List JavaDoc mxf;
29     /** Graph processors. */
30     private List JavaDoc gxf;
31     /** Method processor. */
32     private MethodTransformer xformer;
33    
34     /** Aborted by xformer. */
35     boolean aborted_ = false;
36
37     /**
38      * Creates class transformer and lower-level transformers.
39      * The method transformer is created only if there are processor
40      * lists for it or the graph transformer.
41      *
42      * @param cxf List of class pre/post processors.
43      * @param mxf List of method pre/post processors.
44      * @param gsf List of graph processors.
45      */

46     public ClassTransformer (List JavaDoc cxf, List JavaDoc mxf, List JavaDoc gxf ) {
47         this.cxf = cxf;
48         this.mxf = mxf;
49         this.gxf = gxf;
50         xformer = new MethodTransformer (mxf, gxf);
51     }
52
53     public Hashtable JavaDoc getClassHash() {
54         return classHash;
55     }
56     private void zapClassXformer ( ClassXformer cxf, Exception JavaDoc e) {
57         System.err.println("WARNING: exception in "
58             + cxf.getName() + ": transformation will not be applied" );
59         e.printStackTrace();
60         cxf = null;
61     }
62     public JavaClass xform (JavaClass jc) {
63         if ( jc == null || ! jc.isClass() ) {
64             throw new IllegalArgumentException JavaDoc("null or corrupt JavaClass");
65         }
66         ClassGen clazz = new ClassGen(jc);
67
68         // NEEDS THOUGHT -- do we really want to make all classes
69
// public by default??
70
makePublic(clazz); // in xf[0] ??
71

72         // apply any preprocessors
73
aborted_ = false;
74         ClassXformer[] xf = new ClassXformer[ cxf.size() ];
75         for (int i = 0; i < xf.length; i++) {
76             try {
77                 xf[i] = (ClassXformer) (
78                       (cxf.get(i)).getClass().newInstance() );
79                 xf[i].setClassTransformer(this);
80             } catch (IllegalAccessException JavaDoc e) {
81                 zapClassXformer (xf[i], e);
82             } catch (InstantiationException JavaDoc e) {
83                 zapClassXformer (xf[i], e);
84             }
85             if ( xf[i] != null && !aborted_) {
86                 xf[i].preMethods(clazz);
87             }
88         }
89
90         // IF there are transformations to be done at the method or
91
// graph level ...
92
if ( mxf.size() > 0 || gxf.size() > 0 && !aborted_) {
93             // extract the methods and do wondrous things with them
94
Method [] methods = clazz.getMethods();
95             for (int i = 0; i < methods.length; i++) {
96                 String JavaDoc methodName = methods[i].getName();
97                 if (methods[i].getCode() != null
98                                         && ! methodName.startsWith("q$$q") ) {
99                     // transform the method
100
MethodGen result = xformer.xform ( clazz, methods[i] );
101                     // put it in the ClassGen if it's OK
102
if (result != null) {
103                         clazz.replaceMethod(methods[i], result.getMethod());
104                         // be a good citizen:
105
InstructionList ilist = result.getInstructionList();
106                         ilist.dispose();
107                         result = null;
108                     }
109                 }
110             }
111         }
112         // apply any postprocessors
113
for (int i = xf.length - 1; i >= 0; i--) {
114             if (xf[i] != null && !aborted_) {
115                 xf[i].postMethods(clazz);
116             }
117         }
118         if (clazz == null || aborted_) {
119             System.out.println(
120                 "ClassTransformer WARNING could not transform class");
121             return jc;
122         } else {
123             return clazz.getJavaClass();
124         }
125     }
126
127     /**
128      * Make the class public. XXX Consider making this optional.
129      *
130      * @param cg ClassGen template for class to be made public.
131      */

132     protected static void makePublic (ClassGen cg) {
133         int flags = cg.getAccessFlags();
134         flags &= ~ (org.apache.bcel.Constants.ACC_PRIVATE
135                   | org.apache.bcel.Constants.ACC_PROTECTED);
136         flags |= org.apache.bcel.Constants.ACC_PUBLIC;
137         cg.setAccessFlags(flags);
138         if (!cg.isPublic()) {
139             System.out.println("WARNING: makePublic for "
140                 + cg.getClassName() + " failed");
141         }
142     }
143     /** Abort the class transformation. */
144     public void abort() {
145         aborted_= true;
146     }
147 }
148
Popular Tags