diff options
| author | 2018-12-08 11:21:18 +0100 | |
|---|---|---|
| committer | 2018-12-08 11:21:18 +0100 | |
| commit | 4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5 (patch) | |
| tree | 99e43aa385d7fa1248c7fe474c022db55c364592 /src/main/java/cuchaz/enigma/analysis/ParsedJar.java | |
| parent | work around Procyon weirdness (diff) | |
| download | enigma-fork-4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5.tar.gz enigma-fork-4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5.tar.xz enigma-fork-4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5.zip | |
add barebones plugin framework, cleanup
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/ParsedJar.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/analysis/ParsedJar.java | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/ParsedJar.java b/src/main/java/cuchaz/enigma/analysis/ParsedJar.java index 55f2141..86655d0 100644 --- a/src/main/java/cuchaz/enigma/analysis/ParsedJar.java +++ b/src/main/java/cuchaz/enigma/analysis/ParsedJar.java | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | 11 | ||
| 12 | package cuchaz.enigma.analysis; | 12 | package cuchaz.enigma.analysis; |
| 13 | 13 | ||
| 14 | import com.google.common.io.ByteStreams; | ||
| 14 | import cuchaz.enigma.mapping.entry.ClassEntry; | 15 | import cuchaz.enigma.mapping.entry.ClassEntry; |
| 15 | import org.objectweb.asm.ClassReader; | 16 | import org.objectweb.asm.ClassReader; |
| 17 | import org.objectweb.asm.ClassVisitor; | ||
| 16 | import org.objectweb.asm.tree.ClassNode; | 18 | import org.objectweb.asm.tree.ClassNode; |
| 17 | 19 | ||
| 18 | import java.io.BufferedInputStream; | 20 | import java.io.BufferedInputStream; |
| @@ -20,14 +22,17 @@ import java.io.IOException; | |||
| 20 | import java.io.InputStream; | 22 | import java.io.InputStream; |
| 21 | import java.util.*; | 23 | import java.util.*; |
| 22 | import java.util.function.Consumer; | 24 | import java.util.function.Consumer; |
| 25 | import java.util.function.Function; | ||
| 23 | import java.util.jar.JarEntry; | 26 | import java.util.jar.JarEntry; |
| 24 | import java.util.jar.JarFile; | 27 | import java.util.jar.JarFile; |
| 25 | import java.util.jar.JarInputStream; | 28 | import java.util.jar.JarInputStream; |
| 26 | 29 | ||
| 27 | public class ParsedJar { | 30 | public class ParsedJar { |
| 28 | private final Map<String, ClassNode> nodes = new LinkedHashMap<>(); | 31 | private final Map<String, byte[]> classBytes; |
| 32 | private final Map<String, ClassNode> nodeCache = new HashMap<>(); | ||
| 29 | 33 | ||
| 30 | public ParsedJar(JarFile jar) throws IOException { | 34 | public ParsedJar(JarFile jar) throws IOException { |
| 35 | Map<String, byte[]> uClassBytes = new LinkedHashMap<>();; | ||
| 31 | try { | 36 | try { |
| 32 | // get the jar entries that correspond to classes | 37 | // get the jar entries that correspond to classes |
| 33 | Enumeration<JarEntry> entries = jar.entries(); | 38 | Enumeration<JarEntry> entries = jar.entries(); |
| @@ -36,60 +41,75 @@ public class ParsedJar { | |||
| 36 | // is this a class file? | 41 | // is this a class file? |
| 37 | if (entry.getName().endsWith(".class")) { | 42 | if (entry.getName().endsWith(".class")) { |
| 38 | try (InputStream input = new BufferedInputStream(jar.getInputStream(entry))) { | 43 | try (InputStream input = new BufferedInputStream(jar.getInputStream(entry))) { |
| 39 | // read the ClassNode from the jar | ||
| 40 | ClassReader reader = new ClassReader(input); | ||
| 41 | ClassNode node = new ClassNode(); | ||
| 42 | reader.accept(node, 0); | ||
| 43 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); | 44 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); |
| 44 | nodes.put(path, node); | 45 | uClassBytes.put(path, ByteStreams.toByteArray(input)); |
| 45 | } | 46 | } |
| 46 | } | 47 | } |
| 47 | } | 48 | } |
| 48 | } finally { | 49 | } finally { |
| 49 | jar.close(); | 50 | jar.close(); |
| 51 | classBytes = Collections.unmodifiableMap(uClassBytes); | ||
| 50 | } | 52 | } |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | public ParsedJar(JarInputStream jar) throws IOException { | 55 | public ParsedJar(JarInputStream jar) throws IOException { |
| 56 | Map<String, byte[]> uClassBytes = new LinkedHashMap<>(); | ||
| 54 | try { | 57 | try { |
| 55 | // get the jar entries that correspond to classes | 58 | // get the jar entries that correspond to classes |
| 56 | JarEntry entry; | 59 | JarEntry entry; |
| 57 | while ((entry = jar.getNextJarEntry()) != null) { | 60 | while ((entry = jar.getNextJarEntry()) != null) { |
| 58 | // is this a class file? | 61 | // is this a class file? |
| 59 | if (entry.getName().endsWith(".class")) { | 62 | if (entry.getName().endsWith(".class")) { |
| 60 | // read the ClassNode from the jar | ||
| 61 | ClassReader reader = new ClassReader(jar); | ||
| 62 | ClassNode node = new ClassNode(); | ||
| 63 | reader.accept(node, 0); | ||
| 64 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); | 63 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); |
| 65 | nodes.put(path, node); | 64 | uClassBytes.put(path, ByteStreams.toByteArray(jar)); |
| 66 | jar.closeEntry(); | 65 | jar.closeEntry(); |
| 67 | } | 66 | } |
| 68 | } | 67 | } |
| 69 | } finally { | 68 | } finally { |
| 70 | jar.close(); | 69 | jar.close(); |
| 70 | classBytes = Collections.unmodifiableMap(uClassBytes); | ||
| 71 | } | 71 | } |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | public void visit(Consumer<ClassNode> visitor) { | 74 | public void visitReader(Function<String, ClassVisitor> visitorFunction, int options) { |
| 75 | for (ClassNode node : nodes.values()) { | 75 | for (String s : classBytes.keySet()) { |
| 76 | visitor.accept(node); | 76 | ClassNode nodeCached = nodeCache.get(s); |
| 77 | if (nodeCached != null) { | ||
| 78 | nodeCached.accept(visitorFunction.apply(s)); | ||
| 79 | } else { | ||
| 80 | new ClassReader(classBytes.get(s)).accept(visitorFunction.apply(s), options); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | public void visitNode(Consumer<ClassNode> consumer) { | ||
| 86 | for (String s : classBytes.keySet()) { | ||
| 87 | consumer.accept(getClassNode(s)); | ||
| 77 | } | 88 | } |
| 78 | } | 89 | } |
| 79 | 90 | ||
| 80 | public int getClassCount() { | 91 | public int getClassCount() { |
| 81 | return nodes.size(); | 92 | return classBytes.size(); |
| 82 | } | 93 | } |
| 83 | 94 | ||
| 84 | public List<ClassEntry> getClassEntries() { | 95 | public List<ClassEntry> getClassEntries() { |
| 85 | List<ClassEntry> entries = new ArrayList<>(nodes.size()); | 96 | List<ClassEntry> entries = new ArrayList<>(classBytes.size()); |
| 86 | for (ClassNode node : nodes.values()) { | 97 | for (String s : classBytes.keySet()) { |
| 87 | entries.add(new ClassEntry(node.name)); | 98 | entries.add(new ClassEntry(s)); |
| 88 | } | 99 | } |
| 89 | return entries; | 100 | return entries; |
| 90 | } | 101 | } |
| 91 | 102 | ||
| 92 | public ClassNode getClassNode(String name) { | 103 | public ClassNode getClassNode(String name) { |
| 93 | return nodes.get(name); | 104 | return nodeCache.computeIfAbsent(name, (n) -> { |
| 105 | ClassReader reader = new ClassReader(classBytes.get(name)); | ||
| 106 | ClassNode node = new ClassNode(); | ||
| 107 | reader.accept(node, 0); | ||
| 108 | return node; | ||
| 109 | }); | ||
| 94 | } | 110 | } |
| 111 | |||
| 112 | public Map<String, byte[]> getClassDataMap() { | ||
| 113 | return classBytes; | ||
| 114 | } | ||
| 95 | } | 115 | } |