Commit 10602445 authored by daryl herzmann's avatar daryl herzmann Committed by GitHub

Merge pull request #655 from guusdk/Plugin-fixes

Plugin fixes
parents 771bbab3 fb589eba
...@@ -2585,14 +2585,14 @@ plugin.admin.info=Plugins add new functionality to the server. The list of plugi ...@@ -2585,14 +2585,14 @@ plugin.admin.info=Plugins add new functionality to the server. The list of plugi
<a href="available-plugins.jsp">Available Plugins</a> page. <a href="available-plugins.jsp">Available Plugins</a> page.
plugin.admin.deleted_success=Plugin deleted successfully. plugin.admin.deleted_success=Plugin deleted successfully.
plugin.admin.deleted_failure=Unable to delete plugin. plugin.admin.deleted_failure=Unable to delete plugin.
plugin.admin.uploaded_success=Plugin uploaded successfully. It may take a short time for the \ plugin.admin.uploaded_success=Plugin uploaded successfully.
plugin to appear in the list of installed plugins.
plugin.admin.uploaded_failure=Unable to upload plugin. See server error logs. plugin.admin.uploaded_failure=Unable to upload plugin. See server error logs.
plugin.admin.upload_plugin=Upload Plugin plugin.admin.upload_plugin=Upload Plugin
plugin.admin.upload_plugin.info=Plugin files (.jar) can be uploaded directly by using the form below. plugin.admin.upload_plugin.info=Plugin files (.jar) can be uploaded directly by using the form below.
plugin.admin.click_reload=Reload the plugin. plugin.admin.click_reload=Reload the plugin.
plugin.admin.reload_success=Plugin was successfully reloaded. It may take a short time for the \ plugin.admin.reload_success=Plugin was successfully reloaded.
plugin to appear in the list of installed plugins again. plugin.admin.reload_failure=Unable to reload the plugin. Refer to the log files for additional information.
plugin.admin.monitortask_running=The plugin manager is currently running. It may take a short time for the list of installed plugins to be complete.
plugin.admin.name=Plugins plugin.admin.name=Plugins
plugin.admin.description=Description plugin.admin.description=Description
plugin.admin.version=Version plugin.admin.version=Version
......
...@@ -39,6 +39,7 @@ import java.io.IOException; ...@@ -39,6 +39,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
...@@ -580,6 +581,38 @@ public class PluginManager ...@@ -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 * 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 * 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 ...@@ -594,7 +627,7 @@ public class PluginManager
* *
* @param pluginName the name of the plugin to unload. * @param pluginName the name of the plugin to unload.
*/ */
public void unloadPlugin( String pluginName ) void unloadPlugin( String pluginName )
{ {
Log.debug( "Unloading plugin '{}'...", pluginName ); Log.debug( "Unloading plugin '{}'...", pluginName );
...@@ -609,15 +642,14 @@ public class PluginManager ...@@ -609,15 +642,14 @@ public class PluginManager
// See if any child plugins are defined. // See if any child plugins are defined.
if ( parentPluginMap.containsKey( plugin ) ) if ( parentPluginMap.containsKey( plugin ) )
{ {
String[] childPlugins = String[] childPlugins = parentPluginMap.get( plugin ).toArray( new String[ parentPluginMap.get( plugin ).size() ] );
parentPluginMap.get( plugin ).toArray( new String[ parentPluginMap.get( plugin ).size() ] );
parentPluginMap.remove( plugin );
for ( String childPlugin : childPlugins ) for ( String childPlugin : childPlugins )
{ {
Log.debug( "Unloading child plugin: '{}'.", childPlugin ); Log.debug( "Unloading child plugin: '{}'.", childPlugin );
childPluginMap.remove( plugins.get( childPlugin ) ); childPluginMap.remove( plugins.get( childPlugin ) );
unloadPlugin( childPlugin ); unloadPlugin( childPlugin );
} }
parentPluginMap.remove( plugin );
} }
Path webXML = pluginDirectory.resolve( pluginName ).resolve( "web" ).resolve( "WEB-INF" ).resolve( "web.xml" ); Path webXML = pluginDirectory.resolve( pluginName ).resolve( "web" ).resolve( "WEB-INF" ).resolve( "web.xml" );
...@@ -1015,4 +1047,9 @@ public class PluginManager ...@@ -1015,4 +1047,9 @@ public class PluginManager
} }
} }
} }
public boolean isMonitorTaskRunning()
{
return pluginMonitor.isTaskRunning();
}
} }
\ No newline at end of file
...@@ -45,6 +45,8 @@ public class PluginMonitor ...@@ -45,6 +45,8 @@ public class PluginMonitor
private ScheduledExecutorService executor; private ScheduledExecutorService executor;
private boolean isTaskRunning = false;
public PluginMonitor( final PluginManager pluginManager ) public PluginMonitor( final PluginManager pluginManager )
{ {
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
...@@ -84,6 +86,11 @@ public class PluginMonitor ...@@ -84,6 +86,11 @@ public class PluginMonitor
} }
} }
public boolean isTaskRunning()
{
return isTaskRunning;
}
/** /**
* Immediately run a check of the plugin directory. * Immediately run a check of the plugin directory.
*/ */
...@@ -111,6 +118,7 @@ public class PluginMonitor ...@@ -111,6 +118,7 @@ public class PluginMonitor
// Prevent two tasks from running in parallel by using the plugin monitor itself as a mutex. // Prevent two tasks from running in parallel by using the plugin monitor itself as a mutex.
synchronized ( PluginMonitor.this ) synchronized ( PluginMonitor.this )
{ {
isTaskRunning = true;
try try
{ {
// The directory that contains all plugins. // The directory that contains all plugins.
...@@ -319,6 +327,10 @@ public class PluginMonitor ...@@ -319,6 +327,10 @@ public class PluginMonitor
{ {
Log.error( "An unexpected exception occurred:", e ); Log.error( "An unexpected exception occurred:", e );
} }
finally
{
isTaskRunning = false;
}
} }
} }
......
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
REST API Plugin Changelog REST API Plugin Changelog
</h1> </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> <p><b>1.2.4</b> -- July 4th, 2016</p>
<ul> <ul>
<li>Fixed: Send a presence by affiliation change</li> <li>Fixed: Send a presence by affiliation change</li>
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
<name>REST API</name> <name>REST API</name>
<description>Allows administration over a RESTful API.</description> <description>Allows administration over a RESTful API.</description>
<author>Roman Soldatow</author> <author>Roman Soldatow</author>
<version>1.2.4</version> <version>1.2.5</version>
<date>07/04/2016</date> <date>10/14/2016</date>
<minServerVersion>4.0.0</minServerVersion> <minServerVersion>4.1.0</minServerVersion>
<adminconsole> <adminconsole>
<tab id="tab-server"> <tab id="tab-server">
<sidebar id="sidebar-server-settings"> <sidebar id="sidebar-server-settings">
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
if(is2Reload) { if(is2Reload) {
String pluginName = pluginManager.getName(plugin); String pluginName = pluginManager.getName(plugin);
String pluginDir = pluginManager.getPluginDirectory(plugin).getName(); String pluginDir = pluginManager.getPluginDirectory(plugin).getName();
pluginManager.unloadPlugin(pluginDir); pluginManager.reloadPlugin(pluginDir);
// Log the event // Log the event
admin.logEvent("reloaded plugin "+ pluginName, null); admin.logEvent("reloaded plugin "+ pluginName, null);
......
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
<%@ page import="org.apache.commons.fileupload.FileItem" %> <%@ page import="org.apache.commons.fileupload.FileItem" %>
<%@ page import="org.apache.commons.fileupload.FileUploadException" %> <%@ page import="org.apache.commons.fileupload.FileUploadException" %>
<%@ taglib uri="admin" prefix="admin" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager" /> <jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager" />
<% webManager.init(request, response, session, application, out ); %> <% webManager.init(request, response, session, application, out ); %>
...@@ -96,7 +98,7 @@ ...@@ -96,7 +98,7 @@
for (Plugin plugin : plugins) { for (Plugin plugin : plugins) {
File pluginDir = pluginManager.getPluginDirectory(plugin); File pluginDir = pluginManager.getPluginDirectory(plugin);
if (reloadPlugin.equals(pluginDir.getName())) { if (reloadPlugin.equals(pluginDir.getName())) {
pluginManager.unloadPlugin(reloadPlugin); pluginManager.reloadPlugin(reloadPlugin);
// Log the event // Log the event
webManager.logEvent("reloaded plugin "+reloadPlugin, null); webManager.logEvent("reloaded plugin "+reloadPlugin, null);
response.sendRedirect("plugin-admin.jsp?reloadsuccess=true"); response.sendRedirect("plugin-admin.jsp?reloadsuccess=true");
...@@ -421,51 +423,42 @@ ...@@ -421,51 +423,42 @@
</head> </head>
<body> <body>
<c:if test="${param.deletesuccess eq 'true'}">
<% if ("true".equals(request.getParameter("deletesuccess"))) { %> <admin:infobox type="success">
<fmt:message key="plugin.admin.deleted_success" />
<div class="success"> </admin:infobox>
<fmt:message key="plugin.admin.deleted_success"/> </c:if>
</div> <c:if test="${param.deletesuccess eq 'false'}">
<br> <admin:infobox type="error">
<fmt:message key="plugin.admin.deleted_failure" />
<% } </admin:infobox>
else if ("false".equals(request.getParameter("deletesuccess"))) { %> </c:if>
<c:if test="${param.reloadsuccess eq 'true'}">
<div class="error"> <admin:infobox type="success">
<fmt:message key="plugin.admin.deleted_failure"/> <fmt:message key="plugin.admin.reload_success" />
</div> </admin:infobox>
<br> </c:if>
<c:if test="${param.reloadsuccess eq 'false'}">
<% } %> <admin:infobox type="success">
<fmt:message key="plugin.admin.reload_failure" />
<% if ("true".equals(request.getParameter("reloadsuccess"))) { %> </admin:infobox>
</c:if>
<div class="success"> <c:if test="${param.uploadsuccess eq 'true'}">
<fmt:message key="plugin.admin.reload_success"/> <admin:infobox type="success">
</div> <fmt:message key="plugin.admin.uploaded_success" />
<br> </admin:infobox>
</c:if>
<% } %> <c:if test="${param.uploadsuccess eq 'false'}">
<admin:infobox type="error">
<% if ("true".equals(request.getParameter("uploadsuccess"))) { %> <fmt:message key="plugin.admin.uploaded_failure" />
</admin:infobox>
<div class="success"> </c:if>
<fmt:message key="plugin.admin.uploaded_success"/> <c:if test="${ webManager.XMPPServer.pluginManager.monitorTaskRunning }">
</div> <admin:infobox type="info">
<br> <fmt:message key="plugin.admin.monitortask_running" />
</admin:infobox>
<% } </c:if>
else if ("false".equals(request.getParameter("uploadsuccess"))) { %> <p>
<div class="error">
<fmt:message key="plugin.admin.uploaded_failure"/>
</div>
<br>
<% } %>
<p>
<fmt:message key="plugin.admin.info"/> <fmt:message key="plugin.admin.info"/>
</p> </p>
...@@ -557,7 +550,7 @@ else if ("false".equals(request.getParameter("uploadsuccess"))) { %> ...@@ -557,7 +550,7 @@ else if ("false".equals(request.getParameter("uploadsuccess"))) { %>
<%= pluginAuthor != null ? pluginAuthor : "" %> &nbsp; <%= pluginAuthor != null ? pluginAuthor : "" %> &nbsp;
</td> </td>
<td width="1%" align="center" valign="top" class="<%= update != null ? "update-top" : "line-bottom-border"%>"> <td width="1%" align="center" valign="top" class="<%= update != null ? "update-top" : "line-bottom-border"%>">
<a href="plugin-admin.jsp?reloadplugin=<%= dirName %>" <a href="plugin-admin.jsp?csrf=${csrf}&reloadplugin=<%= dirName %>"
title="<fmt:message key="plugin.admin.click_reload" />" title="<fmt:message key="plugin.admin.click_reload" />"
><img src="images/refresh-16x16.gif" width="16" height="16" border="0" alt="<fmt:message key="global.refresh" />"></a> ><img src="images/refresh-16x16.gif" width="16" height="16" border="0" alt="<fmt:message key="global.refresh" />"></a>
</td> </td>
......
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