au.net.causal.maven.plugins.boxdb.JavaRunner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boxdb-maven-plugin Show documentation
Show all versions of boxdb-maven-plugin Show documentation
Maven plugin to start databases using Docker and VMs
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 extends Path> jarFiles;
private final String mainClassName;
private final ClassLoaderCache classLoaderCache;
private Thread runnerThread;
public JavaRunner(List extends Path> 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 extends RunnerDependency> 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();
}
}