dimanche 14 mai 2017

Loading classes dynamically in osgi bundle running in karaf runtime

I have a requirement where I have to provide the functionality to the user to specify a library and its function to call at runtime. For now, I have to add support or java.util.Math and java.lang.String which further drills down to having a class which required static method call(Math) and a class which requires object to be created(String).

Issue is: When I am trying to load the class in my Osgi bundle, it is throwing ClassNotFoundException. After debugging I have found that the classloader does not have the java.lang.Math class. My queries are: 1. How to make the same available in the classloader in osgi bundle? 2. Will there be a difference in coding approach for calling the class having all static methods and a class that requires object to be constructed.

Code:

For getting the classloader:

   public static ClassLoader getClassLoader(ClassLoader specifiedLoader, boolean useContextClassLoader, Class callingClass) {
        if (specifiedLoader != null) {
            return specifiedLoader;
        }
        if (useContextClassLoader) {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            if (classLoader != null) {
                return classLoader; // This returns the classloader
            }
        }
        return getClassLoader(callingClass);
    }

For getting the method:

public static Object invokeStaticMethod( final Class objectClass, final String methodName, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

if (parameterTypes == null) {
    parameterTypes = EMPTY_CLASS_PARAMETERS;
}
if (args == null) {
    args = EMPTY_OBJECT_ARRAY;
}

final Method method = getMatchingAccessibleMethod(
        objectClass,
        methodName,
        parameterTypes);
if (method == null) {
    throw new NoSuchMethodException("No such accessible method: " +
            methodName + "() on class: " + objectClass.getName());
}
return method.invoke(null, args);

}

The following code uses the above:

Class classObj = null;
                    ClassLoader classLoader = ClassLoaderUtils.getClassLoader(null, true, this.getClass());
                    if (classLoader != null){
                        classObj = Class.forName(className, true, classLoader); // <-- Raises ClassNotFoundException
                    }
                    Object[] parameterValues = paramValues.toArray();
                    Class[] parameterTypes = (Class[]) (paramTypes.toArray(new Class[paramTypes.size()]));
                    result = MethodUtils.invokeStaticMethod(classObj, methodName, parameterValues, parameterTypes);





Aucun commentaire:

Enregistrer un commentaire