1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.bcel.generic;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.fail;
23 import static org.junit.jupiter.api.Assumptions.assumeTrue;
24
25 import java.io.File;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.nio.file.FileSystems;
29 import java.nio.file.FileVisitResult;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.PathMatcher;
33 import java.nio.file.SimpleFileVisitor;
34 import java.nio.file.attribute.BasicFileAttributes;
35 import java.util.Enumeration;
36 import java.util.jar.JarEntry;
37 import java.util.jar.JarFile;
38
39 import org.apache.bcel.classfile.ClassParser;
40 import org.apache.bcel.classfile.Code;
41 import org.apache.bcel.classfile.JavaClass;
42 import org.apache.bcel.classfile.Method;
43 import org.apache.bcel.util.ModularRuntimeImage;
44 import org.apache.commons.lang3.JavaVersion;
45 import org.apache.commons.lang3.SystemUtils;
46 import org.junit.jupiter.api.condition.DisabledOnJre;
47 import org.junit.jupiter.api.condition.JRE;
48 import org.junit.jupiter.params.ParameterizedTest;
49 import org.junit.jupiter.params.provider.MethodSource;
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 public class JdkGenericDumpTestCase {
76
77 private static class ClassParserFilesVisitor extends SimpleFileVisitor<Path> {
78
79 private final PathMatcher matcher;
80
81 @SuppressWarnings("resource")
82 ClassParserFilesVisitor(final String pattern) {
83 matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
84 }
85
86 private void find(final Path path) throws IOException {
87 final Path name = path.getFileName();
88 if (name != null && matcher.matches(name)) {
89 try (final InputStream inputStream = Files.newInputStream(path)) {
90 final ClassParser classParser = new ClassParser(inputStream, name.toAbsolutePath().toString());
91 assertNotNull(classParser.parse());
92 }
93 }
94 }
95
96 @Override
97 public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
98 find(dir);
99 return FileVisitResult.CONTINUE;
100 }
101
102 @Override
103 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
104 find(file);
105 return FileVisitResult.CONTINUE;
106 }
107
108 @Override
109 public FileVisitResult visitFileFailed(final Path file, final IOException e) {
110 System.err.println(e);
111 return FileVisitResult.CONTINUE;
112 }
113 }
114
115 private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
116
117 private static String bytesToHex(final byte[] bytes) {
118 final char[] hexChars = new char[bytes.length * 3];
119 int i = 0;
120 for (final byte b : bytes) {
121 final int v = b & 0xFF;
122 hexChars[i++] = hexArray[v >>> 4];
123 hexChars[i++] = hexArray[v & 0x0F];
124 hexChars[i++] = ' ';
125 }
126 return new String(hexChars);
127 }
128
129 private void compare(final String name, final Method method) {
130
131 final Code code = method.getCode();
132 if (code == null) {
133 return;
134 }
135 final byte[] src = code.getCode();
136 final InstructionList instructionList = new InstructionList(src);
137 final byte[] out = instructionList.getByteCode();
138 if (src.length == out.length) {
139 assertArrayEquals(src, out, () -> name + ": " + method.toString());
140 } else {
141 System.out.println(name + ": " + method.toString() + " " + src.length + " " + out.length);
142 System.out.println(bytesToHex(src));
143 System.out.println(bytesToHex(out));
144 for (final InstructionHandle instructionHandle : instructionList) {
145 System.out.println(instructionHandle.toString(false));
146 }
147 fail("Array comparison failure");
148 }
149 }
150
151 private void testJar(final Path file) throws Exception {
152 System.out.println(file);
153 try (JarFile jar = new JarFile(file.toFile())) {
154 final Enumeration<JarEntry> en = jar.entries();
155 while (en.hasMoreElements()) {
156 final JarEntry jarEntry = en.nextElement();
157 final String name = jarEntry.getName();
158 if (name.endsWith(JavaClass.EXTENSION)) {
159
160 try (InputStream inputStream = jar.getInputStream(jarEntry)) {
161 final ClassParser classParser = new ClassParser(inputStream, name);
162 final JavaClass javaClass = classParser.parse();
163 for (final Method method : javaClass.getMethods()) {
164 compare(name, method);
165 }
166 }
167 }
168 }
169 }
170 }
171
172 @ParameterizedTest
173 @MethodSource("org.apache.bcel.generic.JavaHome#streamJarPath")
174 public void testJdkJars(final Path jarPath) throws Exception {
175 testJar(jarPath);
176 }
177
178 @ParameterizedTest
179 @MethodSource("org.apache.bcel.generic.JavaHome#streamModulePath")
180 @DisabledOnJre(value = JRE.JAVA_8)
181 public void testJdkModules(final Path jmodPath) throws Exception {
182 testJar(jmodPath);
183 }
184
185 @ParameterizedTest
186 @MethodSource("org.apache.bcel.generic.JavaHome#streamJavaHome")
187 public void testJreModules(final JavaHome javaHome) throws Exception {
188 assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9));
189 try (final ModularRuntimeImage mri = javaHome.getModularRuntimeImage()) {
190 for (final Path path : mri.modules()) {
191 Files.walkFileTree(path, new ClassParserFilesVisitor("*.class"));
192 }
193 }
194 }
195
196 }