📄 pluginmanager.java
字号:
if (plugins.containsKey(parentPlugin)) {
pluginLoader = classloaders.get(getPlugin(parentPlugin));
pluginLoader.addDirectory(pluginDir, classesDir != null);
}
else {
// See if the parent plugin exists but just hasn't been loaded yet.
// This can only be the case if this plugin name is alphabetically before
// the parent.
if (pluginName.compareTo(parentPlugin) < 0) {
// See if the parent exists.
File file = new File(pluginDir.getParentFile(), parentPlugin + ".jar");
if (file.exists()) {
// Silently return. The child plugin will get loaded up on the next
// plugin load run after the parent.
return;
}
else {
file = new File(pluginDir.getParentFile(), parentPlugin + ".war");
if (file.exists()) {
// Silently return. The child plugin will get loaded up on the next
// plugin load run after the parent.
return;
}
else {
String msg = "Ignoring plugin " + pluginName + ": parent plugin " +
parentPlugin + " not present.";
Log.warn(msg);
System.out.println(msg);
return;
}
}
}
else {
String msg = "Ignoring plugin " + pluginName + ": parent plugin " +
parentPlugin + " not present.";
Log.warn(msg);
System.out.println(msg);
return;
}
}
}
// This is not a child plugin, so create a new class loader.
else {
pluginLoader = new PluginClassLoader();
pluginLoader.addDirectory(pluginDir, classesDir != null);
}
// Check to see if development mode is turned on for the plugin. If it is,
// configure dev mode.
PluginDevEnvironment dev = null;
if (webRoot != null || classesDir != null) {
dev = new PluginDevEnvironment();
System.out.println("Plugin " + pluginName + " is running in development mode.");
Log.info("Plugin " + pluginName + " is running in development mode.");
if (webRoot != null) {
File webRootDir = new File(webRoot);
if (!webRootDir.exists()) {
// Ok, let's try it relative from this plugin dir?
webRootDir = new File(pluginDir, webRoot);
}
if (webRootDir.exists()) {
dev.setWebRoot(webRootDir);
}
}
if (classesDir != null) {
File classes = new File(classesDir);
if (!classes.exists()) {
// ok, let's try it relative from this plugin dir?
classes = new File(pluginDir, classesDir);
}
if (classes.exists()) {
dev.setClassesDir(classes);
pluginLoader.addURLFile(classes.getAbsoluteFile().toURL());
}
}
}
String className = pluginXML.selectSingleNode("/plugin/class").getText().trim();
plugin = (Plugin)pluginLoader.loadClass(className).newInstance();
if (parentPluginNode != null) {
String parentPlugin = parentPluginNode.getTextTrim();
// See if the parent is already loaded.
if (plugins.containsKey(parentPlugin)) {
pluginLoader = classloaders.get(getPlugin(parentPlugin));
classloaders.put(plugin, pluginLoader);
}
}
plugins.put(pluginName, plugin);
pluginDirs.put(plugin, pluginDir);
// If this is a child plugin, register it as such.
if (parentPluginNode != null) {
String parentPlugin = parentPluginNode.getTextTrim();
List<String> childrenPlugins = parentPluginMap.get(plugins.get(parentPlugin));
if (childrenPlugins == null) {
childrenPlugins = new ArrayList<String>();
parentPluginMap.put(plugins.get(parentPlugin), childrenPlugins);
}
childrenPlugins.add(pluginName);
// Also register child to parent relationship.
childPluginMap.put(plugin, parentPlugin);
}
else {
// Only register the class loader in the case of this not being
// a child plugin.
classloaders.put(plugin, pluginLoader);
}
// Check the plugin's database schema (if it requires one).
if (!DbConnectionManager.getSchemaManager().checkPluginSchema(plugin)) {
// The schema was not there and auto-upgrade failed.
Log.error(pluginName + " - " +
LocaleUtils.getLocalizedString("upgrade.database.failure"));
System.out.println(pluginName + " - " +
LocaleUtils.getLocalizedString("upgrade.database.failure"));
}
// Load any JSP's defined by the plugin.
File webXML = new File(pluginDir, "web" + File.separator + "WEB-INF" +
File.separator + "web.xml");
if (webXML.exists()) {
PluginServlet.registerServlets(this, plugin, webXML);
}
// Load any custom-defined servlets.
File customWebXML = new File(pluginDir, "web" + File.separator + "WEB-INF" +
File.separator + "web-custom.xml");
if (customWebXML.exists()) {
PluginServlet.registerServlets(this, plugin, customWebXML);
}
if (dev != null) {
pluginDevelopment.put(plugin, dev);
}
// Configure caches of the plugin
configureCaches(pluginDir, pluginName);
// Init the plugin.
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(pluginLoader);
plugin.initializePlugin(this, pluginDir);
Thread.currentThread().setContextClassLoader(oldLoader);
// If there a <adminconsole> section defined, register it.
Element adminElement = (Element)pluginXML.selectSingleNode("/plugin/adminconsole");
if (adminElement != null) {
Element appName = (Element)adminElement.selectSingleNode(
"/plugin/adminconsole/global/appname");
if (appName != null) {
// Set the plugin name so that the proper i18n String can be loaded.
appName.addAttribute("plugin", pluginName);
}
// If global images are specified, override their URL.
Element imageEl = (Element)adminElement.selectSingleNode(
"/plugin/adminconsole/global/logo-image");
if (imageEl != null) {
imageEl.setText("plugins/" + pluginName + "/" + imageEl.getText());
// Set the plugin name so that the proper i18n String can be loaded.
imageEl.addAttribute("plugin", pluginName);
}
imageEl = (Element)adminElement.selectSingleNode("/plugin/adminconsole/global/login-image");
if (imageEl != null) {
imageEl.setText("plugins/" + pluginName + "/" + imageEl.getText());
// Set the plugin name so that the proper i18n String can be loaded.
imageEl.addAttribute("plugin", pluginName);
}
// Modify all the URL's in the XML so that they are passed through
// the plugin servlet correctly.
List urls = adminElement.selectNodes("//@url");
for (Object url : urls) {
Attribute attr = (Attribute)url;
attr.setValue("plugins/" + pluginName + "/" + attr.getValue());
}
// In order to internationalize the names and descriptions in the model,
// we add a "plugin" attribute to each tab, sidebar, and item so that
// the the renderer knows where to load the i18n Strings from.
String[] elementNames = new String [] { "tab", "sidebar", "item" };
for (String elementName : elementNames) {
List values = adminElement.selectNodes("//" + elementName);
for (Object value : values) {
Element element = (Element) value;
// Make sure there's a name or description. Otherwise, no need to
// override i18n settings.
if (element.attribute("name") != null ||
element.attribute("value") != null) {
element.addAttribute("plugin", pluginName);
}
}
}
AdminConsole.addModel(pluginName, adminElement);
}
firePluginCreatedEvent(pluginName, plugin);
}
else {
Log.warn("Plugin " + pluginDir + " could not be loaded: no plugin.xml file found");
}
}
catch (Throwable e) {
Log.error("Error loading plugin: " + pluginDir, e);
}
}
private void configureCaches(File pluginDir, String pluginName) {
File cacheConfig = new File(pluginDir, "cache-config.xml");
if (cacheConfig.exists()) {
PluginCacheConfigurator configurator = new PluginCacheConfigurator();
try {
configurator.setInputStream(new BufferedInputStream(new FileInputStream(cacheConfig)));
configurator.configure(pluginName);
}
catch (Exception e) {
Log.error(e);
}
}
}
private void firePluginCreatedEvent(String name, Plugin plugin) {
for(PluginListener listener : pluginListeners) {
listener.pluginCreated(name, plugin);
}
}
private void firePluginsMonitored() {
for(PluginManagerListener listener : pluginManagerListeners) {
listener.pluginsMonitored();
}
}
/**
* Unloads a plugin. The {@link Plugin#destroyPlugin()} method will be called and then
* any resources will be released. The name should be the name of the plugin directory
* and not the name as given by the plugin meta-data. This method only removes
* the plugin but does not delete the plugin JAR file. Therefore, if the plugin JAR
* still exists after this method is called, the plugin will be started again the next
* time the plugin monitor process runs. This is useful for "restarting" plugins.<p>
* <p/>
* This method is called automatically when a plugin's JAR file is deleted.
*
* @param pluginName the name of the plugin to unload.
*/
public void unloadPlugin(String pluginName) {
Log.debug("PluginManager: Unloading plugin " + pluginName);
Plugin plugin = plugins.get(pluginName);
if (plugin != null) {
// Remove from dev mode if it exists.
pluginDevelopment.remove(plugin);
// See if any child plugins are defined.
if (parentPluginMap.containsKey(plugin)) {
for (String childPlugin : parentPluginMap.get(plugin)) {
Log.debug("PluginManager: Unloading child plugin: " + childPlugin);
unloadPlugin(childPlugin);
}
parentPluginMap.remove(plugin);
}
File webXML = new File(pluginDirectory, pluginName + File.separator + "web" + File.separator + "WEB-INF" +
File.separator + "web.xml");
if (webXML.exists()) {
AdminConsole.removeModel(pluginName);
PluginServlet.unregisterServlets(webXML);
}
File customWebXML = new File(pluginDirectory, pluginName + File.separator + "web" + File.separator + "WEB-INF" +
File.separator + "web-custom.xml");
if (customWebXML.exists()) {
PluginServlet.unregisterServlets(customWebXML);
}
// Wrap destroying the plugin in a try/catch block. Otherwise, an exception raised
// in the destroy plugin process will disrupt the whole unloading process. It's still
// possible that classloader destruction won't work in the case that destroying the plugin
// fails. In that case, Openfire may need to be restarted to fully cleanup the plugin
// resources.
try {
plugin.destroyPlugin();
}
catch (Exception e) {
Log.error(e);
}
}
// Remove references to the plugin so it can be unloaded from memory
// If plugin still fails to be removed then we will add references back
// Anyway, for a few seconds admins may not see the plugin in the admin console
// and in a subsequent refresh it will appear if failed to be removed
plugins.remove(pluginName);
File pluginFile = pluginDirs.remove(plugin);
PluginClassLoader pluginLoader = classloaders.remove(plugin);
// Try to remove the folder where the plugin was exploded. If this works then
// the plugin was successfully removed. Otherwise, some objects created by the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -