• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
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 
PackageRemapper(List<Rule> ruleList, boolean verbose)37     public PackageRemapper(List<Rule> ruleList, boolean verbose) {
38         this.verbose = verbose;
39         wildcards = PatternElement.createWildcards(ruleList);
40     }
41 
42     // also used by KeepProcessor
isArrayForName(String value)43     static boolean isArrayForName(String value) {
44       return ARRAY_FOR_NAME_PATTERN.matcher(value).matches();
45     }
46 
map(String key)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 
mapPath(String path)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             s = s.substring(0, s.length() - RESOURCE_SUFFIX.length()) + end;
80             pathCache.put(path, s);
81         }
82         return s;
83     }
84 
mapValue(Object value)85     public Object mapValue(Object value) {
86         if (value instanceof String) {
87             String s = valueCache.get(value);
88             if (s == null) {
89                 s = (String)value;
90                 if (isArrayForName(s)) {
91                     String desc1 = s.replace('.', '/');
92                     String desc2 = mapDesc(desc1);
93                     if (!desc2.equals(desc1))
94                         return desc2.replace('/', '.');
95                 } else {
96                     s = mapPath(s);
97                     if (s.equals(value)) {
98                         boolean hasDot = s.indexOf('.') >= 0;
99                         boolean hasSlash = s.indexOf('/') >= 0;
100                         if (!(hasDot && hasSlash)) {
101                             if (hasDot) {
102                                 s = replaceHelper(s.replace('.', '/')).replace('/', '.');
103                             } else {
104                                 s = replaceHelper(s);
105                             }
106                         }
107                     }
108                 }
109                 valueCache.put(value, s);
110             }
111             // TODO: add back class name to verbose message
112             if (verbose && !s.equals(value))
113                 System.err.println("Changed \"" + value + "\" -> \"" + s + "\"");
114             return s;
115         } else {
116             return super.mapValue(value);
117         }
118     }
119 
replaceHelper(String value)120     private String replaceHelper(String value) {
121         for (Wildcard wildcard : wildcards) {
122             String test = wildcard.replace(value);
123             if (test != null)
124                 return test;
125         }
126         return value;
127     }
128 }
129