play.plugins.PluginCollection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
RePlay is a fork of the Play1 framework, created by Codeborne.
package play.plugins;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.ClasspathResource;
import play.Play;
import play.PlayPlugin;
import play.data.binding.RootParamNode;
import play.inject.Injector;
import play.mvc.Http;
import play.mvc.Http.Request;
import play.mvc.Http.Response;
import play.mvc.Scope.Flash;
import play.mvc.Scope.RenderArgs;
import play.mvc.Scope.Session;
import play.mvc.results.Result;
import play.templates.Template;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Stream;
import static java.lang.Integer.parseInt;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toList;
/**
* Class handling all plugins used by Play.
*
* Loading/reloading/enabling/disabling is handled here.
*
* This class also exposes many PlayPlugin-methods which when called, the method is executed on all enabled plugins.
*
* Since all the enabled-plugins-iteration is done here, the code elsewhere is cleaner.
*/
@ParametersAreNonnullByDefault
public class PluginCollection {
private static final Logger logger = LoggerFactory.getLogger(PluginCollection.class);
/**
* List that holds all loaded plugins, both enabled and disabled
*/
private final List allPlugins = new ArrayList<>();
public PluginCollection() {}
public PluginCollection(SortedSet pluginsToLoad) {
loadPlugins(pluginsToLoad);
}
/**
* Load plugins from .plugin files, if any
*/
public void loadPlugins() {
logger.trace("Loading plugins");
List pluginsFiles = getPlayPluginFiles();
// Sort plugins by index
SortedSet pluginsToLoad = pluginsFiles.stream()
.map(this::readPluginsDescriptor)
.flatMap(List::stream)
.collect(toCollection(TreeSet::new));
loadPlugins(pluginsToLoad);
}
private List readPluginsDescriptor(ClasspathResource pluginsFile) {
logger.trace("Found one plugins descriptor, {}", pluginsFile);
return pluginsFile.lines().stream()
.filter(line -> !line.trim().isEmpty())
.map(line -> toPluginDescriptor(pluginsFile, line))
.collect(toList());
}
@Nonnull
@CheckReturnValue
private PluginDescriptor toPluginDescriptor(ClasspathResource pluginsFile, String line) {
String[] lineParts = line.split(":");
return new PluginDescriptor(lineParts[1].trim(), parseInt(lineParts[0]), pluginsFile.url());
}
public void loadPlugins(SortedSet pluginsToLoad) {
for (PluginDescriptor info : pluginsToLoad) {
logger.trace("Loading plugin {}", info.name);
PlayPlugin plugin = Injector.getBeanOfType(info.name);
plugin.index = info.index;
addPlugin(plugin);
logger.trace("Plugin {} loaded", plugin);
}
// Now we call onLoad for all plugins, and we detect if a plugin disables another plugin the
// old way, by removing it from Play.plugins.
getEnabledPlugins().forEach(plugin -> {
logger.trace("Initializing plugin {}", plugin);
plugin.onLoad();
});
}
List getPlayPluginFiles() {
String[] pluginsDescriptorFilenames = Play.configuration.getProperty("play.plugins.descriptor", "play.plugins").split(",");
List pluginDescriptors = Arrays.stream(pluginsDescriptorFilenames)
.map(fileName -> ClasspathResource.files(fileName))
.flatMap(List::stream)
.collect(toList());
logger.info("Found plugin descriptors: {}", pluginDescriptors);
return pluginDescriptors;
}
/**
* Adds one plugin and enables it
*
* @param plugin
* The given plugin
*/
protected synchronized void addPlugin(PlayPlugin plugin) {
if (allPlugins.contains(plugin)) {
throw new IllegalStateException("Plugin already added: " + plugin);
}
allPlugins.add(plugin);
Collections.sort(allPlugins);
}
/**
* Returns the first instance of a loaded plugin of specified type
*
* @param pluginClazz
* The plugin class
* @return PlayPlugin
*/
@Nullable
@SuppressWarnings("unchecked")
public T getPluginInstance(Class pluginClazz) {
return getAllPlugins()
.filter(p -> pluginClazz.isInstance(p))
.map(p -> (T) p)
.findAny().orElse(null);
}
public Stream getEnabledPlugins() {
return getAllPlugins().filter(p -> p.isEnabled());
}
/**
* Returns readonly view of all enabled plugins in reversed order
*
* @return Collection of plugins
*/
Stream getReversedEnabledPlugins() {
return getEnabledPlugins().sorted(Collections.reverseOrder());
}
/**
* Returns new readonly list of all plugins
*
* @return List of plugins
*/
public Stream getAllPlugins() {
return allPlugins.stream();
}
public void onJobInvocationFinally() {
getEnabledPlugins().forEach(plugin -> plugin.onJobInvocationFinally());
}
public void beforeInvocation() {
getEnabledPlugins().forEach(plugin -> plugin.beforeInvocation());
}
public void afterInvocation() {
getEnabledPlugins().forEach(plugin -> plugin.afterInvocation());
}
public void onInvocationSuccess() {
getEnabledPlugins().forEach(plugin -> plugin.onInvocationSuccess());
}
public void onActionInvocationException(@Nonnull Http.Request request, @Nonnull Response response, @Nonnull Throwable e) {
getEnabledPlugins().forEach(plugin -> {
try {
plugin.onActionInvocationException(request, response, e);
} catch (Throwable ex) {
logger.error("Failed to handle action invocation exception by plugin {}", plugin.getClass().getName(), ex);
}
});
}
public void onJobInvocationException(@Nonnull Throwable e) {
getEnabledPlugins().forEach(plugin -> {
try {
plugin.onJobInvocationException(e);
} catch (Throwable ex) {
logger.error("Failed to handle job invocation exception by plugin {}", plugin.getClass().getName(), ex);
}
});
}
public void detectChange() {
getEnabledPlugins().forEach(plugin -> plugin.detectChange());
}
public void onConfigurationRead() {
getEnabledPlugins().forEach(plugin -> plugin.onConfigurationRead());
}
public void onApplicationStart() {
getEnabledPlugins().forEach(plugin -> plugin.onApplicationStart());
}
public void afterApplicationStart() {
getEnabledPlugins().forEach(plugin -> plugin.afterApplicationStart());
}
public void onApplicationStop() {
getReversedEnabledPlugins().forEach(plugin -> {
try {
plugin.onApplicationStop();
} catch (Throwable t) {
logger.error("Error while stopping {}", plugin, t);
}
});
}
public Optional
© 2015 - 2024 Weber Informatics LLC | Privacy Policy