Browse Source

Add InvalidPluginDescriptorException

Add more javadoc in AbstractPluginManager
pull/565/head
Decebal Suiu 10 months ago
parent
commit
a33c7b084a
  1. 106
      pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
  2. 30
      pf4j/src/main/java/org/pf4j/InvalidPluginDescriptorException.java

106
pf4j/src/main/java/org/pf4j/AbstractPluginManager.java

@ -38,8 +38,8 @@ import java.util.stream.Collectors;
* This class implements the boilerplate plugin code that any {@link PluginManager}
* implementation would have to support.
* It helps cut the noise out of the subclass that handles plugin management.
*
* <p>This class is not thread-safe.
* <p>
* This class is not thread-safe.
*
* @author Decebal Suiu
*/
@ -160,14 +160,9 @@ public abstract class AbstractPluginManager implements PluginManager {
*/
@Override
public List<PluginWrapper> getPlugins(PluginState pluginState) {
List<PluginWrapper> plugins = new ArrayList<>();
for (PluginWrapper plugin : getPlugins()) {
if (pluginState.equals(plugin.getPluginState())) {
plugins.add(plugin);
}
}
return plugins;
return getPlugins().stream()
.filter(plugin -> pluginState.equals(plugin.getPluginState()))
.collect(Collectors.toList());
}
@Override
@ -190,6 +185,14 @@ public abstract class AbstractPluginManager implements PluginManager {
return plugins.get(pluginId);
}
/**
* Load a plugin.
*
* @param pluginPath the plugin location
* @return the pluginId of the loaded plugin as specified in its {@linkplain PluginDescriptor metadata}
* @throws IllegalArgumentException if the plugin location does not exist
* @throws PluginRuntimeException if something goes wrong
*/
@Override
public String loadPlugin(Path pluginPath) {
if ((pluginPath == null) || Files.notExists(pluginPath)) {
@ -212,6 +215,7 @@ public abstract class AbstractPluginManager implements PluginManager {
@Override
public void loadPlugins() {
log.debug("Lookup plugins in '{}'", pluginsRoots);
// check for plugins roots
if (pluginsRoots.isEmpty()) {
log.warn("No plugins roots configured");
@ -264,12 +268,22 @@ public abstract class AbstractPluginManager implements PluginManager {
/**
* Unload the specified plugin and it's dependents.
*
* @param pluginId the pluginId of the plugin to unload
* @return true if the plugin was unloaded, otherwise false
*/
@Override
public boolean unloadPlugin(String pluginId) {
return unloadPlugin(pluginId, true);
}
/**
* Unload the specified plugin and it's dependents.
*
* @param pluginId the pluginId of the plugin to unload
* @param unloadDependents if true, unload dependents
* @return true if the plugin was unloaded, otherwise false
*/
protected boolean unloadPlugin(String pluginId, boolean unloadDependents) {
try {
if (unloadDependents) {
@ -347,9 +361,7 @@ public abstract class AbstractPluginManager implements PluginManager {
// notify the plugin as it's deleted
plugin.delete();
Path pluginPath = pluginWrapper.getPluginPath();
return pluginRepository.deletePluginPath(pluginPath);
return pluginRepository.deletePluginPath(pluginWrapper.getPluginPath());
}
/**
@ -405,7 +417,7 @@ public abstract class AbstractPluginManager implements PluginManager {
}
for (PluginDependency dependency : pluginDescriptor.getDependencies()) {
// start dependency only if it marked as required (non optional) or if it optional and loaded
// start dependency only if it marked as required (non-optional) or if it optional and loaded
if (!dependency.isOptional() || plugins.containsKey(dependency.getPluginId())) {
startPlugin(dependency.getPluginId());
}
@ -455,6 +467,13 @@ public abstract class AbstractPluginManager implements PluginManager {
return stopPlugin(pluginId, true);
}
/**
* Stop the specified plugin and it's dependents.
*
* @param pluginId the pluginId of the plugin to stop
* @param stopDependents if true, stop dependents
* @return the plugin state after stopping
*/
protected PluginState stopPlugin(String pluginId, boolean stopDependents) {
checkPluginId(pluginId);
@ -491,6 +510,12 @@ public abstract class AbstractPluginManager implements PluginManager {
return pluginWrapper.getPluginState();
}
/**
* Check if the plugin exists in the list of plugins.
*
* @param pluginId the pluginId to check
* @throws IllegalArgumentException if the plugin does not exist
*/
protected void checkPluginId(String pluginId) {
if (!plugins.containsKey(pluginId)) {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
@ -741,6 +766,7 @@ public abstract class AbstractPluginManager implements PluginManager {
}
pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR;
return Collections.singletonList(Paths.get(pluginsDir));
}
@ -760,19 +786,30 @@ public abstract class AbstractPluginManager implements PluginManager {
return true;
}
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
log.warn("Plugin '{}' requires a minimum system version of {}, and you have {}",
getPluginLabel(pluginDescriptor),
getPluginLabel(pluginWrapper.getDescriptor()),
requires,
getSystemVersion());
return false;
}
/**
* Check if the plugin is disabled.
*
* @param pluginId the pluginId to check
* @return true if the plugin is disabled, otherwise false
*/
protected boolean isPluginDisabled(String pluginId) {
return pluginStatusProvider.isPluginDisabled(pluginId);
}
/**
* It resolves the plugins by checking the dependencies.
* It also checks for cyclic dependencies, missing dependencies and wrong versions of the dependencies.
*
* @throws PluginRuntimeException if something goes wrong
*/
protected void resolvePlugins() {
// retrieves the plugins descriptors
List<PluginDescriptor> descriptors = new ArrayList<>();
@ -815,6 +852,12 @@ public abstract class AbstractPluginManager implements PluginManager {
}
}
/**
* Fire a plugin state event.
* This method is called when a plugin is loaded, started, stopped, etc.
*
* @param event the plugin state event
*/
protected synchronized void firePluginStateEvent(PluginStateEvent event) {
for (PluginStateListener listener : pluginStateListeners) {
log.trace("Fire '{}' to '{}'", event, listener);
@ -822,6 +865,14 @@ public abstract class AbstractPluginManager implements PluginManager {
}
}
/**
* Load the plugin from the specified path.
*
* @param pluginPath the path to the plugin
* @return the loaded plugin
* @throws PluginAlreadyLoadedException if the plugin is already loaded
* @throws InvalidPluginDescriptorException if the plugin is invalid
*/
protected PluginWrapper loadPluginFromPath(Path pluginPath) {
// Test for plugin path duplication
String pluginId = idForPath(pluginPath);
@ -886,15 +937,21 @@ public abstract class AbstractPluginManager implements PluginManager {
}
/**
* creates the plugin wrapper. override this if you want to prevent plugins having full access to the plugin manager
* Creates the plugin wrapper.
* <p>
* Override this if you want to prevent plugins having full access to the plugin manager.
*
* @return
* @param pluginDescriptor the plugin descriptor
* @param pluginPath the path to the plugin
* @param pluginClassLoader the class loader for the plugin
* @return the plugin wrapper
*/
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;
}
@ -918,19 +975,21 @@ public abstract class AbstractPluginManager implements PluginManager {
* Override this to change the validation criteria.
*
* @param descriptor the plugin descriptor to validate
* @throws PluginRuntimeException if validation fails
* @throws InvalidPluginDescriptorException if validation fails
*/
protected void validatePluginDescriptor(PluginDescriptor descriptor) {
if (StringUtils.isNullOrEmpty(descriptor.getPluginId())) {
throw new PluginRuntimeException("Field 'id' cannot be empty");
throw new InvalidPluginDescriptorException("Field 'id' cannot be empty");
}
if (descriptor.getVersion() == null) {
throw new PluginRuntimeException("Field 'version' cannot be empty");
throw new InvalidPluginDescriptorException("Field 'version' cannot be empty");
}
}
/**
* Check if the exact version in requires is allowed.
*
* @return true if exact versions in requires is allowed
*/
public boolean isExactVersionAllowed() {
@ -954,7 +1013,10 @@ 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}.
*
* @param pluginDescriptor the plugin descriptor
* @return the plugin label
*/
protected String getPluginLabel(PluginDescriptor pluginDescriptor) {
return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion();

30
pf4j/src/main/java/org/pf4j/InvalidPluginDescriptorException.java

@ -0,0 +1,30 @@
/*
* 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 exception signals incomplete or wrong information in the descriptor for a plugin.
*
* @see PluginDescriptor
* @author Decebal Suiu
*/
public class InvalidPluginDescriptorException extends PluginRuntimeException {
public InvalidPluginDescriptorException(String message) {
super(message);
}
}
Loading…
Cancel
Save