package Sequenic.T2ext.Instrumenter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.bcel.Repository; import org.apache.bcel.classfile.Attribute; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; public class Main { /** * Target class. */ private Class C ; /** * Full path to the target class. */ private String classFile ; /** * Full path to the orclass file (this is the copy of the original * class file). */ private String orgclassFile ; /** * @param classpath A single classpath leading to the root of the target. * @param t Fully qualified Java name of the target class. */ private Main(String cp, String tclass) { try { C = Class.forName(tclass) ; } catch (ClassNotFoundException e) { throw new Error(tclass + " does not exist.",e) ; } if (cp==null) cp="." ; if (cp.endsWith("/")) cp = cp.substring(0, cp.length() -1) ; File classpath = new File(cp) ; if (!classpath.exists()) throw new Error(cp + " does not exist.") ; classFile = cp + "/" + tclass.replace('.', '/') + CLASS ; orgclassFile = cp + "/" + tclass.replace('.', '/') + ORGCLASS ; File tfile = new File(classFile) ; if (tfile == null) throw new Error(classFile + " does not exist.") ; /* doesn't work... try { System.out.println(">>> " + ClassLoader.getSystemResource(tclass)) ; if (! ClassLoader.getSystemResource(tclass).getPath().equals(classpath.getCanonicalPath())) throw new Error("The given target is found in a different location. Duplicate?") ; } catch (Exception e) { throw new Error(e) ; } */ } private static final String CLASS = ".class" ; private static final String ORGCLASS = ".orgclass" ; static private File getClassFile(File orgclassfile){ String orgclassPath = orgclassfile.getPath() ; int N = orgclassPath.length() ; String fcpath = orgclassPath.substring(0,N-ORGCLASS.length()) + CLASS ; return new File(fcpath) ; } static private File getOrgClassFile(File classfile){ String classPath = classfile.getPath() ; int N = classPath.length() ; String forgpath = classPath.substring(0,N-CLASS.length()) + ORGCLASS ; return new File(forgpath) ; } /** * Delete the target class and its orgclass. */ private void cleanup(){ delete(new File(classFile)) ; delete(new File(orgclassFile)) ; } private void delete(File f){ if (! f.exists()) return ; boolean ok = f.delete() ; if (!ok) throw new Error("Fail to delete " + f.getPath()) ; } private void rename(File f1, File f2){ boolean ok = f1.renameTo(f2) ; if (!ok) throw new Error ("Fail to rename " + f1.getPath() + " " + f2.getName()) ; } /** * Will restore .orgclass to .class. */ private void restore(){ delete(new File(classFile)) ; rename(new File(orgclassFile), new File(classFile)) ; } private void copy(File src, File dst) { try { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf,0,len); } in.close(); } catch (IOException e) { throw new Error("Fail to copy " + src.getPath(), e) ; } } private void instrument() { if(ClassInstrumenter.isInstrumented(C)) { System.out.println(C+" is already instrumented."); return; } // Make a copy first: File orgclass = new File(orgclassFile) ; delete(orgclass) ; copy(new File(classFile), orgclass) ; // And now do instrumentation on target: ClassInstrumenter CI = new ClassInstrumenter(C,classFile) ; CI.doInject = true ; //CI.debug = true ; CI.doInstrumenting() ; } /** * The first arg is a single classpath to the root of the target. * * The second arg is a fully qualified Java name of the target. * * The 3rd arg is an option. */ static public void main(String[] args){ if (args.length < 2) throw new Error("Too few arguments.") ; Main M = new Main(args[0],args[1]) ; if (args.length>2) { if (args[2].equals("--restore")) { M.restore() ; return ; } if (args[2].equals("--clean")) { M.cleanup() ; return ; } } M.instrument() ; } }