Tuesday, September 21, 2010

How to Dynamically Load JAR Files

Suppose we have a Java application that need to load all the JAR files in a particular directory, e.g. plugins directory, here is how to do it.

plugin-api project
Hello.java
package myproject.api;

public interface Hello { 
    public String getMessage(); 
} 
Export this class as a JAR, e.g. plugin-api.jar


hello-impl project
HelloImpl.java
package myproject.api.impl;

import myproject.api.Hello;

public class HelloImpl implements Hello {

    @Override 
    public String getMessage() { 
        return "Hello World"; 
    } 
} 
Make sure the plugin-api.jar is in the hello-impl project classpath. Export the JAR as hello-impl.jar to main-project/plugins (see below).


bye-impl project
ByeImpl.java
package myproject.api.impl;

import myproject.api.Hello;

public class ByeImpl implements Hello {

    @Override 
    public String getMessage() { 
        return "Bye World"; 
    } 
} 
Make sure the plugin-api.jar is in the bye-impl project classpath. Export the JAR as bye-impl.jar to main-project/plugins (see below).


main project
Main.java
import java.io.File; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile;

import myproject.api.Hello;

public class Main {

    public static void main(String[] args) throws Exception { 
        for (File file : new File("plugins").listFiles()) { 
            URLClassLoader ucl = new URLClassLoader(new URL[] {file.toURI().toURL()}, 
                    Main.class.getClassLoader()); 
            Enumeration<JarEntry> jarEntries = new JarFile(file).entries(); 
            while (jarEntries.hasMoreElements()) { 
                JarEntry jarEntry = jarEntries.nextElement(); 
                if (jarEntry.getName().endsWith(".class")) { 
                    String className = jarEntry.getName().replace("/", 
                            ".").substring(0, 
                            jarEntry.getName().indexOf(".class")); 
                    Class c = Class.forName(className, true, ucl); 
                    for (Class i : c.getInterfaces()) { 
                        if ("myproject.api.Hello".equals(i.getName())) { 
                            Hello hello = (Hello) c.newInstance(); 
                            System.out.println(hello.getMessage()); 
                        } 
                    } 
                } 
            } 
        } 
    } 
} 
Make sure the plugin-api.jar is in the main project classpath. And create plugins directory and drop all the two implementation JARs into the plugins directory, such as below
main/plugins/hello-impl.jar 
             bye-impl.jar

No comments:

Post a Comment