/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.transformer.bytecode.util; import lucee.commons.lang.StringUtil; import lucee.runtime.type.util.ListUtil; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class ClassRenamer extends ClassVisitor implements Opcodes { private final String newName; private String oldName; private boolean doNothing; ClassRenamer(ClassVisitor cv, String newName) { super(ASM4, cv); newName=ListUtil.trim(newName, "\\/"); this.newName = newName; } @Override public void visit(int version, int access, String name, String signature,String superName, String[] interfaces) { oldName=name; doNothing=oldName.equals(newName); cv.visit(version, ACC_PUBLIC, newName, signature, superName, interfaces); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = cv.visitMethod(access, name, fixDesc(desc),fixSignature(signature), exceptions); if (mv != null && (access & ACC_ABSTRACT) == 0) { mv = new MethodRenamer(mv); } return mv; } class MethodRenamer extends MethodVisitor { public MethodRenamer(final MethodVisitor mv) { super(ASM4, mv); } @Override public void visitTypeInsn(int i, String s) { if (!doNothing && oldName.equals(s)) { s = newName; } mv.visitTypeInsn(i, s); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (!doNothing && oldName.equals(owner)) { mv.visitFieldInsn(opcode, newName, name, fixDesc(desc)); } else { mv.visitFieldInsn(opcode, owner, name, fixDesc(desc)); } } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (!doNothing && oldName.equals(owner)) { mv.visitMethodInsn(opcode, newName, name, fixDesc(desc)); } else { mv.visitMethodInsn(opcode, owner, name, fixDesc(desc)); } } } private String fixDesc(String desc) { //print.e("fixDesc:"+desc); return _fix(desc); } private String fixSignature(String signature) { //print.e("fixSignature:"+signature); return _fix(signature); } private String _fix(String str) { if (!doNothing && !StringUtil.isEmpty(str)) { if (str.indexOf(oldName) != -1) { str = StringUtil.replace(str, oldName, newName,false); } } return str; } public static byte[] rename(byte[] src, String newName){ ClassReader cr = new ClassReader(src); ClassWriter cw = ASMUtil.getClassWriter(); ClassVisitor ca = new ClassRenamer(cw,newName); cr.accept(ca, 0); return cw.toByteArray(); } }