jueves, 16 de octubre de 2008

Plugins en Java

Java 6 ofrece la clase ServiceLoader, que permite cargar plugins en tiempo de ejecución.

Los plugins son objetos que implementan cierta interfaz. Por ejemplo, la sgte interfaz :


package plugintest;

public interface Saludador {
public abstract void saludar(String name);
}


Esa interfaz la podemos compilar en un .jar, para ser incluído en el proyecto principal y en el proyecto del plugin.

Entonces, en el proyecto del plugin, creamos la sgte clase que implementa la interfaz:


package plugintest.impl;

import plugintest.Saludador;

public class SaludadorIngles implements Saludador {

public void saludar(String name) {
System.out.println("hello "+name);
}

}


Luego, el proyecto del plugin lo compilamos como un jar para incluirlo en el proyecto principal.
Antes de compilar el jar del plugin, hay que crear, dentro de su directorio src, un directorio META-INF/services/ y allí, un archivo con las rutas de los plugins que implementan la interfaz. Para indicar qué interfaz implementan, ese archivo debe tener el mismo nombre que el nombre completo de la interfaz: plugintest.Saludador
El contenido del archivo debe tener una línea por cada ruta de plugin. En nuestro ejemplo el contenido será:

plugintest.impl.SaludadorIngles


Finalmente, en el proyecto principal incluímos el jar del plugin. Estos jars de plugins, en vez de dejarlos en el directorio lib, se pueden dejar en un directorio especial, ej: "plugins"

De esta manera, usando la clase ServiceLoader de java, podemos instanciar y usar los plugins. Ej:


public class Tester {

public static void main(String[] args) throws IOException {
ServiceLoader loader = ServiceLoader.load(Saludador.class,getClassLoader());
for (Saludador inst : loader) {
inst.saludar("Pablo");
}
}

private static ClassLoader getClassLoader(){
File dir = new File("plugins");
File[] files = dir.listFiles();
ArrayList urls = new ArrayList();
for (File file : files) {
System.out.println("agregando jar: "+file.getName());
try {
urls.add(file.toURI().toURL());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
URLClassLoader cl = new URLClassLoader(urls.toArray(new URL[0]));

return cl;
}

No hay comentarios: