Kelas Java ini memindai konten dari semua konten WAR dan JAR yang ditemukan di bawah daftar direktori, dan mencetak ringkasan versi file kelas java untuk setiap komponen termasuk setiap JAR dalam WARs:
public class ShowClassVersions {
private static final byte[] CLASS_MAGIC = new byte[] {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe};
private final byte[] bytes = new byte[8];
private TreeMap<String,ArrayList<String>> vers = new TreeMap<>();
private void scan(Path f) throws IOException {
if (Files.isDirectory(f)) {
Pattern pattern = Pattern.compile("\\.[wj]ar$"); // or |\\.class
try(var stream = Files.find(f, Integer.MAX_VALUE, (p,a) -> a.isRegularFile() && pattern.matcher(p.toString()).find())) {
stream.forEach(this::scanFile);
}
return;
}
scanFile(f);
}
private void scanFile(Path f) {
String fn = f.getFileName().toString();
try {
if (fn.endsWith(".jar"))
scanArchive(f);
else if (fn.endsWith(".war"))
scanArchive(f);
else if (fn.endsWith(".class"))
record(f, versionOfClass(f));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private void scanArchive(Path p) throws IOException {
try(InputStream in = Files.newInputStream(p)) {
scanArchive(p.toAbsolutePath().toString(), in);
}
}
private String scanArchive(String desc, InputStream in) throws IOException {
String version = null;
ZipInputStream zip = new ZipInputStream(in);
ZipEntry entry = null;
while ((entry = zip.getNextEntry()) != null) {
String name = entry.getName();
if (version == null && name.endsWith(".class")) {
version = versionOfClass(zip);
}
else if (name.endsWith(".jar")) {
scanArchive(desc+" ==>> "+name, zip);
}
}
if (version != null)
record(desc, version);
return version;
}
private String versionOfClass(Path p) throws IOException {
String version = null;
try(InputStream in = Files.newInputStream(p)) {
version = versionOfClass(in);
}
return version;
}
private String versionOfClass(InputStream in) throws IOException {
String version = null;
int c = in.read(bytes);
if (c == bytes.length && Arrays.mismatch(bytes, CLASS_MAGIC) == CLASS_MAGIC.length) {
int minorVersion = (bytes[4] << 8) + (bytes[4] << 0);
int majorVersion = (bytes[6] << 8) + (bytes[7] << 0);
version = ""+majorVersion + "." + minorVersion;
}
return version;
}
private void record(String p, String v) {
vers.computeIfAbsent(String.valueOf(v), k -> new ArrayList<String>()).add(p);
}
private void record(Path p, String v) {
record(p.toAbsolutePath().toString(), v);
}
public static void main(String[] args) throws IOException {
ShowClassVersions v = new ShowClassVersions();
var files = Arrays.stream(args).map(Path::of).collect(Collectors.toList());
for (var f : files) {
v.scan(f);
}
for (var ver : v.vers.keySet()) {
System.out.println("Version: "+ver);
for (var p : v.vers.get(ver)) {
System.out.println(" "+p);
}
};
}
}