0

I am designing a system using Spring where some users should able to implement some classes, submit a JAR and be able to execute their submission provided that the classes inside the Jar comply with the interfaces that are supposed to be implemented. The idea is to have a framework for extensiblility using jars (and some xml configuration files).

My questions is, is this possible? How should I approach the execution of the mentioned Jars and can I validate that the content of the jars complies with the API during submission?

Thank you!

LECHIP
  • 81
  • 1
  • 8
  • 1
    Can you trust your users? You should be very careful not to execute untrusted code. – 5gon12eder Sep 28 '15 at 15:09
  • Yes, the users are trusted, the extension framework if for them to construct theirs modules quickly and be able to integrate them on the system easily. The number of users doing this is manageable and they are qualified and trusted. There are other mechanisms for handling the submission, but let's assume for answering the question that this is not an issue. – LECHIP Sep 28 '15 at 15:13

2 Answers2

1
URLClassLoader child = new URLClassLoader (myJar.toURL(), this.getClass().getClassLoader());
Class classToLoad = Class.forName ("com.MyClass", true, child);
Method method = classToLoad.getDeclaredMethod ("myMethod");
Object instance = classToLoad.newInstance ();
Object result = method.invoke (instance);

How should I load Jars dynamically at runtime?

restrict permissions of loaded jars Java security: Sandboxing plugins loaded via URLClassLoader

use reflection to test classes How can I determine whether a Java class is abstract by reflection https://docs.oracle.com/javase/tutorial/reflect/

Community
  • 1
  • 1
Vovka
  • 599
  • 3
  • 10
  • What I am doing is part of a Spring boot project where the user sends JAR files and I make a loader service that can use the sent jars. Will something like your answer will work with it? (I'll check during this week). I've seen multiple posts trying to achieve this but they are extremely inconclusive. – LECHIP Nov 10 '15 at 21:35
  • Well, this totally breaks my design. Since the idea was to develop a framework where developers can extend a class and submit it through HTTP. I was using Spring-Boot for the REST and persistence but the only way of achieving the possibility to make runtime-loadable jars seems to be abandoned by Spring... Will check on OSGi, but I cannot seem to find a good alternative that offers all the other capabilities that spring gave me. – LECHIP Nov 12 '15 at 18:10
1

I ended up using JCL: https://github.com/kamranzafar/JCL

I used it with something like this:

public class AnalyticsMethodsClassPathLoader {

private JarClassLoader jcl;
private JclObjectFactory factory;

public AnalyticsMethodsClassPathLoader(String analyticsMethodsJarsFolder) {

    //JCL object for loading jars
    jcl = new JarClassLoader();
    //Loading classes from different sources
    jcl.add(analyticsMethodsJarsFolder);

    // Set ClassPathLoader priorities to prevent collisions when loading
    jcl.getParentLoader().setOrder(1);
    jcl.getLocalLoader().setOrder(2);
    jcl.getSystemLoader().setOrder(3);
    jcl.getThreadLoader().setOrder(4);
    jcl.getCurrentLoader().setOrder(5);

    // Set default to cglib (from version 2.2.1)
    ProxyProviderFactory.setDefaultProxyProvider( new CglibProxyProvider() );
    factory = JclObjectFactory.getInstance(true);
}

public AnalyticsMethod loadClass(String implementingClass) throws AnalyticsMethodLoaderException {
    //Create object of loaded class
    AnalyticsMethod abstractMethod;
    try{
        abstractMethod = (AnalyticsMethod) factory.create(jcl, implementingClass);
        return abstractMethod;
    }
    catch (JclException e)
    {
        e.printStackTrace();
        throw new AnalyticsMethodLoaderException("The class " + implementingClass +
                " was not found or does not implement the framework.");
    }
    catch (java.lang.NoSuchMethodError error)
    {
        error.printStackTrace();
        throw new AnalyticsMethodLoaderException("The class " + implementingClass +
                " does not have an empty constructor.");
    }
}

}

It is relatively stable and allows me to do just what I needed in spring without the need to combine it with the now unsupported OSGi features of spring. I do know that it has limitations and is not the absolute best solution in all cases, but for submitting and executing simple jars works just fine.

LECHIP
  • 81
  • 1
  • 8