package org.coldswap.asm.field; import org.coldswap.asm.FieldBox; import org.coldswap.asm.ReferenceReplacer; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.*; import java.util.Iterator; import java.util.List; /** * (C) Copyright 2013 Faur Ioan-Aurel. * <p/> * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-2.1.html * <p/> * 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. * <p/> * Contributors: * faur * <p/> * Created at: * 4:57 PM 4/30/13 */ public class PublicStaticFieldReferenceReplacer extends FieldBox implements ReferenceReplacer { /** * Constructs a container for a field reference that should be searched and replaced. * * @param oldClass the old class reference. * @param fieldToReplace the field that should be instrumented. * @param newClass the new class reference for the field. */ public PublicStaticFieldReferenceReplacer(String oldClass, FieldNode fieldToReplace, String newClass) { super(oldClass, fieldToReplace, newClass); } @SuppressWarnings("unchecked") @Override public int findAndReplace(ClassNode classNode) { int counter = 0; List<MethodNode> methodNodes = classNode.methods; for (MethodNode method : methodNodes) { InsnList inst = method.instructions; Iterator iter = inst.iterator(); while (iter.hasNext()) { AbstractInsnNode absIns = (AbstractInsnNode) iter.next(); int opcode = absIns.getOpcode(); // check if instruction is GETSTATIC or PUTSTATIC if (opcode == Opcodes.GETSTATIC) { // get type if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = {false}; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (oldClass.equals(s) && fieldToReplace.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.GETSTATIC, newClass, fieldToReplace.name, fieldToReplace.desc)); counter++; } } } else if (opcode == Opcodes.PUTSTATIC) { if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = {false}; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (oldClass.equals(s) && fieldToReplace.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.PUTSTATIC, newClass, fieldToReplace.name, fieldToReplace.desc)); counter++; } } } } } return counter; } }