/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Anthony Dahanne  <anthony.dahanne@compuware.com> - enhance ETF to be able to launch several tests in several bundles - https://bugs.eclipse.org/330613
 *******************************************************************************/
package org.eclipse.test;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;

import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestListener;
import junit.framework.TestResult;

/**
 * A TestRunner for JUnit that supports Ant JUnitResultFormatters and running
 * tests inside Eclipse. Example call: EclipseTestRunner -classname
 * junit.samples.SimpleTest
 * formatter=org.apache.tools.ant.taskdefs.optional.junit
 * .XMLJUnitResultFormatter
 */
public class EclipseTestRunner implements TestListener {
	class TestFailedException extends Exception {

		private static final long serialVersionUID = 6009335074727417445L;

		TestFailedException(String message) {
			super(message);
		}

		TestFailedException(Throwable e) {
			super(e);
		}
	}
	
	static class ThreadDump extends Exception {

		private static final long serialVersionUID = 1L;

		ThreadDump(String message) {
			super(message);
		}
	}

	static class StreamForwarder extends Thread {
		private InputStream fProcessOutput;

		private PrintStream fStream;

		public StreamForwarder(InputStream processOutput, PrintStream stream) {
			fProcessOutput= processOutput;
			fStream= stream;
		}

		@Override
		public void run() {
			try (BufferedReader reader= new BufferedReader(new InputStreamReader(fProcessOutput))) {
				String line= null;
				while ((line= reader.readLine()) != null) {
					fStream.println(line);
				}
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * No problems with this test.
	 */
	public static final int SUCCESS = 0;
	/**
	 * Some tests failed.
	 */
	public static final int FAILURES = 1;
	/**
	 * An error occured.
	 */
	public static final int ERRORS = 2;

	private static final String SUITE_METHODNAME = "suite";
	/**
	 * SECONDS_BEFORE_TIMEOUT_BUFFER is the time we allow ourselves to take
	 * stack traces, get a screen shot, delay "SECONDS_BETWEEN_DUMPS", then do
	 * it again. On current build machine, it takes about 30 seconds to do all
	 * that, so 2 minutes should be suffiencient time allowed for most machines.
	 * Though, should increase, say, if we increase the "time beteen dumps" to a
	 * minute or more.
	 */
	private static final int SECONDS_BEFORE_TIMEOUT_BUFFER = 120;

	/**
	 * SECONDS_BETWEEN_DUMPS is the time we wait from first to second dump of
	 * stack trace and screenshots. In most cases, this should suffice to
	 * determine if still busy doing something, or, hung, or waiting for user
	 * input.
	 */
	private static final int SECONDS_BETWEEN_DUMPS = 5;

	/**
	 * The current test result
	 */
	private TestResult fTestResult;
	/**
	 * The name of the plugin containing the test
	 */
	private String fTestPluginName;
	/**
	 * The corresponding testsuite.
	 */
	private Test fSuite;
	/**
	 * Formatters from the command line.
	 */
	private static Vector<JUnitResultFormatter> fgFromCmdLine = new Vector<>();
	/**
	 * Holds the registered formatters.
	 */
	private Vector<JUnitResultFormatter> formatters = new Vector<>();
	/**
	 * Do we stop on errors.
	 */
	private boolean fHaltOnError = false;
	/**
	 * Do we stop on test failures.
	 */
	private boolean fHaltOnFailure = false;
	/**
	 * The TestSuite we are currently running.
	 */
	private JUnitTest fJunitTest;
	/**
	 * output written during the test
	 */
	private PrintStream fSystemError;
	/**
	 * Error output during the test
	 */
	private PrintStream fSystemOut;
	/**
	 * Exception caught in constructor.
	 */
	private Exception fException;
	/**
	 * Returncode
	 */
	private int fRetCode = SUCCESS;

	/**
	 * The main entry point (the parameters are not yet consistent with the Ant
	 * JUnitTestRunner, but eventually they should be). Parameters
	 * 
	 * <pre>
	 * -className: the name of the testSuite
	 * -testPluginName: the name of the containing plugin
	 * haltOnError: halt test on errors?
	 * haltOnFailure: halt test on failures?
	 * -testlistener listenerClass: deprecated
	 * 		print a warning that this option is deprecated
	 * formatter: a JUnitResultFormatter given as classname,filename. 
	 *  	If filename is ommitted, System.out is assumed.
	 * </pre>
	 */
	public static void main(String[] args) throws IOException {
		System.exit(run(args));
	}

	public static int run(String[] args) throws IOException {
		String className = null;
		String classesNames = null;
		String testPluginName = null;
		String testPluginsNames = null;
		String formatterString = null;
		String timeoutString = null;
		String junitReportOutput = null;

		boolean haltError = false;
		boolean haltFail = false;

		Properties props = new Properties();

		int startArgs = 0;
		if (args.length > 0) {
			// support the JUnit task commandline syntax where
			// the first argument is the name of the test class
			if (!args[0].startsWith("-")) {
				className = args[0];
				startArgs++;
			}
		}
		for (int i = startArgs; i < args.length; i++) {
			if (args[i].toLowerCase().equals("-classname")) {
				if (i < args.length - 1)
					className = args[i + 1];
				i++;
			} else if (args[i].toLowerCase().equals("-classesnames")) {
				if (i < args.length - 1)
					classesNames = args[i + 1];
				i++;
			} else if (args[i].toLowerCase().equals("-testpluginname")) {
				if (i < args.length - 1)
					testPluginName = args[i + 1];
				i++;
			} else if (args[i].toLowerCase().equals("-testpluginsnames")) {
				if (i < args.length - 1)
					testPluginsNames = args[i + 1];
				i++;
			} else if (args[i].equals("-junitReportOutput")) {
				if (i < args.length - 1)
					junitReportOutput = args[i + 1];
				i++;
			} else if (args[i].startsWith("haltOnError=")) {
				haltError = Project.toBoolean(args[i].substring(12));
			} else if (args[i].startsWith("haltOnFailure=")) {
				haltFail = Project.toBoolean(args[i].substring(14));
			} else if (args[i].startsWith("formatter=")) {
				formatterString = args[i].substring(10);
			} else if (args[i].startsWith("propsfile=")) {
				try (FileInputStream in = new FileInputStream(args[i].substring(10))) {
					props.load(in);
				}
			} else if (args[i].equals("-testlistener")) {
            	System.err.println("The -testlistener option is no longer supported\nuse the formatter= option instead");
				return ERRORS;
			} else if (args[i].equals("-timeout")) {
				if (i < args.length - 1)
					timeoutString = args[i + 1];
				i++;
			}
		}
		// Add/overlay system properties on the properties from the Ant project
		Hashtable<Object, Object> p = System.getProperties();
		for (Enumeration<Object> _enum = p.keys(); _enum.hasMoreElements();) {
			Object key = _enum.nextElement();
			props.put(key, p.get(key));
		}

		if (timeoutString == null || timeoutString.isEmpty()) {
			System.err.println("INFO: optional timeout was not specified.");
		} else {
			String timeoutScreenOutputDir = null;
			if (junitReportOutput == null || junitReportOutput.isEmpty()) {
				timeoutScreenOutputDir = "timeoutScreens";
			} else {
				timeoutScreenOutputDir = junitReportOutput + "/timeoutScreens";
			}
			System.err.println("INFO: timeoutScreenOutputDir: " + timeoutScreenOutputDir);
			System.err.println("INFO: timeout: " + timeoutString);
			startStackDumpTimeoutTimer(timeoutString, new File(
					timeoutScreenOutputDir), className);
		}

		if (testPluginsNames != null && classesNames != null) {
			// we have several plugins to look tests for, let's parse their
			// names
			String[] testPlugins = testPluginsNames.split(",");
			String[] suiteClasses = classesNames.split(",");
			try {
				createAndStoreFormatter(formatterString, suiteClasses);
			} catch (BuildException be) {
				System.err.println(be.getMessage());
				return ERRORS;
			}
			int returnCode = 0;
			int j = 0;
			for (String oneClassName : suiteClasses) {
				JUnitTest t = new JUnitTest(oneClassName);
				t.setProperties(props);
				EclipseTestRunner runner = new EclipseTestRunner(t, testPlugins[j],
						haltError, haltFail);
				transferFormatters(runner, j);
				runner.run();
				j++;
				if (runner.getRetCode() != 0) {
					returnCode = runner.getRetCode();
				}
			}
			return returnCode;
		}
		try {
			createAndStoreFormatter(formatterString);
		} catch (BuildException be) {
			System.err.println(be.getMessage());
			return ERRORS;
		}
		if (className == null)
			throw new IllegalArgumentException("Test class name not specified");

		JUnitTest t = new JUnitTest(className);

		t.setProperties(props);

	    EclipseTestRunner runner= new EclipseTestRunner(t, testPluginName, haltError, haltFail);
		transferFormatters(runner);
		runner.run();
		return runner.getRetCode();
	}

	/**
	 * Starts a timer that dumps interesting debugging information shortly
	 * before the given timeout expires.
	 * 
	 * @param timeoutArg
	 *            the -timeout argument from the command line
	 * @param outputDirectory
	 *            where the test results end up
	 * @param classname
	 *            the class that is running the tests suite
	 */
	private static void startStackDumpTimeoutTimer(final String timeoutArg,
			final File outputDirectory, final String classname) {
		try {
			/*
			 * The delay (in ms) is the sum of - the expected time it took for
			 * launching the current VM and reaching this method - the time it
			 * will take to run the garbage collection and dump all the infos
			 * (twice)
			 */
			int delay = SECONDS_BEFORE_TIMEOUT_BUFFER * 1000;

			int timeout = Integer.parseInt(timeoutArg) - delay;
			String time0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z",
					Locale.US).format(new Date());
			System.err.println("starting EclipseTestRunner Timer with timeout="
					+ timeout + " at " + time0);
			if (timeout > 0) {
				new Timer("EclipseTestRunner Timer", true).schedule(
						new TimerTask() {
							
							volatile boolean assumeUiThreadIsResponsive;
							
							@Override
							public void run() {
								assumeUiThreadIsResponsive = true;
								dump(0);
								try {
									Thread.sleep(SECONDS_BETWEEN_DUMPS * 1000);
								} catch (InterruptedException e) {
									// continue
								}
								dump(SECONDS_BETWEEN_DUMPS);
							}

							/**
							 * 
							 * @param num 
							 *     num is purely a lable used in naming the screen capture files. 
							 *     By convention, we pass in 0 or "SECONDS_BETWEEN_DUMPS" just as 
							 *     a subtle reminder of how much time as elapsed.  
							 *     Thus, files end up with names similar to 
							 *     <classname>_screen0.png, <classname>_screem5.png
                             *     in a directory named "timeoutScreens" under "results", 
                             *     such as .../results/linux.gtk.x86_64/timeoutScreens/ 
							 */
							private void dump(final int num) {
								// Time elapsed time to do each dump, so we'll
								// know if/when we get too close to the 2
								// minutes we allow
								long start = System.currentTimeMillis();

								// Dump all stacks:
								dumpStackTraces(num, System.err);
								dumpStackTraces(num, System.out); // System.err could be blocked, see https://bugs.eclipse.org/506304
								
								if (!dumpSwtDisplay(num)) {
									String screenshotFile= getScreenshotFile(num);
									dumpAwtScreenshot(screenshotFile);
								}
								
								// Elapsed time in milliseconds
								long elapsedTimeMillis = System
										.currentTimeMillis() - start;

								// Print in seconds
								float elapsedTimeSec = elapsedTimeMillis / 1000F;
								System.err.println("INFO: Seconds to do dump "
										+ num + ": " + elapsedTimeSec);
							}

							private void dumpStackTraces(int num, PrintStream out) {
								out
										.println("EclipseTestRunner almost reached timeout '"
												+ timeoutArg + "'.");
								out.println("totalMemory:            "
										+ Runtime.getRuntime().totalMemory());
								out.println("freeMemory (before GC): "
										+ Runtime.getRuntime().freeMemory());
								out.flush(); // bug 420258: flush aggressively, we could be low on memory
								System.gc();
								out.println("freeMemory (after GC):  "
										+ Runtime.getRuntime().freeMemory());
								String time = new SimpleDateFormat(
										"yyyy-MM-dd HH:mm:ss Z", Locale.US)
										.format(new Date());
								out.println("Thread dump " + num
										+ " at " + time + ":");
								out.flush();
								Map<Thread, StackTraceElement[]> stackTraces = Thread
										.getAllStackTraces();
								for (Entry<Thread, StackTraceElement[]> entry : stackTraces
										.entrySet()) {
									String name = entry.getKey().getName();
									StackTraceElement[] stack = entry
											.getValue();
									ThreadDump exception = new ThreadDump("for thread \"" + name + "\"");
									exception.setStackTrace(stack);
									exception.printStackTrace();
								}
								out.flush();
							}

							String getScreenshotFile(final int num) {
								if (!outputDirectory.exists()) {
									outputDirectory.mkdirs();
								}
								String filename = outputDirectory.getAbsolutePath()
										+ "/"
										+ classname
										+ "_screen"
										+ num
										+ ".png";
								return filename;
							}

							@SuppressWarnings("deprecation")
							private boolean dumpSwtDisplay(final int num) {
								try {
									final Display display = Display.getDefault();
									
									if (!assumeUiThreadIsResponsive) {
										String message = "trying to make UI thread respond";
										IllegalStateException toThrow = new IllegalStateException(message);
										Thread t = display.getThread();
										// Initialize the cause. Its stack trace will be that of the current thread.
										toThrow.initCause(new RuntimeException(message));
										// Set the stack trace to that of the target thread.
										toThrow.setStackTrace(t.getStackTrace());
										// Stop the thread using the specified throwable.
										try {
											t.stop(toThrow);
										} catch (UnsupportedOperationException e) {
											// Thread#stop(Throwable) doesn't work any more in JDK 8. Try stop0:
											try {
												Method stop0 = Thread.class.getDeclaredMethod("stop0", Object.class);
												stop0.setAccessible(true);
												stop0.invoke(t, toThrow);
											} catch (Exception e1) {
												e1.printStackTrace();
											}
										}
									}
	
									assumeUiThreadIsResponsive = false;
									
									display.asyncExec(new Runnable() {
										@Override
										public void run() {
											assumeUiThreadIsResponsive= true;
											
											dumpDisplayState(System.err);
											dumpDisplayState(System.out); // System.err could be blocked, see https://bugs.eclipse.org/506304
	
											// Take a screenshot:
											GC gc = new GC(display);
											final Image image = new Image(display,
													display.getBounds());
											gc.copyArea(image, 0, 0);
											gc.dispose();
	
											ImageLoader loader = new ImageLoader();
											loader.data = new ImageData[] { image
													.getImageData() };
											String filename= getScreenshotFile(num);
											loader.save(filename, SWT.IMAGE_PNG);
											System.err.println("Screenshot saved to: " + filename);
											System.out.println("Screenshot saved to: " + filename);
											image.dispose();
										}

										private void dumpDisplayState(PrintStream out) {
											// Dump focus control, parents, and
											// shells:
											Control focusControl = display
													.getFocusControl();
											if (focusControl != null) {
												out.println("FocusControl: ");
												StringBuilder indent = new StringBuilder("  ");
												do {
													out.println(indent
															.toString()
															+ focusControl);
													focusControl = focusControl
															.getParent();
													indent.append("  ");
												} while (focusControl != null);
											}
											Shell[] shells = display.getShells();
											if (shells.length > 0) {
												out.println("Shells: ");
												for (int i = 0; i < shells.length; i++) {
													Shell shell = shells[i];
													out.println((shell
															.isVisible() ? "  visible: "
															: "  invisible: ")
															+ shell);
												}
											}
											out.flush(); // for bug 420258
										}
									});
									return true;
								} catch (SWTException e) {
									e.printStackTrace();
									return false;
								}
							}
							
						}, timeout);
			} else {
				System.err
						.println("EclipseTestRunner argument error: '-timeout "
								+ timeoutArg
								+ "' was too short to accommodate time delay required ("
								+ delay + ").");
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}

	public EclipseTestRunner(JUnitTest test, String testPluginName,
			boolean haltOnError, boolean haltOnFailure) {
		fJunitTest = test;
		fTestPluginName = testPluginName;
		fHaltOnError = haltOnError;
		fHaltOnFailure = haltOnFailure;

		try {
			fSuite = getTest(test.getName());
		} catch (Exception e) {
			fRetCode = ERRORS;
			fException = e;
		}
	}

	protected Test getTest(String suiteClassName) throws TestFailedException {
		if (suiteClassName.isEmpty()) {
			clearStatus();
			return null;
		}
		Class<?> testClass = null;
		try {
			testClass = loadSuiteClass(suiteClassName);
		} catch (ClassNotFoundException e) {
			if (e.getCause() != null) {
				runFailed(e.getCause());
			}
			String clazz = e.getMessage();
			if (clazz == null)
				clazz = suiteClassName;
			runFailed("Class not found \"" + clazz + "\"");
			return null;
		} catch (Exception e) {
			runFailed(e);
			return null;
		}
		Method suiteMethod = null;
		try {
			suiteMethod = testClass.getMethod(SUITE_METHODNAME);
		} catch (Exception e) {
			// try to extract a test suite automatically
			clearStatus();
			return new junit.framework.JUnit4TestAdapter(testClass);
		}
		if (!Modifier.isStatic(suiteMethod.getModifiers())) {
			runFailed("suite() method must be static");
			return null;
		}
		Test test = null;
		try {
			test = (Test) suiteMethod.invoke(null); // static method
			if (test == null)
				return test;
		} catch (InvocationTargetException e) {
			runFailed("Failed to invoke suite():"
					+ e.getTargetException().toString());
			return null;
		} catch (IllegalAccessException e) {
			runFailed("Failed to invoke suite():" + e.toString());
			return null;
		}
		clearStatus();
		return test;
	}

	protected void runFailed(String message) throws TestFailedException {
		System.err.println(message);
		throw new TestFailedException(message);
	}

	protected void runFailed(Throwable e) throws TestFailedException {
		e.printStackTrace();
		throw new TestFailedException(e);
	}

	protected void clearStatus() {
	}

	/**
	 * Loads the class either with the system class loader or a plugin class
	 * loader if a plugin name was specified
	 */
	protected Class<?> loadSuiteClass(String suiteClassName)
			throws ClassNotFoundException {
		if (fTestPluginName == null)
			return Class.forName(suiteClassName);
		Bundle bundle = Platform.getBundle(fTestPluginName);
		if (bundle == null) {
			throw new ClassNotFoundException(suiteClassName, new Exception(
					"Could not find plugin \"" + fTestPluginName + "\""));
		}

		// is the plugin a fragment?
		Dictionary<String, String> headers = bundle.getHeaders();
		String hostHeader = headers.get(Constants.FRAGMENT_HOST);
		if (hostHeader != null) {
			// we are a fragment for sure
			// we need to find which is our host
			ManifestElement[] hostElement = null;
			try {
				hostElement = ManifestElement.parseHeader(
						Constants.FRAGMENT_HOST, hostHeader);
			} catch (BundleException e) {
				throw new RuntimeException("Could not find host for fragment:"
						+ fTestPluginName, e);
			}
			Bundle host = Platform.getBundle(hostElement[0].getValue());
			// we really want to get the host not the fragment
			bundle = host;
		}

		return bundle.loadClass(suiteClassName);
	}

	public void run() {
		// IPerformanceMonitor pm =
		// PerfMsrCorePlugin.getPerformanceMonitor(true);

		fTestResult = new TestResult();
		fTestResult.addListener(this);
		for (int i = 0; i < formatters.size(); i++) {
			fTestResult.addListener(formatters.elementAt(i));
		}

		long start = System.currentTimeMillis();
		fireStartTestSuite();

		if (fException != null) { // had an exception in the constructor
			for (int i = 0; i < formatters.size(); i++) {
				formatters.elementAt(i).addError(null, fException);
			}
			fJunitTest.setCounts(1, 0, 1);
			fJunitTest.setRunTime(0);
		} else {
			ByteArrayOutputStream errStrm = new ByteArrayOutputStream();
			fSystemError = new PrintStream(errStrm);

			ByteArrayOutputStream outStrm = new ByteArrayOutputStream();
			fSystemOut = new PrintStream(outStrm);

			try {
				// pm.snapshot(1); // before
				fSuite.run(fTestResult);
			} finally {
				// pm.snapshot(2); // after
				fSystemError.close();
				fSystemError = null;
				fSystemOut.close();
				fSystemOut = null;
				sendOutAndErr(new String(outStrm.toByteArray()), new String(
						errStrm.toByteArray()));
				fJunitTest.setCounts(fTestResult.runCount(),
						fTestResult.failureCount(), fTestResult.errorCount());
				fJunitTest.setRunTime(System.currentTimeMillis() - start);
			}
		}
		fireEndTestSuite();

		if (fRetCode != SUCCESS || fTestResult.errorCount() != 0) {
			fRetCode = ERRORS;
		} else if (fTestResult.failureCount() != 0) {
			fRetCode = FAILURES;
		}

		// pm.upload(getClass().getName());
	}

	/**
	 * Returns what System.exit() would return in the standalone version.
	 * 
	 * @return 2 if errors occurred, 1 if tests failed else 0.
	 */
	public int getRetCode() {
		return fRetCode;
	}

	@Override
	public void startTest(Test t) {
	}

	@Override
	public void endTest(Test test) {
	}

	@Override
	public void addFailure(Test test, AssertionFailedError t) {
		if (fHaltOnFailure) {
			fTestResult.stop();
		}
	}

	@Override
	public void addError(Test test, Throwable t) {
		if (fHaltOnError) {
			fTestResult.stop();
		}
	}

	private void fireStartTestSuite() {
		for (int i = 0; i < formatters.size(); i++) {
			formatters.elementAt(i).startTestSuite(fJunitTest);
		}
	}

	private void fireEndTestSuite() {
		for (int i = 0; i < formatters.size(); i++) {
			formatters.elementAt(i).endTestSuite(fJunitTest);
		}
	}

	public void addFormatter(JUnitResultFormatter f) {
		formatters.addElement(f);
	}

	/**
	 * Line format is: formatter=<classname>(,<pathname>)?
	 */
	private static void createAndStoreFormatter(String line)
			throws BuildException {
		String formatterClassName = null;
		File formatterFile = null;

		int pos = line.indexOf(',');
		if (pos == -1) {
			formatterClassName = line;
		} else {
			formatterClassName = line.substring(0, pos);
			formatterFile = new File(line.substring(pos + 1)); // the method is
																// package
																// visible
		}
		fgFromCmdLine.addElement(createFormatter(formatterClassName,
				formatterFile));
	}

	/**
	 * Line format is: formatter=<pathname>
	 */
	private static void createAndStoreFormatter(String line,
			String... suiteClassesNames) throws BuildException {
		String formatterClassName = null;
		File formatterFile = null;

		int pos = line.indexOf(',');
		if (pos == -1) {
			formatterClassName = line;
		} else {
			formatterClassName = line.substring(0, pos);
		}
		File outputDirectory = new File(line.substring(pos + 1));
		outputDirectory.mkdir();
		for (String suiteClassName : suiteClassesNames) {

			String pathname = "TEST-" + suiteClassName + ".xml";
			if (outputDirectory.exists()) {
				pathname = outputDirectory.getAbsolutePath() + "/" + pathname;
			}
			formatterFile = new File(pathname);
			fgFromCmdLine.addElement(createFormatter(formatterClassName,
					formatterFile));
		}

	}

	private static void transferFormatters(EclipseTestRunner runner, int j) {
		runner.addFormatter(fgFromCmdLine.elementAt(j));
	}

	private static void transferFormatters(EclipseTestRunner runner) {
		for (int i = 0; i < fgFromCmdLine.size(); i++) {
			runner.addFormatter(fgFromCmdLine.elementAt(i));
		}
	}

	/*
	 * DUPLICATED from FormatterElement, since it is package visible only
	 */
	private static JUnitResultFormatter createFormatter(String classname,
			File outfile) throws BuildException {
		OutputStream out = System.out;

		if (classname == null) {
			throw new BuildException("you must specify type or classname");
		}
		Class<?> f = null;
		try {
			f = EclipseTestRunner.class.getClassLoader().loadClass(classname);
		} catch (ClassNotFoundException e) {
			throw new BuildException(e);
		}

		Object o = null;
		try {
			o = f.getDeclaredConstructor().newInstance();
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
				| NoSuchMethodException | SecurityException e) {
			throw new BuildException(e);
		}

		if (!(o instanceof JUnitResultFormatter)) {
			throw new BuildException(classname
					+ " is not a JUnitResultFormatter");
		}

		JUnitResultFormatter r = (JUnitResultFormatter) o;

		if (outfile != null) {
			try {
				out = new FileOutputStream(outfile);
			} catch (java.io.IOException e) {
				throw new BuildException(e);
			}
		}
		r.setOutput(out);
		return r;
	}

	public static void dumpAwtScreenshot(String screenshotFile) {
		try {
			URL location= AwtScreenshot.class.getProtectionDomain().getCodeSource().getLocation();
			String cp= location.toURI().getPath();
			String javaHome= System.getProperty("java.home");
			String javaExe= javaHome + File.separatorChar + "bin" + File.separatorChar + "java";
			if (File.separatorChar == '\\') {
				javaExe+= ".exe"; // assume it's Windows
			}
			String[] args = new String[] { javaExe, "-cp", cp, AwtScreenshot.class.getName(), screenshotFile };
			System.err.println("Start process: " + Arrays.asList(args));
			ProcessBuilder processBuilder = new ProcessBuilder(args);
			if ("Mac OS X".equals(System.getProperty("os.name"))) {
				processBuilder.environment().put("AWT_TOOLKIT", "CToolkit");
			}
			Process process= processBuilder.start();
			new StreamForwarder(process.getErrorStream(), System.err).start();
			new StreamForwarder(process.getInputStream(), System.err).start();
			int screenshotTimeout= 15;
			long end= System.currentTimeMillis() + screenshotTimeout * 1000;
			boolean done= false;
			do {
				try {
					process.exitValue();
					done= true;
				} catch (IllegalThreadStateException e) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e1) {
					}
				}
			} while (!done && System.currentTimeMillis() < end);
			
			if (done) {
				System.err.println("AwtScreenshot VM finished with exit code " + process.exitValue() + ".");
			} else {
				process.destroy();
				System.err.println("Killed AwtScreenshot VM after " + screenshotTimeout + " seconds.");
			}
		} catch (URISyntaxException|IOException e) {
			e.printStackTrace();
		}
	}

	private void sendOutAndErr(String out, String err) {
		for (int i = 0; i < formatters.size(); i++) {
			JUnitResultFormatter formatter = formatters.elementAt(i);

			formatter.setSystemOutput(out);
			formatter.setSystemError(err);
		}
	}

	protected void handleOutput(String line) {
		if (fSystemOut != null) {
			fSystemOut.println(line);
		}
	}

	protected void handleErrorOutput(String line) {
		if (fSystemError != null) {
			fSystemError.println(line);
		}
	}
}
