1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.tonicsystems.jarjar;
18
19 import com.tonicsystems.jarjar.util.*;
20 import java.io.*;
21 import java.util.*;
22 import org.objectweb.asm.*;
23 import org.objectweb.asm.Type;
24 import org.objectweb.asm.commons.*;
25
26
27 class KeepProcessor extends Remapper implements JarProcessor
28 {
29 private final ClassVisitor cv = new RemappingClassAdapter(new EmptyClassVisitor(), this);
30 private final List<Wildcard> wildcards;
31 private final List<String> roots = new ArrayList<String>();
32 private final Map<String, Set<String>> depend = new HashMap<String, Set<String>>();
33
34 public KeepProcessor(List<Keep> patterns) {
35 wildcards = PatternElement.createWildcards(patterns);
36 }
37
38 public boolean isEnabled() {
39 return !wildcards.isEmpty();
40 }
41
42 public Set<String> getExcludes() {
43 Set<String> closure = new HashSet<String>();
44 closureHelper(closure, roots);
45 Set<String> removable = new HashSet<String>(depend.keySet());
46 removable.removeAll(closure);
47 return removable;
48 }
49
50 private void closureHelper(Set<String> closure, Collection<String> process) {
51 if (process == null)
52 return;
53 for (String name : process) {
54 if (closure.add(name))
55 closureHelper(closure, depend.get(name));
56 }
57 }
58
59 private Set<String> curSet;
60 private byte[] buf = new byte[0x2000];
61
62 public boolean process(EntryStruct struct) throws IOException {
63 try {
64 if (struct.name.endsWith(".class")) {
65 String name = struct.name.substring(0, struct.name.length() - 6);
66 for (Wildcard wildcard : wildcards)
67 if (wildcard.matches(name))
68 roots.add(name);
69 depend.put(name, curSet = new HashSet<String>());
70 new ClassReader(new ByteArrayInputStream(struct.data)).accept(cv,
71 ClassReader.EXPAND_FRAMES);
72 curSet.remove(name);
73 }
74 } catch (Exception e) {
75 System.err.println("Error reading " + struct.name + ": " + e.getMessage());
76 }
77 return true;
78 }
79
80 public String map(String key) {
81 if (key.startsWith("java/"))
82 return null;
83 curSet.add(key);
84 return null;
85 }
86
87 public Object mapValue(Object value) {
88 if (value instanceof String) {
89 String s = (String)value;
90 if (PackageRemapper.isArrayForName(s)) {
91 mapDesc(s.replace('.', '/'));
92 } else if (isForName(s)) {
93 map(s.replace('.', '/'));
94 }
95 return value;
96 } else {
97 return super.mapValue(value);
98 }
99 }
100
101
102 private static boolean isForName(String value) {
103 if (value.equals(""))
104 return false;
105 for (int i = 0, len = value.length(); i < len; i++) {
106 char c = value.charAt(i);
107 if (c != '.' && !Character.isJavaIdentifierPart(c))
108 return false;
109 }
110 return true;
111 }
112 }