summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis/ClassCache.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/ClassCache.java')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/ClassCache.java127
1 files changed, 0 insertions, 127 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/ClassCache.java b/src/main/java/cuchaz/enigma/analysis/ClassCache.java
deleted file mode 100644
index f694bf3..0000000
--- a/src/main/java/cuchaz/enigma/analysis/ClassCache.java
+++ /dev/null
@@ -1,127 +0,0 @@
1package cuchaz.enigma.analysis;
2
3import com.google.common.cache.Cache;
4import com.google.common.cache.CacheBuilder;
5import com.google.common.collect.ImmutableSet;
6import cuchaz.enigma.ClassProvider;
7import cuchaz.enigma.ProgressListener;
8import cuchaz.enigma.analysis.index.JarIndex;
9import cuchaz.enigma.bytecode.translators.LocalVariableFixVisitor;
10import cuchaz.enigma.utils.Utils;
11import org.objectweb.asm.ClassReader;
12import org.objectweb.asm.ClassVisitor;
13import org.objectweb.asm.Opcodes;
14import org.objectweb.asm.tree.ClassNode;
15
16import javax.annotation.Nullable;
17import java.io.IOException;
18import java.nio.file.FileSystem;
19import java.nio.file.FileSystems;
20import java.nio.file.Files;
21import java.nio.file.Path;
22import java.util.concurrent.ExecutionException;
23import java.util.concurrent.TimeUnit;
24import java.util.function.Supplier;
25
26public final class ClassCache implements AutoCloseable, ClassProvider {
27 private final FileSystem fileSystem;
28 private final ImmutableSet<String> classNames;
29
30 private final Cache<String, ClassNode> nodeCache = CacheBuilder.newBuilder()
31 .maximumSize(128)
32 .expireAfterAccess(1, TimeUnit.MINUTES)
33 .build();
34
35 private ClassCache(FileSystem fileSystem, ImmutableSet<String> classNames) {
36 this.fileSystem = fileSystem;
37 this.classNames = classNames;
38 }
39
40 public static ClassCache of(Path jarPath) throws IOException {
41 FileSystem fileSystem = FileSystems.newFileSystem(jarPath, (ClassLoader) null);
42 ImmutableSet<String> classNames = collectClassNames(fileSystem);
43
44 return new ClassCache(fileSystem, classNames);
45 }
46
47 private static ImmutableSet<String> collectClassNames(FileSystem fileSystem) throws IOException {
48 ImmutableSet.Builder<String> classNames = ImmutableSet.builder();
49 for (Path root : fileSystem.getRootDirectories()) {
50 Files.walk(root).map(Path::toString)
51 .forEach(path -> {
52 if (path.endsWith(".class")) {
53 String name = path.substring(1, path.length() - ".class".length());
54 classNames.add(name);
55 }
56 });
57 }
58
59 return classNames.build();
60 }
61
62 @Nullable
63 @Override
64 public ClassNode getClassNode(String name) {
65 if (!classNames.contains(name)) {
66 return null;
67 }
68
69 try {
70 return nodeCache.get(name, () -> parseNode(name));
71 } catch (ExecutionException e) {
72 throw new RuntimeException(e);
73 }
74 }
75
76 private ClassNode parseNode(String name) throws IOException {
77 ClassReader reader = getReader(name);
78
79 ClassNode node = new ClassNode();
80
81 LocalVariableFixVisitor visitor = new LocalVariableFixVisitor(Utils.ASM_VERSION, node);
82 reader.accept(visitor, 0);
83
84 return node;
85 }
86
87 private ClassReader getReader(String name) throws IOException {
88 Path path = fileSystem.getPath(name + ".class");
89 byte[] bytes = Files.readAllBytes(path);
90 return new ClassReader(bytes);
91 }
92
93 public int getClassCount() {
94 return classNames.size();
95 }
96
97 public void visit(Supplier<ClassVisitor> visitorSupplier, int readFlags) {
98 for (String className : classNames) {
99 ClassVisitor visitor = visitorSupplier.get();
100
101 ClassNode cached = nodeCache.getIfPresent(className);
102 if (cached != null) {
103 cached.accept(visitor);
104 continue;
105 }
106
107 try {
108 ClassReader reader = getReader(className);
109 reader.accept(visitor, readFlags);
110 } catch (IOException e) {
111 System.out.println("Failed to visit class " + className);
112 e.printStackTrace();
113 }
114 }
115 }
116
117 @Override
118 public void close() throws IOException {
119 this.fileSystem.close();
120 }
121
122 public JarIndex index(ProgressListener progress) {
123 JarIndex index = JarIndex.empty();
124 index.indexJar(this, progress);
125 return index;
126 }
127}