@@ -860,10 +860,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 +887,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. |
@@ -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); | |||
} |
@@ -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); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |