mirror of https://github.com/halo-dev/halo
fix: different jar file with the same name appears in the plugins directory after a failed installation (#3841)
#### What type of PR is this? /kind bug /area core /milestone 2.5.x #### What this PR does / why we need it: 修复插件安装后无法启动会导致卸载后插件 JAR 文件残留的问题 how to test it? 1. 安装一个无法启动的插件,比如在插件声明周期方法中抛一个异常 2. 启动插件,然后卸载插件看插件 JAR 是否被正确删除 3. 如果是插件开发模式则不会删除文件 #### Which issue(s) this PR fixes: Fixes #3840 #### Does this PR introduce a user-facing change? ```release-note 修复插件安装后无法启动会导致卸载后插件 JAR 文件残留的问题 ```pull/3845/head
parent
2dcbceea5e
commit
d589ce56cc
|
@ -1,5 +1,6 @@
|
||||||
package run.halo.app.core.extension.reconciler;
|
package run.halo.app.core.extension.reconciler;
|
||||||
|
|
||||||
|
import static org.pf4j.util.FileUtils.isJarFile;
|
||||||
import static run.halo.app.plugin.PluginConst.DELETE_STAGE;
|
import static run.halo.app.plugin.PluginConst.DELETE_STAGE;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -22,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.pf4j.PluginDescriptor;
|
import org.pf4j.PluginDescriptor;
|
||||||
|
import org.pf4j.PluginRuntimeException;
|
||||||
import org.pf4j.PluginState;
|
import org.pf4j.PluginState;
|
||||||
import org.pf4j.PluginWrapper;
|
import org.pf4j.PluginWrapper;
|
||||||
import org.pf4j.RuntimeMode;
|
import org.pf4j.RuntimeMode;
|
||||||
|
@ -277,6 +279,15 @@ public class PluginReconciler implements Reconciler<Request> {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentState != desiredState) {
|
||||||
|
log.error("Plugin [{}] state transition failed: {}", name,
|
||||||
|
haloPluginManager.getPluginStartingError(name));
|
||||||
|
var e = new PluginRuntimeException("Plugin [" + name + "] state transition from ["
|
||||||
|
+ currentState + "] to [" + desiredState + "] failed");
|
||||||
|
persistenceFailureStatus(name, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void persistenceFailureStatus(String pluginName, Throwable e) {
|
void persistenceFailureStatus(String pluginName, Throwable e) {
|
||||||
|
@ -554,25 +565,41 @@ public class PluginReconciler implements Reconciler<Request> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginWrapper pluginWrapper = haloPluginManager.getPlugin(name);
|
PluginWrapper pluginWrapper = haloPluginManager.getPlugin(name);
|
||||||
if (pluginWrapper == null) {
|
if (pluginWrapper != null) {
|
||||||
return;
|
// pluginWrapper must not be null in below code
|
||||||
}
|
// stop and unload plugin, see also PluginBeforeStopSyncListener
|
||||||
// pluginWrapper must not be null in below code
|
if (!haloPluginManager.unloadPlugin(name)) {
|
||||||
// stop and unload plugin, see also PluginBeforeStopSyncListener
|
throw new IllegalStateException("Failed to unload plugin: " + name);
|
||||||
if (!haloPluginManager.unloadPlugin(name)) {
|
}
|
||||||
throw new IllegalStateException("Failed to unload plugin: " + name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete plugin resources
|
// delete plugin resources
|
||||||
if (RuntimeMode.DEPLOYMENT.equals(pluginWrapper.getRuntimeMode())) {
|
Path pluginPath = determinePluginLocation(plugin);
|
||||||
|
if (pluginPath != null && !isDevelopmentMode(name) && isJarFile(pluginPath)) {
|
||||||
// delete plugin file
|
// delete plugin file
|
||||||
try {
|
try {
|
||||||
Files.deleteIfExists(pluginWrapper.getPluginPath());
|
Files.deleteIfExists(pluginPath);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Path determinePluginLocation(Plugin plugin) {
|
||||||
|
final var name = plugin.getMetadata().getName();
|
||||||
|
PluginWrapper pluginWrapper = haloPluginManager.getPlugin(name);
|
||||||
|
return Optional.ofNullable(pluginWrapper)
|
||||||
|
.map(PluginWrapper::getPluginPath)
|
||||||
|
.orElseGet(() -> {
|
||||||
|
var localtionUri = plugin.statusNonNull().getLoadLocation();
|
||||||
|
if (localtionUri != null) {
|
||||||
|
return Path.of(localtionUri);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void createInitialReverseProxyIfNotPresent(Plugin plugin) {
|
void createInitialReverseProxyIfNotPresent(Plugin plugin) {
|
||||||
String pluginName = plugin.getMetadata().getName();
|
String pluginName = plugin.getMetadata().getName();
|
||||||
String reverseProxyName = initialReverseProxyName(pluginName);
|
String reverseProxyName = initialReverseProxyName(pluginName);
|
||||||
|
|
Loading…
Reference in New Issue