1 /* ClassTransformer.java */
2 package org.quilt.cl;
3
4 import java.util.Hashtable;
5 import java.util.List;
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 classHash = new Hashtable();
24
25 /*** Class pre- and post-processors. */
26 private List cxf;
27 /*** Method pre- and post-processors. */
28 private List mxf;
29 /*** Graph processors. */
30 private List 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 cxf, List mxf, List gxf ) {
47 this.cxf = cxf;
48 this.mxf = mxf;
49 this.gxf = gxf;
50 xformer = new MethodTransformer (mxf, gxf);
51 }
52
53 public Hashtable getClassHash() {
54 return classHash;
55 }
56 private void zapClassXformer ( ClassXformer cxf, Exception 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("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 e) {
81 zapClassXformer (xf[i], e);
82 } catch (InstantiationException 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 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 }
This page was automatically generated by Maven