]> source.dussan.org Git - javassist.git/commitdiff
implemented CodeConverter.replaceNew(CtClass,CtClass)
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Mon, 8 Sep 2008 10:56:50 +0000 (10:56 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Mon, 8 Sep 2008 10:56:50 +0000 (10:56 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@454 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/CodeConverter.java
src/main/javassist/convert/TransformNewClass.java [new file with mode: 0644]

index 4ffe1eeb4880da4e0cd201dadd96af72b6c3a4ee..91f5657a2da84b66ce8cc882878f7a02ce8b9bf5 100644 (file)
@@ -97,6 +97,32 @@ public class CodeConverter {
                                         calledClass.getName(), calledMethod);
     }
 
+    /**
+     * Modify a method body so that instantiation of the class
+     * specified by <code>oldClass</code>
+     * is replaced with instantiation of another class <code>newClass</code>.
+     * For example,
+     * <code>replaceNew(ctPoint, ctPoint2)</code>
+     * (where <code>ctPoint</code> and <code>ctPoint2</code> are
+     * compile-time classes for class <code>Point</code> and class
+     * <code>Point2</code>, respectively)
+     * replaces all occurrences of:
+     *
+     * <ul><code>new Point(x, y)</code></ul>
+     *
+     * in the method body with:
+     *
+     * <ul><code>new Point2(x, y)</code></ul>
+     *
+     * <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>.
+     * 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 <a href="kabir.khan@jboss.com">Kabir Khan</a>
-     * @version $Revision: 1.14 $
+     * @version $Revision: 1.15 $
      */
     public interface ArrayAccessReplacementMethodNames
     {
@@ -612,7 +638,7 @@ public class CodeConverter {
      * accesses to array elements.
      *
      * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
-     * @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 (file)
index 0000000..f34ef83
--- /dev/null
@@ -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;
+    }
+}