Index: /trunk/autoquest-generic-event-monitor-test/src/test/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorServerTest.java
===================================================================
--- /trunk/autoquest-generic-event-monitor-test/src/test/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorServerTest.java	(revision 2159)
+++ /trunk/autoquest-generic-event-monitor-test/src/test/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorServerTest.java	(revision 2159)
@@ -0,0 +1,649 @@
+//   Copyright 2012 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+package de.ugoe.cs.autoquest.genericeventmonitor;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.ugoe.cs.autoquest.genericeventmonitor.ClientInfos;
+import de.ugoe.cs.autoquest.genericeventmonitor.GenericEvent;
+import de.ugoe.cs.autoquest.genericeventmonitor.GenericEventMonitorMessageListener;
+import de.ugoe.cs.autoquest.genericeventmonitor.GenericEventMonitorServer;
+import de.ugoe.cs.autoquest.genericeventmonitor.GenericEventTarget;
+import de.ugoe.cs.util.console.TextConsole;
+
+/**
+ *
+ * @author Patrick Harms
+ */
+public class GenericEventMonitorServerTest implements GenericEventMonitorMessageListener {
+    
+    /**
+     * 
+     */
+    public static final TextConsole CONSOLE = new TextConsole();
+    
+    /**
+     * 
+     */
+    private static final int PORT = 19098;
+
+    /**
+     * 
+     */
+    private GenericEvent[] events;
+
+    /**
+     * 
+     */
+    private GenericEventTarget[] eventTargetStructures;
+
+    /**
+     * 
+     */
+    private String eventHandlingError;
+
+    /**
+     * 
+     */
+    private GenericEventMonitorServer server;
+
+    /**
+     * 
+     */
+    @Before
+    public void setUp() throws Exception {
+        server = new GenericEventMonitorServer(PORT, this);
+        server.init();
+        server.start();
+    }
+    
+    /**
+     * 
+     */
+    @After
+    public void tearDown() throws Exception {
+        events = null;
+        eventHandlingError = null;
+
+        if (server != null) {
+            try {
+                server.stop();
+            }
+            finally {
+                server = null;
+            }
+        }
+    }
+    
+
+    /**
+     * 
+     */
+    @Test
+    public void testSimpleMessage() throws Exception {
+        String clientId = "123";
+        String appId = "456";
+        
+        String message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"" + clientId + "\"," +
+            "      \"appId\":\"" + appId + "\"," +
+            "    }," +
+            "    \"targetStructure\": [{" +
+            "      \"targetId\":\"target1\"," +
+            "      \"param1\":\"value1\"," +
+            "      \"param3\":\"value3\"," +
+            "      \"param2\":\"value2\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"targetId\":\"target3\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"targetId\":\"target2\"," +
+            "          \"htmlId\":\"gsr\"," +
+            "        }" +
+            "      ]" +
+            "    }]," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"12345\"," +
+            "        \"eventTargetId\":\"target2\"," +
+            "        \"eventType\":\"gaze\"," +
+            "        \"xcoordinate\": \"194\"," +
+            "        \"ycoordinate\": \"12\"" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+        
+        sendMessageAndAssertResponse(message);
+        
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+        
+        // check the target structure
+        GenericEventTarget parent = null;
+        
+        assertEquals(1, eventTargetStructures.length);
+        GenericEventTarget target = eventTargetStructures[0];
+        
+        assertTarget(target, parent, 2, new String[] {"param1", "value1"},
+                     new String[] {"param2", "value2"},
+                     new String[] {"param3", "value3"});
+        
+        parent = target;
+        target = parent.getChildren().get(0);
+        assertTarget(target, parent, 0, new String[] {"index", "0"});
+        target = parent.getChildren().get(1);
+        assertTarget(target, parent, 0, new String[] {"htmlId", "gsr"});
+
+        // check the event
+        assertNotNull(events);
+        assertEquals(1, events.length);
+        
+        assertEvent(0, 12345, target, "gaze", new String[] {"xcoordinate", "194"},
+                    new String[] {"ycoordinate", "12"});
+        
+    }
+
+    /**
+     * 
+     */
+    @Test
+    public void testComplexMessage() throws Exception {
+        String clientId = "123";
+        String appId = "456";
+        
+        String message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"" + clientId + "\"," +
+            "      \"appId\":\"" + appId + "\"," +
+            "    }," +
+            "    \"targetStructure\": [{" +
+            "      \"targetId\":\"html\"," +
+            "      \"index\":\"0\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"targetId\":\"head\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"tagName\":\"body\"," +
+            "          \"targetId\":\"gsr\"," +
+            "          \"children\":" +
+            "          [ {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input1\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input2\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input3\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input4\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input5\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input6\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input7\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input8\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input9\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input10\"," +
+            "            }," +
+            "          ]" +
+            "        }" +
+            "      ]" +
+            "    }]," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"1\"," +
+            "        \"eventTargetId\":\"input1\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"194\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"2\"," +
+            "        \"eventTargetId\":\"input2\"," +
+            "        \"eventType\":\"ondblclick\"," +
+            "        \"coordinates\": \"194\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"3\"," +
+            "        \"eventTargetId\":\"input3\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"4\"," +
+            "        \"eventTargetId\":\"input4\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"255\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"5\"," +
+            "        \"eventTargetId\":\"input5\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"6\"," +
+            "        \"eventTargetId\":\"input6\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"7\"," +
+            "        \"eventTargetId\":\"input7\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"8\"," +
+            "        \"eventTargetId\":\"input8\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"255\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"9\"," +
+            "        \"eventTargetId\":\"input9\"," +
+            "        \"eventType\":\"onscroll\"," +
+            "        \"scrollPosition\": \"194\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"10\"," +
+            "        \"eventTargetId\":\"input10\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"194\"" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+ 
+        sendMessageAndAssertResponse(message);
+        
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+        
+        // check the target structure
+        GenericEventTarget parent = null;
+        
+        assertEquals(1, eventTargetStructures.length);
+        GenericEventTarget target = eventTargetStructures[0];
+        
+        assertTarget(target, parent, 2, new String[] {"index", "0"});
+
+        parent = target;
+        target = parent.getChildren().get(0);
+        assertTarget(target, parent, 0, new String[] {"index", "0"});
+        target = parent.getChildren().get(1);
+        assertTarget(target, parent, 10, new String[] {"tagName", "body"});
+        
+        parent = target;
+        for (GenericEventTarget child : parent.getChildren()) {
+            assertTarget(child, parent, 0, new String[] {"tagName", "input_button"});
+        }
+
+        // check the events
+        assertNotNull(events);
+        assertEquals(10, events.length);
+
+        for (int i = 0; i < events.length; i++) {
+            String eventType;
+            if ((i == 1)) {
+                eventType = "ondblclick";
+            }
+            else if ((i == 2) || ((4 <= i) && (i <= 6))) {
+                eventType = "onfocus";
+            }
+            else if ((i == 8)) {
+                eventType = "onscroll";
+            }
+            else {
+                eventType = "onclick";
+            }
+            
+            String[] parameter = null;
+            if (i <= 1) {
+                parameter = new String[] { "coordinates", "194" };
+            }
+            else if (i == 3) {
+                parameter = new String[] { "coordinates", "255" };
+            }
+            else if (i == 7) {
+                parameter = new String[] { "coordinates", "255" };
+            }
+            else if (i == 8) {
+                parameter = new String[] { "scrollPosition", "194" };
+            }
+            else if (i == 9) {
+                parameter = new String[] { "coordinates", "194" };
+            }
+           
+            if (parameter != null) {
+                 assertEvent(i, i + 1, target.getChildren().get(i), eventType, parameter);
+            }
+            else {
+                assertEvent(i, i + 1, target.getChildren().get(i), eventType);
+            }
+            
+        }
+    }
+    
+    /**
+     * 
+     */
+    @Test
+    public void testInvalidMessages() throws Exception {
+        String message = "}";
+        
+        sendMessageAndAssertResponse(message);
+            
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+
+        assertNull(events);
+
+        message = "blaublbidalslkdjflqkerowercalksdjfdlkkjdjfk";
+        
+        sendMessageAndAssertResponse(message);
+            
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+
+        assertNull(events);
+        
+        // the following message doesn't work because of the missing scroll position in the event
+        message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"123\"," +
+            "      \"userAgent\":\"Agent\"," +
+            "      \"title\":\"Title\"," +
+            "      \"url\":\"http://host/path\"" +
+            "    }," +
+            "    \"guiModel\": {" +
+            "      \"tagName\":\"html\"," +
+            "      \"index\":\"0\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"tagName\":\"head\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"tagName\":\"body\"," +
+            "          \"htmlId\":\"gsr\"," +
+            "        }" +
+            "      ]" +
+            "    }," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"9\"," +
+            "        \"path\":\"/html[0]/body(htmlId=gsr)\"," +
+            "        \"eventType\":\"onscroll\"," +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+        
+        sendMessageAndAssertResponse(message);
+        
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+
+        assertNull(events);
+        
+        // the following message doesn't work because of the missing client id
+        message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"userAgent\":\"Agent\"," +
+            "      \"title\":\"Title\"," +
+            "      \"url\":\"http://host/path\"" +
+            "    }," +
+            "    \"guiModel\": {" +
+            "      \"tagName\":\"html\"," +
+            "      \"index\":\"0\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"tagName\":\"head\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"tagName\":\"body\"," +
+            "          \"htmlId\":\"gsr\"," +
+            "        }" +
+            "      ]" +
+            "    }," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"12345\"," +
+            "        \"path\":\"/html[0]/body(htmlId=gsr)\"," +
+            "        \"eventType\":\"onunload\"" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+        
+        sendMessageAndAssertResponse(message);
+        
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+
+        assertNull(events);
+        
+        // the following message doesn't work because of the invalid time stamp
+        message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"123\"," +
+            "      \"userAgent\":\"Agent\"," +
+            "      \"title\":\"Title\"," +
+            "      \"url\":\"http://host/path\"" +
+            "    }," +
+            "    \"guiModel\": {" +
+            "      \"tagName\":\"html\"," +
+            "      \"index\":\"0\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"tagName\":\"head\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"tagName\":\"body\"," +
+            "          \"htmlId\":\"gsr\"," +
+            "        }" +
+            "      ]" +
+            "    }," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"blub\"," +
+            "        \"path\":\"/html[0]/body(htmlId=gsr)\"," +
+            "        \"eventType\":\"onunload\"" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+        
+        sendMessageAndAssertResponse(message);
+        
+        if (eventHandlingError != null) {
+            fail(eventHandlingError);
+        }
+
+        assertNull(events);
+        
+    }
+    
+    /* (non-Javadoc)
+     * @see GenericEventMonitorMessageListener#handleEvents(ClientInfos, GenericEvent[])
+     */
+    @Override
+    public void handleEvents(ClientInfos clientInfos, GenericEvent[] events) {
+        if (clientInfos == null) {
+            eventHandlingError = "client infos were null";
+        }
+        else if (events == null) {
+            eventHandlingError = "events were null";
+        }
+        else {
+            Map<String, GenericEventTarget> roots = new HashMap<>();
+            
+            for (GenericEvent event : events) {
+                if (!clientInfos.equals(event.getClientInfos())) {
+                    eventHandlingError = "one of the events did not have a correct client info";
+                }
+                
+                GenericEventTarget parent = event.getTarget();
+                
+                while (parent.getParent() != null) {
+                    parent = parent.getParent();
+                }
+                
+                roots.put(parent.getId(), parent);
+            }
+            
+            this.events = events;
+            this.eventTargetStructures =
+                roots.values().toArray(new GenericEventTarget[roots.size()]);
+        }
+    }
+
+    /**
+     *
+     */
+    private void sendMessageAndAssertResponse(String message) throws Exception {
+        DefaultHttpClient httpclient = new DefaultHttpClient();
+        HttpPost httpPost = new HttpPost("http://localhost:" + PORT + "/");
+        //HttpPost httpPost = new HttpPost("http://localhost:8090/");
+        HttpEntity entity = new StringEntity(message, ContentType.APPLICATION_JSON);
+        httpPost.setEntity(entity);
+        
+        try {
+            HttpResponse response = httpclient.execute(httpPost);
+            
+            // the monitor always returns 200 without any additional information. The client must
+            // never get more or less information. This is especially important for preventing
+            // hackers from finding out more
+            assertEquals(200, response.getStatusLine().getStatusCode());
+            assertTrue
+                ((response.getEntity() == null) || (response.getEntity().getContentLength() == 0) ||
+                 ((response.getEntity().getContentLength() == 1) &&
+                  (response.getEntity().getContent().read() == ' ')));
+        }
+        finally {
+            httpPost.releaseConnection();
+        }
+    }
+
+    /**
+     *
+     */
+    private void assertTarget(GenericEventTarget target,
+                              GenericEventTarget parent,
+                              int                noOfChildren,
+                              String[] ...       parameters)
+    {
+        if (parent != null) {
+            assertNotNull(target.getParent());
+            assertEquals(parent.getId(), target.getParent().getId());
+        }
+        else {
+            assertNull(target.getParent());
+        }
+        
+        assertNotNull(target.getId());
+        
+        if (noOfChildren > 0) {
+            assertNotNull(target.getChildren());
+            assertEquals(noOfChildren, target.getChildren().size());
+        }
+        else {
+            assertNull(target.getChildren());
+        }
+        
+        assertEquals(parameters.length, target.getParameters().size());
+        
+        for (String[] parameter : parameters) {
+            assertEquals(parameter[1], target.getParameters().get(parameter[0]));
+        }
+    }
+
+    /**
+     *
+     */
+    private void assertEvent(int                index,
+                             long               timestamp,
+                             GenericEventTarget target,
+                             String             eventType,
+                             String[] ...       parameters)
+    {
+        assertEquals("event " + index, new Long(timestamp), events[index].getTime());
+        assertEquals("event " + index, target, events[index].getTarget());
+        assertEquals("event " + index, eventType, events[index].getEventType());
+        
+        
+        assertEquals("event " + index, parameters.length, events[index].getParameters().size());
+        
+        for (String[] parameter : parameters) {
+            assertEquals
+                ("event " + index, parameter[1], events[index].getParameters().get(parameter[0]));
+        }
+    }
+
+}
Index: /trunk/autoquest-generic-event-monitor-test/src/test/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorTest.java
===================================================================
--- /trunk/autoquest-generic-event-monitor-test/src/test/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorTest.java	(revision 2159)
+++ /trunk/autoquest-generic-event-monitor-test/src/test/java/de/ugoe/cs/autoquest/genericeventmonitor/GenericEventMonitorTest.java	(revision 2159)
@@ -0,0 +1,668 @@
+//   Copyright 2012 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+package de.ugoe.cs.autoquest.genericeventmonitor;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.ugoe.cs.autoquest.genericeventmonitor.GenericEventMonitor;
+import de.ugoe.cs.util.console.TextConsole;
+
+/**
+ *  
+ * @author Patrick Harms
+ */
+public class GenericEventMonitorTest {
+
+    /**
+     * 
+     */
+    public static final TextConsole CONSOLE = new TextConsole();
+    
+    /**
+     * 
+     */
+    private final static String LOG_FILE_DIR = "target/tmp/logfiles/";
+    
+    /**
+     * 
+     */
+    private static final int PORT = 19098;
+
+    /**
+     * 
+     */
+    private GenericEventMonitor genericEventMonitor;
+
+    /**
+     *
+     */
+    @Before
+    public void setUp() throws Exception {
+        genericEventMonitor = new GenericEventMonitor(new String[] { LOG_FILE_DIR, Integer.toString(PORT) });
+        genericEventMonitor.init();
+        genericEventMonitor.start();
+    }
+
+    /**
+     *
+     */
+    @After
+    public void tearDown() throws Exception {
+        if (genericEventMonitor != null) {
+            try {
+                genericEventMonitor.stop();
+            }
+            finally {
+                genericEventMonitor = null;
+            }
+        }
+        
+        deleteFiles(new File(LOG_FILE_DIR));
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testOneSimpleMessage() throws Exception {
+        String clientId = "123";
+        String appId = "456";
+        
+        String message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"" + clientId + "\"," +
+            "      \"appId\":\"" + appId + "\"," +
+            "    }," +
+            "    \"targetStructure\": [{" +
+            "      \"targetId\":\"target1\"," +
+            "      \"param1\":\"value1\"," +
+            "      \"param3\":\"value3\"," +
+            "      \"param2\":\"value2\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"targetId\":\"target3\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"targetId\":\"target2\"," +
+            "          \"htmlId\":\"gsr\"," +
+            "        }" +
+            "      ]" +
+            "    }]," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"12345\"," +
+            "        \"eventTargetId\":\"target2\"," +
+            "        \"eventType\":\"gaze\"," +
+            "        \"xcoordinate\": \"194\"," +
+            "        \"ycoordinate\": \"12\"" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+
+        sendMessageAndAssertResponse(message);
+        
+        genericEventMonitor.stop();
+        genericEventMonitor = null;
+
+        File logFile = new File(LOG_FILE_DIR + File.separator + appId + File.separator +
+                                clientId + File.separator + "genericevents_" + clientId + "_000.log");
+        
+        assertTrue(logFile.exists());
+        
+        /*HTMLLogParser parser = new HTMLLogParser(null);
+        
+        parser.parseFile(logFile);
+        
+        // check the GUI model
+        GUIModel guiModel = parser.getGuiModel();
+        assertNotNull(guiModel);
+        
+        List<IGUIElement> nodes = guiModel.getRootElements();
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get server node
+        IGUIElement node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLServer);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get document node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLDocument);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get html node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLPageElement);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size()); // only one child as the head tag should have been ignored
+        
+        // get body node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLPageElement);
+        assertEquals("HTML", node.getPlatform());
+        assertTrue(node.isUsed());
+
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(0, nodes.size());
+        
+        // check the sequences
+        Collection<List<Event>> sequences = parser.getSequences();
+        
+        assertNotNull(sequences);
+        
+        Iterator<List<Event>> iterator = sequences.iterator();
+        assertTrue(iterator.hasNext());
+        
+        List<Event> sequence = iterator.next();
+        assertFalse(iterator.hasNext());
+        
+        assertNotNull(sequence);
+        assertEquals(1, sequence.size());
+        
+        assertEvent(sequence.get(0), 12345, MouseClick.class, node, 194, 7);*/
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testSeveralMessagesInOneSession() throws Exception {
+        String clientId = "123";
+        String appId = "456";
+        
+        String message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"" + clientId + "\"," +
+            "      \"appId\":\"" + appId + "\"," +
+            "    }," +
+            "    \"targetStructure\": [{" +
+            "      \"targetId\":\"html\"," +
+            "      \"index\":\"0\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"targetId\":\"head\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"tagName\":\"body\"," +
+            "          \"targetId\":\"gsr\"," +
+            "          \"children\":" +
+            "          [ {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input1\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input2\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input3\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input4\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input5\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input6\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input7\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input8\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input9\"," +
+            "            }," +
+            "            {" +
+            "              \"tagName\":\"input_button\"," +
+            "              \"targetId\":\"input10\"," +
+            "            }," +
+            "          ]" +
+            "        }" +
+            "      ]" +
+            "    }]," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"1\"," +
+            "        \"eventTargetId\":\"input1\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"194\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"2\"," +
+            "        \"eventTargetId\":\"input2\"," +
+            "        \"eventType\":\"ondblclick\"," +
+            "        \"coordinates\": \"194\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"3\"," +
+            "        \"eventTargetId\":\"input3\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"4\"," +
+            "        \"eventTargetId\":\"input4\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"255\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"5\"," +
+            "        \"eventTargetId\":\"input5\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"6\"," +
+            "        \"eventTargetId\":\"input6\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"7\"," +
+            "        \"eventTargetId\":\"input7\"," +
+            "        \"eventType\":\"onfocus\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"8\"," +
+            "        \"eventTargetId\":\"input8\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"255\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"9\"," +
+            "        \"eventTargetId\":\"input9\"," +
+            "        \"eventType\":\"onscroll\"," +
+            "        \"scrollPosition\": \"194\"" +
+            "      }," +
+            "      {" +
+            "        \"time\":\"10\"," +
+            "        \"eventTargetId\":\"input10\"," +
+            "        \"eventType\":\"onclick\"," +
+            "        \"coordinates\": \"194\"" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+ 
+        sendMessageAndAssertResponse(message);
+        
+        genericEventMonitor.stop();
+        genericEventMonitor = null;
+
+        File logFile = new File(LOG_FILE_DIR + File.separator + appId + File.separator +
+                                clientId + File.separator + "genericevents_" + clientId + "_000.log");
+        
+        assertTrue(logFile.exists());
+        
+        /*HTMLLogParser parser = new HTMLLogParser(null);
+        
+        parser.parseFile(logFile);
+        
+        // check the GUI model
+        GUIModel guiModel = parser.getGuiModel();
+        assertNotNull(guiModel);
+        
+        List<IGUIElement> nodes = guiModel.getRootElements();
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get server node
+        IGUIElement node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLServer);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get document node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLDocument);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get html node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLPageElement);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size()); // only one child as the head tag should have been ignored
+        
+        // get body node
+        IGUIElement body = nodes.get(0);
+        assertNotNull(body);
+        assertTrue(body instanceof HTMLPageElement);
+        assertEquals("HTML", body.getPlatform());
+        assertTrue(body.isUsed());
+
+        nodes = guiModel.getChildren(body);
+        assertNotNull(nodes);
+        
+        // wait for all 10 GUI elements on the same page to be logged although only 9 are used
+        assertEquals(10, nodes.size());
+        
+        Map<String, IGUIElement> inputs = new HashMap<>();
+        
+        // get input nodes
+        for (int i = 0; i < nodes.size(); i++) {
+            node = nodes.get(i);
+            assertNotNull(node);
+            assertTrue(node instanceof HTMLPageElement);
+            assertEquals("HTML", node.getPlatform());
+            
+            if (!"input9".equals(((HTMLPageElement) node).getHtmlId())) {
+                assertTrue(node.isUsed());
+            }
+            else {
+                assertFalse(node.isUsed());
+            }
+            
+            inputs.put(((HTMLPageElement) node).getHtmlId(), node);
+
+            assertNotNull(guiModel.getChildren(node));
+            assertEquals(0, guiModel.getChildren(node).size());
+        }
+        
+        // check the sequences
+        Collection<List<Event>> sequences = parser.getSequences();
+        
+        assertNotNull(sequences);
+        
+        Iterator<List<Event>> iterator = sequences.iterator();
+        assertTrue(iterator.hasNext());
+        
+        List<Event> sequence = iterator.next();
+        assertFalse(iterator.hasNext());
+        
+        assertNotNull(sequence);
+        assertEquals(10, sequence.size());
+        
+        assertEvent(sequence.get(0), 1, MouseClick.class, inputs.get("input1"), 194, 7);
+        assertEvent(sequence.get(1), 2, MouseDoubleClick.class, inputs.get("input2"), 194, 7);
+        assertEvent(sequence.get(2), 3, KeyboardFocusChange.class, inputs.get("input3"), 0, 0);
+        assertEvent(sequence.get(3), 4, MouseClick.class, inputs.get("input4"), 125, 14);
+        assertEvent(sequence.get(4), 5, KeyboardFocusChange.class, inputs.get("input5"), 0, 0);
+        assertEvent(sequence.get(5), 6, KeyboardFocusChange.class, inputs.get("input6"), 0, 0);
+        assertEvent(sequence.get(6), 7, KeyboardFocusChange.class, inputs.get("input7"), 0, 0);
+        assertEvent(sequence.get(7), 8, MouseClick.class, inputs.get("input8"), 255, 4);
+        assertEvent(sequence.get(8), 9, Scroll.class, body, 0, 0);
+        assertEvent(sequence.get(9), 10, MouseClick.class, inputs.get("input10"), 516, 154);*/
+
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testSeveralSessions() throws Exception {
+        String clientId = "123";
+       
+        String message =
+            "{" +
+            "  \"message\": {" +
+            "    \"clientInfos\": {" +
+            "      \"clientId\":\"" + clientId + "\"," +
+            "      \"userAgent\":\"Agent\"," +
+            "      \"title\":\"Title\"," +
+            "      \"url\":\"http://host/path\"" +
+            "    }," +
+            "    \"guiModel\": {" +
+            "      \"tagName\":\"html\"," +
+            "      \"index\":\"0\"," +
+            "      \"children\":" +
+            "      [ {" +
+            "          \"tagName\":\"head\"," +
+            "          \"index\":\"0\"," +
+            "        }," +
+            "        {" +
+            "          \"tagName\":\"body\"," +
+            "          \"htmlId\":\"gsr\"," +
+            "        }" +
+            "      ]" +
+            "    }," +
+            "    \"events\":" +
+            "    [ {" +
+            "        \"time\":\"12345\"," +
+            "        \"path\":\"/html[0]/body(htmlId=gsr)\"," +
+            "        \"eventType\":\"onclick\"" +
+            "        \"coordinates\": [\"194\", \"7\"]" +
+            "      }" +
+            "    ]" +
+            "  }" +
+            "}";
+
+        sendMessageAndAssertResponse(message);
+        
+        int numberOfSessions = 10;
+        for (int i = 0; i < numberOfSessions; i++) {
+            genericEventMonitor.stop();
+            genericEventMonitor =
+                new GenericEventMonitor(new String[] { LOG_FILE_DIR, Integer.toString(PORT) });
+            
+            genericEventMonitor.init();
+            genericEventMonitor.start();
+            sendMessageAndAssertResponse(message);
+        }
+        
+        genericEventMonitor.stop();
+        genericEventMonitor = null;
+        
+        /*HTMLLogParser parser = new HTMLLogParser(null);
+        
+        // assert 9 already rotated log files
+        for (int i = 0; i < numberOfSessions; i++) {
+            File logFile = new File(LOG_FILE_DIR + File.separator + "host" + File.separator +
+                                    clientId + File.separator + "htmlmonitor_" + clientId + "_00" +
+                                    i + ".log");
+       
+            assertTrue(logFile.exists());
+       
+            parser.parseFile(logFile);
+        }
+
+        // check the GUI model
+        GUIModel guiModel = parser.getGuiModel();
+        assertNotNull(guiModel);
+        
+        List<IGUIElement> nodes = guiModel.getRootElements();
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get server node
+        IGUIElement node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLServer);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get document node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLDocument);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size());
+        
+        // get html node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLPageElement);
+        assertEquals("HTML", node.getPlatform());
+        assertFalse(node.isUsed());
+        
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.size()); // only one child as the head tag should have been ignored
+        
+        // get body node
+        node = nodes.get(0);
+        assertNotNull(node);
+        assertTrue(node instanceof HTMLPageElement);
+        assertEquals("HTML", node.getPlatform());
+        assertTrue(node.isUsed());
+
+        nodes = guiModel.getChildren(node);
+        assertNotNull(nodes);
+        assertEquals(0, nodes.size());
+        
+        // check the sequences
+        Collection<List<Event>> sequences = parser.getSequences();
+        
+        assertNotNull(sequences);
+        assertEquals(numberOfSessions, sequences.size());
+        
+        Iterator<List<Event>> iterator = sequences.iterator();
+        
+        while (iterator.hasNext()) {
+            List<Event> sequence = iterator.next();
+        
+            assertNotNull(sequence);
+            assertEquals(1, sequence.size());
+       
+            assertEvent(sequence.get(0), 12345, MouseClick.class, node, 194, 7);
+        }*/
+    }
+
+    /**
+     *
+     */
+    private void sendMessageAndAssertResponse(String message) throws Exception {
+        DefaultHttpClient httpclient = new DefaultHttpClient();
+        HttpPost httpPost = new HttpPost("http://localhost:" + PORT + "/");
+        HttpEntity entity = new StringEntity(message, ContentType.APPLICATION_JSON);
+        httpPost.setEntity(entity);
+        
+        try {
+            HttpResponse response = httpclient.execute(httpPost);
+            
+            // the monitor always returns 200 without any additional information. The client must
+            // never get more or less information. This is especially important for preventing
+            // hackers from finding out more
+            assertEquals(200, response.getStatusLine().getStatusCode());
+            assertTrue
+                ((response.getEntity() == null) || (response.getEntity().getContentLength() == 0) ||
+                 ((response.getEntity().getContentLength() == 1) &&
+                  (response.getEntity().getContent().read() == ' ')));
+        }
+        finally {
+            httpPost.releaseConnection();
+        }
+    }
+
+    /**
+     *
+     */
+    /*private void assertEvent(Event                       event,
+                             int                         timestamp,
+                             Class<? extends IEventType> eventType,
+                             IGUIElement                 eventTarget,
+                             int                         xCoordinate,
+                             int                         yCoordinate)
+    {
+        assertEquals(timestamp, event.getTimestamp());
+        assertTrue(eventType.isInstance(event.getType()));
+        assertEquals(eventTarget, event.getTarget());
+        
+        if (event.getType() instanceof MouseButtonInteraction) {
+            assertEquals(xCoordinate, ((MouseButtonInteraction) event.getType()).getX());
+            assertEquals(yCoordinate, ((MouseButtonInteraction) event.getType()).getY());
+        }
+    }
+
+    /**
+     *
+     */
+    private void deleteFiles(File file) {
+        if (file.exists()) {
+            if (file.isDirectory()) {
+                for (File child : file.listFiles()) {
+                    deleteFiles(child);
+                }
+            }
+            
+            try {
+                file.delete();
+            }
+            catch (Exception e) {
+                // ignore and delete as much as possible
+            }
+        }
+    }
+
+}
