]> source.dussan.org Git - javassist.git/commitdiff
fixed JIRA JASSIST-77
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Thu, 2 Jul 2009 11:17:17 +0000 (11:17 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Thu, 2 Jul 2009 11:17:17 +0000 (11:17 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@485 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

Readme.html
src/main/javassist/bytecode/AttributeInfo.java
src/main/javassist/bytecode/ClassFile.java
src/main/javassist/bytecode/CodeAttribute.java
src/main/javassist/bytecode/LocalVariableAttribute.java
src/main/javassist/bytecode/LocalVariableTypeAttribute.java [new file with mode: 0644]
src/main/javassist/bytecode/SignatureAttribute.java

index 6317e262a9c2887e77953cafad8ee9cbae470643..7d5792aa16565d34c8bc3e73f1b68d3f4d8fcef5 100644 (file)
@@ -283,7 +283,7 @@ see javassist.Dump.
 
 <p>-version 3.11
 <ul>
-       <li>JIRA JASSIST-67, 68, 74, 75, 76, 81, 83, 84, 85 were fixed.
+       <li>JIRA JASSIST-67, 68, 74, 75, 76, 77, 81, 83, 84, 85 were fixed.
        <li>Now javassist.bytecode.CodeIterator can insert a gap into
        a large method body more than 32KB.  (JIRA JASSIST-79, 80)
 </ul>
index 67d1c48e8367c7b8e0c10d045dae8434c2ccacb0..915f291f3787f69cfa2ad607368816fa1cb2c412 100644 (file)
@@ -21,6 +21,8 @@ import java.io.IOException;
 import java.util.Map;
 import java.util.LinkedList;
 import java.util.ListIterator;
+import java.util.List;
+import java.util.Iterator;
 
 // Note: if you define a new subclass of AttributeInfo, then
 //       update AttributeInfo.read(), .copy(), and (maybe) write().
@@ -92,9 +94,10 @@ public class AttributeInfo {
              */
             if (nameStr.equals(LineNumberAttribute.tag))
                 return new LineNumberAttribute(cp, name, in);
-            else if (nameStr.equals(LocalVariableAttribute.tag)
-                     || nameStr.equals(LocalVariableAttribute.typeTag))
+            else if (nameStr.equals(LocalVariableAttribute.tag))
                 return new LocalVariableAttribute(cp, name, in);
+            else if (nameStr.equals(LocalVariableTypeAttribute.tag))
+                return new LocalVariableTypeAttribute(cp, name, in);
             else if (nameStr.equals(AnnotationsAttribute.visibleTag)
                      || nameStr.equals(AnnotationsAttribute.invisibleTag)) {
                 // RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations
@@ -243,4 +246,28 @@ public class AttributeInfo {
 
         return newList;
     }
+
+    /* The following two methods are used to implement
+     * ClassFile.renameClass().
+     * Only CodeAttribute and LocalVariableAttribute override
+     * this method.
+     */
+    void renameClass(String oldname, String newname) {}
+    void renameClass(Map classnames) {}
+
+    static void renameClass(List attributes, String oldname, String newname) {
+        Iterator iterator = attributes.iterator();
+        while (iterator.hasNext()) {
+            AttributeInfo ai = (AttributeInfo)iterator.next();
+            ai.renameClass(oldname, newname);
+        }
+    }
+
+    static void renameClass(List attributes, Map classnames) {
+        Iterator iterator = attributes.iterator();
+        while (iterator.hasNext()) {
+            AttributeInfo ai = (AttributeInfo)iterator.next();
+            ai.renameClass(classnames);
+        }
+    }
 }
index b2828f20935b401aa96ca0b2de7e80f3d338424c..f03537c87282a0a5936ccc10013990333adb7b28 100644 (file)
@@ -404,12 +404,14 @@ public final class ClassFile {
         newname = Descriptor.toJvmName(newname);
         constPool.renameClass(oldname, newname);
 
+        AttributeInfo.renameClass(attributes, oldname, newname);
         list = methods;
         n = list.size();
         for (int i = 0; i < n; ++i) {
             MethodInfo minfo = (MethodInfo)list.get(i);
             String desc = minfo.getDescriptor();
             minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
+            AttributeInfo.renameClass(minfo.getAttributes(), oldname, newname);
         }
 
         list = fields;
@@ -418,6 +420,7 @@ public final class ClassFile {
             FieldInfo finfo = (FieldInfo)list.get(i);
             String desc = finfo.getDescriptor();
             finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
+            AttributeInfo.renameClass(finfo.getAttributes(), oldname, newname);
         }
     }
 
@@ -438,12 +441,14 @@ public final class ClassFile {
 
         constPool.renameClass(classnames);
 
+        AttributeInfo.renameClass(attributes, classnames);
         ArrayList list = methods;
         int n = list.size();
         for (int i = 0; i < n; ++i) {
             MethodInfo minfo = (MethodInfo)list.get(i);
             String desc = minfo.getDescriptor();
             minfo.setDescriptor(Descriptor.rename(desc, classnames));
+            AttributeInfo.renameClass(minfo.getAttributes(), classnames);
         }
 
         list = fields;
@@ -452,6 +457,7 @@ public final class ClassFile {
             FieldInfo finfo = (FieldInfo)list.get(i);
             String desc = finfo.getDescriptor();
             finfo.setDescriptor(Descriptor.rename(desc, classnames));
+            AttributeInfo.renameClass(finfo.getAttributes(), classnames);
         }
     }
 
index 34a4fa5b57764de4a65463c9804500e6a44ef2db..0f81ae59833988e775d315fe2732ba9382068bbf 100644 (file)
@@ -20,6 +20,7 @@ import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.List;
 import java.util.LinkedList;
+import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -191,6 +192,14 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
         throw new UnsupportedOperationException("CodeAttribute.set()");
     }
 
+    void renameClass(String oldname, String newname) {
+        AttributeInfo.renameClass(attributes, oldname, newname);
+    }
+
+    void renameClass(Map classnames) {
+        AttributeInfo.renameClass(attributes, classnames);
+    }
+
     /**
      * Returns the name of the class declaring the method including
      * this code attribute.
index 80f96533ae226aa06b7c55ac6fe8879b4e886efd..d01aa4085c1b152668935bbbdc32f8faffcbc739 100644 (file)
@@ -20,8 +20,7 @@ import java.io.IOException;
 import java.util.Map;
 
 /**
- * <code>LocalVariableTable_attribute</code> or
- * <code>LocalVariableTypeTable_attribute</code>.
+ * <code>LocalVariableTable_attribute</code>.
  */
 public class LocalVariableAttribute extends AttributeInfo {
     /**
@@ -38,7 +37,8 @@ public class LocalVariableAttribute extends AttributeInfo {
      * Constructs an empty LocalVariableTable.
      */
     public LocalVariableAttribute(ConstPool cp) {
-        this(cp, tag);
+        super(cp, tag, new byte[2]);
+        ByteArray.write16bit(0, info, 0);
     }
 
     /**
@@ -50,6 +50,7 @@ public class LocalVariableAttribute extends AttributeInfo {
      * @see #tag
      * @see #typeTag
      * @since 3.1
+     * @deprecated
      */
     public LocalVariableAttribute(ConstPool cp, String name) {
         super(cp, name, new byte[2]);
@@ -62,7 +63,7 @@ public class LocalVariableAttribute extends AttributeInfo {
         super(cp, n, in);
     }
 
-    private LocalVariableAttribute(ConstPool cp, String name, byte[] i) {
+    LocalVariableAttribute(ConstPool cp, String name, byte[] i) {
         super(cp, name, i);
     }
 
@@ -91,6 +92,42 @@ public class LocalVariableAttribute extends AttributeInfo {
         info = newInfo;
     }
 
+    void renameClass(String oldname, String newname) {
+        ConstPool cp = getConstPool();
+        int n = tableLength();
+        for (int i = 0; i < n; ++i) {
+            int pos = i * 10 + 2;
+            int index = ByteArray.readU16bit(info, pos + 6);
+            if (index != 0) {
+                String desc = cp.getUtf8Info(index);
+                desc = renameEntry(desc, oldname, newname);
+                ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
+            }
+        }
+    }
+
+    String renameEntry(String desc, String oldname, String newname) {
+        return Descriptor.rename(desc, oldname, newname);
+    }
+
+    void renameClass(Map classnames) {
+        ConstPool cp = getConstPool();
+        int n = tableLength();
+        for (int i = 0; i < n; ++i) {
+            int pos = i * 10 + 2;
+            int index = ByteArray.readU16bit(info, pos + 6);
+            if (index != 0) {
+                String desc = cp.getUtf8Info(index);
+                desc = renameEntry(desc, classnames);
+                ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
+            }
+        }
+    }
+
+    String renameEntry(String desc, Map classnames) {
+        return Descriptor.rename(desc, classnames);
+    }
+
     /**
      * For each <code>local_variable_table[i].index</code>,
      * this method increases <code>index</code> by <code>delta</code>.
@@ -257,8 +294,7 @@ public class LocalVariableAttribute extends AttributeInfo {
         byte[] src = get();
         byte[] dest = new byte[src.length];
         ConstPool cp = getConstPool();
-        LocalVariableAttribute attr
-            = new LocalVariableAttribute(newCp, getName(), dest);
+        LocalVariableAttribute attr = makeThisAttr(newCp, dest);
         int n = ByteArray.readU16bit(src, 0);
         ByteArray.write16bit(n, dest, 0);
         int j = 2;
@@ -289,4 +325,9 @@ public class LocalVariableAttribute extends AttributeInfo {
 
         return attr;
     }
+
+    // LocalVariableTypeAttribute overrides this method.
+    LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
+        return new LocalVariableAttribute(cp, tag, dest);
+    }
 }
diff --git a/src/main/javassist/bytecode/LocalVariableTypeAttribute.java b/src/main/javassist/bytecode/LocalVariableTypeAttribute.java
new file mode 100644 (file)
index 0000000..d7ac098
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.bytecode;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <code>LocalVariableTypeTable_attribute</code>.
+ *
+ * @since 3.11
+ */
+public class LocalVariableTypeAttribute extends LocalVariableAttribute {
+    /**
+     * The name of the attribute <code>"LocalVariableTypeTable"</code>.
+     */
+    public static final String tag = LocalVariableAttribute.typeTag;
+
+    /**
+     * Constructs an empty LocalVariableTypeTable.
+     */
+    public LocalVariableTypeAttribute(ConstPool cp) {
+        super(cp, tag, new byte[2]);
+        ByteArray.write16bit(0, info, 0);
+    }
+
+    LocalVariableTypeAttribute(ConstPool cp, int n, DataInputStream in)
+        throws IOException
+    {
+        super(cp, n, in);
+    }
+
+    private LocalVariableTypeAttribute(ConstPool cp, byte[] dest) {
+        super(cp, tag, dest);
+    }
+
+    String renameEntry(String desc, String oldname, String newname) {
+        return SignatureAttribute.renameClass(desc, oldname, newname);
+    }
+
+    String renameEntry(String desc, Map classnames) {
+        return SignatureAttribute.renameClass(desc, classnames);
+    }
+
+    LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
+        return new LocalVariableTypeAttribute(cp, dest);
+    }
+}
index 2c8f0e9b444fe792613b37644cd386456e2e21d2..267098f81d339a287ec9224818a7730fc4690e01 100644 (file)
@@ -61,6 +61,18 @@ public class SignatureAttribute extends AttributeInfo {
         return getConstPool().getUtf8Info(ByteArray.readU16bit(get(), 0));
     }
 
+    /**
+     * Sets <code>signature_index</code> to the index of the given signature,
+     * which is added to a constant pool.
+     *
+     * @param sig       new signature.
+     * @since 3.11
+     */
+    public void setSignature(String sig) {
+        int index = getConstPool().addUtf8Info(sig);
+        ByteArray.write16bit(index, info, 0);
+    }
+
     /**
      * Makes a copy.  Class names are replaced according to the
      * given <code>Map</code> object.
@@ -73,6 +85,107 @@ public class SignatureAttribute extends AttributeInfo {
         return new SignatureAttribute(newCp, getSignature());
     }
 
+    void renameClass(String oldname, String newname) {
+        String sig = renameClass(getSignature(), oldname, newname);
+        setSignature(sig);
+    }
+
+    void renameClass(Map classnames) {
+        String sig = renameClass(getSignature(), classnames);
+        setSignature(sig);
+    }
+
+    static String renameClass(String desc, String oldname, String newname) {
+        if (desc.indexOf(oldname) < 0)
+            return desc;
+
+        StringBuffer newdesc = new StringBuffer();
+        int head = 0;
+        int i = 0;
+        for (;;) {
+            int j = desc.indexOf('L', i);
+            if (j < 0)
+                break;
+
+            int k = j;
+            int p = 0;
+            char c;
+            boolean match = true;
+            try {
+                int len = oldname.length();
+                while (isNamePart(c = desc.charAt(++k)))
+                    if (p >= len || c != oldname.charAt(p++))
+                        match = false;
+            }
+            catch (IndexOutOfBoundsException e) { break; }
+            i = k + 1;
+            if (match && p == oldname.length()) {
+                newdesc.append(desc.substring(head, j));
+                newdesc.append('L');
+                newdesc.append(newname);
+                newdesc.append(c);
+                head = i;
+            }
+        }
+
+        if (head == 0)
+            return desc;
+        else {
+            int len = desc.length();
+            if (head < len)
+                newdesc.append(desc.substring(head, len));
+
+            return newdesc.toString();
+        }
+    }
+
+    static String renameClass(String desc, Map map) {
+        if (map == null)
+            return desc;
+
+        StringBuffer newdesc = new StringBuffer();
+        int head = 0;
+        int i = 0;
+        for (;;) {
+            int j = desc.indexOf('L', i);
+            if (j < 0)
+                break;
+
+            StringBuffer nameBuf = new StringBuffer();
+            int k = j;
+            char c;
+            try {
+                while (isNamePart(c = desc.charAt(++k)))
+                    nameBuf.append(c);
+            }
+            catch (IndexOutOfBoundsException e) { break; }
+            i = k + 1;
+            String name = nameBuf.toString();
+            String name2 = (String)map.get(name);
+            if (name2 != null) {
+                newdesc.append(desc.substring(head, j));
+                newdesc.append('L');
+                newdesc.append(name2);
+                newdesc.append(c);
+                head = i;
+            }
+        }
+
+        if (head == 0)
+            return desc;
+        else {
+            int len = desc.length();
+            if (head < len)
+                newdesc.append(desc.substring(head, len));
+
+            return newdesc.toString();
+        }
+    }
+
+    private static boolean isNamePart(int c) {
+        return c != ';' && c != '<';
+    }
+
     static private class Cursor {
         int position = 0;