001    package railo.transformer.bytecode.util;
002    
003    import org.objectweb.asm.ClassReader;
004    import org.objectweb.asm.ClassVisitor;
005    import org.objectweb.asm.ClassWriter;
006    import org.objectweb.asm.MethodVisitor;
007    import org.objectweb.asm.Opcodes;
008    
009    import railo.commons.lang.StringUtil;
010    import railo.runtime.type.util.ListUtil;
011    
012    public class ClassRenamer extends ClassVisitor implements Opcodes {
013    
014            private final String newName;
015            private String oldName;
016            private boolean doNothing;
017    
018            ClassRenamer(ClassVisitor cv, String newName) {
019                    super(ASM4, cv);
020                    newName=ListUtil.trim(newName, "\\/");
021                    this.newName = newName;
022            }
023    
024            public void visit(int version, int access, String name, String signature,String superName, String[] interfaces) {
025                    oldName=name;
026                    doNothing=oldName.equals(newName);
027                    
028                    cv.visit(version, ACC_PUBLIC, newName, signature, superName, interfaces);
029            }
030    
031            public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
032                    MethodVisitor mv = cv.visitMethod(access, name, fixDesc(desc),fixSignature(signature), exceptions);
033                    if (mv != null && (access & ACC_ABSTRACT) == 0) {
034                            mv = new MethodRenamer(mv);
035                    }
036                    return mv;
037            }
038    
039            class MethodRenamer extends MethodVisitor {
040    
041                    public MethodRenamer(final MethodVisitor mv) {
042                            super(ASM4, mv);
043                    }
044    
045                    public void visitTypeInsn(int i, String s) {
046                            if (!doNothing && oldName.equals(s)) {
047                                    s = newName;
048                            }
049                            mv.visitTypeInsn(i, s);
050                    }
051    
052                    public void visitFieldInsn(int opcode, String owner, String name,
053                                    String desc) {
054                            if (!doNothing && oldName.equals(owner)) {
055                                    mv.visitFieldInsn(opcode, newName, name, fixDesc(desc));
056                            } else {
057                                    mv.visitFieldInsn(opcode, owner, name, fixDesc(desc));
058                            }
059                    }
060    
061                    public void visitMethodInsn(int opcode, String owner, String name,
062                                    String desc) {
063                            if (!doNothing && oldName.equals(owner)) {
064                                    mv.visitMethodInsn(opcode, newName, name, fixDesc(desc));
065                            } else {
066                                    mv.visitMethodInsn(opcode, owner, name, fixDesc(desc));
067                            }
068                    }
069            }
070    
071            private String fixDesc(String desc) {
072                    //print.e("fixDesc:"+desc);
073                    return _fix(desc);
074            }
075    
076            private String fixSignature(String signature) {
077                    //print.e("fixSignature:"+signature);
078                    return _fix(signature);
079            }
080    
081            private String _fix(String str) {
082                    if (!doNothing && !StringUtil.isEmpty(str)) {
083                            if (str.indexOf(oldName) != -1) {
084                                    str = StringUtil.replace(str, oldName, newName,false);
085                            }
086                    }
087                    return str;
088            }
089            
090            public static byte[] rename(byte[] src, String newName){
091                    ClassReader cr = new ClassReader(src);
092                    ClassWriter cw = ASMUtil.getClassWriter();
093                    ClassVisitor ca = new ClassRenamer(cw,newName);
094                    cr.accept(ca, ClassReader.SKIP_DEBUG);
095                    return cw.toByteArray();
096            }
097    
098            /*public static void main(String[] args) throws Throwable {
099                    String path = "/Users/mic/Projects/Railo/webroot/WEB-INF/railo/cfclasses/CF_Users_mic_Projects_Railo_webroot_jm4653/jira/test/test_cfm$cf.class";
100                    ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
101                    Resource res = frp.getResource(path);
102                    print.e(getClassName(res));
103            }*/
104    }