001: package org.hansel;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.FileOutputStream;
005: import java.lang.instrument.ClassDefinition;
006: import java.lang.instrument.ClassFileTransformer;
007: import java.lang.instrument.IllegalClassFormatException;
008: import java.lang.instrument.Instrumentation;
009: import java.lang.instrument.UnmodifiableClassException;
010: import java.security.ProtectionDomain;
011: import java.util.List;
012: import java.util.Set;
013: import java.util.Vector;
014:
015: import org.objectweb.asm.ClassReader;
016: import org.objectweb.asm.ClassWriter;
017: import org.objectweb.asm.tree.ClassNode;
018:
019: public class Transformer implements ClassFileTransformer {
020: private Set<String> classNames;
021: private List<ClassEntry> redefinedClasses = new Vector<ClassEntry>();
022:
023: public Transformer(Set<String> classNames) {
024: this .classNames = classNames;
025: }
026:
027: public byte[] transform(ClassLoader loader, String className,
028: Class<?> classBeingRedefined,
029: ProtectionDomain protectionDomain, byte[] classfileBuffer)
030: throws IllegalClassFormatException {
031:
032: if (!classNames.contains(className.replace('/', '.'))) {
033: return null;
034: }
035:
036: try {
037: ClassReader cr = new ClassReader(new ByteArrayInputStream(
038: classfileBuffer));
039: ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
040: + ClassWriter.COMPUTE_MAXS);
041:
042: ClassNode cn = new ClassNode();
043: cr.accept(cn, 0);
044:
045: TransformingAdapter ta = new TransformingAdapter(cw, cn,
046: loader);
047:
048: cn.accept(ta);
049:
050: //System.out.println("Redefining class: " + className + " " + loader);
051: redefinedClasses.add(new ClassEntry(className, loader,
052: classfileBuffer));
053: byte[] result = cw.toByteArray();
054:
055: if (cn.name.endsWith("Example")) {
056: FileOutputStream out = new FileOutputStream(
057: "test.class");
058: out.write(result);
059: out.close();
060: }
061: //System.out.println("Success: " + className);
062:
063: return result;
064: } catch (Throwable e) {
065: e.printStackTrace();
066: throw new IllegalClassFormatException(e.getMessage());
067: }
068: }
069:
070: public void undo(Instrumentation instrumentation)
071: throws ClassNotFoundException, UnmodifiableClassException {
072:
073: ClassDefinition[] oldClasses = new ClassDefinition[redefinedClasses
074: .size()];
075:
076: for (int i = 0; i < oldClasses.length; i++) {
077: oldClasses[i] = redefinedClasses.get(i).toClassDefinition();
078: }
079:
080: instrumentation.redefineClasses(oldClasses);
081: }
082:
083: private static class ClassEntry {
084: private ClassLoader cl;
085: private byte[] classBuffer;
086: private String classname;
087:
088: public ClassEntry(String classname, ClassLoader cl,
089: byte[] classBuffer) {
090: this .cl = cl;
091: this .classname = classname;
092: this .classBuffer = classBuffer;
093:
094: /*try {
095: if (classname.endsWith("EventQueue")) {
096: FileOutputStream out = new FileOutputStream("testHansel.class");
097: out.write(classBuffer);
098: out.close();
099: }} catch (Exception e) {
100: e.printStackTrace();
101: } */
102: }
103:
104: public ClassDefinition toClassDefinition()
105: throws ClassNotFoundException {
106: return new ClassDefinition(cl.loadClass(classname.replace(
107: '/', '.')), classBuffer);
108: }
109: }
110: }
|