From: chiba Date: Mon, 8 Sep 2008 10:56:50 +0000 (+0000) Subject: implemented CodeConverter.replaceNew(CtClass,CtClass) X-Git-Tag: rel_3_17_1_ga~191 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7f87aaa503eae6730f2b077b428d65f9bc3efc14;p=javassist.git implemented CodeConverter.replaceNew(CtClass,CtClass) git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@454 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- diff --git a/src/main/javassist/CodeConverter.java b/src/main/javassist/CodeConverter.java index 4ffe1eeb..91f5657a 100644 --- a/src/main/javassist/CodeConverter.java +++ b/src/main/javassist/CodeConverter.java @@ -97,6 +97,32 @@ public class CodeConverter { calledClass.getName(), calledMethod); } + /** + * Modify a method body so that instantiation of the class + * specified by oldClass + * is replaced with instantiation of another class newClass. + * For example, + * replaceNew(ctPoint, ctPoint2) + * (where ctPoint and ctPoint2 are + * compile-time classes for class Point and class + * Point2, respectively) + * replaces all occurrences of: + * + * + * + * in the method body with: + * + * + * + *

Note that Point2 must be type-compatible with Point. + * It must have the same set of methods, fields, and constructors as the + * replaced class. + */ + public void replaceNew(CtClass oldClass, CtClass newClass) { + transformers = new TransformNewClass(transformers, oldClass.getName(), + newClass.getName()); + } + /** * Modify a method body so that field read/write expressions access * a different field from the original one. @@ -503,7 +529,7 @@ public class CodeConverter { * as array access replacements. * * @author Kabir Khan - * @version $Revision: 1.14 $ + * @version $Revision: 1.15 $ */ public interface ArrayAccessReplacementMethodNames { @@ -612,7 +638,7 @@ public class CodeConverter { * accesses to array elements. * * @author Kabir Khan - * @version $Revision: 1.14 $ + * @version $Revision: 1.15 $ */ public static class DefaultArrayAccessReplacementMethodNames implements ArrayAccessReplacementMethodNames diff --git a/src/main/javassist/convert/TransformNewClass.java b/src/main/javassist/convert/TransformNewClass.java new file mode 100644 index 00000000..f34ef83b --- /dev/null +++ b/src/main/javassist/convert/TransformNewClass.java @@ -0,0 +1,82 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist.convert; + +import javassist.bytecode.*; +import javassist.CtClass; +import javassist.CannotCompileException; + +final public class TransformNewClass extends Transformer { + private int nested; + private String classname, newClassName; + private int newClassIndex, newMethodNTIndex, newMethodIndex; + + public TransformNewClass(Transformer next, + String classname, String newClassName) { + super(next); + this.classname = classname; + this.newClassName = newClassName; + } + + public void initialize(ConstPool cp, CodeAttribute attr) { + nested = 0; + newClassIndex = newMethodNTIndex = newMethodIndex = 0; + } + + /** + * Modifies a sequence of + * NEW classname + * DUP + * ... + * INVOKESPECIAL classname:method + */ + public int transform(CtClass clazz, int pos, CodeIterator iterator, + ConstPool cp) throws CannotCompileException + { + int index; + int c = iterator.byteAt(pos); + if (c == NEW) { + index = iterator.u16bitAt(pos + 1); + if (cp.getClassInfo(index).equals(classname)) { + if (iterator.byteAt(pos + 3) != DUP) + throw new CannotCompileException( + "NEW followed by no DUP was found"); + + if (newClassIndex == 0) + newClassIndex = cp.addClassInfo(newClassName); + + iterator.write16bit(newClassIndex, pos + 1); + ++nested; + } + } + else if (c == INVOKESPECIAL) { + index = iterator.u16bitAt(pos + 1); + int typedesc = cp.isConstructor(classname, index); + if (typedesc != 0 && nested > 0) { + int nt = cp.getMethodrefNameAndType(index); + if (newMethodNTIndex != nt) { + newMethodNTIndex = nt; + newMethodIndex = cp.addMethodrefInfo(newClassIndex, nt); + } + + iterator.write16bit(newMethodIndex, pos + 1); + --nested; + } + } + + return pos; + } +}