Skip to content

Plugin Dependency Checker

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

Plugin Dependency Checker

An Ant build task that validates plugin dependency declarations against actual bytecode usage, ensuring all required plugins are declared and unnecessary imports are avoided.

Overview

The PluginDependencyChecker is an Ant task (org.jnode.build.dependencies.PluginDependencyChecker) that performs build-time validation of JNode's plugin dependency graph. It parses plugin XML descriptors and analyzes compiled JAR bytecode to detect:

  • Unresolved class dependencies (classes used but not in any plugin)
  • Unnecessary plugin imports (plugins imported but not actually used)
  • Missing import declarations (classes used from imported plugins but not exported)
  • Unresolved plugin references
  • Useless plugins (no runtime, extensions, or plugin class)

Key Components

Class / File Role
PluginDependencyChecker.java Main Ant task, orchestrates the validation pipeline
Inner Plugin class Represents a plugin, tracks contained and used classes
Inner Fragment class Represents a fragment attached to a host plugin
Inner JarFiles class Maps plugin IDs to JAR file paths

How It Works

Validation Pipeline

1. Read descriptor XMLs → PluginDescriptor objects
2. Match descriptors to JAR files (by plugin ID + version)
3. For each JAR:
   a. Extract all .class entries → containedClasses
   b. Analyze bytecode (BCEL) → usedClasses
4. For each plugin:
   a. collectUnmatchedDependencies() — classes used but not in any plugin
   b. isNotUseful() — plugin with no runtime, extensions, or plugin class
   c. assortClassesContainedInImportedPlugins() — imports vs actual usage

Bytecode Analysis (BCEL)

The task uses Apache BCEL to analyze class files. For each contained class, it traces references from:

analyzeClass(className, javaClass)
├── analyzeSuperClass()        // getSuperclassName()
├── analyzeInterfaces()        // getInterfaceNames()
├── analyzeFields()            // field types from Field.getType()
├── analyzeMethods()           // argument & return types
└── analyzeConstantPool()      // CONSTANT_Class, CONSTANT_NameAndType

This builds a usedClasses map: usingClass → Set<usedClassName>.

Dependency Validation

private boolean collectUnmatchedDependencies(...) {
    // For every class used by the plugin...
    for (String className : usedClasses.get(usingClass)) {
        // Check if it's contained in ANY known plugin
        if (!containedClasses.containsKey(className)) {
            // UNRESOLVED — error
        }
    }
}

Import Usage Validation

private boolean assortClassesContainedInImportedPlugins(...) {
    // Check each declared prerequisite plugin
    for (PluginPrerequisite prerequisite : plugin.descr.getPrerequisites()) {
        Plugin usedPlugin = findPlugin(idOfUsedPlugin);
        // Does the plugin actually use any classes from the import?
        if (!allClasses.removeAll(usedPlugin.containedClasses)) {
            // UNNECESSARY — plugin imports but doesn't use it
        }
    }
}

Ant Integration

Used in all/build.xml:

<pluginDependencyChecker>
    <descriptors .../>
    <plugins .../>
</pluginDependencyChecker>

The task is configured via nested <descriptors> and <plugins> FileSets that match descriptor XMLs and JAR files respectively.

Gotchas

  • Fragment handling — Fragments are treated as plugins but track their host plugin separately via getFullPluginIdOfOwningPlugin().
  • System plugins excluded — Classes from system plugins are removed from the undeclared set before reporting.
  • Recursive analysisassortClassesContainedInImportedPlugins() recursively validates transitive dependencies.
  • BCEL SyntheticRepository — Class loading uses SyntheticRepository with the JAR itself as the classpath, enabling offline analysis.
  • Missing JAR warning — If no JAR exists for a descriptor, only a warning is issued (not an error) to allow partial builds.
  • Type signature parsing — Uses regex \u004C[a-zA-Z_0-9/\u002E\u0024]*; to extract L-prefixed type descriptors from bytecode signatures.

Related Pages

Clone this wiki locally