use of io.gomint.proxprox.api.plugin.PluginMeta in project ProxProx by GoMint.
the class PluginAutoDetector method checkPlugin.
/**
* Check if the jar given is useable as plugin
*
* @param jarFile The jar file which should be checked
* @return a loaded plugin meta or null when not usable as plugin
*/
public PluginMeta checkPlugin(JarFile jarFile) {
Enumeration<JarEntry> jarEntries = jarFile.entries();
if (jarEntries == null) {
logger.warn("Could not load Plugin. File " + jarFile + " is empty");
return null;
}
try {
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
if (jarEntry != null && jarEntry.getName().endsWith(".class")) {
ClassFile classFile = new ClassFile(new DataInputStream(jarFile.getInputStream(jarEntry)));
if (classFile.getSuperclass().equals("io.gomint.proxprox.api.plugin.Plugin")) {
PluginMeta pluginDescription = new PluginMeta();
pluginDescription.setName(classFile.getName().substring(classFile.getName().lastIndexOf('.') + 1));
AnnotationsAttribute visible = (AnnotationsAttribute) classFile.getAttribute(AnnotationsAttribute.visibleTag);
for (Annotation annotation : visible.getAnnotations()) {
switch(annotation.getTypeName()) {
case "io.gomint.proxprox.api.plugin.annotation.Description":
pluginDescription.setDescription(((StringMemberValue) annotation.getMemberValue("value")).getValue());
break;
case "io.gomint.proxprox.api.plugin.annotation.Version":
int major = ((IntegerMemberValue) annotation.getMemberValue("major")).getValue();
int minor = ((IntegerMemberValue) annotation.getMemberValue("minor")).getValue();
pluginDescription.setVersion(new PluginVersion(major, minor));
break;
case "io.gomint.proxprox.api.plugin.annotation.Depends":
MemberValue[] dependsValues = ((ArrayMemberValue) annotation.getMemberValue("value")).getValue();
HashSet<String> dependsStringValues = new HashSet<>();
for (MemberValue value : dependsValues) {
dependsStringValues.add(((StringMemberValue) value).getValue());
}
pluginDescription.setDepends(dependsStringValues);
break;
case "io.gomint.proxprox.api.plugin.annotation.Name":
pluginDescription.setName(((StringMemberValue) annotation.getMemberValue("value")).getValue());
break;
default:
break;
}
}
pluginDescription.setMainClass(classFile.getName());
return pluginDescription;
}
}
}
return null;
} catch (IOException e) {
logger.warn("Could not load Plugin. File " + jarFile + " is corrupted", e);
return null;
}
}
use of io.gomint.proxprox.api.plugin.PluginMeta in project ProxProx by GoMint.
the class PluginManager method loadPlugins.
/**
* Load all plugins
*/
public void loadPlugins() {
Map<PluginMeta, Boolean> pluginStatuses = new HashMap<>();
// Put in all currently loaded Plugins
for (Map.Entry<String, Plugin> namePluginEntry : plugins.entrySet()) {
pluginStatuses.put(namePluginEntry.getValue().getMeta(), true);
}
for (Map.Entry<String, PluginMeta> entry : toLoad.entrySet()) {
PluginMeta plugin = entry.getValue();
if (!enablePlugin(pluginStatuses, new Stack<>(), plugin)) {
logger.warn("Failed to enable " + entry.getKey());
}
}
toLoad.clear();
toLoad = null;
}
use of io.gomint.proxprox.api.plugin.PluginMeta in project ProxProx by GoMint.
the class PluginManager method enablePlugin.
private boolean enablePlugin(Map<PluginMeta, Boolean> pluginStatuses, Stack<PluginMeta> dependStack, PluginMeta plugin) {
// Fast out when already loaded
if (pluginStatuses.containsKey(plugin)) {
return pluginStatuses.get(plugin);
}
// combine all dependencies for 'for loop'
Set<String> dependencies = new HashSet<>();
if (plugin.getDepends() != null) {
dependencies.addAll(plugin.getDepends());
}
// success status
boolean status = true;
// try to load dependencies first
for (String dependName : dependencies) {
PluginMeta depend = toLoad.containsKey(dependName) ? toLoad.get(dependName) : (plugins.containsKey(dependName)) ? plugins.get(dependName).getMeta() : null;
Boolean dependStatus = (depend != null) ? pluginStatuses.get(depend) : Boolean.FALSE;
if (dependStatus == null) {
if (dependStack.contains(depend)) {
StringBuilder dependencyGraph = new StringBuilder();
for (PluginMeta element : dependStack) {
dependencyGraph.append(element.getName()).append(" -> ");
}
dependencyGraph.append(plugin.getName()).append(" -> ").append(dependName);
logger.warn("Circular dependency detected: " + dependencyGraph);
status = false;
} else {
dependStack.push(plugin);
dependStatus = this.enablePlugin(pluginStatuses, dependStack, depend);
dependStack.pop();
}
}
if (dependStatus == Boolean.FALSE) {
logger.warn("%s (required by %s) is unavailable", String.valueOf(dependName), plugin.getName());
status = false;
}
if (!status) {
break;
}
}
// do actual loading
if (status) {
try {
URLClassLoader loader = new PluginClassLoader(new URL[] { plugin.getPluginFile().toURI().toURL() });
Class<?> main = loader.loadClass(plugin.getMainClass());
Plugin clazz = (Plugin) main.getConstructor().newInstance();
// TODO: Secure this
clazz.setMeta(plugin);
clazz.setPluginManager(this);
clazz.setLogger(LoggerFactory.getLogger(main));
clazz.setScheduler(new PluginScheduler(clazz, this.scheduler));
toEnable.put(plugin.getName(), clazz);
clazz.onStartup();
logger.info("Loaded plugin {} version {}", plugin.getName(), plugin.getVersion());
} catch (Throwable t) {
logger.warn("Error enabling plugin " + plugin.getName(), t);
}
}
pluginStatuses.put(plugin, status);
return status;
}
use of io.gomint.proxprox.api.plugin.PluginMeta in project ProxProx by GoMint.
the class PluginManager method detectPlugins.
/**
* Load all plugins from the specified folder.
*/
public void detectPlugins() {
Preconditions.checkNotNull(container, "folder");
Preconditions.checkArgument(container.isDirectory(), "Must load from a directory");
if (toLoad == null) {
toLoad = new HashMap<>();
}
File[] filesToLoad = container.listFiles();
if (filesToLoad == null) {
return;
}
for (File file : filesToLoad) {
if (file.isFile() && file.getName().endsWith(".jar")) {
try (JarFile jar = new JarFile(file)) {
PluginMeta desc = pluginAutoDetector.checkPlugin(jar);
Preconditions.checkNotNull(desc, "Plugin could not be autodetected");
if (!plugins.containsKey(desc.getName())) {
desc.setPluginFile(file);
toLoad.put(desc.getName(), desc);
}
} catch (Throwable ex) {
logger.warn("Could not load plugin from file " + file, ex);
}
}
}
}
Aggregations