OF-1203: Prevent plugin (un)load concurrency issues

This commit removes direct interaction with the plugin manager state, when
working with the admin console. Instead, such actions will now cause the
plugin monitor to run, which will indirectly apply the desired changes to
the state of the plugin manager. This avoid concurrency issues in situations
where the admin console and plugin monitor attempt to modify the state of
the plugin manager at the same time.
parent 009a26df
......@@ -39,6 +39,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
......@@ -580,6 +581,38 @@ public class PluginManager
}
}
public boolean reloadPlugin( String pluginName )
{
Log.debug( "Reloading plugin '{}'..." );
final Plugin plugin = getPlugin( pluginName );
if ( plugin == null )
{
Log.warn( "Unable to reload plugin '{}'. No such plugin loaded.", pluginName );
return false;
}
final Path path = getPluginPath( plugin );
if ( path == null )
{
// When there's a plugin, there should be a path. If there isn't, our code is buggy.
throw new IllegalStateException( "Unable to determine installation path of plugin: " + pluginName );
}
try
{
Files.setLastModifiedTime( path, FileTime.fromMillis( 0 ) );
}
catch ( IOException e )
{
Log.warn( "Unable to reload plugin '{}'. Unable to reset the 'last modified time' of the plugin path. Try removing and restoring the plugin jar file manually." );
return false;
}
pluginMonitor.runNow( false );
return true;
}
/**
* Unloads a plugin. The {@link Plugin#destroyPlugin()} method will be called and then any resources will be
* released. The name should be the canonical name of the plugin (based on the plugin directory name) and not the
......@@ -594,7 +627,7 @@ public class PluginManager
*
* @param pluginName the name of the plugin to unload.
*/
public void unloadPlugin( String pluginName )
void unloadPlugin( String pluginName )
{
Log.debug( "Unloading plugin '{}'...", pluginName );
......
......@@ -44,6 +44,12 @@
REST API Plugin Changelog
</h1>
<p><b>1.2.5</b> -- October 14th, 2016</p>
<ul>
<li>Updated to match new API in Openfire 4.1.0</li>
<li>Requires Openfire 4.1.0 or later.</li>
</ul>
<p><b>1.2.4</b> -- July 4th, 2016</p>
<ul>
<li>Fixed: Send a presence by affiliation change</li>
......
......@@ -5,9 +5,9 @@
<name>REST API</name>
<description>Allows administration over a RESTful API.</description>
<author>Roman Soldatow</author>
<version>1.2.4</version>
<date>07/04/2016</date>
<minServerVersion>4.0.0</minServerVersion>
<version>1.2.5</version>
<date>10/14/2016</date>
<minServerVersion>4.1.0</minServerVersion>
<adminconsole>
<tab id="tab-server">
<sidebar id="sidebar-server-settings">
......
......@@ -55,7 +55,7 @@
if(is2Reload) {
String pluginName = pluginManager.getName(plugin);
String pluginDir = pluginManager.getPluginDirectory(plugin).getName();
pluginManager.unloadPlugin(pluginDir);
pluginManager.reloadPlugin(pluginDir);
// Log the event
admin.logEvent("reloaded plugin "+ pluginName, null);
......
......@@ -96,7 +96,7 @@
for (Plugin plugin : plugins) {
File pluginDir = pluginManager.getPluginDirectory(plugin);
if (reloadPlugin.equals(pluginDir.getName())) {
pluginManager.unloadPlugin(reloadPlugin);
pluginManager.reloadPlugin(reloadPlugin);
// Log the event
webManager.logEvent("reloaded plugin "+reloadPlugin, null);
response.sendRedirect("plugin-admin.jsp?reloadsuccess=true");
......
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