diff options
author | rreich <rainer.reich@coremedia.com> | 2020-11-05 14:37:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-05 15:37:08 +0200 |
commit | f6ede83be37a29b069a602fdf4b4864c16f2c3d2 (patch) | |
tree | 079e30e562d5f4a0f0f68fd2c87ec684b489bcdc /pf4j/src/main | |
parent | c2d9998350b3a15ff7678c9053bca434463cf915 (diff) | |
download | pf4j-f6ede83be37a29b069a602fdf4b4864c16f2c3d2.tar.gz pf4j-f6ede83be37a29b069a602fdf4b4864c16f2c3d2.zip |
Support multiple plugin root directories (#404)
Diffstat (limited to 'pf4j/src/main')
9 files changed, 136 insertions, 71 deletions
diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 3d109e2..9562257 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -25,12 +25,14 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * This class implements the boilerplate plugin code that any {@link PluginManager} @@ -51,7 +53,7 @@ public abstract class AbstractPluginManager implements PluginManager { public static final String DEFAULT_PLUGINS_DIR = "plugins"; public static final String DEVELOPMENT_PLUGINS_DIR = "../plugins"; - protected Path pluginsRoot; + protected final List<Path> pluginsRoots = new ArrayList<>(); protected ExtensionFinder extensionFinder; @@ -109,19 +111,28 @@ public abstract class AbstractPluginManager implements PluginManager { protected VersionManager versionManager; /** - * The plugins root is supplied by {@code System.getProperty("pf4j.pluginsDir", "plugins")}. + * The plugins roots are supplied as comma-separated list by {@code System.getProperty("pf4j.pluginsDir", "plugins")}. */ public AbstractPluginManager() { initialize(); } /** - * Constructs {@code AbstractPluginManager} with the given plugins root. + * Constructs {@code AbstractPluginManager} with the given plugins roots. * - * @param pluginsRoot the root to search for plugins + * @param pluginsRoots the roots to search for plugins */ - public AbstractPluginManager(Path pluginsRoot) { - this.pluginsRoot = pluginsRoot; + public AbstractPluginManager(Path... pluginsRoots) { + this(Arrays.asList(pluginsRoots)); + } + + /** + * Constructs {@code AbstractPluginManager} with the given plugins roots. + * + * @param pluginsRoots the roots to search for plugins + */ + public AbstractPluginManager(List<Path> pluginsRoots) { + this.pluginsRoots.addAll(pluginsRoots); initialize(); } @@ -200,12 +211,17 @@ public abstract class AbstractPluginManager implements PluginManager { */ @Override public void loadPlugins() { - log.debug("Lookup plugins in '{}'", pluginsRoot); - // check for plugins root - if (Files.notExists(pluginsRoot) || !Files.isDirectory(pluginsRoot)) { - log.warn("No '{}' root", pluginsRoot); + log.debug("Lookup plugins in '{}'", pluginsRoots); + // check for plugins roots + if (pluginsRoots.isEmpty()) { + log.warn("No plugins roots configured"); return; } + pluginsRoots.forEach(path -> { + if (Files.notExists(path) || !Files.isDirectory(path)) { + log.warn("No '{}' root", path); + } + }); // get all plugin paths from repository List<Path> pluginPaths = pluginRepository.getPluginPaths(); @@ -599,8 +615,15 @@ public abstract class AbstractPluginManager implements PluginManager { return pluginLoader; } + @Override public Path getPluginsRoot() { - return pluginsRoot; + return pluginsRoots.stream() + .findFirst() + .orElseThrow(() -> new IllegalStateException("pluginsRoots have not been initialized, yet.")); + } + + public List<Path> getPluginsRoots() { + return Collections.unmodifiableList(pluginsRoots); } @Override @@ -687,8 +710,8 @@ public abstract class AbstractPluginManager implements PluginManager { pluginStateListeners = new ArrayList<>(); - if (pluginsRoot == null) { - pluginsRoot = createPluginsRoot(); + if (pluginsRoots.isEmpty()) { + pluginsRoots.addAll(createPluginsRoot()); } pluginRepository = createPluginRepository(); @@ -704,20 +727,24 @@ public abstract class AbstractPluginManager implements PluginManager { } /** - * Add the possibility to override the plugins root. - * If a {@link #PLUGINS_DIR_PROPERTY_NAME} system property is defined than this method returns that root. + * Add the possibility to override the plugins roots. + * If a {@link #PLUGINS_DIR_PROPERTY_NAME} system property is defined than this method returns that roots. * If {@link #getRuntimeMode()} returns {@link RuntimeMode#DEVELOPMENT} than {@link #DEVELOPMENT_PLUGINS_DIR} * is returned else this method returns {@link #DEFAULT_PLUGINS_DIR}. * * @return the plugins root */ - protected Path createPluginsRoot() { + protected List<Path> createPluginsRoot() { String pluginsDir = System.getProperty(PLUGINS_DIR_PROPERTY_NAME); - if (pluginsDir == null) { - pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR; + if (pluginsDir != null && !pluginsDir.isEmpty()) { + return Arrays.stream(pluginsDir.split(",")) + .map(String::trim) + .map(Paths::get) + .collect(Collectors.toList()); } - return Paths.get(pluginsDir); + pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR; + return Collections.singletonList(Paths.get(pluginsDir)); } /** diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index ea5ad3b..9ab8f96 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -22,11 +22,11 @@ import java.io.FileFilter; import java.io.IOException; import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Decebal Suiu @@ -34,17 +34,21 @@ import java.util.List; */ public class BasePluginRepository implements PluginRepository { - protected final Path pluginsRoot; + protected final List<Path> pluginsRoots; protected FileFilter filter; protected Comparator<File> comparator; - public BasePluginRepository(Path pluginsRoot) { - this(pluginsRoot, null); + public BasePluginRepository(Path... pluginsRoots) { + this(Arrays.asList(pluginsRoots)); } - public BasePluginRepository(Path pluginsRoot, FileFilter filter) { - this.pluginsRoot = pluginsRoot; + public BasePluginRepository(List<Path> pluginsRoots) { + this(pluginsRoots, null); + } + + public BasePluginRepository(List<Path> pluginsRoots, FileFilter filter) { + this.pluginsRoots = pluginsRoots; this.filter = filter; // last modified file is first @@ -67,22 +71,11 @@ public class BasePluginRepository implements PluginRepository { @Override public List<Path> getPluginPaths() { - File[] files = pluginsRoot.toFile().listFiles(filter); - - if ((files == null) || files.length == 0) { - return Collections.emptyList(); - } - - if (comparator != null) { - Arrays.sort(files, comparator); - } - - List<Path> paths = new ArrayList<>(files.length); - for (File file : files) { - paths.add(file.toPath()); - } - - return paths; + return pluginsRoots.stream() + .flatMap(path -> streamFiles(path, filter)) + .sorted(comparator) + .map(File::toPath) + .collect(Collectors.toList()); } @Override @@ -101,4 +94,11 @@ public class BasePluginRepository implements PluginRepository { } } + protected Stream<File> streamFiles(Path directory, FileFilter filter) { + File[] files = directory.toFile().listFiles(filter); + return files != null + ? Arrays.stream(files) + : Stream.empty(); + } + } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index 9cad187..e2667d4 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; /** * Default implementation of the {@link PluginManager} interface. @@ -41,8 +42,12 @@ public class DefaultPluginManager extends AbstractPluginManager { super(); } - public DefaultPluginManager(Path pluginsRoot) { - super(pluginsRoot); + public DefaultPluginManager(Path... pluginsRoots) { + super(pluginsRoots); + } + + public DefaultPluginManager(List<Path> pluginsRoots) { + super(pluginsRoots); } @Override @@ -73,7 +78,11 @@ public class DefaultPluginManager extends AbstractPluginManager { @Override protected PluginStatusProvider createPluginStatusProvider() { String configDir = System.getProperty(PLUGINS_DIR_CONFIG_PROPERTY_NAME); - Path configPath = configDir != null ? Paths.get(configDir) : getPluginsRoot(); + Path configPath = configDir != null + ? Paths.get(configDir) + : getPluginsRoots().stream() + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("No pluginsRoot configured")); return new DefaultPluginStatusProvider(configPath); } @@ -81,9 +90,9 @@ public class DefaultPluginManager extends AbstractPluginManager { @Override protected PluginRepository createPluginRepository() { return new CompoundPluginRepository() - .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment) - .add(new JarPluginRepository(getPluginsRoot()), this::isNotDevelopment) - .add(new DefaultPluginRepository(getPluginsRoot()), this::isNotDevelopment); + .add(new DevelopmentPluginRepository(getPluginsRoots()), this::isDevelopment) + .add(new JarPluginRepository(getPluginsRoots()), this::isNotDevelopment) + .add(new DefaultPluginRepository(getPluginsRoots()), this::isNotDevelopment); } @Override diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index 2fafbc7..82a447f 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -29,6 +29,7 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.nio.file.Path; +import java.util.Arrays; import java.util.List; /** @@ -38,8 +39,12 @@ public class DefaultPluginRepository extends BasePluginRepository { private static final Logger log = LoggerFactory.getLogger(DefaultPluginRepository.class); - public DefaultPluginRepository(Path pluginsRoot) { - super(pluginsRoot); + public DefaultPluginRepository(Path... pluginsRoots) { + this(Arrays.asList(pluginsRoots)); + } + + public DefaultPluginRepository(List<Path> pluginsRoots) { + super(pluginsRoots); AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter()); pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter())); @@ -64,16 +69,18 @@ public class DefaultPluginRepository extends BasePluginRepository { private void extractZipFiles() { // expand plugins zip files - File[] zipFiles = pluginsRoot.toFile().listFiles(new ZipFileFilter()); - if ((zipFiles != null) && zipFiles.length > 0) { - for (File pluginZip : zipFiles) { - try { - FileUtils.expandIfZip(pluginZip.toPath()); - } catch (IOException e) { - log.error("Cannot expand plugin zip '{}'", pluginZip); - log.error(e.getMessage(), e); - } - } + pluginsRoots.stream() + .flatMap(path -> streamFiles(path, new ZipFileFilter())) + .map(File::toPath) + .forEach(this::expandIfZip); + } + + private void expandIfZip(Path filePath) { + try { + FileUtils.expandIfZip(filePath); + } catch (IOException e) { + log.error("Cannot expand plugin zip '{}'", filePath); + log.error(e.getMessage(), e); } } diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java index e8f2c69..fdc74c9 100644 --- a/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java @@ -24,6 +24,8 @@ import org.pf4j.util.OrFileFilter; import java.io.FileFilter; import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; /** * @author Decebal Suiu @@ -33,8 +35,12 @@ public class DevelopmentPluginRepository extends BasePluginRepository { public static final String MAVEN_BUILD_DIR = "target"; public static final String GRADLE_BUILD_DIR = "build"; - public DevelopmentPluginRepository(Path pluginsRoot) { - super(pluginsRoot); + public DevelopmentPluginRepository(Path... pluginsRoots) { + this(Arrays.asList(pluginsRoots)); + } + + public DevelopmentPluginRepository(List<Path> pluginsRoots) { + super(pluginsRoots); AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter()); pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter())); diff --git a/pf4j/src/main/java/org/pf4j/JarPluginManager.java b/pf4j/src/main/java/org/pf4j/JarPluginManager.java index f280466..ebbc63d 100644 --- a/pf4j/src/main/java/org/pf4j/JarPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/JarPluginManager.java @@ -30,8 +30,8 @@ public class JarPluginManager extends DefaultPluginManager { super(); } - public JarPluginManager(Path pluginsRoot) { - super(pluginsRoot); + public JarPluginManager(Path... pluginsRoots) { + super(pluginsRoots); } @Override @@ -49,8 +49,8 @@ public class JarPluginManager extends DefaultPluginManager { @Override protected PluginRepository createPluginRepository() { return new CompoundPluginRepository() - .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment) - .add(new JarPluginRepository(getPluginsRoot()), this::isNotDevelopment); + .add(new DevelopmentPluginRepository(getPluginsRoots()), this::isDevelopment) + .add(new JarPluginRepository(getPluginsRoots()), this::isNotDevelopment); } } diff --git a/pf4j/src/main/java/org/pf4j/JarPluginRepository.java b/pf4j/src/main/java/org/pf4j/JarPluginRepository.java index a8be3ff..d629bbd 100644 --- a/pf4j/src/main/java/org/pf4j/JarPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/JarPluginRepository.java @@ -18,14 +18,20 @@ package org.pf4j; import org.pf4j.util.JarFileFilter; import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; /** * @author Decebal Suiu */ public class JarPluginRepository extends BasePluginRepository { - public JarPluginRepository(Path pluginsRoot) { - super(pluginsRoot, new JarFileFilter()); + public JarPluginRepository(Path... pluginsRoots) { + this(Arrays.asList(pluginsRoots)); + } + + public JarPluginRepository(List<Path> pluginsRoots) { + super(pluginsRoots, new JarFileFilter()); } } diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index 248b1ac..b717656 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -205,12 +205,22 @@ public interface PluginManager { String getSystemVersion(); /** - * Gets the path of the folder where plugins are installed. + * Gets the first path of the folders where plugins are installed. + * + * @deprecated Use {@link #getPluginsRoots()} instead to get all paths where plugins are could be installed. * * @return Path of plugins root */ + @Deprecated Path getPluginsRoot(); + /** + * Gets the a read-only list of all paths of the folders where plugins are installed. + * + * @return Paths of plugins roots + */ + List<Path> getPluginsRoots(); + VersionManager getVersionManager(); } diff --git a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java index a32d156..a22f3c6 100644 --- a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java @@ -42,8 +42,8 @@ public class ZipPluginManager extends DefaultPluginManager { @Override protected PluginRepository createPluginRepository() { return new CompoundPluginRepository() - .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment) - .add(new DefaultPluginRepository(getPluginsRoot()), this::isNotDevelopment); + .add(new DevelopmentPluginRepository(getPluginsRoots()), this::isDevelopment) + .add(new DefaultPluginRepository(getPluginsRoots()), this::isNotDevelopment); } } |