Search in sources :

Example 1 with PluginMeta

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;
    }
}
Also used : ClassFile(javassist.bytecode.ClassFile) PluginMeta(io.gomint.proxprox.api.plugin.PluginMeta) AnnotationsAttribute(javassist.bytecode.AnnotationsAttribute) IOException(java.io.IOException) JarEntry(java.util.jar.JarEntry) DataInputStream(java.io.DataInputStream) PluginVersion(io.gomint.proxprox.api.plugin.PluginVersion) HashSet(java.util.HashSet)

Example 2 with PluginMeta

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;
}
Also used : PluginMeta(io.gomint.proxprox.api.plugin.PluginMeta) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Plugin(io.gomint.proxprox.api.plugin.Plugin)

Example 3 with PluginMeta

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;
}
Also used : PluginMeta(io.gomint.proxprox.api.plugin.PluginMeta) URLClassLoader(java.net.URLClassLoader) Plugin(io.gomint.proxprox.api.plugin.Plugin) PluginScheduler(io.gomint.proxprox.scheduler.PluginScheduler)

Example 4 with PluginMeta

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);
            }
        }
    }
}
Also used : PluginMeta(io.gomint.proxprox.api.plugin.PluginMeta) JarFile(java.util.jar.JarFile) JarFile(java.util.jar.JarFile) File(java.io.File)

Aggregations

PluginMeta (io.gomint.proxprox.api.plugin.PluginMeta)4 Plugin (io.gomint.proxprox.api.plugin.Plugin)2 PluginVersion (io.gomint.proxprox.api.plugin.PluginVersion)1 PluginScheduler (io.gomint.proxprox.scheduler.PluginScheduler)1 DataInputStream (java.io.DataInputStream)1 File (java.io.File)1 IOException (java.io.IOException)1 URLClassLoader (java.net.URLClassLoader)1 HashSet (java.util.HashSet)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 JarEntry (java.util.jar.JarEntry)1 JarFile (java.util.jar.JarFile)1 AnnotationsAttribute (javassist.bytecode.AnnotationsAttribute)1 ClassFile (javassist.bytecode.ClassFile)1