-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathJarInJarUtils.java
69 lines (65 loc) · 2.32 KB
/
JarInJarUtils.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
package software.coley.lljzip;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import software.coley.lljzip.format.compression.ZipCompressions;
import software.coley.lljzip.format.model.LocalFileHeader;
import software.coley.lljzip.format.model.ZipArchive;
import software.coley.lljzip.util.MemorySegmentUtil;
import java.io.IOException;
import java.lang.foreign.MemorySegment;
import java.util.function.Supplier;
/**
* Utilities for zip tests where there are embedded zip files.
*
* @author Matt Coley
*/
public class JarInJarUtils {
/**
* @param archiveSupplier
* Supplies a zip (jar) archive.
*
* @throws IOException
* When the zip cannot be read.
*/
public static void handleJar(Supplier<ZipArchive> archiveSupplier) throws IOException {
ZipArchive zipJvm = archiveSupplier.get();
for (LocalFileHeader lfh : zipJvm.getLocalFiles()) {
String entryName = lfh.getFileNameAsString();
if (entryName.endsWith(".class")) {
// We can verify the correctness of our zip model offsets and compression
// by parsing and writing back the class files contained in the jar.
// If anything is wrong, this process should fail.
handleClass(entryName, lfh);
} else if (entryName.endsWith(".jar")) {
// We should be able to extract contents in the jar in-memory and make the same assumptions
// as we do on the root (that classes can be parsed)
handleJar(() -> {
try {
MemorySegment decompressed = ZipCompressions.decompress(lfh);
return ZipIO.readStandard(decompressed);
} catch (IOException ex) {
throw new IllegalStateException("Failed to read inner jar: " + entryName, ex);
}
});
}
}
}
/**
* Attempts to parse the class file, and write it back. If there's an encoding/compression issue, this process fails.
*
* @param localFileHeader
* Local file header of class.
*
* @throws IOException
* When the class couldn't be parsed.
*/
public static void handleClass(String name, LocalFileHeader localFileHeader) throws IOException {
byte[] entryData = MemorySegmentUtil.toByteArray(ZipCompressions.decompress(localFileHeader));
try {
ClassReader reader = new ClassReader(entryData);
reader.accept(new ClassWriter(0), 0);
} catch (Throwable ex) {
throw new IOException("Failed to parse class: " + name, ex);
}
}
}