Index: trunk/quest-jfcmonitor/.classpath
===================================================================
--- trunk/quest-jfcmonitor/.classpath	(revision 823)
+++ trunk/quest-jfcmonitor/.classpath	(revision 823)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
Index: trunk/quest-jfcmonitor/.project
===================================================================
--- trunk/quest-jfcmonitor/.project	(revision 823)
+++ trunk/quest-jfcmonitor/.project	(revision 823)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>JFCMonitor</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: trunk/quest-jfcmonitor/pom.xml
===================================================================
--- trunk/quest-jfcmonitor/pom.xml	(revision 823)
+++ trunk/quest-jfcmonitor/pom.xml	(revision 823)
@@ -0,0 +1,27 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>de.ugoe.cs.quest</groupId>
+	<artifactId>quest-jfcmonitor</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<name>quest-jfcmonitor</name>
+	<dependencies>
+		<dependency>
+			<groupId>de.ugoe.cs</groupId>
+			<artifactId>java-utils</artifactId>
+			<version>0.0.1-SNAPSHOT</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>
Index: trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JFCComponent.java
===================================================================
--- trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JFCComponent.java	(revision 823)
+++ trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JFCComponent.java	(revision 823)
@@ -0,0 +1,338 @@
+
+package de.ugoe.cs.eventbench.jfcmonitor;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.InvalidParameterException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.accessibility.AccessibleContext;
+
+import de.ugoe.cs.util.StringTools;
+
+/**
+ * <p>
+ * This class manages information about the current GUI. It always contains the current GUI
+ * hierarchy.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class JFCComponent {
+
+    /**
+     * <p>
+     * Map of all known GUI components.
+     * </p>
+     */
+    private static Map<Component, JFCComponent> knownComponents =
+        new HashMap<Component, JFCComponent>();
+
+    /**
+     * <p>
+     * Adds a AWT component to the GUI hierarchy. If the component already exists in the hierarchy,
+     * it is not added a second time.
+     * </p>
+     * 
+     * @param component
+     *            component that is added
+     */
+    public static void add(Component component) {
+        add(component, find(component.getParent()));
+    }
+
+    /**
+     * <p>
+     * Adds a AWT component to the GUI hierarchy. If the component already exists in the hierarchy,
+     * it is not added a second time.
+     * </p>
+     * 
+     * @param component
+     *            component that is added
+     * @param parent
+     *            parent of the component
+     */
+    public static void add(Component component, JFCComponent parent) {
+        if (!knownComponents.containsKey(component)) {
+            knownComponents.put(component, new JFCComponent(component, parent));
+        }
+    }
+
+    /**
+     * <p>
+     * Finds a component in the GUI hierarchy and returns the corresponding JFComponent instance.
+     * Returns null if the component is not found.
+     * </p>
+     * 
+     * @param component
+     *            component that is searched for
+     * @return corresponding JFComponent instance; null if the compenent is not found
+     */
+    public static JFCComponent find(Component component) {
+        return knownComponents.get(component);
+    }
+
+    /**
+     * <p>
+     * Removes a component from the GUI hierarchy. In case the component is not part of the known
+     * hierachy, nothing happens.
+     * </p>
+     * 
+     * @param component
+     *            component to be removed
+     */
+    public static void remove(Component component) {
+        JFCComponent jfcComponent = knownComponents.remove(component);
+        if (jfcComponent != null) {
+            jfcComponent.removeFromParent();
+            jfcComponent.removeChildren();
+        }
+    }
+
+    /**
+     * <p>
+     * Parent of the GUI component. null means, that the component has no parent.
+     * </p>
+     */
+    private JFCComponent parent = null;
+
+    /**
+     * <p>
+     * Child components of the component.
+     * </p>
+     */
+    private List<JFCComponent> children = new LinkedList<JFCComponent>();
+
+    /**
+     * <p>
+     * Reference to the actual GUI component.
+     * </p>
+     */
+    private Component component;
+
+    /**
+     * <p>
+     * Helper attribute that contains the title of the component. Set by {@link #setTitle()}.
+     * </p>
+     */
+    private String title = null;
+
+    /**
+     * <p>
+     * Helper attribute that contains the class of the component. Set by {@link #setClass()}.
+     * </p>
+     */
+    private String componentClass = null;
+
+    /**
+     * <p>
+     * Helper attribute that contains the icon of the component. Set by {@link #setIcon()}.
+     * </p>
+     */
+    private String icon = null;
+
+    /**
+     * <p>
+     * Helper attribute that contains the icon of the component. Set by {@link #setIndex()}.
+     * </p>
+     */
+    private int index = -1;
+
+    /**
+     * <p>
+     * Constructor. Creates a new JFCComponent. Only used internally by
+     * {@link #add(Component, JFCComponent)}.
+     * </p>
+     * 
+     * @param component
+     *            component associated with the JFCComponent
+     * @param parent
+     *            parent of the component; null if there is no parent
+     */
+    private JFCComponent(Component component, JFCComponent parent) {
+        if (component == null) {
+            throw new InvalidParameterException("parameter component must not be null");
+        }
+        this.component = component;
+        this.parent = parent;
+        if (parent != null) {
+            parent.addChild(this);
+        }
+
+        if (component instanceof Container) {
+            for (Component childComponent : ((Container) component).getComponents()) {
+                add(childComponent, this);
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Adds a child component to the current component.
+     * </p>
+     * 
+     * @param child
+     *            child component to be added
+     */
+    private void addChild(JFCComponent child) {
+        children.add(child);
+    }
+
+    /**
+     * <p>
+     * Returns an XML representation of the component.
+     * </p>
+     * 
+     * @return XLM snippet
+     */
+    public String getXML() {
+        setClass();
+        setIcon();
+        setIndex();
+        setTitle();
+        StringBuilder builder = new StringBuilder();
+        if (parent != null) {
+            builder.append(parent.getXML());
+        }
+        builder.append("  <component>" + StringTools.ENDLINE);
+        builder.append("   <param name=\"title\" value=\"" + title + "\" />" + StringTools.ENDLINE);
+        builder.append("   <param name=\"class\" value=\"" + componentClass + "\" />" +
+            StringTools.ENDLINE);
+        builder.append("   <param name=\"icon\" value=\"" + icon + "\" />" + StringTools.ENDLINE);
+        builder.append("   <param name=\"index\" value=\"" + index + "\" />" + StringTools.ENDLINE);
+        builder.append("   <param name=\"hash\" value=\"" +
+            Integer.toHexString(component.hashCode()) + "\" />" + StringTools.ENDLINE);
+        builder.append("  </component>" + StringTools.ENDLINE);
+        return builder.toString();
+    }
+
+    /**
+     * <p>
+     * Removes a child component from the current component.
+     * </p>
+     * 
+     * @param child
+     *            child component to be removed
+     */
+    private void removeChild(JFCComponent child) {
+        children.remove(child);
+    }
+
+    /**
+     * <p>
+     * Removes the component from the list of children of its parent.
+     * </p>
+     */
+    private void removeFromParent() {
+        if (parent != null) {
+            parent.removeChild(this);
+        }
+    }
+
+    /**
+     * <p>
+     * Triggers the removals of all child components from the GUI hierarchy, i.e., calls
+     * {@link #remove(Component)} for all child components.
+     * </p>
+     */
+    private void removeChildren() {
+        for (JFCComponent child : children) {
+            remove(child.component);
+        }
+    }
+
+    /**
+     * <p>
+     * Sets the {@link #title} of the component. The title is defined as follows (first in the list,
+     * that is not null):
+     * <ul>
+     * <li>accessible name of the component if available</li>
+     * <li>{@link #icon} of the component</li>
+     * <li>name of the component</li>
+     * <li>coordinates of the component</li>
+     * </ul>
+     * </p>
+     */
+    private void setTitle() {
+        title = null; // reset title
+
+        AccessibleContext accessibleContext = component.getAccessibleContext();
+        if (accessibleContext != null) {
+            title = accessibleContext.getAccessibleName();
+        }
+        if (title == null) {
+            title = icon;
+        }
+        if (title == null) {
+            title = component.getName();
+        }
+        if (title == null) {
+            // use coordinates as last resort
+            title = "Pos(" + component.getX() + "," + component.getY() + ")";
+        }
+    }
+
+    /**
+     * <p>
+     * Sets the {@link #componentClass} of the component.
+     * </p>
+     */
+    private void setClass() {
+        componentClass = component.getClass().getName();
+    }
+
+    /**
+     * <p>
+     * Sets the {@link #icon} of the component.
+     * </p>
+     */
+    private void setIcon() {
+        icon = null; // reset icon
+
+        Method getIconMethod;
+        try {
+            getIconMethod = component.getClass().getMethod("getIcon", new Class[0]);
+            if (getIconMethod != null) {
+                Object iconObject = getIconMethod.invoke(component, new Object[] { });
+                if (iconObject != null) {
+                    String iconPath = iconObject.toString();
+                    if (!iconPath.contains("@")) {
+                        System.out.println("iconPath");
+                        String[] splitResult =
+                            iconPath.split(File.separatorChar == '\\' ? "\\\\" : File.separator);
+                        icon = splitResult[splitResult.length - 1];
+                    }
+                }
+            }
+        }
+        catch (SecurityException e) {}
+        catch (NoSuchMethodException e) {}
+        catch (IllegalArgumentException e) {}
+        catch (IllegalAccessException e) {}
+        catch (InvocationTargetException e) {
+            System.err.println("Found method with name " + "getIcon" + " but could not access it.");
+        }
+    }
+
+    /**
+     * <p>
+     * Sets the {@link #index} of the component as the index in the parent, if it is accessible.
+     * </p>
+     */
+    private void setIndex() {
+        index = -1; // reset index
+
+        AccessibleContext accessibleContext = component.getAccessibleContext();
+        if (accessibleContext != null) {
+            index = accessibleContext.getAccessibleIndexInParent();
+        }
+    }
+
+}
Index: trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JFCListener.java
===================================================================
--- trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JFCListener.java	(revision 823)
+++ trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JFCListener.java	(revision 823)
@@ -0,0 +1,149 @@
+
+package de.ugoe.cs.eventbench.jfcmonitor;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.event.AWTEventListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import de.ugoe.cs.util.StringTools;
+
+/**
+ * <p>
+ * This class implements monitoring of AWT and Swing mouse and keyboard events. Each of the events
+ * is written to an output stream.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class JFCListener implements AWTEventListener {
+
+    /**
+     * <p>
+     * Writer for logging events.
+     * </p>
+     */
+    final private OutputStreamWriter outputWriter;
+
+    /**
+     * <p>
+     * Constructor. Creates a new JFCListener with a given {@link OutputStreamWriter}, where the
+     * monitored information is logged.
+     * </p>
+     * 
+     * @param outputWriter
+     *            writer for the logged information
+     */
+    public JFCListener(OutputStreamWriter outputWriter) {
+        this.outputWriter = outputWriter;
+        try {
+            outputWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + StringTools.ENDLINE);
+            outputWriter.write("<sessions>" + StringTools.ENDLINE);
+        }
+        catch (IOException e) {
+            System.err.println("JFCMONITOR -- Failure writing to log: " + e.getMessage());
+        }
+    }
+
+    /**
+     * <p>
+     * Writes all received {@link MouseEvent}s and {@link KeyEvent}s to the {@link #outputWriter}.
+     * </p>
+     * 
+     * @see java.awt.event.AWTEventListener#eventDispatched(java.awt.AWTEvent)
+     */
+    @Override
+    public void eventDispatched(AWTEvent event) {
+        StringBuilder builder = new StringBuilder();
+
+        if (event instanceof MouseEvent) {
+            if (!isMouseMovement(event.getID())) {
+                MouseEvent mouseEvent = (MouseEvent) event;
+                builder.append("<event id=\"" + event.getID() + "\">" + StringTools.ENDLINE);
+                builder.append(" <param name=\"X\" value=\"" + mouseEvent.getX() + "\" />" +
+                    StringTools.ENDLINE);
+                builder.append(" <param name=\"Y\" value=\"" + mouseEvent.getY() + "\" />" +
+                    StringTools.ENDLINE);
+                builder.append(" <param name=\"Button\" value=\"" + mouseEvent.getButton() +
+                    "\" />" + StringTools.ENDLINE);
+                builder.append(" <param name=\"Modifiers\" value=\"" + mouseEvent.getModifiers() +
+                    "\" />" + StringTools.ENDLINE);
+                addSourceInfo(builder, event);
+                builder.append("</event>" + StringTools.ENDLINE);
+            }
+        }
+        else if (event instanceof KeyEvent) {
+            if (event.getID() == KeyEvent.KEY_PRESSED || event.getID() == KeyEvent.KEY_RELEASED) {
+                KeyEvent keyEvent = (KeyEvent) event;
+                builder.append("<event id=\"" + event.getID() + "\">" + StringTools.ENDLINE);
+                builder.append(" <param name=\"KeyCode\" value=\"" + keyEvent.getKeyCode() +
+                    "\" />" + StringTools.ENDLINE);
+                builder.append(" <param name=\"Modifiers\" value=\"" + keyEvent.getModifiers() +
+                    "\" />" + StringTools.ENDLINE);
+                addSourceInfo(builder, event);
+                builder.append("</event>" + StringTools.ENDLINE);
+            }
+        }
+        else if (event instanceof FocusEvent) {
+            if (event.getID() == FocusEvent.FOCUS_GAINED) {
+                builder.append("<event id=\"" + event.getID() + "\">" + StringTools.ENDLINE);
+                addSourceInfo(builder, event);
+                builder.append("</event>" + StringTools.ENDLINE);
+            }
+        }
+        if (builder.length() > 0 && outputWriter != null) {
+            try {
+                outputWriter.write(builder.toString());
+                outputWriter.flush();
+            }
+            catch (IOException e) {
+                System.err.println("JFCMONITOR -- Failure writing to log: " + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Appends information about the event to a {@link StringBuilder}.
+     * </p>
+     * 
+     * @param builder
+     *            {@link StringBuilder} where the information is appended
+     * @param event
+     *            event whose information is appended
+     */
+    private void addSourceInfo(StringBuilder builder, AWTEvent event) {
+        builder.append(" <source>" + StringTools.ENDLINE);
+        builder.append("  <param name=\"toString\" value=\"" +
+            StringTools.xmlEntityReplacement(event.getSource().toString()) + "\" />" +
+            StringTools.ENDLINE);
+        if (event.getSource() instanceof Component) {
+            Component source = (Component) event.getSource();
+            JFCComponent jfcComponent = JFCComponent.find(source);
+            if (jfcComponent != null) {
+                builder.append(jfcComponent.getXML());
+            }
+        }
+        builder.append(" </source>" + StringTools.ENDLINE);
+    }
+
+    /**
+     * <p>
+     * Checks if the Id of an {@link AWTEvent} is a mouse movement Id.
+     * </p>
+     * 
+     * @param eventId
+     *            id of the {@link AWTEvent}
+     * @return true, if the event is a mouse movement event; false otherwise
+     */
+    private boolean isMouseMovement(int eventId) {
+        return eventId == MouseEvent.MOUSE_MOVED || eventId == MouseEvent.MOUSE_DRAGGED ||
+            eventId == MouseEvent.MOUSE_ENTERED || eventId == MouseEvent.MOUSE_EXITED;
+    }
+
+}
Index: trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JarLauncher.java
===================================================================
--- trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JarLauncher.java	(revision 823)
+++ trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JarLauncher.java	(revision 823)
@@ -0,0 +1,271 @@
+
+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.Arrays;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+/**
+ * <p>
+ * Class that launches an executable Jar-file in the same thread and VM where the JarLauncher
+ * instance is created. The requirements on the Jar file are:
+ * <li>Must contain a MANIFEST.</li>
+ * <li>The MANIFEST must define the main-class of the application ("Main-Class" entry).</li>
+ * <li>The MANIFEST must define the classpath of the application ("Class-Path" entry).</li>
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class JarLauncher {
+
+    /**
+     * <p>
+     * Name of the Jar file to be executed.
+     * </p>
+     */
+    private String jarfile;
+
+    /**
+     * <p>
+     * Arguments for launching the Jar file.
+     * </p>
+     */
+    private String[] args;
+
+    /**
+     * <p>
+     * Helper variable with the path to the working directory.
+     * </p>
+     */
+    final String workingDir = System.getProperty("user.dir") + "/";
+
+    /**
+     * <p>
+     * Internal variable used to store the classpath extracted from the Jar file's MANIFEST.
+     * </p>
+     */
+    private String[] classPath = new String[] { };
+
+    /**
+     * <p>
+     * Internal variable used to store the name (including package information) of the Jar file's
+     * main function extracted from the Jar file's MANIFEST.
+     * </p>
+     */
+    private String mainClassName = "";
+
+    /**
+     * <p>
+     * Inner class that defines an exception that is thrown if launching the application in the Jar
+     * file fails.
+     * </p>
+     * 
+     * @author Steffen Herbold
+     * @version 1.0
+     */
+    private static class JarLaunchException extends Exception {
+
+        /**
+         * <p>
+         * Id for object serialization.
+         * </p>
+         */
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * <p>
+         * Constructor. Creates a new JarLaunchException.
+         * </p>
+         * 
+         * @param string
+         *            error message of the exception
+         */
+        public JarLaunchException(String string) {
+            super(string);
+        }
+
+        /**
+         * <p>
+         * Constructor. Creates a new JarLaunchException as a copy of an existing exception.
+         * </p>
+         * 
+         * @param e
+         *            exception that is copied
+         */
+        public JarLaunchException(Exception e) {
+            super(e);
+        }
+
+    }
+
+    /**
+     * <p>
+     * Constructor. Creates a new JarLauncher.
+     * </p>
+     * 
+     * @param jarfile
+     *            file to be launched; must not be complete path but in relation to the current
+     *            working directory
+     * @param args
+     *            arguments with which the main function of the Jar file is called
+     */
+    public JarLauncher(String jarfile, String[] args) {
+        this.jarfile = jarfile;
+        this.args = Arrays.copyOf(args, args.length);
+    }
+
+    /**
+     * <p>
+     * Executes the main function of the Jar file associated with this launcher.
+     * </p>
+     */
+    public void exec() {
+        try {
+            getInfoFromJar();
+            initClassLoader();
+            runMain();
+        }
+        catch (JarLaunchException e) {
+            System.err.println("Failure to launch application.");
+            System.err.println(e.getMessage());
+        }
+    }
+
+    /**
+     * <p>
+     * Retrieves the classpath and main function from the Jar file's MANIFEST.
+     * </p>
+     * 
+     * @throws JarLaunchException
+     *             thrown if reading of Jar file or MANIFEST fails
+     */
+    private void getInfoFromJar() throws JarLaunchException {
+        JarInputStream jarInputStream;
+        try {
+            jarInputStream = new JarInputStream(new FileInputStream(workingDir + jarfile));
+        }
+        catch (FileNotFoundException e) {
+            throw new JarLaunchException(e);
+        }
+        catch (IOException e) {
+            throw new JarLaunchException(e);
+        }
+        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];
+        }
+        try {
+            jarInputStream.close();
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * <p>
+     * Modifies the {@link ClassLoader} of the current VM such that it includes the class path
+     * defined in the Jar file's MANIFEST.
+     * </p>
+     * 
+     * @throws JarLaunchException
+     *             thrown if modification of {@link ClassLoader} fails.
+     */
+    private void initClassLoader() throws JarLaunchException {
+        URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+        Method method;
+        try {
+            method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]
+                { URL.class });
+        }
+        catch (SecurityException e) {
+            throw new JarLaunchException(
+                                         "addURL method of URLClassLoader not accessible via reflection.");
+        }
+        catch (NoSuchMethodException e) {
+            throw new JarLaunchException(
+                                         "URLClassLoader does not have addURL method. Should be impossible!!");
+        }
+        method.setAccessible(true);
+
+        try {
+            method.invoke(classLoader, new Object[]
+                { new URL("file:" + workingDir + jarfile) });
+            for (String element : classPath) {
+                method.invoke(classLoader, new Object[]
+                    { new URL(element) });
+            }
+        }
+        catch (IllegalArgumentException e) {
+            throw new JarLaunchException(
+                                         "Illegal arguments for addURL method. Should be impossible!!");
+        }
+        catch (MalformedURLException e) {
+            throw new JarLaunchException(e);
+        }
+        catch (IllegalAccessException e) {
+            throw new JarLaunchException(
+                                         "addURL method of URLClassLoader not accessible via reflection.");
+        }
+        catch (InvocationTargetException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * <p>
+     * Executes the main function.
+     * </p>
+     * 
+     * @throws JarLaunchException
+     *             thrown if execution of main function fails or the main function itself throws an
+     *             exception
+     */
+    private void runMain() throws JarLaunchException {
+        Class<?> mainClass;
+        try {
+            mainClass = Class.forName(mainClassName);
+        }
+        catch (ClassNotFoundException e) {
+            throw new JarLaunchException("Main class not found: " + mainClassName);
+        }
+        Method mainMethod;
+        try {
+            mainMethod = mainClass.getMethod("main", new Class[]
+                { String[].class });
+        }
+        catch (SecurityException e) {
+            throw new JarLaunchException("Main method not accessible.");
+        }
+        catch (NoSuchMethodException e) {
+            throw new JarLaunchException("Main method not found.");
+        }
+        try {
+            mainMethod.invoke(null, new Object[]
+                { args });
+        }
+        catch (IllegalArgumentException e) {
+            throw new JarLaunchException(
+                                         "Illegal arguments for main method. Should be impossible!!");
+        }
+        catch (IllegalAccessException e) {
+            throw new JarLaunchException("Main method not accessible.");
+        }
+        catch (InvocationTargetException e) {
+            throw new JarLaunchException(e);
+        }
+    }
+}
Index: trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/Runner.java
===================================================================
--- trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/Runner.java	(revision 823)
+++ trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/Runner.java	(revision 823)
@@ -0,0 +1,86 @@
+
+package de.ugoe.cs.eventbench.jfcmonitor;
+
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+import java.awt.event.AWTEventListener;
+import java.awt.event.FocusEvent;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+/**
+ * <p>
+ * Start-up class of the application.
+ * </p>
+ * <p>
+ * Launches the application under test in the same JVM.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class Runner {
+
+    /**
+     * <p>
+     * Debugging variable. If set to true, the logging is also written to the console.
+     * </p>
+     */
+    private final static boolean stdOutputWrite = true;
+
+    /**
+     * <p>
+     * Main method of the application.
+     * </p>
+     * 
+     * @param args
+     *            the first parameter defines the Jar file that contains the start-up information of
+     *            the application under test. The remaining parameters are passed on the toe
+     *            application under test.
+     */
+    public static void main(String[] args) {
+        String logfileName = "jfcmonitor_" + System.currentTimeMillis() + ".log";
+
+        FileOutputStream fis;
+        OutputStreamWriter writer;
+        try {
+            // the writer is not closed explicitly!
+            fis = new FileOutputStream(logfileName, true);
+            writer = new OutputStreamWriter(fis, "UTF-16");
+        }
+        catch (IOException e) {
+            System.err.println("JFCMONITOR -- failure opening logfile: " + e.getMessage());
+            return;
+        }
+
+        AWTEventListener listenerFile = new JFCListener(writer);
+        Toolkit.getDefaultToolkit().addAWTEventListener(listenerFile, AWTEvent.KEY_EVENT_MASK);
+        Toolkit.getDefaultToolkit().addAWTEventListener(listenerFile, AWTEvent.MOUSE_EVENT_MASK);
+        Toolkit.getDefaultToolkit().addAWTEventListener(listenerFile, FocusEvent.FOCUS_EVENT_MASK);
+        Toolkit.getDefaultToolkit().addAWTEventListener(new WindowMonitor(),
+                                                        AWTEvent.WINDOW_EVENT_MASK);
+
+        if (stdOutputWrite) {
+            AWTEventListener listenerStdOut;
+            try {
+                listenerStdOut = new JFCListener(new OutputStreamWriter(System.out, "UTF-8"));
+                Toolkit.getDefaultToolkit().addAWTEventListener(listenerStdOut,
+                                                                AWTEvent.KEY_EVENT_MASK);
+                Toolkit.getDefaultToolkit().addAWTEventListener(listenerStdOut,
+                                                                AWTEvent.MOUSE_EVENT_MASK);
+                Toolkit.getDefaultToolkit().addAWTEventListener(listenerStdOut,
+                                                                FocusEvent.FOCUS_EVENT_MASK);
+            }
+            catch (UnsupportedEncodingException e) {
+                System.err
+                    .println("JFCMONITOR -- failure to create OutputStreamWriter with UTF-8 encoding to System.out");
+            }
+        }
+
+        JarLauncher launcher = new JarLauncher(args[0], Arrays.copyOfRange(args, 1, args.length));
+        launcher.exec();
+    }
+}
Index: trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/WindowMonitor.java
===================================================================
--- trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/WindowMonitor.java	(revision 823)
+++ trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/WindowMonitor.java	(revision 823)
@@ -0,0 +1,46 @@
+
+package de.ugoe.cs.eventbench.jfcmonitor;
+
+import java.awt.AWTEvent;
+import java.awt.Window;
+import java.awt.event.AWTEventListener;
+import java.awt.event.WindowEvent;
+
+/**
+ * <p>
+ * An AWT event listener responsible to monitor the window creation and destruction.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class WindowMonitor implements AWTEventListener {
+
+    /**
+     * <p>
+     * Adds all created windows (and their child components) to the GUI hierarchy maintained by
+     * {@link JFCComponent} and removes them if a window is destroyed.
+     * </p>
+     * </p>
+     * 
+     * @see java.awt.event.AWTEventListener#eventDispatched(java.awt.AWTEvent)
+     */
+    @Override
+    public void eventDispatched(AWTEvent event) {
+        Window window;
+        switch (event.getID())
+        {
+            case WindowEvent.WINDOW_OPENED:
+                window = ((WindowEvent) event).getWindow();
+                JFCComponent.add(window);
+                break;
+            case WindowEvent.WINDOW_CLOSED:
+                window = ((WindowEvent) event).getWindow();
+                JFCComponent.remove(window);
+                break;
+            default:
+                break;
+        }
+    }
+
+}
