package comet.agent;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ProfilerAgent {
/**
* Entry-point to discover classes across both local dev paths and Linux JAR deployments.
*/
public static List<String> discoverLocalApplicationClasses() {
List<String> localClasses = new ArrayList<>();
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (!(classLoader instanceof URLClassLoader)) {
classLoader = ClassLoader.getSystemClassLoader();
}
if (classLoader instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) classLoader).getURLs();
for (URL url : urls) {
File file = new File(url.toURI());
// 1. LOCAL DEVELOPMENT: Loose classes directory
if (file.isDirectory()) {
System.out.println("[PROFILER-AGENT] Scanning local application directory: " + file.getAbsolutePath());
scanDirectoryForClasses(file, "", localClasses);
}
// 2. LINUX DEPLOYMENT: Packaged application JARs
else if (file.isFile() && file.getName().endsWith(".jar") && isApplicationJar(file.getName())) {
System.out.println("[PROFILER-AGENT] Scanning deployed application JAR: " + file.getAbsolutePath());
scanJarForClasses(file, localClasses);
}
}
} else {
// Fallback for non-URLClassLoaders reading system paths
String[] classpathEntries = System.getProperty("java.class.path").split(File.pathSeparator);
for (String entry : classpathEntries) {
File file = new File(entry);
if (file.isDirectory()) {
scanDirectoryForClasses(file, "", localClasses);
} else if (file.isFile() && file.getName().endsWith(".jar") && isApplicationJar(file.getName())) {
scanJarForClasses(file, localClasses);
}
}
}
} catch (Exception e) {
System.err.println("[PROFILER-AGENT] Failed to auto-discover classes: " + e.getMessage());
}
System.out.println("[PROFILER-AGENT] Auto-discovered " + localClasses.size() + " target application classes.");
return localClasses;
}
/**
* Filter to isolate your core application deployment JARs from standard third-party dependencies.
*/
private static boolean isApplicationJar(String jarName) {
String name = jarName.toLowerCase();
return name.contains("cpls") || name.contains("comet") || name.contains("qff");
}
/**
* Reads a packaged JAR file on Linux and extracts class paths directly from its entry index.
*/
private static void scanJarForClasses(File jarFile, List<String> result) {
try (JarFile jar = new JarFile(jarFile)) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
// Track only compiled classes, skipping internal nested anonymous classes ($)
if (name.endsWith(".class") && !name.contains("$")) {
String className = name.substring(0, name.length() - 6).replace('/', '.');
result.add(className);
}
}
} catch (Exception e) {
System.err.println("[PROFILER-AGENT] Error reading JAR entries from " + jarFile.getName() + ": " + e.getMessage());
}
}
/**
* LOCAL MACHINE FALLBACK: Recursively traverses directories to construct
* fully qualified Java class names out of standard build class folders.
*/
private static void scanDirectoryForClasses(File directory, String packageName, List<String> result) {
File[] files = directory.listFiles();
if (files == null) return;
for (File file : files) {
if (file.isDirectory()) {
// Append subfolder to package chain structure
String subPackage = packageName.isEmpty() ? file.getName() : packageName + "." + file.getName();
scanDirectoryForClasses(file, subPackage, result);
} else if (file.getName().endsWith(".class")) {
// Strip the extension to obtain a valid binary class token
String className = file.getName().substring(0, file.getName().length() - 6);
String fullyQualifiedName = packageName.isEmpty() ? className : packageName + "." + className;
// Filter out inner/anonymous generated mappings
if (!fullyQualifiedName.contains("$")) {
result.add(fullyQualifiedName);
}
}
}
}
}
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)