aboutsummaryrefslogtreecommitdiffstats
path: root/pf4j/src/main
diff options
context:
space:
mode:
authorrreich <rainer.reich@coremedia.com>2020-11-05 14:37:08 +0100
committerGitHub <noreply@github.com>2020-11-05 15:37:08 +0200
commitf6ede83be37a29b069a602fdf4b4864c16f2c3d2 (patch)
tree079e30e562d5f4a0f0f68fd2c87ec684b489bcdc /pf4j/src/main
parentc2d9998350b3a15ff7678c9053bca434463cf915 (diff)
downloadpf4j-f6ede83be37a29b069a602fdf4b4864c16f2c3d2.tar.gz
pf4j-f6ede83be37a29b069a602fdf4b4864c16f2c3d2.zip
Support multiple plugin root directories (#404)
Diffstat (limited to 'pf4j/src/main')
-rw-r--r--pf4j/src/main/java/org/pf4j/AbstractPluginManager.java65
-rw-r--r--pf4j/src/main/java/org/pf4j/BasePluginRepository.java46
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginManager.java21
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java31
-rw-r--r--pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java10
-rw-r--r--pf4j/src/main/java/org/pf4j/JarPluginManager.java8
-rw-r--r--pf4j/src/main/java/org/pf4j/JarPluginRepository.java10
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginManager.java12
-rw-r--r--pf4j/src/main/java/org/pf4j/ZipPluginManager.java4
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);
}
}