From c867d45898a99a843cb955563638b5fac18bc4f5 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 3 Apr 2014 10:23:51 -0400 Subject: [PATCH 1/2] Implement delete plugin --- .../fortsoft/pf4j/DefaultPluginManager.java | 81 +++++++++++++++---- .../java/ro/fortsoft/pf4j/PluginManager.java | 8 ++ .../java/ro/fortsoft/pf4j/util/FileUtils.java | 37 +++++++-- 3 files changed, 104 insertions(+), 22 deletions(-) diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java index 1bca676..1e33d2f 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java @@ -257,12 +257,14 @@ public class DefaultPluginManager implements PluginManager { // expand all plugin archives FileFilter zipFilter = new ZipFileFilter(); File[] zipFiles = pluginsDirectory.listFiles(zipFilter); - for (File zipFile : zipFiles) { - try { - expandPluginArchive(zipFile); - } catch (IOException e) { - log.error(e.getMessage(), e); - } + if (zipFiles != null) { + for (File zipFile : zipFiles) { + try { + expandPluginArchive(zipFile); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } } // check for no plugins @@ -271,20 +273,24 @@ public class DefaultPluginManager implements PluginManager { filterList.add(new NotFileFilter(createHiddenPluginFilter())); FileFilter pluginsFilter = new AndFileFilter(filterList); File[] directories = pluginsDirectory.listFiles(pluginsFilter); - log.debug("Found possible {} plugins: {}", directories.length, Arrays.asList(directories)); - if (directories.length == 0) { + List dirArray = new ArrayList(); + if (directories != null) { + dirArray.addAll(Arrays.asList(directories)); + } + log.debug("Found possible {} plugins: {}", dirArray.size(), dirArray); + if (dirArray.size() == 0) { log.info("No plugins"); return; } // load any plugin from plugins directory - for (File directory : directories) { - try { - loadPlugin(directory); - } catch (PluginException e) { - log.error(e.getMessage(), e); - } - } + for (File directory : dirArray) { + try { + loadPlugin(directory); + } catch (PluginException e) { + log.error(e.getMessage(), e); + } + } // resolve 'unresolvedPlugins' try { @@ -333,6 +339,51 @@ public class DefaultPluginManager implements PluginManager { return false; } + @Override + public boolean deletePlugin(String pluginId) { + if (!plugins.containsKey(pluginId)) { + throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId)); + } + PluginWrapper pw = getPlugin(pluginId); + PluginState state = stopPlugin(pluginId); + + if (PluginState.STOPPED != state) { + log.error(String.format("Failed to stop plugin %s on delete", pluginId)); + return false; + } + + if (!unloadPlugin(pluginId)) { + log.error(String.format("Failed to unload plugin %s on delete", pluginId)); + return false; + } + + File pluginFolder = new File(pluginsDirectory, pw.getPluginPath()); + File pluginZip = null; + + FileFilter zipFilter = new ZipFileFilter(); + File[] zipFiles = pluginsDirectory.listFiles(zipFilter); + if (zipFiles != null) { + // strip prepended / from the plugin path + String dirName = pw.getPluginPath().substring(1); + // find the zip file that matches the plugin path + for (File zipFile : zipFiles) { + String name = zipFile.getName().substring(0, zipFile.getName().lastIndexOf('.')); + if (name.equals(dirName)) { + pluginZip = zipFile; + break; + } + } + } + + if (pluginFolder.exists()) { + FileUtils.delete(pluginFolder); + } + if (pluginZip != null && pluginZip.exists()) { + FileUtils.delete(pluginZip); + } + return true; + } + /** * Get plugin class loader for this path. */ diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java index 6ffe4cf..57fb890 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java @@ -79,6 +79,14 @@ public interface PluginManager { */ public boolean unloadPlugin(String pluginId); + /** + * Deletes a plugin. + * + * @param pluginId + * @return true if the plugin was deleted + */ + public boolean deletePlugin(String pluginId); + public PluginClassLoader getPluginClassLoader(String pluginId); public List getExtensions(Class type); diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java b/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java index 0b8c38a..68cc2b3 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java @@ -1,11 +1,11 @@ /* * Copyright 2012 Decebal Suiu - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with * the License. You may obtain a copy of the License in the LICENSE file, or at: - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. @@ -25,11 +25,11 @@ import java.util.List; */ public class FileUtils { - public static List readLines(File file, boolean ignoreComments) throws IOException { + public static List readLines(File file, boolean ignoreComments) throws IOException { if (!file.exists() || !file.isFile()) { return Collections.emptyList(); } - + List lines = new ArrayList(); BufferedReader reader = null; @@ -46,8 +46,31 @@ public class FileUtils { reader.close(); } } - + return lines; } - + + /** + * Delete a file or recursively delete a folder. + * + * @param fileOrFolder + * @return true, if successful + */ + public static boolean delete(File fileOrFolder) { + boolean success = false; + if (fileOrFolder.isDirectory()) { + File [] files = fileOrFolder.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + success |= delete(file); + } else { + success |= file.delete(); + } + } + } + } + success |= fileOrFolder.delete(); + return success; + } } From c2fe1da41260a4a1b4390eb9591995d2069a7f00 Mon Sep 17 00:00:00 2001 From: James Moger Date: Fri, 4 Apr 2014 08:00:24 -0400 Subject: [PATCH 2/2] Simplify changes per review --- .../ro/fortsoft/pf4j/DefaultPluginManager.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java index 1e33d2f..7254206 100644 --- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java @@ -16,7 +16,6 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -273,18 +272,17 @@ public class DefaultPluginManager implements PluginManager { filterList.add(new NotFileFilter(createHiddenPluginFilter())); FileFilter pluginsFilter = new AndFileFilter(filterList); File[] directories = pluginsDirectory.listFiles(pluginsFilter); - List dirArray = new ArrayList(); - if (directories != null) { - dirArray.addAll(Arrays.asList(directories)); + if (directories == null) { + directories = new File[0]; } - log.debug("Found possible {} plugins: {}", dirArray.size(), dirArray); - if (dirArray.size() == 0) { + log.debug("Found possible {} plugins: {}", directories.length, directories); + if (directories.length == 0) { log.info("No plugins"); return; } // load any plugin from plugins directory - for (File directory : dirArray) { + for (File directory : directories) { try { loadPlugin(directory); } catch (PluginException e) { @@ -348,12 +346,12 @@ public class DefaultPluginManager implements PluginManager { PluginState state = stopPlugin(pluginId); if (PluginState.STOPPED != state) { - log.error(String.format("Failed to stop plugin %s on delete", pluginId)); + log.error("Failed to stop plugin {} on delete", pluginId); return false; } if (!unloadPlugin(pluginId)) { - log.error(String.format("Failed to unload plugin %s on delete", pluginId)); + log.error("Failed to unload plugin {} on delete", pluginId); return false; }