Browse Source

Add InvalidPluginDescriptorException

Add more javadoc in AbstractPluginManager
tags/release-3.11.0
Decebal Suiu 3 months ago
parent
commit
a33c7b084a

+ 84
- 22
pf4j/src/main/java/org/pf4j/AbstractPluginManager.java View File

* This class implements the boilerplate plugin code that any {@link PluginManager} * This class implements the boilerplate plugin code that any {@link PluginManager}
* implementation would have to support. * implementation would have to support.
* It helps cut the noise out of the subclass that handles plugin management. * 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 * @author Decebal Suiu
*/ */
*/ */
@Override @Override
public List<PluginWrapper> getPlugins(PluginState pluginState) { 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 @Override
return plugins.get(pluginId); 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 @Override
public String loadPlugin(Path pluginPath) { public String loadPlugin(Path pluginPath) {
if ((pluginPath == null) || Files.notExists(pluginPath)) { if ((pluginPath == null) || Files.notExists(pluginPath)) {
@Override @Override
public void loadPlugins() { public void loadPlugins() {
log.debug("Lookup plugins in '{}'", pluginsRoots); log.debug("Lookup plugins in '{}'", pluginsRoots);

// check for plugins roots // check for plugins roots
if (pluginsRoots.isEmpty()) { if (pluginsRoots.isEmpty()) {
log.warn("No plugins roots configured"); log.warn("No plugins roots configured");


/** /**
* Unload the specified plugin and it's dependents. * 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 @Override
public boolean unloadPlugin(String pluginId) { public boolean unloadPlugin(String pluginId) {
return unloadPlugin(pluginId, true); 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) { protected boolean unloadPlugin(String pluginId, boolean unloadDependents) {
try { try {
if (unloadDependents) { if (unloadDependents) {
// notify the plugin as it's deleted // notify the plugin as it's deleted
plugin.delete(); plugin.delete();


Path pluginPath = pluginWrapper.getPluginPath();

return pluginRepository.deletePluginPath(pluginPath);
return pluginRepository.deletePluginPath(pluginWrapper.getPluginPath());
} }


/** /**
} }


for (PluginDependency dependency : pluginDescriptor.getDependencies()) { 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())) { if (!dependency.isOptional() || plugins.containsKey(dependency.getPluginId())) {
startPlugin(dependency.getPluginId()); startPlugin(dependency.getPluginId());
} }
return stopPlugin(pluginId, true); 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) { protected PluginState stopPlugin(String pluginId, boolean stopDependents) {
checkPluginId(pluginId); checkPluginId(pluginId);


return pluginWrapper.getPluginState(); 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) { protected void checkPluginId(String pluginId) {
if (!plugins.containsKey(pluginId)) { if (!plugins.containsKey(pluginId)) {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId)); throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
} }


pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR; pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR;

return Collections.singletonList(Paths.get(pluginsDir)); return Collections.singletonList(Paths.get(pluginsDir));
} }


return true; return true;
} }


PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
log.warn("Plugin '{}' requires a minimum system version of {}, and you have {}", log.warn("Plugin '{}' requires a minimum system version of {}, and you have {}",
getPluginLabel(pluginDescriptor),
getPluginLabel(pluginWrapper.getDescriptor()),
requires, requires,
getSystemVersion()); getSystemVersion());


return false; 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) { protected boolean isPluginDisabled(String pluginId) {
return pluginStatusProvider.isPluginDisabled(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() { protected void resolvePlugins() {
// retrieves the plugins descriptors // retrieves the plugins descriptors
List<PluginDescriptor> descriptors = new ArrayList<>(); List<PluginDescriptor> descriptors = new ArrayList<>();
} }
} }


/**
* 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) { protected synchronized void firePluginStateEvent(PluginStateEvent event) {
for (PluginStateListener listener : pluginStateListeners) { for (PluginStateListener listener : pluginStateListeners) {
log.trace("Fire '{}' to '{}'", event, listener); log.trace("Fire '{}' to '{}'", event, listener);
} }
} }


/**
* 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) { protected PluginWrapper loadPluginFromPath(Path pluginPath) {
// Test for plugin path duplication // Test for plugin path duplication
String pluginId = idForPath(pluginPath); String pluginId = idForPath(pluginPath);
} }


/** /**
* 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) { protected PluginWrapper createPluginWrapper(PluginDescriptor pluginDescriptor, Path pluginPath, ClassLoader pluginClassLoader) {
// create the plugin wrapper // create the plugin wrapper
log.debug("Creating wrapper for plugin '{}'", pluginPath); log.debug("Creating wrapper for plugin '{}'", pluginPath);
PluginWrapper pluginWrapper = new PluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader); PluginWrapper pluginWrapper = new PluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader);
pluginWrapper.setPluginFactory(getPluginFactory()); pluginWrapper.setPluginFactory(getPluginFactory());

return pluginWrapper; return pluginWrapper;
} }


* Override this to change the validation criteria. * Override this to change the validation criteria.
* *
* @param descriptor the plugin descriptor to validate * @param descriptor the plugin descriptor to validate
* @throws PluginRuntimeException if validation fails
* @throws InvalidPluginDescriptorException if validation fails
*/ */
protected void validatePluginDescriptor(PluginDescriptor descriptor) { protected void validatePluginDescriptor(PluginDescriptor descriptor) {
if (StringUtils.isNullOrEmpty(descriptor.getPluginId())) { 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) { 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 * @return true if exact versions in requires is allowed
*/ */
public boolean isExactVersionAllowed() { public boolean isExactVersionAllowed() {
} }


/** /**
* 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) { protected String getPluginLabel(PluginDescriptor pluginDescriptor) {
return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion(); return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion();

+ 30
- 0
pf4j/src/main/java/org/pf4j/InvalidPluginDescriptorException.java View File

/*
* 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