1ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba/** 2ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * Copyright 2007 Google Inc. 3ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * 4ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * Licensed under the Apache License, Version 2.0 (the "License"); 5ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * you may not use this file except in compliance with the License. 6ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * You may obtain a copy of the License at 7ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * 8ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * http://www.apache.org/licenses/LICENSE-2.0 9ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * 10ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * Unless required by applicable law or agreed to in writing, software 11ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * distributed under the License is distributed on an "AS IS" BASIS, 12ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * See the License for the specific language governing permissions and 14ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba * limitations under the License. 15ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba */ 16ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 17ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibapackage com.tonicsystems.jarjar; 18ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 19ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaimport com.tonicsystems.jarjar.util.*; 20ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaimport java.io.*; 21ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaimport java.util.*; 22ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaimport org.objectweb.asm.*; 23ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaimport org.objectweb.asm.Type; 24ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaimport org.objectweb.asm.commons.*; 25ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 26ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba// TODO: this can probably be refactored into JarClassVisitor, etc. 27ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosibaclass KeepProcessor extends Remapper implements JarProcessor 28ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba{ 29ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private final ClassVisitor cv = new RemappingClassAdapter(new EmptyClassVisitor(), this); 30ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private final List<Wildcard> wildcards; 31ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private final List<String> roots = new ArrayList<String>(); 32ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private final Map<String, Set<String>> depend = new HashMap<String, Set<String>>(); 33ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 34ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba public KeepProcessor(List<Keep> patterns) { 35ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba wildcards = PatternElement.createWildcards(patterns); 36ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 37ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 38ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba public boolean isEnabled() { 39ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return !wildcards.isEmpty(); 40ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 41ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 42ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba public Set<String> getExcludes() { 43ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba Set<String> closure = new HashSet<String>(); 44ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba closureHelper(closure, roots); 45ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba Set<String> removable = new HashSet<String>(depend.keySet()); 46ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba removable.removeAll(closure); 47ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return removable; 48ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 49ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 50ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private void closureHelper(Set<String> closure, Collection<String> process) { 51ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (process == null) 52ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return; 53ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba for (String name : process) { 54ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (closure.add(name)) 55ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba closureHelper(closure, depend.get(name)); 56ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 57ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 58ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 59ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private Set<String> curSet; 60ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private byte[] buf = new byte[0x2000]; 61ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 62ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba public boolean process(EntryStruct struct) throws IOException { 63ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba try { 64ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (struct.name.endsWith(".class")) { 65ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba String name = struct.name.substring(0, struct.name.length() - 6); 66ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba for (Wildcard wildcard : wildcards) 67ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (wildcard.matches(name)) 68ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba roots.add(name); 69ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba depend.put(name, curSet = new HashSet<String>()); 70ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba new ClassReader(new ByteArrayInputStream(struct.data)).accept(cv, 71ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba ClassReader.EXPAND_FRAMES); 72ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba curSet.remove(name); 73ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 74ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } catch (Exception e) { 75ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba System.err.println("Error reading " + struct.name + ": " + e.getMessage()); 76ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 77ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return true; 78ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 79ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 80ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba public String map(String key) { 81ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (key.startsWith("java/") || key.startsWith("javax/")) 82ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return null; 83ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba curSet.add(key); 84ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return null; 85ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 86ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 87ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba public Object mapValue(Object value) { 88ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (value instanceof String) { 89ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba String s = (String)value; 90ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (PackageRemapper.isArrayForName(s)) { 91ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba mapDesc(s.replace('.', '/')); 92ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } else if (isForName(s)) { 93ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba map(s.replace('.', '/')); 94ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 95ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return value; 96ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } else { 97ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return super.mapValue(value); 98ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 99ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 100ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba 101ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba // TODO: use this for package remapping too? 102ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba private static boolean isForName(String value) { 103ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (value.equals("")) 104ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return false; 105ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba for (int i = 0, len = value.length(); i < len; i++) { 106ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba char c = value.charAt(i); 107ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba if (c != '.' && !Character.isJavaIdentifierPart(c)) 108ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return false; 109ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 110ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba return true; 111ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba } 112ab61347a2cb3254688c42c993278cefd43e5d99dMarcin Kosiba} 113