package de.ugoe.cs.eventbench.jfcmonitor;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

// TODO decent exception handling; currently no exception are caught!
public class JarLauncher {
	
	String workingDir = System.getProperty("user.dir") + "/";
	String jarfile;
	String[] args;
	
	String[] classPath = new String[]{};
	String mainClassName = "";
	ClassLoader costumClassLoader;
	
	public JarLauncher(String jarfile, String[] args) {
		this.jarfile = jarfile;
		this.args = args;
	}

	public void exec() throws FileNotFoundException, IOException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InterruptedException {
		getInfoFromJar();
		initClassLoader();
		startSUT();
	}
	
	private void getInfoFromJar() throws FileNotFoundException, IOException {
		JarInputStream jarInputStream = new JarInputStream(new FileInputStream(workingDir+jarfile));
		Manifest manifest = jarInputStream.getManifest();
		mainClassName = manifest.getMainAttributes().getValue("Main-Class");
		String jarClassPath = manifest.getMainAttributes().getValue("Class-Path");
		String[] jarClassPathElements = jarClassPath.split(" ");
		classPath = new String[jarClassPathElements.length];
		for (int i=0; i<jarClassPathElements.length ; i++) {
			classPath[i] = "file:"+workingDir+jarClassPathElements[i];
		}
	}
	
	private void initClassLoader() throws MalformedURLException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		URLClassLoader classLoader = (URLClassLoader) ClassLoader
				.getSystemClassLoader();
		Method method= URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
		method.setAccessible(true);
		
		method.invoke(classLoader, new Object[]{new URL("file:"+workingDir+jarfile)});
		
		for (String element : classPath) {
			method.invoke(classLoader, new Object[]{new URL(element)});
		}
	}
	
	private void startSUT() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InterruptedException {
		Class<?> mainClass = Class.forName(mainClassName);
		Method mainMethod = mainClass.getMethod("main", new Class[]{String[].class});
		mainMethod.invoke(null, new Object[]{args});
	}
}
