1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.tonicsystems.jarjar;
18
19 import org.objectweb.asm.*;
20 import org.objectweb.asm.commons.*;
21 import java.util.*;
22 import java.util.regex.Pattern;
23
24 class PackageRemapper extends Remapper
25 {
26 private static final String RESOURCE_SUFFIX = "RESOURCE";
27
28 private static final Pattern ARRAY_FOR_NAME_PATTERN
29 = Pattern.compile("\\[L[\\p{javaJavaIdentifierPart}\\.]+?;");
30
31 private final List<Wildcard> wildcards;
32 private final Map<String, String> typeCache = new HashMap<String, String>();
33 private final Map<String, String> pathCache = new HashMap<String, String>();
34 private final Map<Object, String> valueCache = new HashMap<Object, String>();
35 private final boolean verbose;
36
37 public PackageRemapper(List<Rule> ruleList, boolean verbose) {
38 this.verbose = verbose;
39 wildcards = PatternElement.createWildcards(ruleList);
40 }
41
42
43 static boolean isArrayForName(String value) {
44 return ARRAY_FOR_NAME_PATTERN.matcher(value).matches();
45 }
46
47 public String map(String key) {
48 String s = typeCache.get(key);
49 if (s == null) {
50 s = replaceHelper(key);
51 if (key.equals(s))
52 s = null;
53 typeCache.put(key, s);
54 }
55 return s;
56 }
57
58 public String mapPath(String path) {
59 String s = pathCache.get(path);
60 if (s == null) {
61 s = path;
62 int slash = s.lastIndexOf('/');
63 String end;
64 if (slash < 0) {
65 end = s;
66 s = RESOURCE_SUFFIX;
67 } else {
68 end = s.substring(slash + 1);
69 s = s.substring(0, slash + 1) + RESOURCE_SUFFIX;
70 }
71 boolean absolute = s.startsWith("/");
72 if (absolute) s = s.substring(1);
73
74 s = replaceHelper(s);
75
76 if (absolute) s = "/" + s;
77 if (s.indexOf(RESOURCE_SUFFIX) < 0)
78 return path;
79 if (end.length() > 0)
80 s = s.substring(0, s.length() - RESOURCE_SUFFIX.length()) + end;
81 else
82 s = s.substring(0, s.lastIndexOf('/') + 1);
83 pathCache.put(path, s);
84 }
85 return s;
86 }
87
88 public Object mapValue(Object value) {
89 if (value instanceof String) {
90 String s = valueCache.get(value);
91 if (s == null) {
92 s = (String)value;
93 if (isArrayForName(s)) {
94 String desc1 = s.replace('.', '/');
95 String desc2 = mapDesc(desc1);
96 if (!desc2.equals(desc1))
97 return desc2.replace('/', '.');
98 } else {
99 s = mapPath(s);
100 if (s.equals(value)) {
101 boolean hasDot = s.indexOf('.') >= 0;
102 boolean hasSlash = s.indexOf('/') >= 0;
103 if (!(hasDot && hasSlash)) {
104 if (hasDot) {
105 s = replaceHelper(s.replace('.', '/')).replace('/', '.');
106 } else {
107 s = replaceHelper(s);
108 }
109 }
110 }
111 }
112 valueCache.put(value, s);
113 }
114
115 if (verbose && !s.equals(value))
116 System.err.println("Changed \"" + value + "\" -> \"" + s + "\"");
117 return s;
118 } else {
119 return super.mapValue(value);
120 }
121 }
122
123 private String replaceHelper(String value) {
124 for (Wildcard wildcard : wildcards) {
125 String test = wildcard.replace(value);
126 if (test != null)
127 return test;
128 }
129 return value;
130 }
131 }