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

au.net.causal.maven.plugins.boxdb.JavaRunner Maven / Gradle / Ivy

There is a newer version: 3.3
Show newest version
package au.net.causal.maven.plugins.boxdb;

import au.net.causal.maven.plugins.boxdb.db.RunnerDependency;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.DependencyResolutionException;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Runs Java main classes.
 */
public class JavaRunner
{
	private final List jarFiles;
	private final String mainClassName;
	private final ClassLoaderCache classLoaderCache;

	private Thread runnerThread;

	public JavaRunner(List jarFiles, String mainClassName, ClassLoaderCache classLoaderCache)
	{
		Objects.requireNonNull(jarFiles, "jarFiles == null");
		Objects.requireNonNull(mainClassName, "mainClassName == null");
		Objects.requireNonNull(classLoaderCache, "classLoaderCache == null");
		this.jarFiles = new ArrayList<>(jarFiles);
		this.mainClassName = mainClassName;
		this.classLoaderCache = classLoaderCache;
	}

	public static JavaRunner createFromDependencies(String mainClassName,
	                                                List dependencies,
	                                                RepositorySystem repositorySystem,
	                                                RepositorySystemSession repositorySystemSession,
	                                                List remoteRepositories, 
													ClassLoaderCache classLoaderCache)
	throws DependencyResolutionException
	{
		return new JavaRunner(DependencyUtils.resolveDependencies(dependencies, repositorySystem, repositorySystemSession, remoteRepositories),
						mainClassName, classLoaderCache);
	}

	public Class makeClass()
	throws IOException, ClassNotFoundException
	{
		List urls = new ArrayList<>(jarFiles.size());
		for (Path jarFile : jarFiles)
		{
			urls.add(jarFile.toUri().toURL());
		}
		URL[] urlArray = urls.toArray(new URL[urls.size()]);
		URLClassLoader loader = classLoaderCache.create(urlArray);

		return Class.forName(mainClassName, true, loader);
	}

	private Method createMainMethod()
	throws IOException, ClassNotFoundException, NoSuchMethodException
	{
		Class mainClass = makeClass();
		return mainClass.getMethod("main", String[].class);
	}

	public void execute(String... args)
	throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException
	{
		ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
		try
		{
			Method mainMethod = createMainMethod();
			Thread.currentThread().setContextClassLoader(mainMethod.getDeclaringClass().getClassLoader());
			runMain(mainMethod, args);
		}
		finally
		{
			Thread.currentThread().setContextClassLoader(oldLoader);
		}
	}

	/**
	 * Starts executing, does not wait for completion.
	 */
	public void executeAsync(String... args)
	throws IOException, ClassNotFoundException, NoSuchMethodException
	{
		Method mainMethod = createMainMethod();

		runnerThread = new Thread(() -> runMainSafely(mainMethod, args));
		runnerThread.setContextClassLoader(mainMethod.getDeclaringClass().getClassLoader());
		runnerThread.setName("JavaRunner-" + mainMethod.getDeclaringClass().getSimpleName());
		//runnerThread.setUncaughtExceptionHandler();

		runnerThread.start();
	}

	public void runMethodAsync(Method method, Object target, Object... args)
	{
		runnerThread = new Thread(() -> runMethod(method, target, args));
		runnerThread.setContextClassLoader(method.getDeclaringClass().getClassLoader());
		runnerThread.setName("JavaRunner-" + method.getDeclaringClass().getSimpleName());
		//runnerThread.setUncaughtExceptionHandler();

		runnerThread.start();
	}

	public void runMethod(Method method, Object target, Object... args)
	{
		try
		{
			method.invoke(target, args);
		}
		catch (ReflectiveOperationException e)
		{
			throw new RuntimeException(e);
		}
	}

	private void runMainSafely(Method mainMethod, String... args)
	{
		try
		{
			mainMethod.invoke(null, new Object[] {args});
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	private void runMain(Method mainMethod, String... args)
	throws InvocationTargetException
	{
		try
		{
			mainMethod.invoke(null, new Object[] {args});
		}
		catch (InvocationTargetException e)
		{
			throw e;
		}
		catch (Exception e)
		{
			throw new InvocationTargetException(e);
		}
	}

	public void waitForAsyncCompletion()
	throws InterruptedException
	{
		if (runnerThread == null)
			throw new IllegalStateException("Thread never started");

		runnerThread.join();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy