- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClassScanner.java
More file actions
Latest commit
85 lines (78 loc) · 4.04 KB
/
Copy pathClassScanner.java
File metadata and controls
85 lines (78 loc) · 4.04 KB
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
importjava.lang.module.Configuration;
importjava.lang.module.ModuleReader;
importjava.lang.module.ModuleReference;
importjava.lang.module.ResolvedModule;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Optional;
/**
* A utility class for scanning and loading classes from Java modules.
*/
publicclassClassScanner {
// Private constructor to prevent instantiation from outside
privateClassScanner() {}
// Static instance of ClassScanner (singleton instance, created eagerly)
privatestaticfinalClassScannerINSTANCE = newClassScanner();
/**
* Provides access to the singleton instance of ClassScanner.
* @return the singleton instance of ClassScanner
*/
publicstaticClassScannergetInstance() {
returnINSTANCE;
}
/**
* Static method to get the list of all classes found in the modules.
* Uses the singleton instance to perform the scan.
*
* @return List of classes found across Java modules
*/
publicstaticList<Class<?>> totalClasses() {
returnINSTANCE.performClassScan(); // Calls the private method that performs the scanning
}
/**
* Performs the actual class scanning by iterating through modules in the boot layer.
* Only classes within "java." and "jdk." packages are scanned, and only exported packages are included.
*
* @return List of Class<?> objects representing the scanned classes
*/
privateList<Class<?>> performClassScan() {
List<Class<?>> classes = newArrayList<>(); // List to store discovered classes
ModuleLayerbootLayer = ModuleLayer.boot(); // Gets the boot layer, which contains core Java modules
ConfigurationbootConfig = bootLayer.configuration();
// Iterate over modules in the boot layer that start with "java." or "jdk."
bootLayer.modules().stream()
.filter(module -> module.getName().startsWith("java.") || module.getName().startsWith("jdk."))
.forEach(module -> {
// Resolve each module in the configuration, if available
Optional<ResolvedModule> resolved = bootConfig.findModule(module.getName());
resolved.ifPresent(rm -> {
ModuleReferenceref = rm.reference();
// Use ModuleReader to list entries in the module
try (ModuleReaderreader = ref.open()) {
reader.list().forEach(s -> {
// Check if entry is a .class file but not a special info file
if (s.endsWith(".class") && !(s.equals("package-info.class") || s.equals("module-info.class") || s.equals("META-INF.class"))) {
StringpackageName = s.substring(0, s.lastIndexOf('/')).replace('/', '.');
StringclassName = s.replace('/', '.').substring(0, s.length() - ".class".length());
// Check if the package is exported from the module
if (module.isExported(packageName)) {
try {
// Load the class by its name
Class<?> clazz = Class.forName(className);
if (!classes.contains(clazz)) classes.add(clazz); // Add if not already in the list
System.out.println("Loaded: " + clazz.getName());
} catch (ClassNotFoundException | SecurityExceptione) {
System.out.println("Type not found: " + e.getMessage());
}
}
}
});
} catch (IOExceptione) {
System.out.println("Could not open Module: " + e.getMessage());
}
});
});
returnclasses; // Return the list of loaded classes
}
}