-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
ClassLoaderPool.java
139 lines (116 loc) · 3.51 KB
/
ClassLoaderPool.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package javassist;
import nallar.tickthreading.PatchLog;
import net.minecraft.launchwrapper.LaunchClassLoader;
import java.io.*;
import java.net.*;
/**
* This is in the javassist package (which isn't sealed) to access package-local javassist internals needed to load
* from the classloader at runtime for patching purposes.
*/
public class ClassLoaderPool extends ClassPool {
private final boolean preSrg;
public ClassLoaderPool(boolean preSrg) {
this.preSrg = preSrg;
this.appendSystemPath();
this.importPackage("java.util");
this.importPackage("java.lang");
}
@Override
protected void cacheCtClass(String className, CtClass c, boolean dynamic) {
super.cacheCtClass(className, c, dynamic);
}
@Override
public CtClass getCached(String className) {
return super.getCached(className);
}
@Override
protected synchronized CtClass get0(String className, boolean useCache) throws NotFoundException {
CtClass clazz;
if (useCache) {
clazz = getCached(className);
if (clazz != null) {
return clazz;
}
}
clazz = createCtClass(className, useCache);
if (clazz != null) {
// clazz.getName() != classname if classname is "[L<name>;".
if (useCache) {
cacheCtClass(clazz.getName(), clazz, false);
}
}
return clazz;
}
byte[] getClassBytesRuntime(String className) {
if (LaunchClassLoader.instance.excluded(className)) {
return null;
}
byte[] bytes = preSrg ? LaunchClassLoader.instance.getPreSrgBytes(className) : LaunchClassLoader.instance.getSrgBytes(className);
if (bytes == null) {
PatchLog.fine("Failed to find class " + className + ", preSrg: " + preSrg);
}
return bytes;
}
@Override
public URL find(String className) {
byte[] bytes = getClassBytesRuntime(className);
if (bytes != null) {
try {
return new URL(null, "runtimeclass:" + className.replace(".", "/"), new Handler(bytes));
} catch (MalformedURLException e) {
PatchLog.severe("Failed to make fake URL for " + className, e);
}
}
return source.find(className);
}
@Override
InputStream openClassfile(String className) throws NotFoundException {
byte[] bytes = getClassBytesRuntime(className);
if (bytes != null) {
return new ByteArrayInputStream(bytes);
}
return source.openClassfile(className);
}
@Override
void writeClassfile(String className, OutputStream out) throws NotFoundException, IOException, CannotCompileException {
byte[] bytes = getClassBytesRuntime(className);
if (bytes != null) {
out.write(bytes);
} else {
source.writeClassfile(className, out);
}
}
public static class Handler extends URLStreamHandler {
final byte[] data;
public Handler(byte[] data) {
this.data = data;
}
@Override
protected URLConnection openConnection(URL u) throws IOException {
return new MockHttpURLConnection(u, data);
}
public static class MockHttpURLConnection extends HttpURLConnection {
private final byte[] data;
protected MockHttpURLConnection(URL url, byte[] data) {
super(url);
this.data = data;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
@Override
public void connect() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void disconnect() {
throw new UnsupportedOperationException();
}
@Override
public boolean usingProxy() {
return false;
}
}
}
}