All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.common.Java9ModuleUtil Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.common;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.NoSuchElementException;

/**
 * Utility which deals with Java 9 modules using reflection so we can avoid depending on it
 * at compile-time.
 *
 * @author Stéphane Épardaud 
 */
public class Java9ModuleUtil {

	public static Object getModule(Class klass) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Method getModule = Class.class.getMethod("getModule");
		return getModule.invoke(klass);
	}
	
	public static Object findModule(Object fromModule, String name) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        Class moduleClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.reflect.Module");
		Method getLayer = moduleClass.getMethod("getLayer");
		Object layer = getLayer.invoke(fromModule);
		return findModuleFromLayer(layer, name);
	}
	
	private static Object findModuleFromLayer(Object layer, String name) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, SecurityException {
        Class layerClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.reflect.Layer");
        Method findModule = layerClass.getMethod("findModule", String.class);
        Object optionalModule = findModule.invoke(layer, name);
        Class optionalClass = ClassLoader.getSystemClassLoader().loadClass("java.util.Optional");
        Method get = optionalClass.getMethod("get");
        try{
        	return get.invoke(optionalModule);
        }catch(InvocationTargetException x){
        	if(x.getTargetException() instanceof NoSuchElementException)
        		return null;
        	throw x;
        }
	}

	public static ClassLoader getClassLoader(Object module) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, SecurityException{
        Class moduleClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.reflect.Module");
        Method getClassLoader = moduleClass.getMethod("getClassLoader");
        Object classLoader = getClassLoader.invoke(module);
        return (ClassLoader) classLoader;
	}

	public static boolean isNamedModule(Object module) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, SecurityException {
        Class moduleClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.reflect.Module");
        Method isNamed = moduleClass.getMethod("isNamed");
        Boolean ret = (Boolean) isNamed.invoke(module);
        return ret.booleanValue();
	}

	public static Object loadModuleDynamically(String module) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
        String modulePath = System.getProperty("jdk.module.path");
        String[] modulePathEntries = modulePath.split(File.pathSeparator);
        return loadModulesDynamically(modulePathEntries, module);
	}
	
	public static Object loadModulesDynamically(String[] modulePath, String... modules) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
        Path[] paths = new Path[modulePath.length];
        int i=0;
        for(String moduleFolder : modulePath){
        	paths[i++] = Paths.get(moduleFolder);
        }

        // ModuleFinder finder = ModuleFinder.of(paths);
        Class moduleFinderClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.module.ModuleFinder");
        Method ofMethod = moduleFinderClass.getMethod("of", Path[].class);
        Object moduleFinder = ofMethod.invoke(null, (Object)paths);
        
        // Configuration cf = Configuration.resolve(ModuleFinder.empty(),
        //         Layer.boot().configuration(),
        //         finder,
        //         appModuleName);
        Class configurationClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.module.Configuration");
        Class layerClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.reflect.Layer");
        Method resolveMethod = configurationClass.getMethod("resolve", moduleFinderClass, layerClass, moduleFinderClass, String[].class);

        Method emptyMethod = moduleFinderClass.getMethod("empty");
        Object emptyModuleFinder = emptyMethod.invoke(null);

        Method bootMethod = layerClass.getMethod("boot");
        Object bootLayer = bootMethod.invoke(null);
//        Method configurationMethod = layerClass.getMethod("configuration");
//        Object bootConfiguration = configurationMethod.invoke(bootLayer);
        
        Object configuration = resolveMethod.invoke(null, emptyModuleFinder, bootLayer, moduleFinder, modules);

        // cf = cf.bind();
        Method bindMethod = configurationClass.getMethod("bind");
        configuration = bindMethod.invoke(configuration);
        
        // choose a class loader
        // ModuleClassLoader loader = new ModuleClassLoader(cf);
        Class moduleClassLoaderClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.ModuleClassLoader");
        Constructor moduleClassLoaderConstructor = moduleClassLoaderClass.getConstructor(configurationClass);
        final Object moduleClassLoader = moduleClassLoaderConstructor.newInstance(configuration);

        // reify the configuration as a Layer
        // Layer layer = Layer.create(cf, mn -> loader);
        Class classLoaderFinderClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.reflect.Layer$ClassLoaderFinder");
        Method createMethod = layerClass.getMethod("create", configurationClass, classLoaderFinderClass);
        
        InvocationHandler handler = new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				return moduleClassLoader;
			}
		};
		Object classLoaderFinder = Proxy.newProxyInstance(Java9ModuleUtil.class.getClassLoader(), new Class[]{classLoaderFinderClass}, handler );
        
        Object newLayer = createMethod.invoke(null, configuration, classLoaderFinder);
        return findModuleFromLayer(newLayer, modules[0]);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy