[Git][java-team/libpf4j-java][upstream] New upstream version 3.7.0+dfsg
Pierre Gruet (@pgt)
gitlab at salsa.debian.org
Wed Jul 6 12:30:34 BST 2022
Pierre Gruet pushed to branch upstream at Debian Java Maintainers / libpf4j-java
Commits:
c958f621 by Pierre Gruet at 2022-07-04T22:02:32+02:00
New upstream version 3.7.0+dfsg
- - - - -
30 changed files:
- + .github/FUNDING.yml
- + .github/workflows/build.yml
- CHANGELOG.md
- README.md
- demo/api/pom.xml
- demo/app/pom.xml
- demo/plugins/plugin1/pom.xml
- demo/plugins/plugin2/pom.xml
- demo/plugins/pom.xml
- demo/pom.xml
- maven-archetypes/quickstart/pom.xml
- maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml
- pf4j/pom.xml
- + pf4j/src/main/java-templates/org/pf4j/Pf4jInfo.java
- pf4j/src/main/java/module-info.java
- pf4j/src/main/java/org/pf4j/AbstractExtensionFinder.java
- pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
- pf4j/src/main/java/org/pf4j/DefaultVersionManager.java
- pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java
- pf4j/src/main/java/org/pf4j/PluginClassLoader.java
- pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java
- + pf4j/src/main/java/org/pf4j/SecurePluginManagerWrapper.java
- pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java
- pf4j/src/main/java/org/pf4j/util/FileUtils.java
- pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
- pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java
- pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java
- + pf4j/src/test/java/org/pf4j/SecurePluginManagerWrapperTest.java
- pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
- pom.xml
Changes:
=====================================
.github/FUNDING.yml
=====================================
@@ -0,0 +1 @@
+github: decebals
=====================================
.github/workflows/build.yml
=====================================
@@ -0,0 +1,36 @@
+name: Build
+on:
+ push:
+ branches:
+ - '*'
+ pull_request:
+ types: [opened, synchronize, reopened]
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout at v2
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+ - name: Set up JDK 11
+ uses: actions/setup-java at v1
+ with:
+ java-version: 11
+ - name: Cache SonarCloud packages
+ uses: actions/cache at v1
+ with:
+ path: ~/.sonar/cache
+ key: ${{ runner.os }}-sonar
+ restore-keys: ${{ runner.os }}-sonar
+ - name: Cache Maven packages
+ uses: actions/cache at v1
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
+ - name: Build and analyze
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ run: cd pf4j && mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
=====================================
CHANGELOG.md
=====================================
@@ -4,6 +4,27 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### [Unreleased][unreleased]
+#### Fixed
+- [#435]: Fix the path separator used in the SingletonExtensionFactoryTest.java
+- [#451]: Fix Dependency version check fails even if required is '*'
+- [#490]: Fix memory leak in SingletonExtensionFactory
+
+#### Changed
+- Update mockito version from 2.24.0 to 3.8.0
+- [#426]: Update module-info.java
+- [#455]: Do not rely on version from Manifest
+- Update Log4j version to 2.17.1
+
+#### Added
+- [#430]: Add a unit test in AbstractExtensionFinderTest to reproduce #428
+- [#450]: Add wrapper to plugin manager (SecurePluginManagerWrapper)
+- Add code analyses via Sonar
+- Add support for reading plugin descriptor from zip
+
+#### Removed
+
+### [3.6.0] - 2021-01-16
+
#### Fixed
- [#394]: `DependencyResolver` lost dependent info after plugin stop
@@ -413,7 +434,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
#### Removed
-[unreleased]: https://github.com/decebals/pf4j/compare/release-3.5.0...HEAD
+[unreleased]: https://github.com/decebals/pf4j/compare/release-3.6.0...HEAD
+[3.6.0]: https://github.com/decebals/pf4j/compare/release-3.5.0...release-3.6.0
[3.5.0]: https://github.com/decebals/pf4j/compare/release-3.4.1...release-3.5.0
[3.4.1]: https://github.com/decebals/pf4j/compare/release-3.4.0...release-3.4.1
[3.4.1]: https://github.com/decebals/pf4j/compare/release-3.3.0...release-3.4.0
@@ -439,6 +461,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
[0.11.0]: https://github.com/decebals/pf4j/compare/release-0.10.0...release-0.11.0
[0.10.0]: https://github.com/decebals/pf4j/compare/release-0.9.0...release-0.10.0
+[#490]: https://github.com/pf4j/pf4j/pull/490
+[#455]: https://github.com/pf4j/pf4j/pull/455
+[#451]: https://github.com/pf4j/pf4j/pull/451
+[#450]: https://github.com/pf4j/pf4j/pull/450
+[#435]: https://github.com/pf4j/pf4j/pull/435
+[#430]: https://github.com/pf4j/pf4j/pull/430
+[#426]: https://github.com/pf4j/pf4j/pull/426
[#415]: https://github.com/pf4j/pf4j/pull/415
[#404]: https://github.com/pf4j/pf4j/pull/404
[#402]: https://github.com/pf4j/pf4j/pull/402
=====================================
README.md
=====================================
@@ -156,7 +156,7 @@ PF4J is very customizable and comes with a lot of goodies. Please read the docum
Documentation
---------------
-Documentation is available on [pf4j.org](http://www.pf4j.org)
+Documentation is available on [pf4j.org](http://pf4j.org)
Demo
---------------
=====================================
demo/api/pom.xml
=====================================
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-api</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>jar</packaging>
<name>Demo Api</name>
=====================================
demo/app/pom.xml
=====================================
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-app</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>jar</packaging>
<name>Demo App</name>
=====================================
demo/plugins/plugin1/pom.xml
=====================================
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-plugins</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-plugin1</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>jar</packaging>
<name>Demo Plugin #1</name>
=====================================
demo/plugins/plugin2/pom.xml
=====================================
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-plugins</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-plugin2</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>jar</packaging>
<name>Demo Plugin #2</name>
=====================================
demo/plugins/pom.xml
=====================================
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-plugins</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>pom</packaging>
<name>Demo Plugins Parent</name>
=====================================
demo/pom.xml
=====================================
@@ -4,13 +4,13 @@
<parent>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>pom</packaging>
<name>Demo Parent</name>
=====================================
maven-archetypes/quickstart/pom.xml
=====================================
@@ -4,7 +4,7 @@
<parent>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
=====================================
maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml
=====================================
@@ -27,7 +27,7 @@
<pf4j.version>{{project.version}}</pf4j.version>
<slf4j.version>1.7.25</slf4j.version>
- <log4j.version>2.13.1</log4j.version>
+ <log4j.version>2.17.1</log4j.version>
</properties>
<build>
=====================================
pf4j/pom.xml
=====================================
@@ -4,18 +4,34 @@
<parent>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>jar</packaging>
<name>PF4J</name>
<description>Plugin Framework for Java</description>
+ <properties>
+ <sonar.projectKey>pf4j_pf4j</sonar.projectKey>
+ </properties>
+
<build>
<plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>templating-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter-src</id>
+ <goals>
+ <goal>filter-sources</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
=====================================
pf4j/src/main/java-templates/org/pf4j/Pf4jInfo.java
=====================================
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * This class provides access to the current Pf4j version which might otherwise not be possible:
+ * e.g. in Uber-Jars where the Manifest was merged and the Pf4j info was overridden
+ * @author Wolfram Haussig
+ */
+public class Pf4jInfo {
+ /**
+ * the current Pf4j version
+ */
+ public static final String VERSION = "${project.version}";
+}
=====================================
pf4j/src/main/java/module-info.java
=====================================
@@ -26,14 +26,14 @@ module org.pf4j {
// provides javax.annotation
requires java.compiler;
- // provided by the ASM library
- requires org.objectweb.asm;
+ // provided by the ASM library, use "requires static" since it's optional
+ requires static org.objectweb.asm;
// The SLF4J library currently does not provide a module.
// Version 1.8 provides a module called "org.slf4j". But this version is
// currently in beta stage. Therefore I'm not sure, if we already like to
// use it.
- requires slf4j.api;
+ requires org.slf4j;
// The java-semver library currently does not provide a module.
// Maybe we should send them a pull request, that at least they provide an
=====================================
pf4j/src/main/java/org/pf4j/AbstractExtensionFinder.java
=====================================
@@ -83,7 +83,7 @@ public abstract class AbstractExtensionFinder implements ExtensionFinder, Plugin
// classpath's extensions <=> pluginId = null
Set<String> classNames = findClassNames(pluginId);
- if (classNames == null || classNames.isEmpty()) {
+ if (classNames.isEmpty()) {
return result;
}
@@ -218,7 +218,12 @@ public abstract class AbstractExtensionFinder implements ExtensionFinder, Plugin
@Override
public Set<String> findClassNames(String pluginId) {
- return getEntries().get(pluginId);
+ Set<String> classNames = getEntries().get(pluginId);
+ if (classNames == null) {
+ return Collections.emptySet();
+ }
+
+ return classNames;
}
@Override
=====================================
pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
=====================================
@@ -660,17 +660,7 @@ public abstract class AbstractPluginManager implements PluginManager {
}
public String getVersion() {
- String version = null;
-
- Package pf4jPackage = PluginManager.class.getPackage();
- if (pf4jPackage != null) {
- version = pf4jPackage.getImplementationVersion();
- if (version == null) {
- version = pf4jPackage.getSpecificationVersion();
- }
- }
-
- return (version != null) ? version : "0.0.0";
+ return Pf4jInfo.VERSION;
}
protected abstract PluginRepository createPluginRepository();
@@ -860,10 +850,7 @@ public abstract class AbstractPluginManager implements PluginManager {
ClassLoader pluginClassLoader = getPluginLoader().loadPlugin(pluginPath, pluginDescriptor);
log.debug("Loaded plugin '{}' with class loader '{}'", pluginPath, pluginClassLoader);
- // create the plugin wrapper
- log.debug("Creating wrapper for plugin '{}'", pluginPath);
- PluginWrapper pluginWrapper = new PluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader);
- pluginWrapper.setPluginFactory(getPluginFactory());
+ PluginWrapper pluginWrapper = createPluginWrapper(pluginDescriptor, pluginPath, pluginClassLoader);
// test for disabled plugin
if (isPluginDisabled(pluginDescriptor.getPluginId())) {
@@ -890,6 +877,19 @@ 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) {
+ // create the plugin wrapper
+ log.debug("Creating wrapper for plugin '{}'", pluginPath);
+ PluginWrapper pluginWrapper = new PluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader);
+ pluginWrapper.setPluginFactory(getPluginFactory());
+ return pluginWrapper;
+ }
/**
* Tests for already loaded plugins on given path.
=====================================
pf4j/src/main/java/org/pf4j/DefaultVersionManager.java
=====================================
@@ -39,7 +39,7 @@ public class DefaultVersionManager implements VersionManager {
*/
@Override
public boolean checkVersionConstraint(String version, String constraint) {
- return StringUtils.isNullOrEmpty(constraint) || Version.valueOf(version).satisfies(constraint);
+ return StringUtils.isNullOrEmpty(constraint) || "*".equals(constraint) || Version.valueOf(version).satisfies(constraint);
}
@Override
=====================================
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);
+ }
+ }
+
}
=====================================
pf4j/src/main/java/org/pf4j/PluginClassLoader.java
=====================================
@@ -103,7 +103,7 @@ public class PluginClassLoader extends URLClassLoader {
}
// if the class is part of the plugin engine use parent class loader
- if (className.startsWith(PLUGIN_PACKAGE_PREFIX) && !className.startsWith("org.pf4j.demo")) {
+ if (className.startsWith(PLUGIN_PACKAGE_PREFIX) && !className.startsWith("org.pf4j.demo") && !className.startsWith("org.pf4j.test")) {
// log.trace("Delegate the loading of PF4J class '{}' to parent", className);
return getParent().loadClass(className);
}
=====================================
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);
}
}
=====================================
pf4j/src/main/java/org/pf4j/SecurePluginManagerWrapper.java
=====================================
@@ -0,0 +1,305 @@
+package org.pf4j;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Use this class to wrap the original plugin manager to prevent full access from within plugins.
+ * Override AbstractPluginManager.createPluginWrapper to use this class
+ * @author Wolfram Haussig
+ *
+ */
+public class SecurePluginManagerWrapper implements PluginManager {
+
+ private static final String PLUGIN_PREFIX = "Plugin ";
+ /**
+ * the current plugin
+ */
+ private String currentPluginId;
+ /**
+ * the original plugin manager
+ */
+ private PluginManager original;
+
+ /**
+ * The registered {@link PluginStateListener}s.
+ */
+ protected List<PluginStateListener> pluginStateListeners = new ArrayList<>();
+ /**
+ * wrapper for pluginStateListeners
+ */
+ private PluginStateListenerWrapper listenerWrapper = new PluginStateListenerWrapper();
+
+ /**
+ * constructor
+ * @param original the original plugin manager
+ * @param currentPlugin the current pluginId
+ */
+ public SecurePluginManagerWrapper(PluginManager original, String currentPluginId) {
+ this.original = original;
+ this.currentPluginId = currentPluginId;
+ }
+
+ @Override
+ public boolean isDevelopment() {
+ return original.isDevelopment();
+ }
+
+ @Override
+ public boolean isNotDevelopment() {
+ return original.isNotDevelopment();
+ }
+
+ @Override
+ public List<PluginWrapper> getPlugins() {
+ return Arrays.asList(getPlugin(currentPluginId));
+ }
+
+ @Override
+ public List<PluginWrapper> getPlugins(PluginState pluginState) {
+ return getPlugins().stream().filter(p -> p.getPluginState() == pluginState).collect(Collectors.toList());
+ }
+
+ @Override
+ public List<PluginWrapper> getResolvedPlugins() {
+ return getPlugins().stream().filter(p -> p.getPluginState().ordinal() >= PluginState.RESOLVED.ordinal()).collect(Collectors.toList());
+ }
+
+ @Override
+ public List<PluginWrapper> getUnresolvedPlugins() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<PluginWrapper> getStartedPlugins() {
+ return getPlugins(PluginState.STARTED);
+ }
+
+ @Override
+ public PluginWrapper getPlugin(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getPlugin(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getPlugin for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public void loadPlugins() {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute loadPlugins!");
+ }
+
+ @Override
+ public String loadPlugin(Path pluginPath) {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute loadPlugin!");
+ }
+
+ @Override
+ public void startPlugins() {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute startPlugins!");
+ }
+
+ @Override
+ public PluginState startPlugin(String pluginId) {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute startPlugin!");
+ }
+
+ @Override
+ public void stopPlugins() {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute stopPlugins!");
+ }
+
+ @Override
+ public PluginState stopPlugin(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.stopPlugin(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute stopPlugin for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public void unloadPlugins() {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute unloadPlugins!");
+ }
+
+ @Override
+ public boolean unloadPlugin(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.unloadPlugin(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute unloadPlugin for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public boolean disablePlugin(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.disablePlugin(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute disablePlugin for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public boolean enablePlugin(String pluginId) {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute enablePlugin!");
+ }
+
+ @Override
+ public boolean deletePlugin(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.deletePlugin(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute deletePlugin for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public ClassLoader getPluginClassLoader(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getPluginClassLoader(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getPluginClassLoader for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public List<Class<?>> getExtensionClasses(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getExtensionClasses(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getExtensionClasses for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public <T> List<Class<? extends T>> getExtensionClasses(Class<T> type) {
+ return getExtensionClasses(type, currentPluginId);
+ }
+
+ @Override
+ public <T> List<Class<? extends T>> getExtensionClasses(Class<T> type, String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getExtensionClasses(type, pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getExtensionClasses for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public <T> List<T> getExtensions(Class<T> type) {
+ return getExtensions(type, currentPluginId);
+ }
+
+ @Override
+ public <T> List<T> getExtensions(Class<T> type, String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getExtensions(type, pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getExtensions for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public List<?> getExtensions(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getExtensions(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getExtensions for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public Set<String> getExtensionClassNames(String pluginId) {
+ if (currentPluginId.equals(pluginId)) {
+ return original.getExtensionClassNames(pluginId);
+ } else {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getExtensionClassNames for foreign pluginId!");
+ }
+ }
+
+ @Override
+ public ExtensionFactory getExtensionFactory() {
+ return original.getExtensionFactory();
+ }
+
+ @Override
+ public RuntimeMode getRuntimeMode() {
+ return original.getRuntimeMode();
+ }
+
+ @Override
+ public PluginWrapper whichPlugin(Class<?> clazz) {
+ ClassLoader classLoader = clazz.getClassLoader();
+ PluginWrapper plugin = getPlugin(currentPluginId);
+ if (plugin.getPluginClassLoader() == classLoader) {
+ return plugin;
+ }
+ return null;
+ }
+
+ @Override
+ public void addPluginStateListener(PluginStateListener listener) {
+ if (pluginStateListeners.isEmpty()) {
+ this.original.addPluginStateListener(listenerWrapper);
+ }
+ pluginStateListeners.add(listener);
+ }
+
+ @Override
+ public void removePluginStateListener(PluginStateListener listener) {
+ pluginStateListeners.remove(listener);
+ if (pluginStateListeners.isEmpty()) {
+ this.original.removePluginStateListener(listenerWrapper);
+ }
+ }
+
+ @Override
+ public void setSystemVersion(String version) {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute setSystemVersion!");
+ }
+
+ @Override
+ public String getSystemVersion() {
+ return original.getSystemVersion();
+ }
+
+ @Override
+ public Path getPluginsRoot() {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getPluginsRoot!");
+ }
+
+ @Override
+ public List<Path> getPluginsRoots() {
+ throw new IllegalAccessError(PLUGIN_PREFIX + currentPluginId + " tried to execute getPluginsRoots!");
+ }
+
+ @Override
+ public VersionManager getVersionManager() {
+ return original.getVersionManager();
+ }
+
+ /**
+ * Wrapper for PluginStateListener events. will only propagate events if they match the current pluginId
+ * @author Wolfram Haussig
+ *
+ */
+ private class PluginStateListenerWrapper implements PluginStateListener {
+
+ @Override
+ public void pluginStateChanged(PluginStateEvent event) {
+ if (event.getPlugin().getPluginId().equals(currentPluginId)) {
+ for (PluginStateListener listener : pluginStateListeners) {
+ listener.pluginStateChanged(event);
+ }
+ }
+ }
+
+ }
+}
=====================================
pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java
=====================================
@@ -19,7 +19,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.WeakHashMap;
/**
* An {@link ExtensionFactory} that always returns a specific instance.
@@ -32,12 +31,18 @@ public class SingletonExtensionFactory extends DefaultExtensionFactory {
private final List<String> extensionClassNames;
- private Map<ClassLoader, Map<String, Object>> cache;
+ private final Map<ClassLoader, Map<String, Object>> cache;
- public SingletonExtensionFactory(String... extensionClassNames) {
+ public SingletonExtensionFactory(PluginManager pluginManager, String... extensionClassNames) {
this.extensionClassNames = Arrays.asList(extensionClassNames);
- cache = new WeakHashMap<>(); // simple cache implementation
+ cache = new HashMap<>();
+
+ pluginManager.addPluginStateListener(event -> {
+ if (event.getPluginState() != PluginState.STARTED) {
+ cache.remove(event.getPlugin().getPluginClassLoader());
+ }
+ });
}
@Override
=====================================
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("\\", "/"), "/");
=====================================
pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
=====================================
@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.testing.compile.Compilation;
import java.util.Comparator;
+import java.util.UUID;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -204,6 +205,45 @@ public class AbstractExtensionFinderTest {
assertEquals(1, result.size());
}
+ /**
+ * Test of {@link org.pf4j.AbstractExtensionFinder#find(java.lang.String)}.
+ */
+ @Test
+ public void testFindExtensionWrappersFromPluginId() {
+ ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) {
+
+ @Override
+ public Map<String, Set<String>> readPluginsStorages() {
+ Map<String, Set<String>> entries = new LinkedHashMap<>();
+
+ Set<String> bucket = new HashSet<>();
+ bucket.add("org.pf4j.test.TestExtension");
+ bucket.add("org.pf4j.test.FailTestExtension");
+ entries.put("plugin1", bucket);
+ bucket = new HashSet<>();
+ bucket.add("org.pf4j.test.TestExtension");
+ entries.put("plugin2", bucket);
+
+ return entries;
+ }
+
+ @Override
+ public Map<String, Set<String>> readClasspathStorages() {
+ return Collections.emptyMap();
+ }
+
+ };
+
+ List<ExtensionWrapper> plugin1Result = instance.find("plugin1");
+ assertEquals(2, plugin1Result.size());
+
+ List<ExtensionWrapper> plugin2Result = instance.find("plugin2");
+ assertEquals(0, plugin2Result.size());
+
+ List<ExtensionWrapper> plugin3Result = instance.find(UUID.randomUUID().toString());
+ assertEquals(0, plugin3Result.size());
+ }
+
@Test
public void findExtensionAnnotation() throws Exception {
Compilation compilation = javac().compile(ExtensionAnnotationProcessorTest.Greeting,
=====================================
pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java
=====================================
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -45,5 +46,11 @@ public class AbstractPluginManagerTest {
List<TestExtensionPoint> extensions = pluginManager.getExtensions(TestExtensionPoint.class);
assertEquals(1, extensions.size());
}
+
+ @Test
+ public void getVersion() {
+ AbstractPluginManager pluginManager = mock(AbstractPluginManager.class, CALLS_REAL_METHODS);
+ assertNotEquals("0.0.0", pluginManager.getVersion());
+ }
}
=====================================
pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java
=====================================
@@ -39,6 +39,7 @@ public class DefaultVersionManagerTest {
public void checkVersionConstraint() {
assertFalse(versionManager.checkVersionConstraint("1.4.3", ">2.0.0")); // simple
assertTrue(versionManager.checkVersionConstraint("1.4.3", ">=1.4.0 & <1.6.0")); // range
+ assertTrue(versionManager.checkVersionConstraint("undefined", "*"));
}
@Test
=====================================
pf4j/src/test/java/org/pf4j/SecurePluginManagerWrapperTest.java
=====================================
@@ -0,0 +1,272 @@
+package org.pf4j;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.test.PluginJar;
+import org.pf4j.test.TestExtension;
+import org.pf4j.test.TestExtensionPoint;
+import org.pf4j.test.TestPlugin;
+
+public class SecurePluginManagerWrapperTest {
+
+ private static final String OTHER_PLUGIN_ID = "test-plugin-2";
+ private static final String THIS_PLUGIN_ID = "test-plugin-1";
+ private PluginJar thisPlugin;
+ private PluginJar otherPlugin;
+ private PluginManager pluginManager;
+ private PluginManager wrappedPluginManager;
+ private int pluginManagerEvents = 0;
+ private int wrappedPluginManagerEvents = 0;
+
+ @TempDir
+ Path pluginsPath;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ pluginManagerEvents = 0;
+ wrappedPluginManagerEvents = 0;
+ thisPlugin = new PluginJar.Builder(pluginsPath.resolve("test-plugin1.jar"), THIS_PLUGIN_ID).pluginClass(TestPlugin.class.getName()).pluginVersion("1.2.3").extension(TestExtension.class.getName()).build();
+ otherPlugin = new PluginJar.Builder(pluginsPath.resolve("test-plugin2.jar"), OTHER_PLUGIN_ID).pluginClass(TestPlugin.class.getName()).pluginVersion("1.2.3").extension(TestExtension.class.getName()).build();
+
+ pluginManager = new JarPluginManager(pluginsPath);
+ wrappedPluginManager = new SecurePluginManagerWrapper(pluginManager, THIS_PLUGIN_ID);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ pluginManager.unloadPlugins();
+
+ thisPlugin = null;
+ otherPlugin = null;
+ pluginManager = null;
+ }
+
+ @Test
+ public void pluginStateListeners() {
+ pluginManager.addPluginStateListener(new PluginStateListener() {
+ @Override
+ public void pluginStateChanged(PluginStateEvent event) {
+ pluginManagerEvents++;
+ }
+ });
+ wrappedPluginManager.addPluginStateListener(new PluginStateListener() {
+ @Override
+ public void pluginStateChanged(PluginStateEvent event) {
+ wrappedPluginManagerEvents++;
+ }
+ });
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+ assertEquals(4, pluginManagerEvents);
+ assertEquals(2, wrappedPluginManagerEvents);
+ }
+
+ @Test
+ public void deletePlugin() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.deletePlugin(OTHER_PLUGIN_ID));
+ assertTrue(wrappedPluginManager.deletePlugin(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void disablePlugin() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.disablePlugin(OTHER_PLUGIN_ID));
+ assertTrue(wrappedPluginManager.disablePlugin(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void enablePlugin() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.enablePlugin(OTHER_PLUGIN_ID));
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.enablePlugin(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void getExtensionClasses() {
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+ assertEquals(1, wrappedPluginManager.getExtensionClasses(TestExtensionPoint.class).size());
+
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getExtensionClasses(TestExtensionPoint.class, OTHER_PLUGIN_ID));
+ assertEquals(1, wrappedPluginManager.getExtensionClasses(TestExtensionPoint.class, THIS_PLUGIN_ID).size());
+
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getExtensionClasses(OTHER_PLUGIN_ID));
+ assertEquals(1, wrappedPluginManager.getExtensionClasses(THIS_PLUGIN_ID).size());
+ }
+
+ @Test
+ public void getExtensionClassNames() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getExtensionClassNames(OTHER_PLUGIN_ID));
+ assertEquals(1, wrappedPluginManager.getExtensionClassNames(THIS_PLUGIN_ID).size());
+ }
+
+ @Test
+ public void getExtensionFactory() {
+ pluginManager.loadPlugins();
+ assertEquals(pluginManager.getExtensionFactory(), wrappedPluginManager.getExtensionFactory());
+ }
+
+ @Test
+ public void getExtensions() {
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+ assertEquals(1, wrappedPluginManager.getExtensions(TestExtensionPoint.class).size());
+
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getExtensions(TestExtensionPoint.class, OTHER_PLUGIN_ID));
+ assertEquals(1, wrappedPluginManager.getExtensions(TestExtensionPoint.class, THIS_PLUGIN_ID).size());
+
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getExtensions(OTHER_PLUGIN_ID));
+ assertEquals(1, wrappedPluginManager.getExtensions(THIS_PLUGIN_ID).size());
+ }
+
+ @Test
+ public void getPlugin() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getPlugin(OTHER_PLUGIN_ID));
+ assertEquals(THIS_PLUGIN_ID, wrappedPluginManager.getPlugin(THIS_PLUGIN_ID).getPluginId());
+ }
+
+ @Test
+ public void getPluginClassLoader() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getPluginClassLoader(OTHER_PLUGIN_ID));
+ assertNotNull(wrappedPluginManager.getPluginClassLoader(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void getPlugins() {
+ pluginManager.loadPlugins();
+ assertEquals(2, pluginManager.getPlugins().size());
+ assertEquals(1, wrappedPluginManager.getPlugins().size());
+ }
+
+ @Test
+ public void getPluginsRoot() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getPluginsRoot());
+ }
+
+ @Test
+ public void getPluginsRoots() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.getPluginsRoots());
+ }
+
+ @Test
+ public void getResolvedPlugins() {
+ pluginManager.loadPlugins();
+ assertEquals(2, pluginManager.getResolvedPlugins().size());
+ assertEquals(1, wrappedPluginManager.getResolvedPlugins().size());
+ }
+
+ @Test
+ public void getRuntimeMode() {
+ assertEquals(pluginManager.getRuntimeMode(), wrappedPluginManager.getRuntimeMode());
+ }
+
+ @Test
+ public void getStartedPlugins() {
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+ assertEquals(2, pluginManager.getStartedPlugins().size());
+ assertEquals(1, wrappedPluginManager.getStartedPlugins().size());
+ }
+
+ @Test
+ public void getSystemVersion() {
+ assertEquals(pluginManager.getSystemVersion(), wrappedPluginManager.getSystemVersion());
+ }
+
+ @Test
+ public void getUnresolvedPlugins() {
+ assertNotNull(wrappedPluginManager);
+ assertNotNull(wrappedPluginManager.getUnresolvedPlugins());
+ assertTrue(wrappedPluginManager.getUnresolvedPlugins().isEmpty());
+ }
+
+ @Test
+ public void getVersionManager() {
+ assertEquals(pluginManager.getVersionManager(), wrappedPluginManager.getVersionManager());
+ }
+
+ @Test
+ public void isDevelopment() {
+ assertEquals(pluginManager.isDevelopment(), wrappedPluginManager.isDevelopment());
+ }
+
+ @Test
+ public void isNotDevelopment() {
+ assertEquals(pluginManager.isNotDevelopment(), wrappedPluginManager.isNotDevelopment());
+ }
+
+ @Test
+ public void loadPlugin() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.loadPlugin(thisPlugin.path()));
+ }
+
+ @Test
+ public void loadPlugins() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.loadPlugins());
+ }
+
+ @Test
+ public void setSystemVersion() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.setSystemVersion("1.0.0"));
+ }
+
+ @Test
+ public void startPlugin() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.startPlugin(OTHER_PLUGIN_ID));
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.startPlugin(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void startPlugins() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.startPlugins());
+ }
+
+ @Test
+ public void stopPlugin() {
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.stopPlugin(OTHER_PLUGIN_ID));
+ assertEquals(PluginState.STOPPED, wrappedPluginManager.stopPlugin(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void stopPlugins() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.stopPlugins());
+ }
+
+ @Test
+ public void unloadPlugin() {
+ pluginManager.loadPlugins();
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.unloadPlugin(OTHER_PLUGIN_ID));
+ assertTrue(wrappedPluginManager.unloadPlugin(THIS_PLUGIN_ID));
+ }
+
+ @Test
+ public void unloadPlugins() {
+ assertThrows(IllegalAccessError.class, () -> wrappedPluginManager.unloadPlugins());
+ }
+
+ @Test
+ public void whichPlugin() {
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+ assertEquals(null, wrappedPluginManager.whichPlugin(pluginManager.getExtensionClasses(OTHER_PLUGIN_ID).get(0)));
+ assertEquals(THIS_PLUGIN_ID, wrappedPluginManager.whichPlugin(pluginManager.getExtensionClasses(THIS_PLUGIN_ID).get(0)).getPluginId());
+ }
+}
=====================================
pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
=====================================
@@ -15,6 +15,8 @@
*/
package org.pf4j;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pf4j.test.FailTestExtension;
import org.pf4j.test.TestExtension;
@@ -33,9 +35,21 @@ import static org.junit.jupiter.api.Assertions.assertSame;
*/
public class SingletonExtensionFactoryTest {
+ private PluginManager pluginManager;
+
+ @BeforeEach
+ public void setUp() {
+ pluginManager = new DefaultPluginManager();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ pluginManager = null;
+ }
+
@Test
public void create() {
- ExtensionFactory extensionFactory = new SingletonExtensionFactory();
+ ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager);
Object extensionOne = extensionFactory.create(TestExtension.class);
Object extensionTwo = extensionFactory.create(TestExtension.class);
assertSame(extensionOne, extensionTwo);
@@ -43,7 +57,7 @@ public class SingletonExtensionFactoryTest {
@Test
public void createNewEachTime() {
- ExtensionFactory extensionFactory = new SingletonExtensionFactory(FailTestExtension.class.getName());
+ ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager, FailTestExtension.class.getName());
Object extensionOne = extensionFactory.create(TestExtension.class);
Object extensionTwo = extensionFactory.create(TestExtension.class);
assertNotSame(extensionOne, extensionTwo);
@@ -52,7 +66,7 @@ public class SingletonExtensionFactoryTest {
@Test
@SuppressWarnings("unchecked")
public void createNewEachTimeFromDifferentClassLoaders() throws Exception {
- ExtensionFactory extensionFactory = new SingletonExtensionFactory();
+ ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager);
// Get classpath locations
URL[] classpathReferences = getClasspathReferences();
@@ -74,7 +88,7 @@ public class SingletonExtensionFactoryTest {
private URL[] getClasspathReferences() throws MalformedURLException {
String classpathProperty = System.getProperty("java.class.path");
- String[] classpaths = classpathProperty.split(":");
+ String[] classpaths = classpathProperty.split(File.pathSeparator);
URL[] uris = new URL[classpaths.length];
for (int index = 0; index < classpaths.length; index++) {
=====================================
pom.xml
=====================================
@@ -10,10 +10,11 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>3.6.0</version>
+ <version>3.7.0</version>
<packaging>pom</packaging>
<name>PF4J Parent</name>
<description>Plugin Framework for Java</description>
+ <url>https://pf4j.org</url>
<licenses>
<license>
@@ -27,7 +28,7 @@
<connection>scm:git:https://github.com/pf4j/pf4j.git</connection>
<developerConnection>scm:git:git at github.com:pf4j/pf4j.git</developerConnection>
<url>git at github.com/pf4j/pf4j.git</url>
- <tag>release-3.6.0</tag>
+ <tag>release-3.7.0</tag>
</scm>
<distributionManagement>
@@ -45,19 +46,22 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>8</maven.compiler.release>
- <slf4j.version>1.7.25</slf4j.version>
- <log4j.version>2.13.1</log4j.version>
- <asm.version>7.1</asm.version>
+ <slf4j.version>1.7.30</slf4j.version>
+ <log4j.version>2.17.1</log4j.version>
+ <asm.version>9.1</asm.version>
<junit.version>5.4.0</junit.version>
<hamcrest.version>2.1</hamcrest.version>
- <mockito.version>2.24.0</mockito.version>
+ <mockito.version>3.8.0</mockito.version>
<cobertura.version>2.7</cobertura.version>
<coveralls.version>3.1.0</coveralls.version>
<javadoc.disabled>false</javadoc.disabled>
<deploy.disabled>false</deploy.disabled>
<source.disabled>false</source.disabled>
+
+ <sonar.organization>pf4j</sonar.organization>
+ <sonar.host.url>https://sonarcloud.io</sonar.host.url>
</properties>
<build>
View it on GitLab: https://salsa.debian.org/java-team/libpf4j-java/-/commit/c958f6217510ab92412fbb31027e40d5a37facb2
--
View it on GitLab: https://salsa.debian.org/java-team/libpf4j-java/-/commit/c958f6217510ab92412fbb31027e40d5a37facb2
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20220706/33c2d2bd/attachment.htm>
More information about the pkg-java-commits
mailing list