DEV Community

Query Filter
Query Filter

Posted on

bridge-12

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);
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)