| /* |
| * Copyright 2007 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.tonicsystems.jarjar; |
| |
| import java.util.*; |
| import java.util.regex.Pattern; |
| import org.objectweb.asm.*; |
| import org.objectweb.asm.commons.*; |
| |
| class PackageRemapper extends Remapper { |
| private static final String RESOURCE_SUFFIX = "RESOURCE"; |
| |
| private static final Pattern ARRAY_FOR_NAME_PATTERN = |
| Pattern.compile("\\[L[\\p{javaJavaIdentifierPart}\\.]+?;"); |
| |
| private final List<Wildcard> wildcards; |
| private final Map<String, String> typeCache = new HashMap<String, String>(); |
| private final Map<String, String> pathCache = new HashMap<String, String>(); |
| private final Map<Object, String> valueCache = new HashMap<Object, String>(); |
| private final boolean verbose; |
| |
| public PackageRemapper(List<Rule> ruleList, boolean verbose) { |
| this.verbose = verbose; |
| wildcards = PatternElement.createWildcards(ruleList); |
| } |
| |
| // also used by KeepProcessor |
| static boolean isArrayForName(String value) { |
| return ARRAY_FOR_NAME_PATTERN.matcher(value).matches(); |
| } |
| |
| public String map(String key) { |
| String s = typeCache.get(key); |
| if (s == null) { |
| s = replaceHelper(key); |
| if (key.equals(s)) { |
| s = null; |
| } |
| typeCache.put(key, s); |
| } |
| return s; |
| } |
| |
| public String mapPath(String path) { |
| String s = pathCache.get(path); |
| if (s == null) { |
| s = path; |
| int slash = s.lastIndexOf('/'); |
| String end; |
| if (slash < 0) { |
| end = s; |
| s = RESOURCE_SUFFIX; |
| } else { |
| end = s.substring(slash + 1); |
| s = s.substring(0, slash + 1) + RESOURCE_SUFFIX; |
| } |
| boolean absolute = s.startsWith("/"); |
| if (absolute) { |
| s = s.substring(1); |
| } |
| |
| s = replaceHelper(s); |
| |
| if (absolute) { |
| s = "/" + s; |
| } |
| if (s.indexOf(RESOURCE_SUFFIX) < 0) { |
| return path; |
| } |
| s = s.substring(0, s.length() - RESOURCE_SUFFIX.length()) + end; |
| pathCache.put(path, s); |
| } |
| return s; |
| } |
| |
| public Object mapValue(Object value) { |
| if (value instanceof String) { |
| String s = valueCache.get(value); |
| if (s == null) { |
| s = (String) value; |
| if (isArrayForName(s)) { |
| String desc1 = s.replace('.', '/'); |
| String desc2 = mapDesc(desc1); |
| if (!desc2.equals(desc1)) { |
| return desc2.replace('/', '.'); |
| } |
| } else { |
| s = mapPath(s); |
| if (s.equals(value)) { |
| boolean hasDot = s.indexOf('.') >= 0; |
| boolean hasSlash = s.indexOf('/') >= 0; |
| if (!(hasDot && hasSlash)) { |
| if (hasDot) { |
| s = replaceHelper(s.replace('.', '/')).replace('/', '.'); |
| } else { |
| s = replaceHelper(s); |
| } |
| } |
| } |
| } |
| valueCache.put(value, s); |
| } |
| // TODO: add back class name to verbose message |
| if (verbose && !s.equals(value)) { |
| System.err.println("Changed \"" + value + "\" -> \"" + s + "\""); |
| } |
| return s; |
| } else { |
| return super.mapValue(value); |
| } |
| } |
| |
| private String replaceHelper(String value) { |
| for (Wildcard wildcard : wildcards) { |
| String test = wildcard.replace(value); |
| if (test != null) { |
| return test; |
| } |
| } |
| return value; |
| } |
| } |