/******************************************************************************* * Copyright (c) 2012 Google, Inc. * 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: * Google, Inc. - initial API and implementation *******************************************************************************/ package com.windowtester.internal.runtime.junit.core.launcher; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.windowtester.internal.debug.LogHandler; import com.windowtester.internal.runtime.junit.core.ISequenceRunner.IRunnable; /** * A factory for Application launchers. */ public class LauncherFactory { /** * Abstract base launcher implementation. */ static abstract class AbstractLauncher implements IApplicationLauncher { List _listeners = new ArrayList(); /* (non-Javadoc) * @see junit.extensions.core.launcher.IApplicationLauncher#addListener(junit.extensions.core.launcher.ILaunchListener) */ public void addListener(ILaunchListener listener) { _listeners.add(listener); } /** * Notify listeners post launch. */ protected void notifyPostLaunch() { for (Iterator iter = _listeners.iterator(); iter.hasNext();) { ILaunchListener listener = (ILaunchListener) iter.next(); listener.postFlight(); } } /** * Notify listeners pre launch. */ protected void notifyPreLaunch() { for (Iterator iter = _listeners.iterator(); iter.hasNext();) { ILaunchListener listener = (ILaunchListener) iter.next(); listener.preFlight(); } } } /** * A special launcher that does nothing (presumably because the application * is bootstrapped elsewhere). * */ static class NoOpLauncher extends AbstractLauncher { /* (non-Javadoc) * @see com.windowtester.runtime.test.launcher.IApplicationLauncher#launch() */ public void launch() { //do nothing } } /** * A launcher that spawns another thread in which to execute. * Note that pre and post launch notifications occur before and after * the thread is started respectively. */ static class SeparateThreadLauncher extends AbstractLauncher { private final IRunnable _runnable; public SeparateThreadLauncher(IRunnable runnable) { _runnable = runnable; } /* (non-Javadoc) * @see com.windowtester.runtime.test.launcher.LauncherFactory.AbstractLauncher#doLaunch() */ public void launch() { notifyPreLaunch(); Thread t = new Thread(new Runnable() { public void run() { try { _runnable.run(); } catch (Throwable e) { e.printStackTrace(); LogHandler.log(e); } } }); t.start(); notifyPostLaunch(); } } /** * A launcher that invokes the main method of a class in a separate * thread. */ static class MainRunner extends SeparateThreadLauncher { public MainRunner(final Class launchClass, final String[] launchArgs) { super(new IRunnable() { public void run() throws Throwable { Object[] realArgs; String[] nullArgs = new String[0]; Method main = launchClass.getMethod("main", new Class[] { String[].class }); // instead pass null string if (launchArgs == null) realArgs = new Object[] {nullArgs}; else realArgs = new Object[]{launchArgs}; // main.setAccessible(true); main.invoke(null, realArgs); } }); } } /** * Launcher factory method; creates a launcher appropriate for the given * arguments. * @param launchClass the class to launch (may be <code>null</code>) * @param launchArgs the program arguments to pass to the launched class (may be <code>null</code>) * @return a launcher appropriate to the given arguments */ public static IApplicationLauncher create(Class launchClass, String[] launchArgs) { if (launchClass == null) return new NoOpLauncher(); return new MainRunner(launchClass, launchArgs); } }