001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.util; 020 021import lucee.commons.lang.StringUtil; 022import lucee.runtime.type.util.ListUtil; 023 024import org.objectweb.asm.ClassReader; 025import org.objectweb.asm.ClassVisitor; 026import org.objectweb.asm.ClassWriter; 027import org.objectweb.asm.MethodVisitor; 028import org.objectweb.asm.Opcodes; 029 030public class ClassRenamer extends ClassVisitor implements Opcodes { 031 032 private final String newName; 033 private String oldName; 034 private boolean doNothing; 035 036 ClassRenamer(ClassVisitor cv, String newName) { 037 super(ASM4, cv); 038 newName=ListUtil.trim(newName, "\\/"); 039 this.newName = newName; 040 } 041 042 public void visit(int version, int access, String name, String signature,String superName, String[] interfaces) { 043 oldName=name; 044 doNothing=oldName.equals(newName); 045 046 cv.visit(version, ACC_PUBLIC, newName, signature, superName, interfaces); 047 } 048 049 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 050 MethodVisitor mv = cv.visitMethod(access, name, fixDesc(desc),fixSignature(signature), exceptions); 051 if (mv != null && (access & ACC_ABSTRACT) == 0) { 052 mv = new MethodRenamer(mv); 053 } 054 return mv; 055 } 056 057 class MethodRenamer extends MethodVisitor { 058 059 public MethodRenamer(final MethodVisitor mv) { 060 super(ASM4, mv); 061 } 062 063 public void visitTypeInsn(int i, String s) { 064 if (!doNothing && oldName.equals(s)) { 065 s = newName; 066 } 067 mv.visitTypeInsn(i, s); 068 } 069 070 public void visitFieldInsn(int opcode, String owner, String name, 071 String desc) { 072 if (!doNothing && oldName.equals(owner)) { 073 mv.visitFieldInsn(opcode, newName, name, fixDesc(desc)); 074 } else { 075 mv.visitFieldInsn(opcode, owner, name, fixDesc(desc)); 076 } 077 } 078 079 public void visitMethodInsn(int opcode, String owner, String name, 080 String desc) { 081 if (!doNothing && oldName.equals(owner)) { 082 mv.visitMethodInsn(opcode, newName, name, fixDesc(desc)); 083 } else { 084 mv.visitMethodInsn(opcode, owner, name, fixDesc(desc)); 085 } 086 } 087 } 088 089 private String fixDesc(String desc) { 090 //print.e("fixDesc:"+desc); 091 return _fix(desc); 092 } 093 094 private String fixSignature(String signature) { 095 //print.e("fixSignature:"+signature); 096 return _fix(signature); 097 } 098 099 private String _fix(String str) { 100 if (!doNothing && !StringUtil.isEmpty(str)) { 101 if (str.indexOf(oldName) != -1) { 102 str = StringUtil.replace(str, oldName, newName,false); 103 } 104 } 105 return str; 106 } 107 108 public static byte[] rename(byte[] src, String newName){ 109 ClassReader cr = new ClassReader(src); 110 ClassWriter cw = ASMUtil.getClassWriter(); 111 ClassVisitor ca = new ClassRenamer(cw,newName); 112 cr.accept(ca, 0); 113 return cw.toByteArray(); 114 } 115 116 /*public static void main(String[] args) throws Throwable { 117 String path = "/Users/mic/Projects/Lucee/webroot/WEB-INF/lucee/cfclasses/CF_Users_mic_Projects_Lucee_webroot_jm4653/jira/test/test_cfm$cf.class"; 118 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 119 Resource res = frp.getResource(path); 120 print.e(getClassName(res)); 121 }*/ 122}