From b7f03a2cd2cfd017ec313a1170fc55b6b7dcbef7 Mon Sep 17 00:00:00 2001 From: dsuiu Date: Sat, 27 Nov 2021 22:00:59 +0200 Subject: [PATCH] Add support for reading plugin descriptor from zip --- .../pf4j/ManifestPluginDescriptorFinder.java | 76 +++++++++++-------- .../PropertiesPluginDescriptorFinder.java | 16 ++-- .../main/java/org/pf4j/util/FileUtils.java | 12 ++- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java index 650b2d7..7425b9d 100644 --- a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java @@ -27,6 +27,8 @@ import java.nio.file.Path; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * Read the plugin descriptor from the manifest file. @@ -48,7 +50,7 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { @Override public boolean isApplicable(Path pluginPath) { - return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isJarFile(pluginPath)); + return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isZipOrJarFile(pluginPath)); } @Override @@ -60,40 +62,14 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { protected Manifest readManifest(Path pluginPath) { if (FileUtils.isJarFile(pluginPath)) { - try (JarFile jar = new JarFile(pluginPath.toFile())) { - Manifest manifest = jar.getManifest(); - if (manifest != null) { - return manifest; - } - } catch (IOException e) { - throw new PluginRuntimeException(e); - } - } - - Path manifestPath = getManifestPath(pluginPath); - if (manifestPath == null) { - throw new PluginRuntimeException("Cannot find the manifest path"); - } - - log.debug("Lookup plugin descriptor in '{}'", manifestPath); - if (Files.notExists(manifestPath)) { - throw new PluginRuntimeException("Cannot find '{}' path", manifestPath); + return readManifestFromJar(pluginPath); } - try (InputStream input = Files.newInputStream(manifestPath)) { - return new Manifest(input); - } catch (IOException e) { - throw new PluginRuntimeException(e); - } - } - - protected Path getManifestPath(Path pluginPath) { - if (Files.isDirectory(pluginPath)) { - // legacy (the path is something like "classes/META-INF/MANIFEST.MF") - return FileUtils.findFile(pluginPath,"MANIFEST.MF"); + if (FileUtils.isZipFile(pluginPath)) { + return readManifestFromZip(pluginPath); } - return null; + return readManifestFromDirectory(pluginPath); } protected PluginDescriptor createPluginDescriptor(Manifest manifest) { @@ -140,4 +116,42 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { return new DefaultPluginDescriptor(); } + protected Manifest readManifestFromJar(Path jarPath) { + try (JarFile jar = new JarFile(jarPath.toFile())) { + return jar.getManifest(); + } catch (IOException e) { + throw new PluginRuntimeException(e, "Cannot read manifest from {}", jarPath); + } + } + + protected Manifest readManifestFromZip(Path zipPath) { + try (ZipFile zip = new ZipFile(zipPath.toFile())) { + ZipEntry manifestEntry = zip.getEntry("classes/META-INF/MANIFEST.MF"); + try (InputStream manifestInput = zip.getInputStream(manifestEntry)) { + return new Manifest(manifestInput); + } + } catch (IOException e) { + throw new PluginRuntimeException(e, "Cannot read manifest from {}", zipPath); + } + } + + 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"); + } + + log.debug("Lookup plugin descriptor in '{}'", manifestPath); + if (Files.notExists(manifestPath)) { + throw new PluginRuntimeException("Cannot find '{}' path", manifestPath); + } + + try (InputStream input = Files.newInputStream(manifestPath)) { + return new Manifest(input); + } catch (IOException e) { + throw new PluginRuntimeException(e, "Cannot read manifest from {}", pluginPath); + } + } + } diff --git a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java index 303b662..a04d268 100644 --- a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java @@ -59,7 +59,7 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder @Override public boolean isApplicable(Path pluginPath) { - return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isJarFile(pluginPath)); + return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isZipOrJarFile(pluginPath)); } @Override @@ -97,13 +97,13 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder protected Path getPropertiesPath(Path pluginPath, String propertiesFileName) { if (Files.isDirectory(pluginPath)) { return pluginPath.resolve(Paths.get(propertiesFileName)); - } else { - // it's a jar file - try { - return FileUtils.getPath(pluginPath, propertiesFileName); - } catch (IOException e) { - throw new PluginRuntimeException(e); - } + } + + // it's a zip or jar file + try { + return FileUtils.getPath(pluginPath, propertiesFileName); + } catch (IOException e) { + throw new PluginRuntimeException(e); } } diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java index 0edcf97..285a280 100644 --- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java @@ -217,9 +217,19 @@ public final class FileUtils { return Files.isRegularFile(path) && path.toString().toLowerCase().endsWith(".jar"); } + /** + * Return true only if path is a jar or zip file. + * + * @param path to a file/dir + * @return true if file ending in {@code .zip} or {@code .jar} + */ + public static boolean isZipOrJarFile(Path path) { + return isZipFile(path) || isJarFile(path); + } + public static Path getPath(Path path, String first, String... more) throws IOException { URI uri = path.toUri(); - if (isJarFile(path)) { + if (isZipOrJarFile(path)) { String pathString = path.toAbsolutePath().toString(); // transformation for Windows OS pathString = StringUtils.addStart(pathString.replace("\\", "/"), "/"); -- 2.39.5