aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShigeru Chiba <chibash@users.noreply.github.com>2022-05-12 00:42:15 +0900
committerGitHub <noreply@github.com>2022-05-12 00:42:15 +0900
commitc8b54b3bcec4b244f9faf56d4f459d6beb809e62 (patch)
tree43d85d1519530403d4dbfd186e2ded71d7c85112 /src
parent01c788fb8d00fa3003434cb002b8951e4ea3bb6f (diff)
parentda39aa805002d3b090d7f93410adce36f1e97d84 (diff)
downloadjavassist-c8b54b3bcec4b244f9faf56d4f459d6beb809e62.tar.gz
javassist-c8b54b3bcec4b244f9faf56d4f459d6beb809e62.zip
Merge pull request #299 from pietrobraione/master
Fix renaming of classes in presence of generic signatures and nested classes. This pull request has some problems but I'll fix them later.
Diffstat (limited to 'src')
-rw-r--r--src/main/javassist/bytecode/SignatureAttribute.java94
-rw-r--r--src/test/javassist/bytecode/SignatureAttributeTest.java84
2 files changed, 153 insertions, 25 deletions
diff --git a/src/main/javassist/bytecode/SignatureAttribute.java b/src/main/javassist/bytecode/SignatureAttribute.java
index 6a483057..c17b3f29 100644
--- a/src/main/javassist/bytecode/SignatureAttribute.java
+++ b/src/main/javassist/bytecode/SignatureAttribute.java
@@ -19,6 +19,7 @@ package javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -110,41 +111,84 @@ public class SignatureAttribute extends AttributeInfo {
}
static String renameClass(String desc, Map<String,String> map) {
- if (map == null)
+ if (map == null || map.isEmpty())
return desc;
StringBuilder newdesc = new StringBuilder();
int head = 0;
int i = 0;
for (;;) {
- int j = desc.indexOf('L', i);
+ final int j = desc.indexOf('L', i);
if (j < 0)
break;
- int k = desc.indexOf(';', j);
- if (k < 0)
- break;
-
- int l = desc.indexOf('<', j);
- int classEndIndex;
- char classEndChar;
- if (l < 0 || k < l) {
- classEndIndex = k;
- classEndChar = ';';
- } else {
- classEndIndex = l;
- classEndChar = '<';
+ StringBuilder nameBuf = new StringBuilder();
+ StringBuilder genericParamBuf = new StringBuilder();
+ final ArrayList<StringBuilder> nameBufs = new ArrayList<>();
+ final ArrayList<StringBuilder> genericParamBufs = new ArrayList<>();
+ int k = j;
+ char c;
+ try {
+ while ((c = desc.charAt(++k)) != ';') {
+ if (c == '<') {
+ genericParamBuf.append(c);
+ int level = 1;
+ while (level > 0) {
+ c = desc.charAt(++k);
+ genericParamBuf.append(c);
+ if (c == '<') ++level;
+ else if (c == '>') --level;
+ }
+ } else if (c == '.') {
+ nameBufs.add(nameBuf);
+ genericParamBufs.add(genericParamBuf);
+ nameBuf = new StringBuilder();
+ genericParamBuf = new StringBuilder();
+ } else {
+ nameBuf.append(c);
+ }
+ }
}
- i = classEndIndex + 1;
-
- String name = desc.substring(j + 1, classEndIndex);
- String name2 = map.get(name);
- if (name2 != null) {
- newdesc.append(desc.substring(head, j));
- newdesc.append('L');
- newdesc.append(name2);
- newdesc.append(classEndChar);
- head = i;
+ catch (IndexOutOfBoundsException e) { break; }
+
+ nameBufs.add(nameBuf);
+ genericParamBufs.add(genericParamBuf);
+ i = k + 1;
+
+ String name = String.join("$", nameBufs.toArray(new StringBuilder[0]));
+ String newname = map.get(name);
+ if (newname != null) {
+ final String[] nameSplit = name.split("\\$");
+ final String[] newnameSplit = newname.split("\\$");
+ if (nameSplit.length == newnameSplit.length) {
+ final String[] newnames = new String[nameBufs.size()];
+ for (int start = 0, z = 0; z < nameBufs.size(); ++z) {
+ final int toAggregate = (int) nameBufs.get(z).chars().filter(ch -> ch == '$').count() + 1;
+ String s = String.join("$", Arrays.copyOfRange(newnameSplit, start, start + toAggregate));
+ start += toAggregate;
+ newnames[z] = s;
+ }
+
+
+ newdesc.append(desc.substring(head, j));
+ newdesc.append('L');
+ for (int z = 0; z < newnames.length; ++z) {
+ if (z > 0) {
+ newdesc.append('.');
+ }
+ newdesc.append(newnames[z]);
+ final String newgenericParam;
+ final StringBuilder genericParamBufCurrent = genericParamBufs.get(z);
+ if (genericParamBufCurrent.length() > 0) {
+ newgenericParam = "<" + renameClass(genericParamBufCurrent.substring(1, genericParamBufCurrent.length() - 1), map) + ">";
+ } else {
+ newgenericParam = genericParamBufCurrent.toString(); //empty string
+ }
+ newdesc.append(newgenericParam);
+ }
+ newdesc.append(c); //the final semicolon
+ head = i;
+ }
}
}
diff --git a/src/test/javassist/bytecode/SignatureAttributeTest.java b/src/test/javassist/bytecode/SignatureAttributeTest.java
new file mode 100644
index 00000000..1bf654d4
--- /dev/null
+++ b/src/test/javassist/bytecode/SignatureAttributeTest.java
@@ -0,0 +1,84 @@
+package javassist.bytecode;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashMap;
+
+public class SignatureAttributeTest {
+ void test1() {
+ final String signature = "TX;TY;La/b/C$D$E$J$K;"; //a sequence of three ReferenceTypeSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("a/b/C$D$E$J$K", "o/p/Q$R$S$T$U");
+ map.put("e/F$G$H$I", "v/W$X$Y$Z");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("TX;TY;Lo/p/Q$R$S$T$U;", signatureRenamed);
+ }
+
+ void test2() {
+ final String signature = "La/b/C<TA;TB;>.D<Ljava/lang/Integer;>;"; //a ClassTypeSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("a/b/C$D", "o/p/Q$R");
+ map.put("java/lang/Integer", "java/lang/Long");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("Lo/p/Q<TA;TB;>.R<Ljava/lang/Long;>;", signatureRenamed);
+ }
+
+ void test3() {
+ final String signature = "BJLB<TX;Lc/D$E;>.F<TY;>;TZ;"; //a sequence of four JavaTypeSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("B$F", "P$T");
+ map.put("c/D$E", "q/R$S");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("BJLP<TX;Lq/R$S;>.T<TY;>;TZ;", signatureRenamed);
+ }
+
+ void test4() {
+ final String signature = "La/b/C<TX;>;[[Ld/E<+TY;-Ljava/lang/Object;*>;Z"; //a sequence of three JavaTypeSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("java/lang/Object", "java/util/Map");
+ map.put("d/E", "F");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("La/b/C<TX;>;[[LF<+TY;-Ljava/util/Map;*>;Z", signatureRenamed);
+ }
+
+ void test5() {
+ final String signature = "La/b/C$D$E<TX;Le/F$G<TY;TZ;>.H$I<TU;TV;>;>.J$K;"; //a ClassTypeSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("a/b/C$D$E$J$K", "o/p/Q$R$S$T$U");
+ map.put("e/F$G$H$I", "v/W$X$Y$Z");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("Lo/p/Q$R$S<TX;Lv/W$X<TY;TZ;>.Y$Z<TU;TV;>;>.T$U;", signatureRenamed);
+ }
+
+ void test6() {
+ final String signature = "<X:La/B$C<TY;>.D<TZ;>;:Le/F$G;>Lh/I$J;"; //a ClassSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("a/B$C$D", "o/P$Q$R");
+ map.put("e/F$G", "s/T$U");
+ map.put("h/I$J", "v/W$X");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("<X:Lo/P$Q<TY;>.R<TZ;>;:Ls/T$U;>Lv/W$X;", signatureRenamed);
+ }
+
+ void test7() {
+ final String signature = "<A:La/B$C;:Ld/E<TX;>.F<TY;>;:TZ;B:Ljava/lang/Thread;>(LX;TA;LA;)V^Ljava/lang/Exception;"; //a MethodSignature
+ final HashMap<String, String> map = new HashMap<>();
+ map.put("A", "P");
+ map.put("a/B$C", "s/T$U");
+ map.put("d/E$F", "v/W$X");
+ map.put("X", "V");
+ map.put("java/lang/Exception", "java/lang/RuntimeException");
+ final String signatureRenamed = SignatureAttribute.renameClass(signature, map);
+ assertEquals("<A:Ls/T$U;:Lv/W<TX;>.X<TY;>;:TZ;B:Ljava/lang/Thread;>(LV;TA;LP;)V^Ljava/lang/RuntimeException;", signatureRenamed);
+ }
+
+ public static void main(String[] s) {
+ new SignatureAttributeTest().test1();
+ new SignatureAttributeTest().test2();
+ new SignatureAttributeTest().test3();
+ new SignatureAttributeTest().test4();
+ new SignatureAttributeTest().test5();
+ new SignatureAttributeTest().test6();
+ new SignatureAttributeTest().test7();
+ }
+}