package com.jpmorgan.tracer;

import java.io.*;
import java.util.List;
import java.util.Map;

import com.sun.jdi.Bootstrap;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.VirtualMachineManager;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import com.sun.jdi.connect.ListeningConnector;
import com.sun.jdi.connect.Connector.Argument;

public class TraceServerMain {
	/** The identifier of socket listen connector */
	private static final String SOCKET_LISTENER = "com.sun.jdi.SocketListen";

	private static final int PORT = 1388;

	public static void main(String[] args) {
		if (args.length < 1) {
			printUsage();
			System.exit(-1);
		}

		//check output file
		FileWriter fw = null;
		File outf = new File(args[0]);

		try {
			fw = new FileWriter(outf);
		}
		catch (Exception e) {
			e.printStackTrace(System.err);
			System.exit(-1);
		}

		VirtualMachineManager vmMgr = Bootstrap.virtualMachineManager();
		List<ListeningConnector> listeningConnectors = vmMgr.listeningConnectors();

		ListeningConnector connector = null;
		for (ListeningConnector listeningConnector : listeningConnectors) {
			if (SOCKET_LISTENER.equals(listeningConnector.name())) {
				System.out.println("Connector: " + listeningConnector.name());
				connector = listeningConnector;
				break;
			}
		}

		Map<String, ? extends Argument> argMap = connector.defaultArguments();

		Argument port = argMap.get("port");
		port.setValue(String.valueOf(PORT));

		for (String k : argMap.keySet()) {
			Argument a = argMap.get(k);
			System.out.println("  " + k + " : " + a);
		}

		String addr;
		VirtualMachine vm = null;

		try {
			addr = connector.startListening(argMap);
			System.out.println("Address :" + addr);
			vm = connector.accept(argMap);
		} catch (IOException e) {
			e.printStackTrace(System.err);
			System.exit(-1);
		} catch (IllegalConnectorArgumentsException e) {
			e.printStackTrace(System.err);
			System.exit(-1);
		}

		Tracer t = Tracer.getInstance();
		t.setTargetVM(vm);
		//t.setThreadToTrace("ServerThread");
		t.setStepTrace(true);

		CoverageEventHandler tt = t.generateTrace();

		try {
			fw.write(tt.toString());
			fw.close();
		} catch (Exception e) {
			e.printStackTrace(System.err);
			System.exit(-1);
		}        
	}

	public static void printUsage() {
		System.err.println("Compute the execution trace of a test");
		System.err.println("Usage: java TestServerMain [output_file]");
		System.err.println("   * [output_file] : the output file for the trace");
	}
}
