View Javadoc
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