Skip to content

Plugin System

opencode-agent[bot] edited this page May 10, 2026 · 2 revisions

Plugin System

JNode uses an OSGi-like plugin/extension architecture where each functional unit is a plugin with an XML descriptor defining its dependencies, exports, and extension points.

Overview

The plugin system is JNode's primary modularity mechanism. Every subsystem — filesystem drivers, network protocols, video drivers, shell commands — is packaged as a plugin. Plugins have:

  • Identity — unique ID, version, provider
  • Dependencies<requires> / <import> declarations
  • Exports — packages visible to other plugins
  • Extensions — implementations registered at named extension points
  • Lifecycle — loaded, started, stopped by the PluginManager

Key Components

Class / File Role
core/src/core/org/jnode/plugin/Plugin.java Base class for all plugins
core/src/core/org/jnode/plugin/PluginDescriptor.java Describes a plugin (parsed from XML)
core/src/core/org/jnode/plugin/PluginManager.java Manages plugin lifecycle
core/src/core/org/jnode/plugin/PluginRegistry.java Registry of all known plugins
core/src/core/org/jnode/plugin/Extension.java A plugin's contribution to an extension point
core/src/core/org/jnode/plugin/ExtensionPoint.java A named hook where extensions register
core/src/core/org/jnode/plugin/ConfigurationElement.java XML config data within an extension
core/src/core/org/jnode/plugin/PluginClassLoader.java Per-plugin classloader
core/src/core/org/jnode/plugin/manager/DefaultPluginManager.java Default lifecycle implementation
core/src/core/org/jnode/plugin/model/PluginDescriptorModel.java XML descriptor parser
core/src/core/org/jnode/plugin/model/PluginsClassLoader.java Parent classloader for all plugin classloaders

Descriptor XML Format

Each plugin has an XML file in <subproject>/descriptors/:

<plugin id="org.jnode.driver.video.vga"
        name="JNode Video Standard VGA driver"
        version="@VERSION@"
        license-name="lgpl"
        provider-name="JNode.org">

  <!-- Dependencies on other plugins -->
  <requires>
    <import plugin="org.jnode.awt"/>
    <import plugin="org.jnode.driver.bus.pci"/>
    <import plugin="org.jnode.driver.video.vgahw"/>
  </requires>

  <!-- Packages this plugin makes visible to dependents -->
  <runtime>
    <library name="jnode-gui.jar">
      <export name="org.jnode.driver.video.vga.*"/>
    </library>
  </runtime>

  <!-- Extensions contributed to other plugins' extension points -->
  <extension point="org.jnode.driver.bus.pci.device-factories">
    <device-factory class="org.jnode.driver.video.vga.VGADriver"/>
  </extension>
</plugin>

Descriptor Elements

Element Purpose
<plugin> Root: id, name, version, provider
<requires> / <import> Declares dependencies
<runtime> / <library> JAR files this plugin provides
<export> Packages visible to importing plugins
<extension-point> Defines a hook for other plugins to extend
<extension> Contributes to another plugin's extension point
<fragment> Fragment that attaches to a host plugin

How It Works

Plugin Loading (at boot)

  1. InitJarProcessor extracts plugin JARs and descriptors from the init-jar
  2. PluginDescriptorModel parses each XML descriptor
  3. PluginRegistry stores all descriptors
  4. DefaultPluginManager.startSystemPlugins() sorts by dependency order and activates each plugin

Classloader Hierarchy

BootClassLoader (VM built-in classes)
  └── PluginsClassLoader (shared parent for all plugins)
        ├── PluginClassLoader [org.jnode.driver]
        ├── PluginClassLoader [org.jnode.fs]
        ├── PluginClassLoader [org.jnode.driver.video.vga]
        └── ...

Each PluginClassLoader:

  • Can see classes from its own JAR
  • Can see classes from plugins listed in <requires> / <import>
  • Cannot see classes from other plugins (isolation)

Extension Points

Extension points are the primary mechanism for loose coupling:

  1. Plugin A declares <extension-point id="org.jnode.driver.bus.pci.device-factories">
  2. Plugin B contributes <extension point="org.jnode.driver.bus.pci.device-factories">
  3. At runtime, Plugin A queries its extension point to discover all contributors
  4. ExtensionPoint.getExtensions() returns all Extension objects
  5. Each Extension has ConfigurationElements with class names and parameters

This is how drivers register themselves: the PCI bus plugin defines an extension point for device factories, and each driver plugin contributes a factory.

Plugin Lists

File Purpose
all/conf/default-plugin-list.xml Plugins included in a standard build
all/conf/full-plugin-list.xml All available plugins

The plugin list also declares the main class to launch:

<manifest>
    <attribute key="Main-Class" value="org.jnode.shell.CommandShell"/>
</manifest>

Gotchas & Non-Obvious Behavior

  • Build-time pre-loadingBootImageBuilder pre-loads plugin descriptors and bakes the PluginRegistry into the boot image. The registry field in Main.java is set at build time.
  • No dynamic loading at runtime — Unlike Eclipse OSGi, JNode's plugin system is primarily static. All plugins are loaded at boot from the init-jar.
  • Fragment vs. Plugin — A FragmentDescriptor attaches to a host plugin and shares its classloader. Used for classpath extensions.
  • Version string@VERSION@ in descriptors is replaced at build time by Ant.
  • AutoUnzipPlugin — A special plugin type that auto-extracts ZIP content (used for classpath resources).
  • Circular dependencies — Not supported. The build will fail if plugins have circular imports.

Related Pages

Clone this wiki locally