forked from jnode/jnode
-
Notifications
You must be signed in to change notification settings - Fork 0
Builder Packager
opencode-agent[bot] edited this page May 10, 2026
·
1 revision
Ant build system tools for packaging third-party JARs/resources as JNode plugins with generated descriptors and shell scripts.
The Builder Packager is a set of Ant tasks that transforms third-party JAR files and application directories into JNode plugins suitable for inclusion in the boot image or CD-ROM distribution. It handles plugin descriptor generation, shell script creation, and plugin list integration.
| Class | Purpose |
|---|---|
PluginBuilder |
Main task that builds plugins from user JARs/directories |
PackagerTask |
Abstract base with common property handling |
ScriptBuilder |
Generates JNode scripts from Unix/MS-DOS scripts or from scratch |
MainFinder |
Searches for main classes in JAR files |
PluginListInsertor |
Adds user plugins to plugin lists |
userApplicationsDir
├── plugin.jar → processed → PluginBuilder
├── myapp/ → directory → ScriptBuilder
└── plugins.properties → written by finish()
-
Discovery:
PluginBuilderscansuserApplicationsDirfor.jarfiles and directories -
Descriptor Generation: For each JAR without an
.xmldescriptor, builds one automatically viabuildDescriptor() -
Main Class Detection: Uses
MainFinderto locatemain(String[])methods -
Script Generation:
ScriptBuilderconverts Unix/MS-DOS scripts to JNode.jnsformat -
Property File: Writes
plugins.propertieswith comma-separated plugin IDs
public void execute(ThreadPoolExecutor executor, final Map<String, File> descriptors) {
if (isEnabled()) {
if (path == null) {
throw new BuildException("pathRefId is mandatory");
}
File[] userJars = userApplicationsDir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".jar") || pathname.isDirectory();
}
});
for (File userJar : userJars) {
processUserJar(executor, descriptors, userJar, userPluginIds);
}
}
}The generated XML descriptor (lines 192-250):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plugin SYSTEM "jnode.dtd">
<plugin id="myapp"
name="myapp"
version=""
class="org.jnode.plugin.AutoUnzipPlugin"
auto-start="true"
license-name="unspecified">
<runtime>
<library name="myapp.jar">
<export name="*"/>
</library>
</runtime>
<extension point="org.jnode.shell.aliases">
<alias name="MyMain" class="com.example.MyMain"/>
</extension>
<extension point="org.jnode.security.permissions">
<permission class="java.security.AllPermission" />
</extension>
</plugin>ScriptBuilder.build()尝试三种脚本生成策略,按优先级:
-
Unix scripts (
.sh): Parse with#comment,:path separator -
MS-DOS batches (
.bat): Parse withREMcomment,;path separator -
From scratch: Use
MainFinderto locate main classes, generate scripts
生成的JNode脚本 (.jns):
# File automatically generated by JNode Packager
# enable exception tracing
propset jnode.debug true
# set system properties
# set classpath
classpath --add file:///jnode/myapp/myapp.jar
# TODO : add permissions
# launch the application
java com.example.MyMain arg1 arg2
两种main类��索策略:
-
Manifest 优先: 检查
META-INF/MANIFEST.MF中的Main-Class属性 -
字节码扫描: 使用 ASM 库遍历
.class文件,查找public static void main(String[])
public static List<String> searchMain(File userJar) throws FileNotFoundException, IOException {
List<String> mainList = new ArrayList<String>();
JarFile jarFile = new JarFile(userJar);
// Try manifest first
if (jarFile.getManifest() != null) {
Object value = jarFile.getManifest().getMainAttributes().get(Attributes.Name.MAIN_CLASS);
if (value != null) {
mainList.add(String.valueOf(value));
return mainList;
}
}
// Scan for main methods in bytecode
for (Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements(); ) {
JarEntry entry = e.nextElement();
if (entry.getName().endsWith(".class")) {
// Use ASM to detect main(String[]) method
}
}
return mainList;
}-
Thread Safety:
userPluginIdsis aStringBuilderaccessed from multiple threads viaThreadPoolExecutor -
Descriptor Overwrite: Existing
.xmldescriptors are NOT regenerated; setforce.overwrite=trueto update -
Permission Security: Generated descriptors grant
AllPermission— should be restricted in production -
Script Path: Hard-coded
/jnode/path inScriptBuilder.build()(line 104) should usejava.home - Manifest Priority: MainFinder only scans bytecode if no manifest Main-Class is found
-
Properties File: Must contain
user.plugin.idsproperty; format isplugin1,plugin2,plugin3...
- Build-System — Ant build system integration
- Plugin-System — Plugin framework
- Plugin-Descriptor-Schema — XML descriptor format
- Boot-CD-ROM-Builder — CD-ROM distribution