Hi John,
We use the Rhyno library to execute the Javascript file referenced by the plugin.
Right now we do not have an automated way to reload plugins while Oxygen is running.
A loaded plugin may add various listeners in the application, listeners which would need to be automatically unregistered by us if the plugin is unloaded (in order to be loaded again).
Also a workspace access plugin type receives a notification very early when the application starts so that it can contribute toolbar and menu items. With our current limitations this contribution of toolbar and menu items cannot be done anymore later, when the application is on screen.
Code: Select all
If not, I'm supposing one approach would be to build a loader in Java and make the loader a plugin?
Sure, actually this is also how we implemented the javascript extension on our side. We have a workspace access plugin extension which uses Rhyno to delegate to the Javascript methods.
If it helps, here's our code:
Code: Select all
/**
* Workspace access plugin extension which is created over a Javascript file.
*
* @author radu_coravu
*/
@API(type=APIType.INTERNAL, src=SourceType.PRIVATE)
public class WorkspaceAccessOverJSPluginExtension implements WorkspaceAccessPluginExtension{
/**
* Logger for logging.
*/
private static final Logger logger = Logger.getLogger(WorkspaceAccessOverJSPluginExtension.class.getName());
/**
* The JS File
*/
private URL jsFileURL;
/**
* Plugin workspace access.
*/
private StandalonePluginWorkspace pluginWorkspaceAccess;
/**
* Constructor.
* @param jsFileURL URL pointing to the Javascript file.
*/
public WorkspaceAccessOverJSPluginExtension(URL jsFileURL) {
this.jsFileURL = jsFileURL;}
/**
* @see ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension#applicationStarted(ro.sync.exml.workspace.api.standalone.StandalonePluginWorkspace)
*/
@Override
public void applicationStarted(final StandalonePluginWorkspace pluginWorkspaceAccess) {
this.pluginWorkspaceAccess = pluginWorkspaceAccess;
callFunction(pluginWorkspaceAccess, "applicationStarted");
}
/**
* Constructor.
*
* @param pluginWorkspaceAccess The plugin workspace access.
* @param functionName The function name
* @return The function return value.
*/
public Object callFunction(StandalonePluginWorkspace pluginWorkspaceAccess, String functionName) {
//Use it
org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter();
try{
org.mozilla.javascript.Scriptable globalScope = cx.initStandardObjects();
//EXM-36130 Global field which points to Javascript dir URL.
Object wrappedDispatcher = org.mozilla.javascript.Context.javaToJS(URLUtil.getCanonicalURL(URLUtil.getParentURL(jsFileURL)), globalScope);
org.mozilla.javascript.ScriptableObject.defineProperty(globalScope, "jsDirURL", wrappedDispatcher, org.mozilla.javascript.ScriptableObject.CONST);
// Now evaluate the string we've collected. We'll ignore the result.
cx.evaluateString(globalScope, IOUtil.readURL(jsFileURL, "UTF8").toString(), jsFileURL.toString(), 1, null);
Object fObj = globalScope.get(functionName, globalScope);
org.mozilla.javascript.Function f = (org.mozilla.javascript.Function)fObj;
return f.call(cx, globalScope, globalScope, new Object[]{pluginWorkspaceAccess});
} catch(Exception ex){
logger.error(ex, ex);
pluginWorkspaceAccess.showErrorMessage(ex.getMessage());
} finally{
org.mozilla.javascript.Context.exit();
}
return null;
}
/**
* @see ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension#applicationClosing()
*/
@Override
public boolean applicationClosing() {
Object ret = callFunction(pluginWorkspaceAccess, "applicationClosing");
if(ret instanceof Boolean){
return (Boolean) ret;
}
//Alow close operation to continue
return true;
}
}
Regards,
Radu