From 92add1ac9bb26b85d63135e709d87068d2dc9a90 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sun, 23 Jan 2022 23:29:31 +0200 Subject: [PATCH] Try to work with path instead of file --- .../java/org/pf4j/AbstractPluginManager.java | 8 +- .../main/java/org/pf4j/BasePluginLoader.java | 15 ++-- .../java/org/pf4j/BasePluginRepository.java | 39 ++++---- .../java/org/pf4j/CompoundPluginLoader.java | 4 +- .../org/pf4j/CompoundPluginRepository.java | 10 ++- .../org/pf4j/DefaultPluginRepository.java | 30 +++---- .../org/pf4j/DevelopmentPluginRepository.java | 28 +++--- .../main/java/org/pf4j/JarPluginLoader.java | 2 +- .../java/org/pf4j/JarPluginRepository.java | 4 +- .../pf4j/ManifestPluginDescriptorFinder.java | 11 ++- .../main/java/org/pf4j/PluginClassLoader.java | 14 ++- pf4j/src/main/java/org/pf4j/PluginLoader.java | 4 + .../main/java/org/pf4j/PluginRepository.java | 4 + .../main/java/org/pf4j/util/FileUtils.java | 89 +++++++------------ .../main/java/org/pf4j/util/OrFileFilter.java | 82 ----------------- pf4j/src/main/java/org/pf4j/util/Unzip.java | 43 ++++----- .../AndPathFilter.java} | 47 +++++----- .../DirectoryPathFilter.java} | 14 +-- .../ExtensionPathFilter.java} | 19 ++-- .../HiddenPathFilter.java} | 18 ++-- .../JarPathFilter.java} | 8 +- .../NamePathFilter.java} | 30 ++++--- .../NotPathFilter.java} | 15 ++-- .../java/org/pf4j/util/io/OrPathFilter.java | 81 +++++++++++++++++ .../java/org/pf4j/util/io/PathFilter.java | 12 +++ .../ZipPathFilter.java} | 10 +-- .../CompoundPluginDescriptorFinderTest.java | 4 +- .../org/pf4j/DefaultPluginManagerTest.java | 4 +- .../java/org/pf4j/JarPluginManagerTest.java | 7 +- .../org/pf4j/LegacyExtensionFinderTest.java | 7 +- .../test/java/org/pf4j/LoadPluginsTest.java | 4 +- .../ManifestPluginDescriptorFinderTest.java | 2 +- .../java/org/pf4j/PluginClassLoaderTest.java | 76 +++++++++------- .../PropertiesPluginDescriptorFinderTest.java | 4 +- .../test/java/org/pf4j/test/PluginJar.java | 9 +- .../test/java/org/pf4j/test/PluginZip.java | 9 +- .../java/org/pf4j/util/FileUtilsTest.java | 24 ++++- 37 files changed, 416 insertions(+), 375 deletions(-) delete mode 100644 pf4j/src/main/java/org/pf4j/util/OrFileFilter.java rename pf4j/src/main/java/org/pf4j/util/{AndFileFilter.java => io/AndPathFilter.java} (52%) rename pf4j/src/main/java/org/pf4j/util/{DirectoryFileFilter.java => io/DirectoryPathFilter.java} (72%) rename pf4j/src/main/java/org/pf4j/util/{ExtensionFileFilter.java => io/ExtensionPathFilter.java} (63%) rename pf4j/src/main/java/org/pf4j/util/{HiddenFilter.java => io/HiddenPathFilter.java} (65%) rename pf4j/src/main/java/org/pf4j/util/{JarFileFilter.java => io/JarPathFilter.java} (85%) rename pf4j/src/main/java/org/pf4j/util/{NameFileFilter.java => io/NamePathFilter.java} (52%) rename pf4j/src/main/java/org/pf4j/util/{NotFileFilter.java => io/NotPathFilter.java} (74%) create mode 100644 pf4j/src/main/java/org/pf4j/util/io/OrPathFilter.java create mode 100644 pf4j/src/main/java/org/pf4j/util/io/PathFilter.java rename pf4j/src/main/java/org/pf4j/util/{ZipFileFilter.java => io/ZipPathFilter.java} (80%) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index d57b12e..9496013 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -218,7 +218,7 @@ public abstract class AbstractPluginManager implements PluginManager { return; } pluginsRoots.forEach(path -> { - if (Files.notExists(path) || !Files.isDirectory(path)) { + if (!Files.isDirectory(path)) { log.warn("No '{}' root", path); } }); @@ -877,10 +877,10 @@ public abstract class AbstractPluginManager implements PluginManager { return pluginWrapper; } - + /** * creates the plugin wrapper. override this if you want to prevent plugins having full access to the plugin manager - * + * * @return */ protected PluginWrapper createPluginWrapper(PluginDescriptor pluginDescriptor, Path pluginPath, ClassLoader pluginClassLoader) { @@ -947,7 +947,7 @@ public abstract class AbstractPluginManager implements PluginManager { } /** - * The plugin label is used in logging and it's a string in format {@code pluginId@pluginVersion}. + * The plugin label is used in logging, and it's a string in format {@code pluginId@pluginVersion}. */ protected String getPluginLabel(PluginDescriptor pluginDescriptor) { return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion(); diff --git a/pf4j/src/main/java/org/pf4j/BasePluginLoader.java b/pf4j/src/main/java/org/pf4j/BasePluginLoader.java index e4f22f3..0d0fc99 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginLoader.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginLoader.java @@ -17,7 +17,6 @@ package org.pf4j; import org.pf4j.util.FileUtils; -import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -64,9 +63,9 @@ public class BasePluginLoader implements PluginLoader { */ protected void loadClasses(Path pluginPath, PluginClassLoader pluginClassLoader) { for (String directory : pluginClasspath.getClassesDirectories()) { - File file = pluginPath.resolve(directory).toFile(); - if (file.exists() && file.isDirectory()) { - pluginClassLoader.addFile(file); + Path path = pluginPath.resolve(directory); + if (Files.isDirectory(path)) { + pluginClassLoader.addPath(path); } } } @@ -77,10 +76,10 @@ public class BasePluginLoader implements PluginLoader { */ protected void loadJars(Path pluginPath, PluginClassLoader pluginClassLoader) { for (String jarsDirectory : pluginClasspath.getJarsDirectories()) { - Path file = pluginPath.resolve(jarsDirectory); - List jars = FileUtils.getJars(file); - for (File jar : jars) { - pluginClassLoader.addFile(jar); + Path path = pluginPath.resolve(jarsDirectory); + List jars = FileUtils.getJars(path); + for (Path jar : jars) { + pluginClassLoader.addPath(jar); } } } diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index 9ab8f96..84d7ef4 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -16,17 +16,18 @@ package org.pf4j; import org.pf4j.util.FileUtils; +import org.pf4j.util.io.PathFilter; import java.io.File; -import java.io.FileFilter; import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * @author Decebal Suiu @@ -36,8 +37,8 @@ public class BasePluginRepository implements PluginRepository { protected final List pluginsRoots; - protected FileFilter filter; - protected Comparator comparator; + protected PathFilter filter; + protected Comparator comparator; public BasePluginRepository(Path... pluginsRoots) { this(Arrays.asList(pluginsRoots)); @@ -47,40 +48,45 @@ public class BasePluginRepository implements PluginRepository { this(pluginsRoots, null); } - public BasePluginRepository(List pluginsRoots, FileFilter filter) { + public BasePluginRepository(List pluginsRoots, PathFilter filter) { this.pluginsRoots = pluginsRoots; this.filter = filter; // last modified file is first - this.comparator = Comparator.comparingLong(File::lastModified); + this.comparator = Comparator.comparingLong(path -> { + try { + return Files.getLastModifiedTime(path).toMillis(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); } - public void setFilter(FileFilter filter) { + public void setFilter(PathFilter filter) { this.filter = filter; } /** * Set a {@link File} {@link Comparator} used to sort the listed files from {@code pluginsRoot}. * This comparator is used in {@link #getPluginPaths()} method. - * By default is used a file comparator that returns the last modified files first. + * By default, it's used a file comparator that returns the last modified files first. * If you don't want a file comparator, then call this method with {@code null}. */ - public void setComparator(Comparator comparator) { + public void setComparator(Comparator comparator) { this.comparator = comparator; } @Override public List getPluginPaths() { return pluginsRoots.stream() - .flatMap(path -> streamFiles(path, filter)) + .flatMap(path -> FileUtils.findPaths(path, 1, filter)) .sorted(comparator) - .map(File::toPath) .collect(Collectors.toList()); } @Override public boolean deletePluginPath(Path pluginPath) { - if (!filter.accept(pluginPath.toFile())) { + if (!filter.accept(pluginPath)) { return false; } @@ -90,15 +96,8 @@ public class BasePluginRepository implements PluginRepository { } catch (NoSuchFileException e) { return false; // Return false on not found to be compatible with previous API (#135) } catch (IOException e) { - throw new PluginRuntimeException(e); + throw new UncheckedIOException(e); } } - protected Stream 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/CompoundPluginLoader.java b/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java index c20e4bb..ca1b264 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java @@ -76,7 +76,7 @@ public class CompoundPluginLoader implements PluginLoader { public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) { for (PluginLoader loader : loaders) { if (loader.isApplicable(pluginPath)) { - log.debug("'{}' is applicable for plugin '{}'", loader, pluginPath); + log.debug("'{}' is applicable for plugin '{}'", loader.getName(), pluginPath); try { ClassLoader classLoader = loader.loadPlugin(pluginPath, pluginDescriptor); if (classLoader != null) { @@ -87,7 +87,7 @@ public class CompoundPluginLoader implements PluginLoader { log.error(e.getMessage()); // ?! } } else { - log.debug("'{}' is not applicable for plugin '{}'", loader, pluginPath); + log.debug("'{}' is not applicable for plugin '{}'", loader.getName(), pluginPath); } } diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java index a36b00a..0bd524d 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java @@ -15,6 +15,9 @@ */ package org.pf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -28,6 +31,8 @@ import java.util.function.BooleanSupplier; */ public class CompoundPluginRepository implements PluginRepository { + private static final Logger log = LoggerFactory.getLogger(CompoundPluginRepository.class); + private List repositories = new ArrayList<>(); public CompoundPluginRepository add(PluginRepository repository) { @@ -59,7 +64,9 @@ public class CompoundPluginRepository implements PluginRepository { public List getPluginPaths() { Set paths = new LinkedHashSet<>(); for (PluginRepository repository : repositories) { - paths.addAll(repository.getPluginPaths()); + List pluginPaths = repository.getPluginPaths(); + log.debug("{} -> {}", repository.getName(), pluginPaths); + paths.addAll(pluginPaths); } return new ArrayList<>(paths); @@ -69,6 +76,7 @@ public class CompoundPluginRepository implements PluginRepository { public boolean deletePluginPath(Path pluginPath) { for (PluginRepository repository : repositories) { if (repository.deletePluginPath(pluginPath)) { + log.debug("Delete plugin '{}' from '{}'", pluginPath, repository.getName()); return true; } } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index 82a447f..02c8c79 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -15,19 +15,19 @@ */ package org.pf4j; -import org.pf4j.util.AndFileFilter; -import org.pf4j.util.DirectoryFileFilter; import org.pf4j.util.FileUtils; -import org.pf4j.util.HiddenFilter; -import org.pf4j.util.NotFileFilter; -import org.pf4j.util.OrFileFilter; -import org.pf4j.util.ZipFileFilter; +import org.pf4j.util.io.AndPathFilter; +import org.pf4j.util.io.DirectoryPathFilter; +import org.pf4j.util.io.HiddenPathFilter; +import org.pf4j.util.io.NotPathFilter; +import org.pf4j.util.io.OrPathFilter; +import org.pf4j.util.io.PathFilter; +import org.pf4j.util.io.ZipPathFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileFilter; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -46,8 +46,8 @@ public class DefaultPluginRepository extends BasePluginRepository { public DefaultPluginRepository(List pluginsRoots) { super(pluginsRoots); - AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter()); - pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter())); + AndPathFilter pluginsFilter = new AndPathFilter(new DirectoryPathFilter()); + pluginsFilter.addPathFilter(new NotPathFilter(createHiddenPluginFilter())); setFilter(pluginsFilter); } @@ -63,15 +63,14 @@ public class DefaultPluginRepository extends BasePluginRepository { return super.deletePluginPath(pluginPath); } - protected FileFilter createHiddenPluginFilter() { - return new OrFileFilter(new HiddenFilter()); + protected PathFilter createHiddenPluginFilter() { + return new OrPathFilter(new HiddenPathFilter()); } private void extractZipFiles() { // expand plugins zip files pluginsRoots.stream() - .flatMap(path -> streamFiles(path, new ZipFileFilter())) - .map(File::toPath) + .flatMap(path -> FileUtils.findPaths(path, new ZipPathFilter())) .forEach(this::expandIfZip); } @@ -79,8 +78,7 @@ public class DefaultPluginRepository extends BasePluginRepository { try { FileUtils.expandIfZip(filePath); } catch (IOException e) { - log.error("Cannot expand plugin zip '{}'", filePath); - log.error(e.getMessage(), e); + throw new UncheckedIOException("Cannot expand plugin zip '" + filePath + "'", e); } } diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java index fdc74c9..fd6f760 100644 --- a/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java @@ -15,14 +15,14 @@ */ package org.pf4j; -import org.pf4j.util.AndFileFilter; -import org.pf4j.util.DirectoryFileFilter; -import org.pf4j.util.HiddenFilter; -import org.pf4j.util.NameFileFilter; -import org.pf4j.util.NotFileFilter; -import org.pf4j.util.OrFileFilter; - -import java.io.FileFilter; +import org.pf4j.util.io.AndPathFilter; +import org.pf4j.util.io.DirectoryPathFilter; +import org.pf4j.util.io.HiddenPathFilter; +import org.pf4j.util.io.NamePathFilter; +import org.pf4j.util.io.NotPathFilter; +import org.pf4j.util.io.OrPathFilter; +import org.pf4j.util.io.PathFilter; + import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -42,18 +42,18 @@ public class DevelopmentPluginRepository extends BasePluginRepository { public DevelopmentPluginRepository(List pluginsRoots) { super(pluginsRoots); - AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter()); - pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter())); + AndPathFilter pluginsFilter = new AndPathFilter(new DirectoryPathFilter()); + pluginsFilter.addPathFilter(new NotPathFilter(createHiddenPluginFilter())); setFilter(pluginsFilter); } - protected FileFilter createHiddenPluginFilter() { - OrFileFilter hiddenPluginFilter = new OrFileFilter(new HiddenFilter()); + protected PathFilter createHiddenPluginFilter() { + OrPathFilter hiddenPluginFilter = new OrPathFilter(new HiddenPathFilter()); // skip default build output folders since these will cause errors in the logs hiddenPluginFilter - .addFileFilter(new NameFileFilter(MAVEN_BUILD_DIR)) - .addFileFilter(new NameFileFilter(GRADLE_BUILD_DIR)); + .addPathFilter(new NamePathFilter(MAVEN_BUILD_DIR)) + .addPathFilter(new NamePathFilter(GRADLE_BUILD_DIR)); return hiddenPluginFilter; } diff --git a/pf4j/src/main/java/org/pf4j/JarPluginLoader.java b/pf4j/src/main/java/org/pf4j/JarPluginLoader.java index 40a6a49..98b88ec 100644 --- a/pf4j/src/main/java/org/pf4j/JarPluginLoader.java +++ b/pf4j/src/main/java/org/pf4j/JarPluginLoader.java @@ -39,7 +39,7 @@ public class JarPluginLoader implements PluginLoader { @Override public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) { PluginClassLoader pluginClassLoader = new PluginClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader()); - pluginClassLoader.addFile(pluginPath.toFile()); + pluginClassLoader.addPath(pluginPath); return pluginClassLoader; } diff --git a/pf4j/src/main/java/org/pf4j/JarPluginRepository.java b/pf4j/src/main/java/org/pf4j/JarPluginRepository.java index d629bbd..5d90694 100644 --- a/pf4j/src/main/java/org/pf4j/JarPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/JarPluginRepository.java @@ -15,7 +15,7 @@ */ package org.pf4j; -import org.pf4j.util.JarFileFilter; +import org.pf4j.util.io.JarPathFilter; import java.nio.file.Path; import java.util.Arrays; @@ -31,7 +31,7 @@ public class JarPluginRepository extends BasePluginRepository { } public JarPluginRepository(List pluginsRoots) { - super(pluginsRoots, new JarFileFilter()); + super(pluginsRoots, new JarPathFilter()); } } diff --git a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java index 7425b9d..5a7f003 100644 --- a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java @@ -17,6 +17,8 @@ package org.pf4j; import org.pf4j.util.FileUtils; import org.pf4j.util.StringUtils; +import org.pf4j.util.io.NamePathFilter; +import org.pf4j.util.io.PathFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +50,8 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { public static final String PLUGIN_REQUIRES = "Plugin-Requires"; public static final String PLUGIN_LICENSE = "Plugin-License"; + private static final PathFilter MANIFEST_PATH = new NamePathFilter("MANIFEST.MF", true); + @Override public boolean isApplicable(Path pluginPath) { return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isZipOrJarFile(pluginPath)); @@ -137,10 +141,9 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { protected Manifest readManifestFromDirectory(Path pluginPath) { // legacy (the path is something like "classes/META-INF/MANIFEST.MF") - Path manifestPath = FileUtils.findFile(pluginPath,"MANIFEST.MF"); - if (manifestPath == null) { - throw new PluginRuntimeException("Cannot find the manifest path"); - } + Path manifestPath = FileUtils.findPaths(pluginPath,MANIFEST_PATH) + .findAny() + .orElseThrow(() -> new PluginRuntimeException("Cannot find the manifest path")); log.debug("Lookup plugin descriptor in '{}'", manifestPath); if (Files.notExists(manifestPath)) { diff --git a/pf4j/src/main/java/org/pf4j/PluginClassLoader.java b/pf4j/src/main/java/org/pf4j/PluginClassLoader.java index d22dd55..0106acb 100644 --- a/pf4j/src/main/java/org/pf4j/PluginClassLoader.java +++ b/pf4j/src/main/java/org/pf4j/PluginClassLoader.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -79,12 +80,21 @@ public class PluginClassLoader extends URLClassLoader { super.addURL(url); } + public void addPath(Path path) { + try { + addURL(path.toUri().toURL()); + } catch (IOException e) { +// throw new UncheckedIOException("Cannot add path '" + path + "'", e); + log.warn("Cannot add path '" + path + "'", e); + } + } + public void addFile(File file) { try { addURL(file.getCanonicalFile().toURI().toURL()); } catch (IOException e) { -// throw new RuntimeException(e); - log.error(e.getMessage(), e); +// throw new UncheckedIOException("Cannot add file '" + file + "'", e); + log.warn("Cannot add file '" + file + "'", e); } } diff --git a/pf4j/src/main/java/org/pf4j/PluginLoader.java b/pf4j/src/main/java/org/pf4j/PluginLoader.java index ee98109..a993a3f 100644 --- a/pf4j/src/main/java/org/pf4j/PluginLoader.java +++ b/pf4j/src/main/java/org/pf4j/PluginLoader.java @@ -34,4 +34,8 @@ public interface PluginLoader { ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor); + default String getName() { + return getClass().getSimpleName(); + } + } diff --git a/pf4j/src/main/java/org/pf4j/PluginRepository.java b/pf4j/src/main/java/org/pf4j/PluginRepository.java index 6bc2356..9c2ce66 100644 --- a/pf4j/src/main/java/org/pf4j/PluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/PluginRepository.java @@ -42,4 +42,8 @@ public interface PluginRepository { */ boolean deletePluginPath(Path pluginPath); + default String getName() { + return getClass().getSimpleName(); + } + } diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java index 285a280..429f33c 100644 --- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java @@ -15,14 +15,14 @@ */ package org.pf4j.util; +import org.pf4j.util.io.JarPathFilter; +import org.pf4j.util.io.PathFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; -import java.io.File; -import java.io.FileFilter; -import java.io.FileReader; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; @@ -38,6 +38,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Decebal Suiu @@ -46,15 +48,18 @@ public final class FileUtils { private static final Logger log = LoggerFactory.getLogger(FileUtils.class); + private FileUtils() { + // prevent instantiation + } + public static List readLines(Path path, boolean ignoreComments) throws IOException { - File file = path.toFile(); - if (!file.isFile()) { + if (!Files.isRegularFile(path)) { return new ArrayList<>(); } List lines = new ArrayList<>(); - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + try (BufferedReader reader = Files.newBufferedReader(path)) { String line; while ((line = reader.readLine()) != null) { if (ignoreComments && !line.startsWith("#") && !lines.contains(line)) { @@ -66,14 +71,6 @@ public final class FileUtils { return lines; } - /** - * Use {@link #writeLines(Collection, Path)} instead. - */ - @Deprecated - public static void writeLines(Collection lines, File file) throws IOException { - writeLines(lines, file.toPath()); - } - public static void writeLines(Collection lines, Path path) throws IOException { Files.write(path, lines, StandardCharsets.UTF_8); } @@ -106,29 +103,8 @@ public final class FileUtils { }); } - public static List getJars(Path folder) { - List bucket = new ArrayList<>(); - getJars(bucket, folder); - - return bucket; - } - - private static void getJars(final List bucket, Path folder) { - FileFilter jarFilter = new JarFileFilter(); - FileFilter directoryFilter = new DirectoryFileFilter(); - - if (Files.isDirectory(folder)) { - File[] jars = folder.toFile().listFiles(jarFilter); - for (int i = 0; (jars != null) && (i < jars.length); ++i) { - bucket.add(jars[i]); - } - - File[] directories = folder.toFile().listFiles(directoryFilter); - for (int i = 0; (directories != null) && (i < directories.length); ++i) { - File directory = directories[i]; - getJars(bucket, directory.toPath()); - } - } + public static List getJars(Path folder) { + return findPaths(folder, Integer.MAX_VALUE, new JarPathFilter()).collect(Collectors.toList()); } /** @@ -188,8 +164,8 @@ public final class FileUtils { if (!Files.exists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) { // expand '.zip' file Unzip unzip = new Unzip(); - unzip.setSource(filePath.toFile()); - unzip.setDestination(pluginDirectory.toFile()); + unzip.setSource(filePath); + unzip.setDestination(pluginDirectory); unzip.extract(); log.info("Expanded plugin zip '{}' in '{}'", filePath.getFileName(), pluginDirectory.getFileName()); } @@ -245,6 +221,9 @@ public final class FileUtils { return getFileSystem(uri).getPath(first, more); } + /** + * Quietly close a path. + */ public static void closePath(Path path) { if (path != null) { try { @@ -255,24 +234,22 @@ public final class FileUtils { } } - public static Path findFile(Path directoryPath, String fileName) { - File[] files = directoryPath.toFile().listFiles(); - if (files != null) { - for (File file : files) { - if (file.isFile()) { - if (file.getName().equals(fileName)) { - return file.toPath(); - } - } else if (file.isDirectory()) { - Path foundFile = findFile(file.toPath(), fileName); - if (foundFile != null) { - return foundFile; - } - } - } + public static Stream findPaths(Path path, PathFilter filter) { + return findPaths(path, Integer.MAX_VALUE, filter); + } + + public static Stream findPaths(Path path, int maxDepth, PathFilter filter) { + if (Files.notExists(path)) { + return Stream.empty(); } - return null; + try { + return Files.walk(path, maxDepth) + .filter(p -> !p.equals(path)) + .filter(filter::accept); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } private static FileSystem getFileSystem(URI uri) throws IOException { @@ -283,6 +260,4 @@ public final class FileUtils { } } - private FileUtils() { - } } diff --git a/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java b/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java deleted file mode 100644 index 5798249..0000000 --- a/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License 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. - */ -package org.pf4j.util; - -import java.io.File; -import java.io.FileFilter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * This filter providing conditional OR logic across a list of file filters. - * This filter returns {@code true} if one filter in the list return {@code true}. Otherwise, it returns {@code false}. - * Checking of the file filter list stops when the first filter returns {@code true}. - * - * @author Decebal Suiu - */ -public class OrFileFilter implements FileFilter { - - /** The list of file filters. */ - private List fileFilters; - - public OrFileFilter() { - this(new ArrayList<>()); - } - - public OrFileFilter(FileFilter... fileFilters) { - this(Arrays.asList(fileFilters)); - } - - public OrFileFilter(List fileFilters) { - this.fileFilters = new ArrayList<>(fileFilters); - } - - public OrFileFilter addFileFilter(FileFilter fileFilter) { - fileFilters.add(fileFilter); - - return this; - } - - public List getFileFilters() { - return Collections.unmodifiableList(fileFilters); - } - - public boolean removeFileFilter(FileFilter fileFilter) { - return fileFilters.remove(fileFilter); - } - - public void setFileFilters(List fileFilters) { - this.fileFilters = new ArrayList<>(fileFilters); - } - - @Override - public boolean accept(File file) { - if (this.fileFilters.isEmpty()) { - return true; - } - - for (FileFilter fileFilter : this.fileFilters) { - if (fileFilter.accept(file)) { - return true; - } - } - - return false; - } - -} diff --git a/pf4j/src/main/java/org/pf4j/util/Unzip.java b/pf4j/src/main/java/org/pf4j/util/Unzip.java index 198cf7d..62b2b46 100644 --- a/pf4j/src/main/java/org/pf4j/util/Unzip.java +++ b/pf4j/src/main/java/org/pf4j/util/Unzip.java @@ -15,17 +15,16 @@ */ package org.pf4j.util; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * This class extracts the content of the plugin zip into a directory. * It's a class for only the internal use. @@ -40,26 +39,26 @@ public class Unzip { * Holds the destination directory. * File will be unzipped into the destination directory. */ - private File destination; + private Path destination; /** * Holds path to zip file. */ - private File source; + private Path source; public Unzip() { } - public Unzip(File source, File destination) { + public Unzip(Path source, Path destination) { this.source = source; this.destination = destination; } - public void setSource(File source) { + public void setSource(Path source) { this.source = source; } - public void setDestination(File destination) { + public void setDestination(Path destination) { this.destination = destination; } @@ -71,17 +70,17 @@ public class Unzip { log.debug("Extract content of '{}' to '{}'", source, destination); // delete destination directory if exists - if (destination.exists() && destination.isDirectory()) { - FileUtils.delete(destination.toPath()); + if (Files.isDirectory(destination)) { + FileUtils.delete(destination); } - try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(source))) { + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(source))) { ZipEntry zipEntry; while ((zipEntry = zipInputStream.getNextEntry()) != null) { - File file = new File(destination, zipEntry.getName()); + Path file = destination.resolve(zipEntry.getName()); // create intermediary directories - sometimes zip don't add them - File dir = new File(file.getParent()); + Path dir = file.getParent(); mkdirsOrThrow(dir); @@ -90,7 +89,7 @@ public class Unzip { } else { byte[] buffer = new byte[1024]; int length; - try (FileOutputStream fos = new FileOutputStream(file)) { + try (OutputStream fos = Files.newOutputStream(file)) { while ((length = zipInputStream.read(buffer)) >= 0) { fos.write(buffer, 0, length); } @@ -100,10 +99,12 @@ public class Unzip { } } - private static void mkdirsOrThrow(File dir) throws IOException { - if (!dir.exists() && !dir.mkdirs()) { - throw new IOException("Failed to create directory " + dir); + private static void mkdirsOrThrow(Path dir) throws IOException { + if (Files.isDirectory(dir)) { + return; } + + Files.createDirectories(dir); } } diff --git a/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/AndPathFilter.java similarity index 52% rename from pf4j/src/main/java/org/pf4j/util/AndFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/AndPathFilter.java index 76a17ec..74f72d2 100644 --- a/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/AndPathFilter.java @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; -import java.io.File; -import java.io.FileFilter; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -25,53 +24,53 @@ import java.util.List; /** * This filter providing conditional AND logic across a list of file filters. * This filter returns {@code true} if all filters in the list return {@code true}. Otherwise, it returns {@code false}. - * Checking of the file filter list stops when the first filter returns {@code false}. + * Checking of the path filter list stops when the first filter returns {@code false}. * * @author Decebal Suiu */ -public class AndFileFilter implements FileFilter { +public class AndPathFilter implements PathFilter { - /** The list of file filters. */ - private List fileFilters; + /** The list of path filters. */ + private List pathFilters; - public AndFileFilter() { + public AndPathFilter() { this(new ArrayList<>()); } - public AndFileFilter(FileFilter... fileFilters) { - this(Arrays.asList(fileFilters)); + public AndPathFilter(PathFilter... pathFilters) { + this(Arrays.asList(pathFilters)); } - public AndFileFilter(List fileFilters) { - this.fileFilters = new ArrayList<>(fileFilters); + public AndPathFilter(List pathFilters) { + this.pathFilters = new ArrayList<>(pathFilters); } - public AndFileFilter addFileFilter(FileFilter fileFilter) { - fileFilters.add(fileFilter); + public AndPathFilter addPathFilter(PathFilter fileFilter) { + pathFilters.add(fileFilter); return this; } - public List getFileFilters() { - return Collections.unmodifiableList(fileFilters); + public List getPathFilters() { + return Collections.unmodifiableList(pathFilters); } - public boolean removeFileFilter(FileFilter fileFilter) { - return fileFilters.remove(fileFilter); + public boolean removePathFilter(PathFilter pathFilter) { + return pathFilters.remove(pathFilter); } - public void setFileFilters(List fileFilters) { - this.fileFilters = new ArrayList<>(fileFilters); + public void setPathFilters(List pathFilters) { + this.pathFilters = new ArrayList<>(pathFilters); } @Override - public boolean accept(File file) { - if (this.fileFilters.isEmpty()) { + public boolean accept(Path path) { + if (this.pathFilters.isEmpty()) { return false; } - for (FileFilter fileFilter : this.fileFilters) { - if (!fileFilter.accept(file)) { + for (PathFilter pathFilter : this.pathFilters) { + if (!pathFilter.accept(path)) { return false; } } diff --git a/pf4j/src/main/java/org/pf4j/util/DirectoryFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/DirectoryPathFilter.java similarity index 72% rename from pf4j/src/main/java/org/pf4j/util/DirectoryFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/DirectoryPathFilter.java index db6f4cc..e755253 100644 --- a/pf4j/src/main/java/org/pf4j/util/DirectoryFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/DirectoryPathFilter.java @@ -13,21 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; -import java.io.File; -import java.io.FileFilter; +import java.nio.file.Files; +import java.nio.file.Path; /** - * Filter accepts files that are directories. + * Filter accepts paths that are directories. * * @author Decebal Suiu */ -public class DirectoryFileFilter implements FileFilter { +public class DirectoryPathFilter implements PathFilter { @Override - public boolean accept(File file) { - return file.isDirectory(); + public boolean accept(Path path) { + return Files.isDirectory(path); } } diff --git a/pf4j/src/main/java/org/pf4j/util/ExtensionFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/ExtensionPathFilter.java similarity index 63% rename from pf4j/src/main/java/org/pf4j/util/ExtensionFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/ExtensionPathFilter.java index c97cb61..a44135b 100644 --- a/pf4j/src/main/java/org/pf4j/util/ExtensionFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/ExtensionPathFilter.java @@ -13,28 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; -import java.io.File; -import java.io.FileFilter; +import java.nio.file.Path; /** - * Filter accepts any file ending in extension. The case of the filename is ignored. + * Filter accepts any path ending in extension. The case of the filename is ignored. * * @author Decebal Suiu */ -public class ExtensionFileFilter implements FileFilter { +public class ExtensionPathFilter implements PathFilter { - private String extension; + private final String extension; - public ExtensionFileFilter(String extension) { + public ExtensionPathFilter(String extension) { this.extension = extension; } @Override - public boolean accept(File file) { - // perform a case insensitive check. - return file.getName().toUpperCase().endsWith(extension.toUpperCase()); + public boolean accept(Path path) { + // perform a case-insensitive check + return path.getFileName().toString().toUpperCase().endsWith(extension.toUpperCase()); } } diff --git a/pf4j/src/main/java/org/pf4j/util/HiddenFilter.java b/pf4j/src/main/java/org/pf4j/util/io/HiddenPathFilter.java similarity index 65% rename from pf4j/src/main/java/org/pf4j/util/HiddenFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/HiddenPathFilter.java index 8adfbc0..264e6f8 100644 --- a/pf4j/src/main/java/org/pf4j/util/HiddenFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/HiddenPathFilter.java @@ -13,21 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; -import java.io.File; -import java.io.FileFilter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; /** * Filter that only accepts hidden files. * * @author decebal.suiu */ -public class HiddenFilter implements FileFilter { +public class HiddenPathFilter implements PathFilter { @Override - public boolean accept(File file) { - return file.isHidden(); + public boolean accept(Path path) { + try { + return Files.isHidden(path); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } } diff --git a/pf4j/src/main/java/org/pf4j/util/JarFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/JarPathFilter.java similarity index 85% rename from pf4j/src/main/java/org/pf4j/util/JarFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/JarPathFilter.java index ad8835b..8da6cba 100644 --- a/pf4j/src/main/java/org/pf4j/util/JarFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/JarPathFilter.java @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; /** * File filter that accepts all files ending with .JAR. - * This filter is case insensitive. + * This filter is case-insensitive. * * @author Decebal Suiu */ -public class JarFileFilter extends ExtensionFileFilter { +public class JarPathFilter extends ExtensionPathFilter { /** * The extension that this filter will search for. */ private static final String JAR_EXTENSION = ".JAR"; - public JarFileFilter() { + public JarPathFilter() { super(JAR_EXTENSION); } diff --git a/pf4j/src/main/java/org/pf4j/util/NameFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/NamePathFilter.java similarity index 52% rename from pf4j/src/main/java/org/pf4j/util/NameFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/NamePathFilter.java index 3a1a53f..92dfdbe 100644 --- a/pf4j/src/main/java/org/pf4j/util/NameFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/NamePathFilter.java @@ -13,28 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; -import java.io.File; -import java.io.FileFilter; +import java.nio.file.Path; /** - * Filter accepts any file with this name. The case of the filename is ignored. + * Filter accepts any path with this name. + * By default, the case of the filename is ignored. * * @author Decebal Suiu */ -public class NameFileFilter implements FileFilter { +public class NamePathFilter implements PathFilter { - private String name; + private final String name; + private final boolean ignoreCase; - public NameFileFilter(String name) { + public NamePathFilter(String name) { + this(name, true); + } + + public NamePathFilter(String name, boolean ignoreCase) { this.name = name; + this.ignoreCase = ignoreCase; } @Override - public boolean accept(File file) { - // perform a case insensitive check. - return file.getName().equalsIgnoreCase(name); + public boolean accept(Path path) { + String fileName = path.getFileName().toString(); + if (ignoreCase) { + return fileName.equalsIgnoreCase(name); + } + + return fileName.equals(name); } } diff --git a/pf4j/src/main/java/org/pf4j/util/NotFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/NotPathFilter.java similarity index 74% rename from pf4j/src/main/java/org/pf4j/util/NotFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/NotPathFilter.java index fabb312..09af877 100644 --- a/pf4j/src/main/java/org/pf4j/util/NotFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/NotPathFilter.java @@ -13,27 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; -import java.io.File; -import java.io.FileFilter; +import java.nio.file.Path; /** * This filter produces a logical NOT of the filters specified. * * @author Decebal Suiu */ -public class NotFileFilter implements FileFilter { +public class NotPathFilter implements PathFilter { - private FileFilter filter; + private final PathFilter filter; - public NotFileFilter(FileFilter filter) { + public NotPathFilter(PathFilter filter) { this.filter = filter; } @Override - public boolean accept(File file) { - return !filter.accept(file); + public boolean accept(Path path) { + return !filter.accept(path); } } diff --git a/pf4j/src/main/java/org/pf4j/util/io/OrPathFilter.java b/pf4j/src/main/java/org/pf4j/util/io/OrPathFilter.java new file mode 100644 index 0000000..52462af --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/util/io/OrPathFilter.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License 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. + */ +package org.pf4j.util.io; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * This filter providing conditional OR logic across a list of io filters. + * This filter returns {@code true} if one filter in the list return {@code true}. Otherwise, it returns {@code false}. + * Checking of the io filter list stops when the first filter returns {@code true}. + * + * @author Decebal Suiu + */ +public class OrPathFilter implements PathFilter { + + /** The list of io filters. */ + private List pathFilters; + + public OrPathFilter() { + this(new ArrayList<>()); + } + + public OrPathFilter(PathFilter... pathFilters) { + this(Arrays.asList(pathFilters)); + } + + public OrPathFilter(List pathFilters) { + this.pathFilters = new ArrayList<>(pathFilters); + } + + public OrPathFilter addPathFilter(PathFilter pathFilter) { + pathFilters.add(pathFilter); + + return this; + } + + public List getPathFilters() { + return Collections.unmodifiableList(pathFilters); + } + + public boolean removePathFilter(PathFilter pathFilter) { + return pathFilters.remove(pathFilter); + } + + public void setPathFilters(List pathFilters) { + this.pathFilters = new ArrayList<>(pathFilters); + } + + @Override + public boolean accept(Path path) { + if (this.pathFilters.isEmpty()) { + return true; + } + + for (PathFilter pathFilter : this.pathFilters) { + if (pathFilter.accept(path)) { + return true; + } + } + + return false; + } + +} diff --git a/pf4j/src/main/java/org/pf4j/util/io/PathFilter.java b/pf4j/src/main/java/org/pf4j/util/io/PathFilter.java new file mode 100644 index 0000000..195e1eb --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/util/io/PathFilter.java @@ -0,0 +1,12 @@ +package org.pf4j.util.io; + +import java.nio.file.Path; + +/** + * @author Decebal Suiu + */ +public interface PathFilter { + + boolean accept(Path path); + +} diff --git a/pf4j/src/main/java/org/pf4j/util/ZipFileFilter.java b/pf4j/src/main/java/org/pf4j/util/io/ZipPathFilter.java similarity index 80% rename from pf4j/src/main/java/org/pf4j/util/ZipFileFilter.java rename to pf4j/src/main/java/org/pf4j/util/io/ZipPathFilter.java index 0e8a566..6657b21 100644 --- a/pf4j/src/main/java/org/pf4j/util/ZipFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/io/ZipPathFilter.java @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pf4j.util; +package org.pf4j.util.io; /** - * File filter that accepts all files ending with .ZIP. - * This filter is case insensitive. + * Path filter that accepts all files ending with .ZIP. + * This filter is case-insensitive. * * @author Decebal Suiu */ -public class ZipFileFilter extends ExtensionFileFilter { +public class ZipPathFilter extends ExtensionPathFilter { /** * The extension that this filter will search for. */ private static final String ZIP_EXTENSION = ".ZIP"; - public ZipFileFilter() { + public ZipPathFilter() { super(ZIP_EXTENSION); } diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index f80c19e..3f9d007 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -21,9 +21,7 @@ import org.pf4j.test.PluginJar; import org.pf4j.test.PluginZip; import org.pf4j.test.TestPlugin; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -118,7 +116,7 @@ public class CompoundPluginDescriptorFinderTest { private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { Path path = pluginPath.resolve(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); - try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) { + try (Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { properties.store(writer, ""); } } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java index fab1a02..b9a11f9 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java @@ -170,7 +170,7 @@ public class DefaultPluginManagerTest { boolean deleted = pluginManager.deletePlugin(pluginZip.pluginId()); assertTrue(deleted); - assertFalse(pluginZip.file().exists()); + assertFalse(Files.exists(pluginZip.path())); } @Test @@ -187,7 +187,7 @@ public class DefaultPluginManagerTest { boolean deleted = pluginManager.deletePlugin(pluginJar.pluginId()); assertTrue(deleted); - assertFalse(pluginJar.file().exists()); + assertFalse(Files.exists(pluginJar.path())); } } diff --git a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java index 0e16f75..589b0ea 100644 --- a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java @@ -25,6 +25,7 @@ import org.pf4j.test.TestExtensionPoint; import org.pf4j.test.TestPlugin; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -80,11 +81,11 @@ public class JarPluginManagerTest { boolean unloaded = pluginManager.unloadPlugin(pluginJar.pluginId()); assertTrue(unloaded); - assertTrue(pluginJar.file().exists()); + assertTrue(Files.exists(pluginJar.path())); } @Test - public void deletePlugin() throws Exception { + public void deletePlugin() { pluginManager.loadPlugins(); assertEquals(1, pluginManager.getPlugins().size()); @@ -92,7 +93,7 @@ public class JarPluginManagerTest { boolean deleted = pluginManager.deletePlugin(pluginJar.pluginId()); assertTrue(deleted); - assertFalse(pluginJar.file().exists()); + assertFalse(Files.exists(pluginJar.path())); } } diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java index bde5417..f48a3a7 100644 --- a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java @@ -22,6 +22,7 @@ import org.pf4j.test.PluginJar; import org.pf4j.test.TestExtension; import org.pf4j.test.TestPlugin; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.Set; @@ -48,7 +49,7 @@ public class LegacyExtensionFinderTest { .extension(TestExtension.class.getName()) .build(); - assertTrue(pluginJar.file().exists()); + assertTrue(Files.exists(pluginJar.path())); PluginManager pluginManager = new JarPluginManager(pluginsPath); pluginManager.loadPlugins(); @@ -60,14 +61,14 @@ public class LegacyExtensionFinderTest { assertNotNull(pluginsStorages); pluginManager.unloadPlugin(pluginJar.pluginId()); - boolean fileDeleted = pluginJar.file().delete(); + boolean fileDeleted = Files.deleteIfExists(pluginJar.path()); Set pluginStorages = pluginsStorages.get(pluginJar.pluginId()); assertNotNull(pluginStorages); assertEquals(1, pluginStorages.size()); assertThat(pluginStorages, contains(TestExtension.class.getName())); assertTrue(fileDeleted); - assertFalse(pluginJar.file().exists()); + assertFalse(Files.exists(pluginJar.path())); } } diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index 189bd0a..ad96635 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -104,7 +104,7 @@ public class LoadPluginsTest { pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); } catch (PluginRuntimeException e) { - // Check the path of the loaded plugin remains the same + // Check the io of the loaded plugin remains the same PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); // Check the message includes relevant information @@ -143,7 +143,7 @@ public class LoadPluginsTest { pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); } catch (PluginRuntimeException e) { - // Check the path and version of the loaded plugin remain the same + // Check the io and version of the loaded plugin remain the same PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); assertThat(loadedPlugin.getDescriptor().getVersion(), equalTo(plugin1Version)); diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java index 079d8e2..0d19b55 100644 --- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java @@ -163,7 +163,7 @@ public class ManifestPluginDescriptorFinderTest { private void storeManifestToPath(Manifest manifest, Path pluginPath) throws IOException { Path path = Files.createDirectory(pluginPath.resolve("META-INF")); - try (OutputStream output = new FileOutputStream(path.resolve("MANIFEST.MF").toFile())) { + try (OutputStream output = Files.newOutputStream(path.resolve("MANIFEST.MF"))) { manifest.write(output); } } diff --git a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java index fb75f27..229b0ce 100644 --- a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java @@ -23,9 +23,8 @@ import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; -import java.io.File; import java.io.IOException; -import java.io.PrintWriter; +import java.io.Writer; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; @@ -35,7 +34,11 @@ import java.util.Collections; import java.util.Enumeration; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Sebastian Lövdahl @@ -60,11 +63,9 @@ public class PluginClassLoaderTest { static void setUpGlobal() throws IOException, URISyntaxException { Path parentClassPathBase = Paths.get(PluginClassLoaderTest.class.getClassLoader().getResource(".").toURI()); - File metaInfFile = parentClassPathBase.resolve("META-INF").toFile(); - if (metaInfFile.mkdir()) { - // Only delete the directory if this test created it, guarding for any future usages of the directory. - metaInfFile.deleteOnExit(); - } + Path metaInfPath = parentClassPathBase.resolve("META-INF"); + FileUtils.delete(metaInfPath); + Files.createDirectory(metaInfPath); createFile(parentClassPathBase.resolve("META-INF").resolve("file-only-in-parent")); createFile(parentClassPathBase.resolve("META-INF").resolve("file-in-both-parent-and-dependency-and-plugin")); @@ -73,11 +74,18 @@ public class PluginClassLoaderTest { } private static void createFile(Path pathToFile) throws IOException { - File file = pathToFile.toFile(); + boolean exists = Files.exists(pathToFile); + if (!exists) { + try { + Files.createFile(pathToFile); + exists = true; + } catch (IOException e) { + exists = false; + } + } + assertTrue(exists, "failed to create '" + pathToFile + "'"); - file.deleteOnExit(); - assertTrue(file.exists() || file.createNewFile(), "failed to create '" + pathToFile + "'"); - try (PrintWriter printWriter = new PrintWriter(file)) { + try (Writer printWriter = Files.newBufferedWriter(pathToFile)) { printWriter.write("parent"); } } @@ -116,17 +124,17 @@ public class PluginClassLoaderTest { for (String classesDirectory : pluginDependencyClasspath.getClassesDirectories()) { - File classesDirectoryFile = pluginDependencyZip.unzippedPath().resolve(classesDirectory).toFile(); - parentLastPluginDependencyClassLoader.addFile(classesDirectoryFile); - parentFirstPluginDependencyClassLoader.addFile(classesDirectoryFile); + Path classesDirectoryPath = pluginDependencyZip.unzippedPath().resolve(classesDirectory); + parentLastPluginDependencyClassLoader.addPath(classesDirectoryPath); + parentFirstPluginDependencyClassLoader.addPath(classesDirectoryPath); } for (String jarsDirectory : pluginDependencyClasspath.getJarsDirectories()) { Path jarsDirectoryPath = pluginDependencyZip.unzippedPath().resolve(jarsDirectory); - List jars = FileUtils.getJars(jarsDirectoryPath); - for (File jar : jars) { - parentLastPluginDependencyClassLoader.addFile(jar); - parentFirstPluginDependencyClassLoader.addFile(jar); + List jars = FileUtils.getJars(jarsDirectoryPath); + for (Path jar : jars) { + parentLastPluginDependencyClassLoader.addPath(jar); + parentFirstPluginDependencyClassLoader.addPath(jar); } } @@ -157,17 +165,17 @@ public class PluginClassLoaderTest { pluginManagerParentFirst.addClassLoader(pluginDescriptor.getPluginId(), parentFirstPluginClassLoader); for (String classesDirectory : pluginClasspath.getClassesDirectories()) { - File classesDirectoryFile = pluginZip.unzippedPath().resolve(classesDirectory).toFile(); - parentLastPluginClassLoader.addFile(classesDirectoryFile); - parentFirstPluginClassLoader.addFile(classesDirectoryFile); + Path classesDirectoryPath = pluginZip.unzippedPath().resolve(classesDirectory); + parentLastPluginClassLoader.addPath(classesDirectoryPath); + parentFirstPluginClassLoader.addPath(classesDirectoryPath); } for (String jarsDirectory : pluginClasspath.getJarsDirectories()) { Path jarsDirectoryPath = pluginZip.unzippedPath().resolve(jarsDirectory); - List jars = FileUtils.getJars(jarsDirectoryPath); - for (File jar : jars) { - parentLastPluginClassLoader.addFile(jar); - parentFirstPluginClassLoader.addFile(jar); + List jars = FileUtils.getJars(jarsDirectoryPath); + for (Path jar : jars) { + parentLastPluginClassLoader.addPath(jar); + parentFirstPluginClassLoader.addPath(jar); } } } @@ -334,14 +342,16 @@ public class PluginClassLoaderTest { assertEquals(expectedFirstLine, Files.readAllLines(Paths.get(firstResource.toURI())).get(0)); } - class TestPluginManager extends DefaultPluginManager { + static class TestPluginManager extends DefaultPluginManager { - public TestPluginManager(Path pluginsPath) { - super(pluginsPath); - } + public TestPluginManager(Path pluginsPath) { + super(pluginsPath); + } + + void addClassLoader(String pluginId, PluginClassLoader classLoader) { + getPluginClassLoaders().put(pluginId, classLoader); + } - void addClassLoader(String pluginId, PluginClassLoader classLoader) { - getPluginClassLoaders().put(pluginId, classLoader); - } } + } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 4d73a4f..0862904 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -21,9 +21,7 @@ import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginZip; import org.pf4j.test.TestPlugin; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -167,7 +165,7 @@ public class PropertiesPluginDescriptorFinderTest { private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { Path path = pluginPath.resolve(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); - try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) { + try (Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { properties.store(writer, ""); } } diff --git a/pf4j/src/test/java/org/pf4j/test/PluginJar.java b/pf4j/src/test/java/org/pf4j/test/PluginJar.java index 034b10f..c23605a 100644 --- a/pf4j/src/test/java/org/pf4j/test/PluginJar.java +++ b/pf4j/src/test/java/org/pf4j/test/PluginJar.java @@ -18,11 +18,10 @@ package org.pf4j.test; import org.pf4j.ManifestPluginDescriptorFinder; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; +import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -57,10 +56,6 @@ public class PluginJar { return path; } - public File file() { - return path.toFile(); - } - public String pluginClass() { return pluginClass; } @@ -146,7 +141,7 @@ public class PluginJar { public PluginJar build() throws IOException { Manifest manifest = createManifest(); - try (OutputStream outputStream = new FileOutputStream(path.toFile()); + try (OutputStream outputStream = Files.newOutputStream(path); JarOutputStream jarOutputStream = new JarOutputStream(outputStream, manifest)) { if (!extensions.isEmpty()) { // add extensions.idx diff --git a/pf4j/src/test/java/org/pf4j/test/PluginZip.java b/pf4j/src/test/java/org/pf4j/test/PluginZip.java index 4b9a0c9..1f20fe2 100644 --- a/pf4j/src/test/java/org/pf4j/test/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/test/PluginZip.java @@ -17,9 +17,8 @@ package org.pf4j.test; import org.pf4j.PropertiesPluginDescriptorFinder; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.Map; @@ -53,10 +52,6 @@ public class PluginZip { return path; } - public File file() { - return path.toFile(); - } - public String pluginId() { return pluginId; } @@ -183,7 +178,7 @@ public class PluginZip { map.putAll(properties); } - try (ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile()))) { + try (ZipOutputStream outputStream = new ZipOutputStream(Files.newOutputStream(path))) { ZipEntry propertiesFile = new ZipEntry(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); outputStream.putNextEntry(propertiesFile); createProperties(map).store(outputStream, ""); diff --git a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java index 050b3f1..8e41af1 100644 --- a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java +++ b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java @@ -18,10 +18,14 @@ package org.pf4j.util; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginZip; +import org.pf4j.util.io.ZipPathFilter; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -32,7 +36,7 @@ public class FileUtilsTest { Path pluginsPath; @Test - public void expandIfZipForZipWithOnlyModuleDescriptor() throws Exception { + public void expandIfZipForZipWithOnlyModuleDescriptor() throws IOException { PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); @@ -43,7 +47,7 @@ public class FileUtilsTest { } @Test - public void expandIfZipForZipWithResourceFile() throws Exception { + public void expandIfZipForZipWithResourceFile() throws IOException { PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-second-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .addFile(Paths.get("classes/META-INF/plugin-file"), "plugin") @@ -55,7 +59,7 @@ public class FileUtilsTest { } @Test - public void expandIfZipNonZipFiles() throws Exception { + public void expandIfZipNonZipFiles() throws IOException { // File without .suffix Path extra = pluginsPath.resolve("extra"); assertEquals(extra, FileUtils.expandIfZip(extra)); @@ -65,4 +69,18 @@ public class FileUtilsTest { assertEquals(folder, FileUtils.expandIfZip(folder)); } + @Test + public void findPaths() throws IOException { + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") + .pluginVersion("1.2.3") + .build(); + + Path unzipped = FileUtils.expandIfZip(pluginZip.path()); + assertEquals(pluginZip.unzippedPath(), unzipped); + + List zipPaths = FileUtils.findPaths(pluginsPath, new ZipPathFilter()).collect(Collectors.toList()); + System.out.println("zipPaths = " + zipPaths); + assertEquals(1, zipPaths.size()); + } + } -- 2.39.5