]> source.dussan.org Git - javassist.git/commitdiff
modified redirectMethodCall() in CodeConverter
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Thu, 19 Jul 2007 10:21:26 +0000 (10:21 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Thu, 19 Jul 2007 10:21:26 +0000 (10:21 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@397 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/bytecode/ConstPool.java
src/main/javassist/convert/TransformCall.java

index 2b2348e813c69707938bc34a9819ef1377856eeb..7ac8dc2fb1a41dc4729eae5f6ca75f1f7e6d8fe7 100644 (file)
@@ -205,6 +205,34 @@ public final class ConstPool {
         return ntinfo.typeDescriptor;
     }
 
+    /**
+     * Reads the <code>class_index</code> field of the
+     * <code>CONSTANT_Fieldref_info</code>,
+     * <code>CONSTANT_Methodref_info</code>,
+     * or <code>CONSTANT_Interfaceref_info</code>,
+     * structure at the given index.
+     *
+     * @since 3.6
+     */
+    public int getMemberClass(int index) {
+        MemberrefInfo minfo = (MemberrefInfo)getItem(index);
+        return minfo.classIndex;
+    }
+
+    /**
+     * Reads the <code>name_and_type_index</code> field of the
+     * <code>CONSTANT_Fieldref_info</code>,
+     * <code>CONSTANT_Methodref_info</code>,
+     * or <code>CONSTANT_Interfaceref_info</code>,
+     * structure at the given index.
+     *
+     * @since 3.6
+     */
+    public int getMemberNameAndType(int index) {
+        MemberrefInfo minfo = (MemberrefInfo)getItem(index);
+        return minfo.nameAndTypeIndex;
+    }
+
     /**
      * Reads the <code>class_index</code> field of the
      * <code>CONSTANT_Fieldref_info</code> structure
@@ -274,7 +302,7 @@ public final class ConstPool {
         if (f == null)
             return null;
         else {
-            NameAndTypeInfo n = (NameAndTypeInfo) getItem(f.nameAndTypeIndex);
+            NameAndTypeInfo n = (NameAndTypeInfo)getItem(f.nameAndTypeIndex);
             if(n == null)
                 return null;
             else
@@ -579,6 +607,34 @@ public final class ConstPool {
         return 0;       // false
     }
 
+    /**
+     * Determines whether <code>CONSTANT_Methodref_info</code>,
+     * <code>CONSTANT_Fieldref_info</code>, or
+     * <code>CONSTANT_InterfaceMethodref_info</code> structure
+     * at the given index has the name and the descriptor
+     * given as the arguments.
+     *
+     * @param membername        the member name
+     * @param desc              the descriptor of the member.
+     * @param index             the index into the constant pool table
+     *
+     * @return          the name of the target class specified by
+     *                  the <code>..._info</code> structure
+     *                  at <code>index</code>.
+     *                  Otherwise, null if that structure does not 
+     *                  match the given member name and descriptor.
+     */
+    public String eqMember(String membername, String desc, int index) {
+        MemberrefInfo minfo = (MemberrefInfo)getItem(index);
+        NameAndTypeInfo ntinfo
+                = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
+        if (getUtf8Info(ntinfo.memberName).equals(membername)
+            && getUtf8Info(ntinfo.typeDescriptor).equals(desc))
+            return getClassInfo(minfo.classIndex);
+        else
+            return null;       // false
+    }
+
     private int addItem(ConstInfo info) {
         items.addElement(info);
         return numOfItems++;
index bfa81cb30a7c7e9314b6a526caf147a12456b778..fb8395eecdae4e678898b020f72872837664ab24 100644 (file)
@@ -17,7 +17,9 @@ package javassist.convert;
 
 import javassist.CtClass;
 import javassist.CtMethod;
+import javassist.ClassPool;
 import javassist.Modifier;
+import javassist.NotFoundException;
 import javassist.bytecode.*;
 
 public class TransformCall extends Transformer {
@@ -55,7 +57,10 @@ public class TransformCall extends Transformer {
 
     /**
      * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL
-     * so that a different method is invoked.
+     * so that a different method is invoked.  The class name in the operand
+     * of these instructions might be a subclass of the target class specified
+     * by <code>classname</code>.   This method transforms the instruction
+     * in that case unless the subclass overrides the target method.
      */
     public int transform(CtClass clazz, int pos, CodeIterator iterator,
                          ConstPool cp) throws BadBytecode
@@ -64,15 +69,41 @@ public class TransformCall extends Transformer {
         if (c == INVOKEINTERFACE || c == INVOKESPECIAL
                         || c == INVOKESTATIC || c == INVOKEVIRTUAL) {
             int index = iterator.u16bitAt(pos + 1);
-            int typedesc = cp.isMember(classname, methodname, index);
-            if (typedesc != 0)
-                if (cp.getUtf8Info(typedesc).equals(methodDescriptor))
-                    pos = match(c, pos, iterator, typedesc, cp);
+            String cname = cp.eqMember(methodname, methodDescriptor, index);
+            if (cname != null && matchClass(cname, clazz.getClassPool())) {
+                int ntinfo = cp.getMemberNameAndType(index);
+                pos = match(c, pos, iterator,
+                            cp.getNameAndTypeDescriptor(ntinfo), cp);
+            }
         }
 
         return pos;
     }
 
+    private boolean matchClass(String name, ClassPool pool) {
+        if (classname.equals(name))
+            return true;
+
+        try {
+            CtClass clazz = pool.get(name);
+            CtClass declClazz = pool.get(classname);
+            if (clazz.subtypeOf(declClazz))
+                try {
+                    CtMethod m = clazz.getMethod(methodname, methodDescriptor);
+                    return m.getDeclaringClass().getName().equals(classname);
+                }
+                catch (NotFoundException e) {
+                    // maybe the original method has been removed.
+                    return true;
+                }
+        }
+        catch (NotFoundException e) {
+            return false;
+        }
+
+        return false;
+    }
+
     protected int match(int c, int pos, CodeIterator iterator,
                         int typedesc, ConstPool cp) throws BadBytecode
     {