summaryrefslogtreecommitdiffstats
path: root/pf4j
diff options
context:
space:
mode:
authorJan Høydahl <janhoy@users.noreply.github.com>2017-04-06 12:54:54 +0200
committerDecebal Suiu <decebal.suiu@gmail.com>2017-04-06 13:54:54 +0300
commit39ef17a075a689f5931cd108edaedbb04feeb01f (patch)
treea006414a9ee0c3263fe65c4c796617ad763c3250 /pf4j
parentc9f98de8ff666fb68e56452955002646fef18191 (diff)
downloadpf4j-39ef17a075a689f5931cd108edaedbb04feeb01f.tar.gz
pf4j-39ef17a075a689f5931cd108edaedbb04feeb01f.zip
Unzip plugin zip file in loadPluginFromPath() (#140)
Diffstat (limited to 'pf4j')
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/AbstractPluginManager.java1
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java19
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginRepository.java41
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java47
-rw-r--r--pf4j/src/test/java/ro/fortsoft/pf4j/util/FileUtilsTest.java65
5 files changed, 131 insertions, 42 deletions
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/AbstractPluginManager.java
index 6014717..fa0366b 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/AbstractPluginManager.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/AbstractPluginManager.java
@@ -16,7 +16,6 @@
package ro.fortsoft.pf4j;
import com.github.zafarkhaja.semver.Version;
-import com.github.zafarkhaja.semver.expr.Expression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.fortsoft.pf4j.util.StringUtils;
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
index 81bce1b..b9d6c67 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
@@ -17,6 +17,7 @@ package ro.fortsoft.pf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import ro.fortsoft.pf4j.util.FileUtils;
import java.io.File;
import java.nio.file.Path;
@@ -106,4 +107,22 @@ public class DefaultPluginManager extends AbstractPluginManager {
log.info("PF4J version {} in '{}' mode", getVersion(), getRuntimeMode());
}
+ /**
+ * Load a plugin from disk. If the path is a zip file, first unpack
+ * @param pluginPath plugin location on disk
+ * @return PluginWrapper for the loaded plugin or null if not loaded
+ * @throws PluginException if problems during load
+ */
+ @Override
+ protected PluginWrapper loadPluginFromPath(Path pluginPath) throws PluginException {
+ // First unzip any ZIP files
+ try {
+ pluginPath = FileUtils.expandIfZip(pluginPath);
+ } catch (Exception e) {
+ log.warn("Failed to unzip " + pluginPath, e);
+ return null;
+ }
+
+ return super.loadPluginFromPath(pluginPath);
+ }
}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginRepository.java
index f662bc4..197ae22 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginRepository.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginRepository.java
@@ -24,7 +24,6 @@ import ro.fortsoft.pf4j.util.HiddenFilter;
import ro.fortsoft.pf4j.util.NameFileFilter;
import ro.fortsoft.pf4j.util.NotFileFilter;
import ro.fortsoft.pf4j.util.OrFileFilter;
-import ro.fortsoft.pf4j.util.Unzip;
import ro.fortsoft.pf4j.util.ZipFileFilter;
import java.io.File;
@@ -55,7 +54,7 @@ public class DefaultPluginRepository extends BasePluginRepository {
if ((pluginZips != null) && pluginZips.length > 0) {
for (File pluginZip : pluginZips) {
try {
- expandPluginZip(pluginZip);
+ FileUtils.expandIfZip(pluginZip.toPath());
} catch (IOException e) {
log.error("Cannot expand plugin zip '{}'", pluginZip);
log.error(e.getMessage(), e);
@@ -81,42 +80,4 @@ public class DefaultPluginRepository extends BasePluginRepository {
return hiddenPluginFilter;
}
-
- /**
- * Unzip a plugin zip file in a directory that has the same name as the zip file
- * and it's relative to {@code pluginsRoot}.
- * For example if the zip file is {@code my-plugin.zip} then the resulted directory
- * is {@code my-plugin}.
- *
- * @param pluginZip
- * @return
- * @throws IOException
- */
- private File expandPluginZip(File pluginZip) throws IOException {
- String fileName = pluginZip.getName();
- long pluginZipDate = pluginZip.lastModified();
- String pluginName = fileName.substring(0, fileName.length() - 4);
- File pluginDirectory = pluginsRoot.resolve(pluginName).toFile();
- // check if exists root or the '.zip' file is "newer" than root
- if (!pluginDirectory.exists() || (pluginZipDate > pluginDirectory.lastModified())) {
- log.debug("Expand plugin zip '{}' in '{}'", pluginZip, pluginDirectory);
-
- // do not overwrite an old version, remove it
- if (pluginDirectory.exists()) {
- FileUtils.delete(pluginDirectory.toPath());
- }
-
- // create root for plugin
- pluginDirectory.mkdirs();
-
- // expand '.zip' file
- Unzip unzip = new Unzip();
- unzip.setSource(pluginZip);
- unzip.setDestination(pluginDirectory);
- unzip.extract();
- }
-
- return pluginDirectory;
- }
-
}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java b/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java
index 70b4e01..ab34a19 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java
@@ -15,13 +15,18 @@
*/
package ro.fortsoft.pf4j.util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.*;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -29,8 +34,11 @@ import java.util.List;
* @author Decebal Suiu
*/
public class FileUtils {
+ private static final Logger log = LoggerFactory.getLogger(FileUtils.class);
+
+ private static final List<String> ZIP_EXTENSIONS = Arrays.asList(".zip", ".ZIP", ".Zip");
- public static List<String> readLines(File file, boolean ignoreComments) throws IOException {
+ public static List<String> readLines(File file, boolean ignoreComments) throws IOException {
if (!file.exists() || !file.isFile()) {
return new ArrayList<>();
}
@@ -147,4 +155,41 @@ public class FileUtils {
Files.delete(path);
} catch (IOException ignored) { }
}
+
+ /**
+ * Unzip a zip file in a directory that has the same name as the zip file.
+ * For example if the zip file is {@code my-plugin.zip} then the resulted directory
+ * is {@code my-plugin}.
+ *
+ * @param filePath the file to evaluate
+ * @return Path of unzipped folder or original path if this was not a zip file
+ * @throws IOException on error
+ */
+ public static Path expandIfZip(Path filePath) throws IOException {
+ String fileName = filePath.getFileName().toString();
+ if (!ZIP_EXTENSIONS.contains(fileName.substring(fileName.lastIndexOf(".")))) {
+ return filePath;
+ }
+ FileTime pluginZipDate = Files.getLastModifiedTime(filePath);
+ Path pluginDirectory = filePath.resolveSibling(fileName.substring(0, fileName.lastIndexOf(".")));
+
+ if (!Files.exists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) {
+ // do not overwrite an old version, remove it
+ if (Files.exists(pluginDirectory)) {
+ FileUtils.delete(pluginDirectory);
+ }
+
+ // create root for plugin
+ Files.createDirectories(pluginDirectory);
+
+ // expand '.zip' file
+ Unzip unzip = new Unzip();
+ unzip.setSource(filePath.toFile());
+ unzip.setDestination(pluginDirectory.toFile());
+ unzip.extract();
+ log.info("Expanded plugin zip '{}' in '{}'", filePath.getFileName(), pluginDirectory.getFileName());
+ }
+
+ return pluginDirectory;
+ }
}
diff --git a/pf4j/src/test/java/ro/fortsoft/pf4j/util/FileUtilsTest.java b/pf4j/src/test/java/ro/fortsoft/pf4j/util/FileUtilsTest.java
new file mode 100644
index 0000000..fec02f8
--- /dev/null
+++ b/pf4j/src/test/java/ro/fortsoft/pf4j/util/FileUtilsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 Decebal Suiu
+ *
+ * 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 ro.fortsoft.pf4j.util;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.*;
+import java.util.Collections;
+
+import static org.junit.Assert.*;
+
+public class FileUtilsTest {
+ private Path zipFile;
+ private Path tmpDir;
+ private Path propsFile;
+
+ @Before
+ public void setup() throws IOException {
+ tmpDir = Files.createTempDirectory("pf4j-test");
+ tmpDir.toFile().deleteOnExit();
+ zipFile = tmpDir.resolve("my.zip").toAbsolutePath();
+ propsFile = tmpDir.resolve("plugin.properties");
+ URI file = URI.create("jar:file:"+zipFile.toString());
+ try (FileSystem zipfs = FileSystems.newFileSystem(file, Collections.singletonMap("create", "true"))) {
+ Path propsInZip = zipfs.getPath("/plugin.properties");
+ BufferedWriter br = new BufferedWriter(new FileWriter(propsFile.toString()));
+ br.write("plugin.id=test");
+ br.newLine();
+ br.write("plugin.version=1.2.3");
+ br.newLine();
+ br.write("plugin.class=foo.bar");
+ br.close();
+ Files.move(propsFile, propsInZip);
+ }
+ }
+
+ @Test
+ public void expandIfZip() throws Exception {
+ Path unzipped = FileUtils.expandIfZip(zipFile);
+ assertEquals(tmpDir.resolve("my"), unzipped);
+ assertTrue(Files.exists(tmpDir.resolve("my/plugin.properties")));
+
+ // Non-zip file remains unchanged
+ assertEquals(propsFile, FileUtils.expandIfZip(propsFile));
+ }
+
+}