My favorites | Sign in
Project Logo
                
Search
for
Updated Aug 25, 2009 by 200712@xeoh.net
UsageGuide  
See how you can integrate the JSPF into your project, and how you can develop plugins.

We try to explain by example here, so adopt the strategies to your scenario accordingly.

More Examples

@PluginImplementation(author="Ralf Biedert", isDisabled=false, configurationFile="config.properties")
public class BigPluginImpl implements BigPlugin {

    @InjectPlugin
    public CoolPlugin coolPlugin;

    @InjectPlugin
    public PluginConfigurationFacade configFacade;

    @InjectPlugin
    public InformationBroker broker;


    @Thread
    public void backgroundTask() {
        while(true) broker.publish(new StringItem("item:uri", "value"));
    }

    @Init
    public void init() {
        int port = configFacade.getInt(BigPlugin.class, "server.port", 12345);
        callSetup()
    }

    @Shutdown
    public void shutdown() {
        sayGoodbye()
    }

    @Capabilities
    public String[] caps() {
        return new String[] {"mimetype/big", "functionality:example"};
    }

    @PluginLoaded
    public void newPlugin(RemoteAPI plugin) {
        System.out.printf("Detected new plugin " + plugin);
    }
}





Exporting and Importing Plugins over the Net

Exporting and importing is really easy. And the best thing is: you don't have to hassle with host names or port numbers.

// Get exporter, this one uses Lipe
RemoteAPI remote = pm.getPlugin(RemoteAPILipe.class)

// after this line returns the plugin is exported
remote.exportPlugin(myPlugin);

// import it again over the network, detect its location automatically
MyPlugin myPluginNetwork = remote.getRemoteProxy(new URI("discover://any"), MyPlugin.class);





Enable Caching

The following code should give you faster loading times after the first startup:

final JSPFProperties props = new JSPFProperties();
        
props.setProperty(PluginManager.class, "cache.enabled", "true");
props.setProperty(PluginManager.class, "cache.mode",    "weak"); //optional
props.setProperty(PluginManager.class, "cache.file",    "jspf.cache");

PluginManager pm = PluginManagerFactory.createPluginManager(props);





Recommended Layout

We usually create a package of the structure org.domain.applicationname. Within this folder you would find a single application main class, containing, amongst others, this code:

PluginManager pm = PluginManagerFactory.createPluginManager();
pm.addPluginsFrom(new URI("classpath://*"));

These lines will create a new plugin manager instance and tell it to load all classes it sees within the classpath. Except applets and some special cases this should work just fine. Of course you might want to add other locations as well (for example a special plugin-directory).

Below the main package we ususally create a subpackage named plugins or services. Inside this package go other subpackages, one for each plugin:

Inside a single plugin directory, you'd now place the interface of the plugin. How you design your interface is totally up to you, be we'd strongly recommend to keep it small. You could place, for example, inside the package org.domain.applicationname.plugins.systemapi the following interface file:

public interface SystemAPI extends Plugin {
    /** Tells the system to open the given url using the default application */
    public void openURL(URL href);
}

Enums and other interfaces could go here as well. The only thing remaining would be the interface's implementation.

This usually goes into an impl subfolder, one for each plugin:

In there one SystemAPIImpl.java file might look like that:

@PluginImplementation
public class SystemAPIImpl implements SystemAPI {
    @Init
    public boolean init() {
        return getOS().equals("OSX");
    }

    public void openURL(URL href) {
         doSomething(href);
    }
}





Plugin Design Practices

These hints are by no means required. Technically, for small projects, you should not encounter any problems if you develop all plugins by yourself from one big classpath. However, if you intend to publish you plugins for general usage, consider these points:

To archive this the plugin-jar should contain all interface-definitions it depends on (even foreign ones) and all foreign libraries it uses (unpack the remote.xmlrpc-jar to see what we mean). If you do not follow this rule, this is what can happen:
When an incomplete plugin is deployed into a plugin directory it might get loaded at a random point in time. If a class in your plugin depends on an entity that is not in the classpath (and not in your plugin, because you forgot to put it in there), its creation will fail due to a ClassNotFoundException. If however, you put all dependent interfaces into its jar, the framework will be able to load it properly and inspect its explicitly defined dependencies (using the requiredPlugins() attribute). It can then be put on hold until all these are loaded as well.

Sign in to add a comment
Hosted by Google Code