Commit 035ed39b authored by Piotr Gawron's avatar Piotr Gawron
Browse files

folder for default plugins in tomcat directory + possibility to unload plugins

parent b7469f91
......@@ -58,6 +58,7 @@ function Configuration(json) {
self.setModificationStateTypes(json.modificationStateTypes);
self.setPrivilegeTypes(json.privilegeTypes);
self.setAnnotators(json.annotators);
self.setPluginsData(json.plugins);
}
}
......@@ -239,6 +240,13 @@ Configuration.prototype.setAnnotators = function (annotators) {
}
};
Configuration.prototype.getPluginsData = function () {
return this._pluginsData;
};
Configuration.prototype.setPluginsData = function (pluginsData) {
this._pluginsData = pluginsData;
};
Configuration.prototype.getAnnotators = function () {
return this._annotators;
};
......@@ -318,6 +326,7 @@ Configuration.prototype.update = function (original) {
self.setMapTypes(createCopy(original.getMapTypes()));
self.setModificationStateTypes(createCopy(original.getModificationStateTypes()));
self.setPrivilegeTypes(createCopy(original.getPrivilegeTypes()));
self.setPluginsData(createCopy(original.getPluginsData()));
self._annotators = [];
for (i = 0; i < original.getAnnotators(); i++) {
self._annotators.push(new Annotator(original.getAnnotators()[i]));
......
......@@ -262,6 +262,9 @@ Functions.createElement = function (params) {
if (params.src !== null && params.src !== undefined) {
result.src = params.src;
}
if (params.value !== null && params.value !== undefined) {
result.value = params.value;
}
return result;
};
......
......@@ -58,7 +58,7 @@ ContextMenu.prototype.open = function (x, y, timestamp) {
}).off('click').on('click', 'a', function (e) {
self.hide(e.timeStamp);
if ($(this).data("handler") !== undefined) {
$(this).data("handler")();
return $(this).data("handler")();
} else {
logger.debug("Nothing to do");
}
......
......@@ -18,7 +18,7 @@ OptionsMenu.prototype.constructor = OptionsMenu;
OptionsMenu.prototype._createMenuGui = function () {
var self = this;
self.addOption("Plugins", function () {
var initPromise = Promise.resolve;
var initPromise = Promise.resolve();
if (self._pluginDialog === undefined) {
self._pluginDialog = new PluginDialog({
element: document.createElement("div"),
......@@ -28,7 +28,7 @@ OptionsMenu.prototype._createMenuGui = function () {
initPromise = self._pluginDialog.init();
}
return initPromise.then(function () {
self._pluginDialog.open();
return self._pluginDialog.open();
})
});
};
......
......@@ -11,9 +11,8 @@ var Functions = require('../Functions');
function PluginDialog(params) {
AbstractGuiElement.call(this, params);
var self = this;
self._createPluginGui();
self.setPluginManager(params.pluginManager);
self._knownPlugins = [];
}
PluginDialog.prototype = Object.create(AbstractGuiElement.prototype);
......@@ -23,8 +22,11 @@ PluginDialog.prototype._createPluginGui = function () {
var self = this;
var guiUtils = new GuiUtils();
self.getElement().innerHTML = "";
var pluginFormTab = Functions.createElement({
type: "div",
name: "minerva-plugin-list-tab",
style: "width:100%;display: table;border-spacing: 10px;"
});
self.getElement().appendChild(pluginFormTab);
......@@ -38,38 +40,95 @@ PluginDialog.prototype._createPluginGui = function () {
type: "input",
name: "pluginUrlValue"
});
pluginFormTab.appendChild(guiUtils.createTableRow([pluginUrlLabel, pluginUrlInput]));
var centerTag = Functions.createElement({
type: "center"
});
self.getElement().appendChild(centerTag);
var loadPluginButton = Functions.createElement({
type: "button",
name: "loadPluginButton",
content: "LOAD PLUGIN"
content: "LOAD",
onclick: function () {
return self.getPluginManager().addPlugin({url: pluginUrlInput.value}).then(function () {
self.close();
}).then(null, GuiConnector.alert);
}
});
centerTag.appendChild(loadPluginButton);
loadPluginButton.onclick = function () {
return self.getPluginManager().addPlugin({url: pluginUrlInput.value}).then(function () {
self.close();
}).then(null, GuiConnector.alert);
pluginFormTab.appendChild(guiUtils.createTableRow([pluginUrlLabel, pluginUrlInput, loadPluginButton]));
var pluginManager = self.getPluginManager();
var loadedPlugins = [];
var processedPlugins = [];
var plugins = pluginManager.getPlugins();
var i;
for (i = 0; i < plugins.length; i++) {
loadedPlugins[plugins[i].getOptions().url] = true;
processedPlugins[plugins[i].getOptions().url] = false;
}
for (i = 0; i < self._knownPlugins.length; i++) {
var pluginData = self._knownPlugins[i];
var url = pluginData.url;
var pluginUrl = Functions.createElement({
type: "input",
value: url,
style: "color:#999999"
});
pluginUrl.readOnly = true;
var button;
if (loadedPlugins[url]) {
button = Functions.createElement({
type: "button",
content: "UNLOAD",
onclick: function () {
var promises = [];
for (var i = 0; i < plugins.length; i++) {
if (plugins[i].getOptions().url === $(this).data("url")) {
promises.push(pluginManager.removePlugin(plugins[i]));
}
}
return Promise.all(promises).then(function () {
self.close();
}).then(null, GuiConnector.alert);
}
});
} else {
button = Functions.createElement({
type: "button",
content: "LOAD",
onclick: function () {
return pluginManager.addPlugin({url: $(this).data("url")}).then(function () {
self.close();
}).then(null, GuiConnector.alert);
}
});
}
$(button).data("url", url);
processedPlugins[url] = true;
pluginFormTab.appendChild(guiUtils.createTableRow([Functions.createElement({type: "span"}), pluginUrl, button]));
}
};
PluginDialog.prototype.init = function () {
return Promise.resolve();
var self = this;
return ServerConnector.getConfiguration().then(function (configuration) {
var pluginsData = configuration.getPluginsData();
for (var i = 0; i < pluginsData.length; i++) {
var pluginData = pluginsData[i];
self._knownPlugins.push({url: ServerConnector.getServerBaseUrl() + pluginData.url});
}
});
};
PluginDialog.prototype.open = function () {
var self = this;
self._createPluginGui();
var div = self.getElement();
if (!$(div).hasClass("ui-dialog-content")) {
$(div).dialog({
autoOpen: false,
resizable: false
resizable: false,
width: 400
});
}
......@@ -83,6 +142,7 @@ PluginDialog.prototype.close = function () {
PluginDialog.prototype.destroy = function () {
var self = this;
var div = self.getElement();
if ($(self.getElement()).hasClass("ui-dialog-content")) {
$(self.getElement()).dialog("destroy");
}
......
......@@ -14,6 +14,7 @@ function Plugin(options) {
ObjectWithListeners.call(this);
var self = this;
self.setOptions(options);
self.registerListenerType("onUnload");
}
Plugin.prototype = Object.create(ObjectWithListeners.prototype);
......@@ -41,7 +42,7 @@ Plugin.prototype.getMinervaPluginProxy = function () {
return this._minervaPluginProxy;
};
Plugin.prototype.getPluginId = function () {
this.getMinervaPluginProxy().pluginId;
return this.getMinervaPluginProxy().pluginId;
};
Plugin.prototype.load = function () {
......@@ -57,6 +58,7 @@ Plugin.prototype.load = function () {
var pluginData = undefined;
var error = false;
try {
// noinspection JSUnusedLocalSymbols
var define = function (pluginFunction) {
try {
if (typeof pluginFunction === "function") {
......@@ -98,6 +100,8 @@ Plugin.prototype.unload = function () {
if (removedListeners.length > 0) {
logger.warn("'"+self.getLoadedPluginData().getName() + "' plugin didn't remove all registered listeners");
}
return self.callListeners("onUnload");
}).then(function () {
return self.destroy();
});
};
......
......@@ -71,6 +71,10 @@ PluginManager.prototype.addPlugin = function (options) {
configuration: self.getConfiguration(),
map: self.getMap()
});
plugin.addListener("onUnload", function(){
tabData.content.parentNode.removeChild(tabData.content);
tabData.title.parentNode.parentNode.removeChild(tabData.title.parentNode);
});
}
self._plugins.push(plugin);
return plugin.load().then(function () {
......
......@@ -5,6 +5,7 @@
require("../mocha-config.js");
var OptionsMenu = require('../../../main/js/gui/OptionsMenu');
var PluginManager = require('../../../main/js/plugin/PluginManager');
var chai = require('chai');
var assert = chai.assert;
......@@ -29,13 +30,22 @@ describe('OptionsMenu', function () {
element: testDiv,
customMap: map
});
return menu.init().then(function () {
var pluginManager;
return ServerConnector.getProject().then(function (project) {
pluginManager = new PluginManager({project: project});
return menu.init();
}).then(function () {
menu.setPluginManager(pluginManager);
return menu.open(10, 10, 20);
}).then(function () {
return $("a", testDiv).trigger("click");
return $("a", testDiv).data("handler")();
}).then(function () {
assert.equal(0, logger.getWarnings().length);
return menu.destroy();
}).then(function () {
return pluginManager.destroy();
});
});
});
})
;
......@@ -123,12 +123,12 @@ describe('minerva global', function () {
});
it('create with layout', function () {
var layout, project, plugin, map
var layout, project, plugin, map;
return ServerConnectorMock.getProject().then(function (result) {
project = result;
var options = helper.createCustomMapOptions(project);
plugin = new ProxyAccessPlugin();
plugin = new ProxyAccessPlugin({});
options.getPlugins().push(plugin);
layout = project.getModel().getLayouts()[1];
......
......@@ -7,7 +7,7 @@ var Promise = require('bluebird');
var logger = require('../logger');
function ProxyAccessPlugin() {
function ProxyAccessPlugin(options) {
}
ProxyAccessPlugin.prototype = Object.create(Plugin.prototype);
......@@ -34,4 +34,7 @@ ProxyAccessPlugin.prototype.load = function () {
});
return Promise.resolve();
};
ProxyAccessPlugin.prototype.unload = function () {
return Promise.resolve();
};
module.exports = ProxyAccessPlugin;
......@@ -58,6 +58,7 @@ public class ConfigurationController extends BaseController {
result.put("version", configurationService.getSystemSvnVersion(context.getRealPath("/")));
result.put("buildDate", configurationService.getSystemBuild(context.getRealPath("/")));
result.put("annotators", configurationController.getAnnotators(token));
result.put("plugins", configurationController.getPlugins(token, context.getRealPath("/")));
return result;
}
......
package lcsb.mapviewer.api.configuration;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
......@@ -28,7 +29,6 @@ import lcsb.mapviewer.model.map.species.Element;
import lcsb.mapviewer.model.map.species.field.ModificationState;
import lcsb.mapviewer.model.user.ConfigurationElementType;
import lcsb.mapviewer.model.user.PrivilegeType;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.modelutils.map.ClassTreeNode;
import lcsb.mapviewer.modelutils.map.ElementUtils;
import lcsb.mapviewer.services.SecurityException;
......@@ -274,4 +274,24 @@ public class ConfigurationRestImpl {
return configurationService.getValue(type);
}
public List<Map<String, Object>> getPlugins(String token, String rootPath) {
String path = rootPath + "/resources/js/plugins/";
File folder = new File(path);
logger.debug(folder.getAbsolutePath());
List<Map<String, Object>> result = new ArrayList<>();
if (folder.exists()) {
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
Map<String, Object> row = new HashMap<>();
row.put("url", "resources/js/plugins/" + listOfFiles[i].getName());
row.put("load-on-start", false);
result.add(row);
}
}
}
return result;
}
}
define(function () {
return {
register: function (object) {
console.log("registering test plugin");
},
unregister: function () {
console.log("unregistering test plugin");
},
getName: function () {
return "test plugin";
},
getVersion: function () {
return "0.0.1";
}
};
});
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment