Index: /trunk/autoquest-httpmonitor/.classpath
===================================================================
--- /trunk/autoquest-httpmonitor/.classpath	(revision 1374)
+++ /trunk/autoquest-httpmonitor/.classpath	(revision 1374)
@@ -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.7">
+		<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/autoquest-httpmonitor/.project
===================================================================
--- /trunk/autoquest-httpmonitor/.project	(revision 1374)
+++ /trunk/autoquest-httpmonitor/.project	(revision 1374)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>autoquest-httpmonitor</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.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>
Index: /trunk/autoquest-httpmonitor/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /trunk/autoquest-httpmonitor/.settings/org.eclipse.jdt.core.prefs	(revision 1374)
+++ /trunk/autoquest-httpmonitor/.settings/org.eclipse.jdt.core.prefs	(revision 1374)
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
Index: /trunk/autoquest-httpmonitor/.settings/org.eclipse.m2e.core.prefs
===================================================================
--- /trunk/autoquest-httpmonitor/.settings/org.eclipse.m2e.core.prefs	(revision 1374)
+++ /trunk/autoquest-httpmonitor/.settings/org.eclipse.m2e.core.prefs	(revision 1374)
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
Index: /trunk/autoquest-httpmonitor/bin/isMonitorRunning.sh
===================================================================
--- /trunk/autoquest-httpmonitor/bin/isMonitorRunning.sh	(revision 1374)
+++ /trunk/autoquest-httpmonitor/bin/isMonitorRunning.sh	(revision 1374)
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+#   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.
+
+
+
+# This script checks if the autoquest-httpmonitor, which is in the same folder as
+# this script, is running
+
+
+# Absolute path to this script, e.g. /home/user/bin/stop.sh
+SCRIPT=$(readlink -f $0)
+
+# Find the autoquest-httpmonitor JAR-File and start in the folder of this script
+JAR_FILE=`find $(dirname $SCRIPT) -type f -name 'autoquest-httpmonitor-*.jar'`
+
+# Get the ProcessID of the autoquest-httpmonitor which is in the same folder as this script
+PID=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' monitor ' | awk '{print $1}')
+
+if [ -z "$PID" ]; then
+  echo "autoquest-httpmonitor is not running"
+else
+  echo "autoquest-httpmonitor is running with PID: $PID"
+fi
+
Index: /trunk/autoquest-httpmonitor/bin/isProxyRunning.sh
===================================================================
--- /trunk/autoquest-httpmonitor/bin/isProxyRunning.sh	(revision 1374)
+++ /trunk/autoquest-httpmonitor/bin/isProxyRunning.sh	(revision 1374)
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+#   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.
+
+
+
+# This script checks if the autoquest-httpmonitoring proxy, which is in the same folder as
+# this script, is running
+
+
+# Absolute path to this script, e.g. /home/user/bin/stop.sh
+SCRIPT=$(readlink -f $0)
+
+# Find the autoquest-httpmonitor JAR-File and start in the folder of this script
+JAR_FILE=`find $(dirname $SCRIPT) -type f -name 'autoquest-httpmonitor-*.jar'`
+
+# Get the ProcessID of the autoquest-httpmonitor which is in the same folder as this script
+PID=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' proxy ' | awk '{print $1}')
+
+if [ -z "$PID" ]; then
+  echo "autoquest-httpmonitoring proxy is not running"
+else
+  echo "autoquest-httpmonitoring proxy is running with PID: $PID"
+fi
+
Index: /trunk/autoquest-httpmonitor/bin/runMonitor.sh
===================================================================
--- /trunk/autoquest-httpmonitor/bin/runMonitor.sh	(revision 1374)
+++ /trunk/autoquest-httpmonitor/bin/runMonitor.sh	(revision 1374)
@@ -0,0 +1,165 @@
+#!/bin/sh
+#   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.
+
+
+
+# This script starts the autoquest-httpmonitor which is in the same folder as
+# this script
+
+# Absolute path to this script, e.g. /home/user/bin/foo.sh
+SCRIPT=$(readlink -f $0)
+
+# Find the autoquest-httpmonitor JAR-File and start in the folder of this script
+JAR_FILE=`find $(dirname $SCRIPT) -type f -name 'autoquest-httpmonitor-*.jar'`
+
+# Get the ProcessID of the autoquest-httpmonitor which is in the same folder as this script
+PID=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' monitor ' | awk '{print $1 " " $7}')
+
+
+# Check if this autoquest-httpmonitor is already running
+if [ ! -z "$PID" ]; then
+  echo "autoquest-httpmonitor is already running with PID:$PID"
+  exit 1
+fi
+
+
+
+HOME_DIR=`dirname $0`
+
+# Given the "java" executable as an argument, find JAVA_HOME
+find_java() {
+  # First check if it is a JDK in the /usr/lib/jvm directory, or a symlink there.
+  # The test is somewhat complicated due to the different ways the Java implementations
+  # are set up with the alternatives system
+  # e.g.
+  #  /usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-1.5.0-sun/jre/bin/java
+  # or
+  #  /usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-gcj/bin/java -> /usr/bin/gij-4.2
+
+  JAVA_HOME=$1
+  while true ; do
+    case $JAVA_HOME in
+      /usr/lib/jvm/*)
+        # Found it! Return the correct paremt directory.
+
+        JAVA_HOME=`echo $JAVA_HOME | sed 's:\(/usr/lib/jvm/[^/]*\).*:\1:'`
+	return
+	;;
+      *) ;;
+    esac
+
+    if [ -h $JAVA_HOME ] ; then
+      JAVA_HOME=`readlink $JAVA_HOME`
+    else
+      break
+    fi
+  done
+        
+  # Not found in the Debian alternatives system, so presumably
+  # it is a user-installed JDK/JRE. Might as well be helpful
+  # and try to find JAVA_HOME.
+
+  # First try for a JDK:
+  JAVA_HOME=`readlink -e $1`
+  while [ `dirname $JAVA_HOME` != /  ]; do
+    if [ -e $JAVA_HOME/lib/tools.jar ]; then
+      return
+    fi
+
+    JAVA_HOME=`dirname $JAVA_HOME`
+  done
+
+  # If we get here we did not find a JDK. Search again for a JRE:
+  JAVA_HOME=`readlink -e $1`
+  while [ `dirname $JAVA_HOME` != /  ]; do
+    if [ -e $JAVA_HOME/bin/java ]; then
+      return
+    fi
+
+    JAVA_HOME=`dirname $JAVA_HOME`
+  done
+
+  # Nothing found; leave blank
+  JAVA_HOME=
+}
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  else
+    # Debian patch - search for preferred JRE
+    if [ -n "$JAVACMD" ] ; then
+      find_java "$JAVACMD"
+    else
+      find_java `which java`
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly."
+  echo "  We cannot execute $JAVACMD"
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+cd ${HOME_DIR}
+
+
+if [ ! -f "$JAR_FILE" ] ; then
+  echo "Error: Could not find executable jar file in distribution."
+  echo "  Execution aborted."
+  exit 1
+fi
+
+# ./log is the standard log file. If this folder does not exist
+# create it
+if [ ! -d "./log" ] ; then
+   mkdir "./log"
+fi
+LOGDIR="./log"
+echo "Using LogDir ./log"
+
+
+# Every output from the JAR File will be saved in the Console.log
+# &1 is stdout, &2 is stderr
+echo "Starting autoquest-httpmonitor"
+exec 3>&1 4>&2 >>"$LOGDIR"/console-monitor.log 2>&1
+
+echo ""
+echo "starting HTML monitor"
+date
+echo "using java $JAVACMD"
+
+$JAVACMD -jar ${JAR_FILE} monitor $LOGDIR $1 $2 2>&1 >> "$LOGDIR"/console-monitor.log &
+
+# restore stdout and stderr
+exec 1>&3 2>&4
Index: /trunk/autoquest-httpmonitor/bin/runProxy.sh
===================================================================
--- /trunk/autoquest-httpmonitor/bin/runProxy.sh	(revision 1374)
+++ /trunk/autoquest-httpmonitor/bin/runProxy.sh	(revision 1374)
@@ -0,0 +1,165 @@
+#!/bin/sh
+#   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.
+
+
+
+# This script starts the autoquest-httpmonitoring proxy which is in the same folder as
+# this script
+
+# Absolute path to this script, e.g. /home/user/bin/foo.sh
+SCRIPT=$(readlink -f $0)
+
+# Find the autoquest-httpmonitor JAR-File and start in the folder of this script
+JAR_FILE=`find $(dirname $SCRIPT) -type f -name 'autoquest-httpmonitor-*.jar'`
+
+# Get the ProcessID of the autoquest-httpmonitoring proxy which is in the same folder as this script
+PID=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' proxy ' | awk '{print $1 " " $7}')
+
+
+# Check if this autoquest-httpmonitoring proxy is already running
+if [ ! -z "$PID" ]; then
+  echo "autoquest-httpmonitoring proxy is already running with PID:$PID"
+  exit 1
+fi
+
+
+
+HOME_DIR=`dirname $0`
+
+# Given the "java" executable as an argument, find JAVA_HOME
+find_java() {
+  # First check if it is a JDK in the /usr/lib/jvm directory, or a symlink there.
+  # The test is somewhat complicated due to the different ways the Java implementations
+  # are set up with the alternatives system
+  # e.g.
+  #  /usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-1.5.0-sun/jre/bin/java
+  # or
+  #  /usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-gcj/bin/java -> /usr/bin/gij-4.2
+
+  JAVA_HOME=$1
+  while true ; do
+    case $JAVA_HOME in
+      /usr/lib/jvm/*)
+        # Found it! Return the correct paremt directory.
+
+        JAVA_HOME=`echo $JAVA_HOME | sed 's:\(/usr/lib/jvm/[^/]*\).*:\1:'`
+	return
+	;;
+      *) ;;
+    esac
+
+    if [ -h $JAVA_HOME ] ; then
+      JAVA_HOME=`readlink $JAVA_HOME`
+    else
+      break
+    fi
+  done
+        
+  # Not found in the Debian alternatives system, so presumably
+  # it is a user-installed JDK/JRE. Might as well be helpful
+  # and try to find JAVA_HOME.
+
+  # First try for a JDK:
+  JAVA_HOME=`readlink -e $1`
+  while [ `dirname $JAVA_HOME` != /  ]; do
+    if [ -e $JAVA_HOME/lib/tools.jar ]; then
+      return
+    fi
+
+    JAVA_HOME=`dirname $JAVA_HOME`
+  done
+
+  # If we get here we did not find a JDK. Search again for a JRE:
+  JAVA_HOME=`readlink -e $1`
+  while [ `dirname $JAVA_HOME` != /  ]; do
+    if [ -e $JAVA_HOME/bin/java ]; then
+      return
+    fi
+
+    JAVA_HOME=`dirname $JAVA_HOME`
+  done
+
+  # Nothing found; leave blank
+  JAVA_HOME=
+}
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  else
+    # Debian patch - search for preferred JRE
+    if [ -n "$JAVACMD" ] ; then
+      find_java "$JAVACMD"
+    else
+      find_java `which java`
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly."
+  echo "  We cannot execute $JAVACMD"
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+cd ${HOME_DIR}
+
+
+if [ ! -f "$JAR_FILE" ] ; then
+  echo "Error: Could not find executable jar file in distribution."
+  echo "  Execution aborted."
+  exit 1
+fi
+
+# ./log is the standard log file. If this folder does not exist
+# create it
+if [ ! -d "./log" ] ; then
+   mkdir "./log"
+fi
+LOGDIR="./log"
+echo "Using LogDir ./log"
+
+
+# Every output from the JAR File will be saved in the Console.log
+# &1 is stdout, &2 is stderr
+echo "Starting autoquest-httpmonitoring proxy"
+exec 3>&1 4>&2 >>"$LOGDIR"/console-proxy.log 2>&1
+
+echo ""
+echo "starting HTML monitoring proxy"
+date
+echo "using java $JAVACMD"
+
+$JAVACMD -jar ${JAR_FILE} proxy $LOGDIR $1 $2 $3 2>&1 >> "$LOGDIR"/console-proxy.log &
+
+# restore stdout and stderr
+exec 1>&3 2>&4
Index: /trunk/autoquest-httpmonitor/bin/stopMonitor.sh
===================================================================
--- /trunk/autoquest-httpmonitor/bin/stopMonitor.sh	(revision 1374)
+++ /trunk/autoquest-httpmonitor/bin/stopMonitor.sh	(revision 1374)
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+#   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.
+
+
+
+# This script stops the autoquest-httpmonitor which is in the same folder as
+# this script
+
+
+# Absolute path to this script, e.g. /home/user/bin/stop.sh
+SCRIPT=$(readlink -f $0)
+
+# Find the autoquest-httpmonitor JAR-File and start in the Folder of this Script
+JAR_FILE=`find $(dirname $SCRIPT) -type f -name 'autoquest-httpmonitor-*.jar'`
+
+# Get the ProcessID of the autoquest-httpmonitor which is in the same folder as this script
+PID=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' monitor ' | awk '{print $1}')
+
+if [ -z "$PID" ]; then
+  echo autoquest-httpmonitor is not running
+else
+  #Kill this autoquest-httpmonitor-process
+  kill "$PID"
+  sleep 2
+  # Check if Process is no more
+  CHECK=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' monitor ' | awk '{print $1}')
+  if [ ! -z "$CHECK" ]; then
+	kill -9 "$CHECK"
+  fi
+  echo autoquest-httpmonitor stopped
+fi
+
Index: /trunk/autoquest-httpmonitor/bin/stopProxy.sh
===================================================================
--- /trunk/autoquest-httpmonitor/bin/stopProxy.sh	(revision 1374)
+++ /trunk/autoquest-httpmonitor/bin/stopProxy.sh	(revision 1374)
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+#   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.
+
+
+
+# This script stops the autoquest-httpmonitor which is in the same folder as
+# this script
+
+
+# Absolute path to this script, e.g. /home/user/bin/stop.sh
+SCRIPT=$(readlink -f $0)
+
+# Find the autoquest-httpmonitor JAR-File and start in the Folder of this Script
+JAR_FILE=`find $(dirname $SCRIPT) -type f -name 'autoquest-httpmonitor-*.jar'`
+
+# Get the ProcessID of the autoquest-httpmonitor which is in the same folder as this script
+PID=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' proxy ' | awk '{print $1}')
+
+if [ -z "$PID" ]; then
+  echo autoquest-httpmonitoring proxy is not running
+else
+  #Kill this autoquest-httpmonitor-process
+  kill "$PID"
+  sleep 2
+  # Check if Process is no more
+  CHECK=$(ps ax | grep "$JAR_FILE" | grep -v ' grep ' | grep ' proxy ' | awk '{print $1}')
+  if [ ! -z "$CHECK" ]; then
+	kill -9 "$CHECK"
+  fi
+  echo autoquest-httpmonitoring proxy stopped
+fi
+
Index: /trunk/autoquest-httpmonitor/pom.xml
===================================================================
--- /trunk/autoquest-httpmonitor/pom.xml	(revision 1374)
+++ /trunk/autoquest-httpmonitor/pom.xml	(revision 1374)
@@ -0,0 +1,106 @@
+<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.autoquest</groupId>
+    <artifactId>autoquest-httpmonitor</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>autoquest-httpmonitor</name>
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+        </license>
+    </licenses>
+    <packaging>jar</packaging>
+    <scm>
+        <url>https://autoquest.informatik.uni-goettingen.de/svn/autoquest/trunk/autoquest-httpmonitor</url>
+    </scm>
+    <dependencies>
+        <dependency>
+            <groupId>de.ugoe.cs</groupId>
+            <artifactId>java-utils</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>de.ugoe.cs.autoquest</groupId>
+            <artifactId>autoquest-plugin-http</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>9.1.0.M0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlet</artifactId>
+            <version>9.1.0.M0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-proxy</artifactId>
+            <version>9.1.0.M0</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jvnet.jaxb2.maven2</groupId>
+                <artifactId>maven-jaxb2-plugin</artifactId>
+                <version>0.8.2</version>
+                <configuration>
+                    <generatePackage>de.ugoe.cs.autoquest.httpmonitor.exchange</generatePackage>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addClasspath>true</addClasspath>
+                            <classpathPrefix>lib/</classpathPrefix>
+                            <mainClass>de.ugoe.cs.autoquest.httpmonitor.Runner</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>2.2-beta-2</version>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/main/assembly/bin.xml</descriptor>
+                    </descriptors>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
Index: /trunk/autoquest-httpmonitor/src/main/assembly/bin.xml
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/assembly/bin.xml	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/assembly/bin.xml	(revision 1374)
@@ -0,0 +1,37 @@
+<assembly
+    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>dir</format>
+    <!-- format>tar.bz2</format>
+    <format>zip</format-->
+  </formats>
+  <dependencySets>
+    <dependencySet>
+      <includes></includes>
+      <excludes>
+        <exclude>de.ugoe.cs.autoquest:autoquest-httpmonitor</exclude>
+      </excludes>
+      <outputDirectory>lib</outputDirectory>
+    </dependencySet>
+    <dependencySet>
+      <includes>
+          <include>de.ugoe.cs.autoquest:autoquest-httpmonitor</include>
+      </includes>
+      <outputDirectory></outputDirectory>
+    </dependencySet>
+  </dependencySets>
+  <fileSets>
+    <fileSet>
+      <directory>bin</directory>
+      <outputDirectory></outputDirectory>
+      <fileMode>775</fileMode>
+      <includes>
+        <include>*</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</assembly>
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitor.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitor.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitor.java	(revision 1374)
@@ -0,0 +1,146 @@
+//   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.httpmonitor;
+
+import javax.servlet.Servlet;
+
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * The HTTP monitor starts a web server ({@link HttpMonitorServer}) that receives exchanges
+ * of the HTTP proxy. These exchanges are logged using the {@link HttpMonitorLogManager}. The
+ * class assures that on shutdown e.g. caused by CTRL-C the server and the log manager are
+ * stopped correctly.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class HttpMonitor implements HttpMonitorComponent {
+
+    /**
+     * the port on which the webserver shall listen. Defaults to 8090.
+     */
+    private int port = 8090;
+    
+    /**
+     * the web server receiving the exchanges
+     */
+    private HttpMonitorServer server;
+    
+    /**
+     * the directory into which the log files shall be written
+     */
+    private String logFileBaseDir;
+
+    /**
+     * the log manager being responsible for performing the logging
+     */
+    private HttpMonitorLogManager logManager;
+
+    /**
+     * the thread needed to handle CTRL-C events
+     */
+    private Thread shutdownHook;
+
+    /**
+     * <p>
+     * initializes the monitor with the command line arguments. Those may be the log directory
+     * as first argument and the port to listen on as second
+     * </p>
+     *
+     * @param commandLineArguments the command line arguments when starting the monitor using
+     *                             the {@link Runner}
+     */
+    public HttpMonitor(String[] commandLineArguments) {
+        if (commandLineArguments.length > 0) {
+            this.logFileBaseDir = commandLineArguments[0];
+            Console.println("putting logs into directory " + this.logFileBaseDir);
+        }
+        
+        if (commandLineArguments.length > 1) {
+            try {
+                this.port = Integer.parseInt(commandLineArguments[1]);
+            }
+            catch (NumberFormatException e) {
+                Console.println("ignoring invalid port specification " + commandLineArguments[1]);
+            }
+            Console.println("listening on port " + this.port);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#init()
+     */
+    @Override
+    public synchronized void init() throws HttpMonitorException {
+        if (server != null) {
+            throw new IllegalStateException("already initialized.");
+        }
+        
+        try {
+            logManager = new HttpMonitorLogManager(logFileBaseDir);
+            logManager.init();
+        
+            Servlet servlet = new HttpMonitorServlet(logManager);
+            server = new HttpMonitorServer(port, servlet);
+            server.init();
+        
+            shutdownHook = new Thread(new ShutdownHook(server, logManager));
+        }
+        catch (HttpMonitorException e) {
+            Console.printerrln("could not initialize HTTP monitor: " + e);
+            Console.logException(e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#start()
+     */
+    @Override
+    public synchronized void start() {
+        if (server == null) {
+            throw new IllegalStateException("not initialized.");
+        }
+        
+        try {
+            Runtime.getRuntime().addShutdownHook(shutdownHook);
+            logManager.start();
+            server.start();
+        }
+        catch (HttpMonitorException e) {
+            Console.printerrln("could not start HTTP monitor: " + e);
+            Console.logException(e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#stop()
+     */
+    @Override
+    public synchronized void stop() {
+        if (server == null) {
+            throw new IllegalStateException("not initialized.");
+        }
+        
+        Runtime.getRuntime().removeShutdownHook(shutdownHook);
+        server.stop();
+        logManager.stop();
+        
+        server = null;
+        logManager = null;
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorComponent.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorComponent.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorComponent.java	(revision 1374)
@@ -0,0 +1,54 @@
+//   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.httpmonitor;
+
+/**
+ * <p>
+ * convenience interface for all components making up the HTTP monitor. All components implement
+ * this interface to ensure homogeneity throughout them. A component must first be initialized
+ * ({@link #init()}), then started ({@link #start()}), and finally stopped ({@link #stop()}).
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface HttpMonitorComponent {
+
+    /**
+     * initializes a component, i.e. it does everything needed to prepare starting the component
+     * 
+     * @throws IllegalStateException thrown if the method was already called before but
+     *                               {@link #stop()} wasn't called yet
+     * @throws HttpMonitorException  thrown if the initialization fails, e.g. because needed infos
+     *                               are missing
+     */
+    void init() throws IllegalStateException, HttpMonitorException;
+
+    /**
+     * starts a component
+     * 
+     * @throws IllegalStateException thrown if {@link #init()} wasn't called yet of if the component
+     *                               is already started through a preceding call to this method
+     * @throws HttpMonitorException  thrown if the startup fails, e.g. because needed infos
+     *                               are missing
+     */
+    void start() throws IllegalStateException, HttpMonitorException;
+
+    /**
+     * stops a component and cleans up any derivate. In the following, {@link #init()} must be
+     * callable again. If the component is not initialized or started, nothing must happen. If the
+     * component is initialized but not started, the initialization is revoked.
+     */
+    void stop();
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorException.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorException.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorException.java	(revision 1374)
@@ -0,0 +1,53 @@
+//   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.httpmonitor;
+
+/**
+ * <p>
+ * Exception to notify all irregularities, that are specific to the HTTP monitor and its
+ * components.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class HttpMonitorException extends Exception {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * initializes an exception with a simple message
+     * </p>
+     *
+     * @param message the message of the exception
+     */
+    public HttpMonitorException(String message) {
+        super(message);
+    }
+
+    /**
+     * <p>
+     * initializes an exception with a simple message and a causing exception
+     * </p>
+     *
+     * @param message the message of the exception
+     * @param cause   the root cause of the exception
+     */
+    public HttpMonitorException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorExchangeHandler.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorExchangeHandler.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorExchangeHandler.java	(revision 1374)
@@ -0,0 +1,37 @@
+//   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.httpmonitor;
+
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpExchange;
+
+/**
+ * <p>
+ * an exchange handler to be used either by the monitor or the proxy to handle recorded exchanges.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface HttpMonitorExchangeHandler extends HttpMonitorComponent {
+
+    /**
+     * <p>
+     * handles a newly received exchange
+     * </p>
+     * 
+     * @param httpExchange the exchange to be handled
+     */
+    void handleHttpExchange(HttpExchange httpExchange);
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorLogManager.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorLogManager.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorLogManager.java	(revision 1374)
@@ -0,0 +1,170 @@
+//   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.httpmonitor;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpExchange;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * The log manager handles an {@link HttpMonitorOutputWriter} to perform the logging
+ * of recorded exchanges. It initializes the writer if the first exchange is received and it
+ * closes the writer if for a specific period of time no further exchange was received. The writer
+ * themselves considers log rotation. For handling exchanges, the {@link HttpMonitorExchangeHandler}
+ * mechanism is used.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class HttpMonitorLogManager implements HttpMonitorComponent, HttpMonitorExchangeHandler {
+    
+    /**
+     * the timeout after which the writer is closed
+     */
+    private static final int SESSION_TIMEOUT = 10 * 60 * 1000;
+    
+    /**
+     * the directory into which the log files shall be written
+     */
+    private String logFileBaseDir;
+
+    /**
+     * the writer for the log file
+     */
+    private HttpMonitorOutputWriter writer;
+
+    /**
+     * a timer used to detect timeouts
+     */
+    private Timer logFileMonitorTimer;
+
+    /**
+     * <p>
+     * initializes the log manager with the directory into which the log files shall be stored
+     * </p>
+     *
+     * @param logFileBaseDir the directory into which the log files shall be stored
+     */
+    public HttpMonitorLogManager(String logFileBaseDir) {
+        this.logFileBaseDir = logFileBaseDir;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#init()
+     */
+    @Override
+    public synchronized void init() throws IllegalStateException, HttpMonitorException {
+        if (logFileMonitorTimer != null) {
+            throw new IllegalStateException("already initialized");
+        }
+        
+        logFileMonitorTimer = new Timer();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#start()
+     */
+    @Override
+    public synchronized void start() throws IllegalStateException, HttpMonitorException {
+        if (logFileMonitorTimer == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        logFileMonitorTimer.schedule
+            (new LogFileMonitorTimerTask(), SESSION_TIMEOUT / 2, SESSION_TIMEOUT / 2);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#stop()
+     */
+    @Override
+    public synchronized void stop() {
+        if (logFileMonitorTimer != null) {
+            logFileMonitorTimer.cancel();
+        }
+            
+        if (writer != null) {
+            writer.stop();
+        }
+        
+        writer = null;
+    }
+
+    /* (non-Javadoc)
+     * @see HttpMonitoringListener#handleHttpMessage()
+     */
+    @Override
+    public void handleHttpExchange(HttpExchange httpExchange) {
+        try {
+            if (writer == null) {
+                synchronized (this) {
+                    if (writer == null) {
+                        writer = new HttpMonitorOutputWriter(logFileBaseDir);
+                        writer.init();
+                    }
+                }
+            }
+
+            writer.handleHttpExchange(httpExchange);
+        }
+        catch (Exception e) {
+            Console.printerrln("could not handle message: " + e);
+            e.printStackTrace();
+            Console.logException(e);
+            
+            // determine, if the writer exists but is not able to log something. In this case,
+            // destroy the writer (part of the message may be logged twice through this).
+            if (writer != null) {
+                try {
+                    writer.handleHttpExchange(httpExchange);
+                }
+                catch (Exception e1) {
+                    synchronized (this) {
+                        writer.stop();
+                        writer = null;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * internal timer task used for detecting session timeouts of clients
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    public class LogFileMonitorTimerTask extends TimerTask {
+
+        /* (non-Javadoc)
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            synchronized (HttpMonitorLogManager.this) {
+                if (System.currentTimeMillis() - writer.getLastUpdate() > SESSION_TIMEOUT) {
+                    writer.stop();
+                    writer = null;
+                }
+            }
+        }
+
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorOutputWriter.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorOutputWriter.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorOutputWriter.java	(revision 1374)
@@ -0,0 +1,293 @@
+//   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.httpmonitor;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.text.DecimalFormat;
+import java.util.logging.Level;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpExchange;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.ObjectFactory;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * dumps messages to a log file in the provided base log directory. The name of each finished log
+ * file starts with the "httpmonitor_" followed by an index of the log file. An unfinished log file
+ * has no index yet. A log file is finished if
+ * <ul>
+ *   <li>the session is closed by a timeout</li>
+ *   <li>the HTTP monitor or proxy are normally shut down</li>
+ *   <li>on startup an unfinished log file is detected.</li>
+ *   <li>the {@link #MAXIMUM_LOG_FILE_SIZE} is reached</li>
+ * </ul>
+ * </p>
+ * 
+ * @author Patrick Harms
+ * @version 1.0
+ * 
+ */
+public class HttpMonitorOutputWriter implements HttpMonitorComponent, HttpMonitorExchangeHandler {
+    
+    /**
+     * the maximum size of an individual log file
+     */
+    private static final int MAXIMUM_LOG_FILE_SIZE = 50000000;
+
+    /**
+     * the default log base directory if none is provided through the constructor 
+     */
+    private static final String DEFAULT_LOG_FILE_BASE_DIR = "logs";
+
+    /**
+     * the currently used log file base directory
+     */
+    private File logFileBaseDir;
+
+    /**
+     * the log file into which all messages are currently written
+     */
+    private File logFile;
+
+    /**
+     * an output writer to be used for writing into the log file
+     */
+    private PrintWriter outputWriter;
+
+    /**
+     * the time stamp of the last action taken on this writer (such as logging a message)
+     */
+    private long lastUpdate;
+    
+    /**
+     * <p>
+     * initializes the writer with the log file base directory.
+     * </p>
+     * 
+     * @param logFileBaseDir the log file base directory, or null if the default directory shall
+     *                       be taken
+     */
+    public HttpMonitorOutputWriter(String logFileBaseDir) {
+        if (logFileBaseDir == null) {
+            this.logFileBaseDir = new File(DEFAULT_LOG_FILE_BASE_DIR);
+        }
+        else {
+            this.logFileBaseDir = new File(logFileBaseDir);
+        }
+        
+        lastUpdate = System.currentTimeMillis();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#init()
+     */
+    @Override
+    public synchronized void init() throws HttpMonitorException {
+        if (outputWriter != null) {
+            throw new IllegalStateException("already initialized. Call close() first");
+        }
+        
+        synchronized (HttpMonitorOutputWriter.class) {
+            try {
+                if (!logFileBaseDir.exists()) {
+                    if (!logFileBaseDir.mkdirs()) {
+                        throw new HttpMonitorException("log file directory " + logFileBaseDir +
+                                                       " can not be created");
+                    }
+                }
+                else if (!logFileBaseDir.isDirectory()) {
+                    throw new HttpMonitorException("log file directory " + logFileBaseDir +
+                                                   " already exists as a file");
+                }
+                
+                logFile = new File(logFileBaseDir, getLogFileName(-1));
+                
+                if (logFile.exists()) {
+                    rotateLogFile();
+                }
+            
+                createLogWriter();
+            }
+            catch (IOException e) {
+                throw new HttpMonitorException("could not open logfile " + logFile, e);
+            }
+        }
+        
+        lastUpdate = System.currentTimeMillis();
+    }
+
+    /**
+     * <p>
+     * used to calculate a log file name. If the provided index is smaller 0, then no index
+     * is added to the file name. A filename is e.g. "httpmonitor_001.log". 
+     * </p>
+     *
+     * @param index the index of the log file or -1 one, if no index shall be added
+     * 
+     * @return the file name as described
+     */
+    private String getLogFileName(int index) {
+        String result = "httpmonitor";
+        
+        if (index >= 0) {
+            result += "_" + new DecimalFormat("000" ).format(index);
+        }
+        
+        result += ".log";
+        
+        return result;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#start()
+     */
+    @Override
+    public synchronized void start() throws IllegalStateException, HttpMonitorException {
+        lastUpdate = System.currentTimeMillis();
+    }
+
+    /* (non-Javadoc)
+     * @see HttpMonitorMessageListener#handleHttpMessage()
+     */
+    @Override
+    public synchronized void handleHttpExchange(HttpExchange httpExchange) {
+        if (outputWriter == null) {
+            throw new IllegalStateException("not initialized. Call init() first");
+        }
+        
+        try {
+            JAXBContext jaxbContext =
+                JAXBContext.newInstance(HttpExchange.class.getPackage().getName());
+            Marshaller marshaller = jaxbContext.createMarshaller();
+
+            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+            marshaller.marshal(new ObjectFactory().createHttpExchange(httpExchange), outputWriter);
+        }
+        catch (JAXBException e) {
+            Console.traceln(Level.WARNING, "could not dump exchange to log file: " + e);
+            Console.logException(e);
+        }
+
+        outputWriter.flush();
+        
+        try {
+            considerLogRotate();
+        }
+        catch (IOException e) {
+            throw new IllegalStateException("could not perform log rotation: " + e, e);
+        }
+        
+        lastUpdate = System.currentTimeMillis();
+    }
+
+    /**
+     * <p>
+     * checks, if the log file exceeded the {@link #MAXIMUM_LOG_FILE_SIZE}. If so, the current
+     * log file is closed, the next log file name is determined and this new file is opened for
+     * writing. 
+     * </p>
+     */
+    private synchronized void considerLogRotate() throws IOException {
+        if (logFile.length() > MAXIMUM_LOG_FILE_SIZE) {
+            closeLogWriter();
+            rotateLogFile();
+            createLogWriter();
+        }
+    }
+
+    /**
+     * <p>
+     * renames the current log file to a new log file with the next available index. It further
+     * sets the current log file to the default name, i.e. without index.
+     * </p>
+     */
+    private void rotateLogFile() {
+        File clientLogDir = logFile.getParentFile();
+        File checkFile;
+
+        int logFileIndex = -1;
+        do {
+            logFileIndex++;
+            
+            checkFile = new File(clientLogDir, getLogFileName(logFileIndex));
+        }
+        while (checkFile.exists());
+    
+        if (!logFile.renameTo(checkFile)) {
+            Console.printerrln("could not rename log file " + logFile + " to " + checkFile +
+                               ". Will not perform log rotation.");
+        }
+        else {
+            logFileIndex++;
+            logFile = new File(clientLogDir, getLogFileName(-1));
+        }
+    }
+
+    /**
+     * <p>
+     * instantiates a writer to be used for writing messages into the log file.
+     * </p>
+     */
+    private void createLogWriter() throws IOException {
+        FileOutputStream fis = new FileOutputStream(logFile);
+        outputWriter = new PrintWriter(new OutputStreamWriter(fis, "UTF-8"));
+        outputWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+        outputWriter.println("<session xmlns=\"http://autoquest.informatik.uni-goettingen.de\" >");
+    }
+
+    /**
+     * <p>
+     * closed the current writer if it is open.
+     * </p>
+     */
+    private void closeLogWriter() {
+        if (outputWriter != null) {
+            outputWriter.println("</session>");
+            outputWriter.flush();
+            outputWriter.close();
+            outputWriter = null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#stop()
+     */
+    @Override
+    public synchronized void stop() {
+        closeLogWriter();
+        rotateLogFile();
+
+        lastUpdate = System.currentTimeMillis();
+    }
+
+    /**
+     * <p>
+     * return the time stamp of the last activity that happened on this writer.
+     * </p>
+     *
+     * @return as described
+     */
+    public long getLastUpdate() {
+        return lastUpdate;
+    }
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorServer.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorServer.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorServer.java	(revision 1374)
@@ -0,0 +1,129 @@
+//   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.httpmonitor;
+
+import javax.servlet.Servlet;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * this is the web server, that is used either for the monitor or the proxy. It is initialized with
+ * a port and the servlet to be deployed. It implements the {@link HttpMonitorComponent} to be
+ * simply initialized, started, and stopped. 
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class HttpMonitorServer implements HttpMonitorComponent {
+    
+    /**
+     * the port to listen on
+     */
+    private int port;
+
+    /**
+     * the jetty web server used for receiving messages
+     */
+    private Server server;
+
+    /**
+     * the message listener to forward the messages to
+     */
+    private Servlet servlet;
+
+    /**
+     * <p>
+     * initializes the server with the port to listen on and the servlet to be deployed.
+     * </p>
+     *
+     * @param port    the port to listen on
+     * @param servlet teh servlet to be deployed
+     */
+    public HttpMonitorServer(int port, Servlet servlet) {
+        this.port = port;
+        this.servlet = servlet;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#init()
+     */
+    @Override
+    public synchronized void init() {
+        if (server != null) {
+            throw new IllegalStateException("already initialized. First call stop()");
+        }
+
+        server = new Server(port);
+        
+        /*
+        // the following code can be used to support SSL directly
+        server = new Server();
+        
+        SslSocketConnector connector = new SslSocketConnector();
+        connector.setPort(port);
+        connector.setKeystore("data/keystore");
+        connector.setPassword("123456");
+        connector.setKeyPassword("123456");
+        connector.setTruststore("data/keystore");
+        connector.setTrustPassword("123456");
+        server.addConnector(connector);*/
+
+        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+        context.setContextPath("/");
+        server.setHandler(context);
+ 
+        context.addServlet(new ServletHolder(servlet), "/*");
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#start()
+     */
+    @Override
+    public synchronized void start() throws HttpMonitorException {
+        if (server == null) {
+            throw new IllegalStateException("server not initialized yet. First call init()");
+        }
+        
+        try {
+            server.start();
+        }
+        catch (Exception e) {
+            throw new HttpMonitorException("could not start server", e);
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#stop()
+     */
+    @Override
+    public synchronized void stop() {
+        try {
+            if (server != null) {
+                server.stop();
+            }
+        }
+        catch (Exception e) {
+            Console.printerrln("could not stop server: " + e.getMessage());
+            Console.logException(e);
+        }
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorServlet.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorServlet.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/HttpMonitorServlet.java	(revision 1374)
@@ -0,0 +1,90 @@
+//   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.httpmonitor;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpExchange;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * the servlet deployed in the web server that receives all recorded exchanges from the proxy. The
+ * exchanges are parsed and forwarded to the provided exchange handler. If an exchange can not
+ * be parsed it is discarded. Exchanges are only received via the POST HTTP method.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class HttpMonitorServlet extends HttpServlet {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * the exchange handler to forward received exchanges to.
+     */
+    private transient HttpMonitorExchangeHandler exchangeHandler;
+
+    /**
+     * <p>
+     * initializes the servlet with the exchange handler to which all exchanges shall be forwarded
+     * </p>
+     *
+     * @param exchangeHandler the exchange handler that shall receive all exchanges
+     */
+    HttpMonitorServlet(HttpMonitorExchangeHandler exchangeHandler) {
+        this.exchangeHandler = exchangeHandler;
+    }
+
+    /**
+     * this implements handling of doPost. For this servlet this means that
+     * the data from the post request will be parsed and the contained exchanges forwarded to the
+     * exchange handler.
+     * 
+     * (non-Javadoc)
+     * @see org.mortbay.jetty.servlet.DefaultServlet#doPost(HttpServletRequest, HttpServletResponse)
+     */
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse response)
+        throws ServletException, IOException
+    {
+        try {
+            JAXBContext jaxbContext =
+                JAXBContext.newInstance(HttpExchange.class.getPackage().getName());
+            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+            
+            @SuppressWarnings("unchecked")
+            JAXBElement<HttpExchange> jaxObject =
+                (JAXBElement<HttpExchange>) unmarshaller.unmarshal(request.getReader());
+            
+            exchangeHandler.handleHttpExchange(jaxObject.getValue());
+        }
+        catch (JAXBException e) {
+            Console.printerrln
+                ("could not parse incoming data --> discarding it (" + e.toString() + ")");
+        }
+    }
+    
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/Runner.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/Runner.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/Runner.java	(revision 1374)
@@ -0,0 +1,83 @@
+//   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.httpmonitor;
+
+import java.util.Arrays;
+
+import de.ugoe.cs.autoquest.httpmonitor.proxy.HttpMonitoringProxy;
+import de.ugoe.cs.util.console.Console;
+import de.ugoe.cs.util.console.TextConsole;
+
+/**
+ * <p>
+ * implements the main method to start the {@link HttpMonitor} or the {@link HttpMonitoringProxy}.
+ * Which one is to be started is determined by the first command line argument. If this is set to
+ * "proxy" then the proxy is started. If this is set to "monitor" or left out then the monitor is
+ * started.
+ * </p>
+ * 
+ * @author Patrick Harms
+ * @version 1.0
+ */
+public class Runner {
+
+    /**
+     * <p>
+     * Main method of the application.
+     * </p>
+     * 
+     * @param args command line arguments
+     */
+    public static void main(String[] args) {
+        new TextConsole();
+        
+        String type;
+        if (args.length > 0) {
+            type = args[0];
+        }
+        else {
+            type = "monitor";
+        }
+        
+        HttpMonitorComponent component;
+        String[] remainingArgs = Arrays.copyOfRange(args, 1, args.length);
+        
+        if ("monitor".equalsIgnoreCase(type)) {
+            component = new HttpMonitor(remainingArgs);
+        }
+        else if ("proxy".equalsIgnoreCase(type)) {
+            component = new HttpMonitoringProxy(remainingArgs);
+        }
+        else {
+            throw new IllegalArgumentException("unknown type of server requested: " + type);
+        }
+        
+        try {
+            component.init();
+        }
+        catch (HttpMonitorException e) {
+            Console.printerrln("could not initialize HTTP " + type + " server: " + e.getMessage());
+            Console.logException(e);
+        }
+        
+        try {
+            component.start();
+        }
+        catch (HttpMonitorException e) {
+            Console.printerrln("could not start HTTP " + type + " server: " + e.getMessage());
+            Console.logException(e);
+        }
+    }
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/ShutdownHook.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/ShutdownHook.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/ShutdownHook.java	(revision 1374)
@@ -0,0 +1,60 @@
+//   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.httpmonitor;
+
+/**
+ * <p>
+ * used to be able to shut down any {@link HttpMonitorComponent} that must be stopped if the
+ * application stops.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class ShutdownHook implements Runnable {
+
+    /**
+     * the components to be stopped on shutdown
+     */
+    private HttpMonitorComponent[] components;
+    
+    /**
+     * <p>
+     * initializes the shutdown hook with the components to be shut down on shutdown of the whole
+     * application
+     * </p>
+     *
+     */
+    public ShutdownHook(HttpMonitorComponent... components) {
+        this.components = components;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Thread#run()
+     */
+    @Override
+    public void run() {
+        for (HttpMonitorComponent component : components) {
+            if (component != null) {
+                try {
+                    component.stop();
+                }
+                catch (Exception e) {
+                    // ignore and go on
+                }
+            }
+        }
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/ExchangeListener.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/ExchangeListener.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/ExchangeListener.java	(revision 1374)
@@ -0,0 +1,313 @@
+//   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.httpmonitor.proxy;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Address;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Content;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Cookie;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Cookies;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Header;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Headers;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpExchange;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpRequest;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpResponse;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Method;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.ObjectFactory;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Protocol;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Status;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class ExchangeListener {
+    
+    /**
+     * 
+     */
+    private HttpMonitorExchangeHandler exchangeHandler;
+    
+    /**
+     * 
+     */
+    private HttpServletRequest request;
+
+    /**
+     * 
+     */
+    private List<ByteBuffer> requestData = new LinkedList<ByteBuffer>();
+    
+    /**
+     * 
+     */
+    private HttpServletResponse response;
+
+    /**
+     * 
+     */
+    private List<ByteBuffer> responseData = new LinkedList<ByteBuffer>();
+    
+    /**
+     * 
+     */
+    private long lastUpdate = System.currentTimeMillis();
+    
+    /**
+     *
+     */
+    ExchangeListener(HttpMonitorExchangeHandler exchangeHandler) {
+        this.exchangeHandler = exchangeHandler;
+    }
+
+    /**
+     * 
+     */
+    public void onRequest(HttpServletRequest request) throws IllegalStateException {
+        Console.traceln(Level.FINEST, this + ": onRequest " + request);
+
+        if (request == null) {
+            throw new IllegalArgumentException("request must not be null");
+        }
+
+        lastUpdate = System.currentTimeMillis();
+        this.request = request;
+    }
+
+    /**
+     * 
+     */
+    public void onRequestContent(ByteBuffer data) {
+        Console.traceln(Level.FINEST, this + ": onRequestContent " + data);
+
+        if (data == null) {
+            throw new IllegalArgumentException("data must not be null");
+        }
+
+        lastUpdate = System.currentTimeMillis();
+        requestData.add(data);
+    }
+    
+    /**
+     * 
+     */
+    public void onResponse(HttpServletResponse response) {
+        Console.traceln(Level.FINEST, this + ": onResponse " + response);
+
+        if (response == null) {
+            throw new IllegalArgumentException("response must not be null");
+        }
+
+        lastUpdate = System.currentTimeMillis();
+        this.response = response;
+    }
+    
+    /**
+     * 
+     */
+    public void onResponseContent(ByteBuffer data) {
+        Console.traceln(Level.FINEST, this + ": onResponseContent " + data);
+
+        if (data == null) {
+            throw new IllegalArgumentException("data must not be null");
+        }
+
+        lastUpdate = System.currentTimeMillis();
+        responseData.add(data);
+    }
+    
+    /**
+     * 
+     */
+    public void onFinish(Status status) {
+        Console.traceln(Level.FINEST, this + ": onFinish " + status);
+
+        if (status == null) {
+            throw new IllegalArgumentException("status must not be null");
+        }
+
+        lastUpdate = System.currentTimeMillis();
+        sendToExchangeHandler(status);
+    }
+    
+    /**
+     * @return the request
+     */
+    HttpServletRequest getRequest() {
+        return request;
+    }
+
+    /**
+     *
+     */
+    long getLastUpdate() {
+        return lastUpdate;
+    }
+
+    /**
+     *
+     */
+    private void sendToExchangeHandler(Status status) {
+        ObjectFactory eventObjectFactory = new ObjectFactory();
+        HttpExchange exchange = eventObjectFactory.createHttpExchange();
+        
+        exchange.setStatus(status);
+        
+        // the remote address
+        Address address = eventObjectFactory.createAddress();
+        address.setIp(request.getRemoteAddr());
+        address.setHost(request.getRemoteHost());
+        address.setPort(BigInteger.valueOf(request.getRemotePort()));
+        exchange.setSender(address);
+        
+        // the local address
+        address = eventObjectFactory.createAddress();
+        address.setIp(request.getLocalAddr());
+        address.setHost(request.getLocalName());
+        address.setPort(BigInteger.valueOf(request.getLocalPort()));
+        exchange.setReceiver(address);
+        
+        exchange.setRequest(map(request, eventObjectFactory));
+        exchange.setResponse(map(response, eventObjectFactory));
+        
+        exchangeHandler.handleHttpExchange(exchange);
+    }
+
+    /**
+     *
+     */
+    private HttpRequest map(HttpServletRequest request, ObjectFactory eventObjectFactory) {
+        HttpRequest eventRequest = eventObjectFactory.createHttpRequest();
+        eventRequest.setMethod(Method.fromValue(request.getMethod()));
+        eventRequest.setProtocol(Protocol.fromValue(request.getProtocol()));
+        eventRequest.setUrl(request.getRequestURL().toString());
+        eventRequest.setQuery(request.getQueryString());
+        
+        Headers headers = eventObjectFactory.createHeaders();
+        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+            String headerName = headerNames.nextElement();
+            
+            Enumeration<String> headerValues = request.getHeaders(headerName);
+            while (headerValues.hasMoreElements()) {
+                Header header = eventObjectFactory.createHeader();
+                header.setKey(headerName);
+                header.setValue(headerValues.nextElement());
+                headers.getHeader().add(header);
+            }
+        }
+        eventRequest.setHeaders(headers);
+        
+        if (request.getCookies() != null) {
+            Cookies cookies = eventObjectFactory.createCookies();
+            for (javax.servlet.http.Cookie requestCookie : request.getCookies()) {
+                Cookie cookie = eventObjectFactory.createCookie();
+                cookie.setComment(requestCookie.getComment());
+                cookie.setDomain(requestCookie.getDomain());
+                cookie.setIsHttpOnly(requestCookie.isHttpOnly());
+                cookie.setIsSecure(requestCookie.getSecure());
+                cookie.setMaxAge(BigInteger.valueOf(requestCookie.getMaxAge()));
+                cookie.setName(requestCookie.getName());
+                cookie.setPath(requestCookie.getPath());
+                cookie.setValue(requestCookie.getValue());
+                cookie.setVersion(BigInteger.valueOf(requestCookie.getVersion()));
+                cookies.getCookie().add(cookie);
+            }
+            eventRequest.setCookies(cookies);
+        }
+        
+        eventRequest.setAuthType(request.getAuthType());
+        eventRequest.setRemoteUser(request.getRemoteUser());
+        eventRequest.setRequestedSessionId(request.getRequestedSessionId());
+        
+        if (requestData.size() > 0) {
+            Content content = eventObjectFactory.createContent();
+            content.setEncoding(request.getCharacterEncoding());
+            content.setType(request.getContentType());
+            content.setLength(request.getContentLength());
+            content.setData(createString(requestData));
+            eventRequest.setContent(content);
+        }
+        
+        return eventRequest;
+    }
+
+    /**
+     *
+     */
+    private HttpResponse map(HttpServletResponse response, ObjectFactory eventObjectFactory) {
+        HttpResponse eventResponse = eventObjectFactory.createHttpResponse();
+        
+        eventResponse.setStatus(BigInteger.valueOf(response.getStatus()));
+
+        Headers headers = eventObjectFactory.createHeaders();
+        Collection<String> headerNames = response.getHeaderNames();
+        for (String headerName : headerNames) {
+            Collection<String> headerValues = response.getHeaders(headerName);
+            for (String headerValue : headerValues) {
+                Header header = eventObjectFactory.createHeader();
+                header.setKey(headerName);
+                header.setValue(headerValue);
+                headers.getHeader().add(header);
+            }
+        }
+        eventResponse.setHeaders(headers);
+        
+        if (responseData.size() > 0) {
+            Content content = eventObjectFactory.createContent();
+            content.setEncoding(response.getCharacterEncoding());
+            content.setType(response.getContentType());
+
+            String data = createString(responseData);
+            content.setLength(data.length());
+            content.setData(data);
+            
+            eventResponse.setContent(content);
+        }
+        
+        return eventResponse;
+    }
+
+    /**
+     *
+     */
+    private String createString(List<ByteBuffer> bufferList) {
+        StringBuffer str = new StringBuffer();
+        
+        for (ByteBuffer buffer : bufferList) {
+            while (buffer.hasRemaining()) {
+                str.append((char) buffer.get());
+            }
+        }
+        
+        return str.toString();
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/ExchangeListenerManager.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/ExchangeListenerManager.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/ExchangeListenerManager.java	(revision 1374)
@@ -0,0 +1,224 @@
+//   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.httpmonitor.proxy;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.logging.Level;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorException;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Status;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO update comment
+ * The log manager handles different {@link HttpMonitorOutputWriter}s to perform the logging
+ * of recorded messages. It initializes a new writer if the first message for a specific
+ * client is received and it closes a writer if for a specific period of time no further message
+ * of the same client was received. The writers themselves consider log rotation. For handling
+ * messages, the {@link HttpMonitorExchangeHandler} mechanism provided by the
+ * {@link HttpMonitorServer} is used.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class ExchangeListenerManager implements HttpMonitorComponent {
+    
+    /**
+     * the timeout after which a writer of an inactive client is closed
+     */
+    private static final int SESSION_TIMEOUT = 10 * 60 * 1000;
+    
+    /**
+     * 
+     */
+    private HttpMonitorExchangeHandler exchangeHandler;
+    
+    /**
+     * the mapping of client ids to the respective writers.
+     */
+    private Map<HttpServletRequest, ExchangeListener> listeners;
+
+    /**
+     * a timer used to detect exchange timeouts
+     */
+    private Timer listenerTimer;
+
+    /**
+     *
+     *
+     */
+    ExchangeListenerManager(HttpMonitorExchangeHandler exchangeHandler) {
+        this.exchangeHandler = exchangeHandler;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#init()
+     */
+    @Override
+    public synchronized void init() throws IllegalStateException, HttpMonitorException {
+        Console.traceln(Level.FINER, "initializing exchange listener manager");
+        
+        if (listeners != null) {
+            throw new IllegalStateException("already initialized");
+        }
+        
+        listeners = new HashMap<HttpServletRequest, ExchangeListener>();
+        listenerTimer = new Timer();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#start()
+     */
+    @Override
+    public synchronized void start() throws IllegalStateException, HttpMonitorException {
+        Console.traceln(Level.FINER, "starting exchange listener manager");
+
+        if (listeners == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        listenerTimer.schedule
+            (new ListenerMonitorTimerTask(), SESSION_TIMEOUT / 2, SESSION_TIMEOUT / 2);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HtmlMonitorComponent#stop()
+     */
+    @Override
+    public synchronized void stop() {
+        Console.traceln(Level.FINER, "stopping exchange listener manager");
+
+        if (listenerTimer != null) {
+            listenerTimer.cancel();
+        }
+        
+        if (listeners != null) {
+            for (ExchangeListener listener : listeners.values()) {
+                listener.onFinish(Status.TIMEOUT);
+            }
+        }
+        
+        listeners = null;
+    }
+
+    /**
+     * 
+     */
+    public void onRequest(HttpServletRequest request) throws IllegalStateException {
+        ensureListener(request).onRequest(request);
+    }
+
+    /**
+     * 
+     */
+    public void onRequestContent(HttpServletRequest request, ByteBuffer data)
+        throws IllegalStateException
+    {
+        ensureListener(request).onRequestContent(data);
+    }
+
+    /**
+     * 
+     */
+    public void onResponse(HttpServletRequest request, HttpServletResponse response)
+        throws IllegalStateException
+    {
+        ensureListener(request).onResponse(response);
+    }
+
+    /**
+     * 
+     */
+    public void onResponseContent(HttpServletRequest request, ByteBuffer data)
+        throws IllegalStateException
+    {
+        ensureListener(request).onResponseContent(data);
+    }
+
+    /**
+     * 
+     */
+    public void onFinish(HttpServletRequest request, Status status) throws IllegalStateException {
+        ensureListener(request).onFinish(status);
+        Console.traceln(Level.FINEST, "removing exchange listener for " + request);
+        listeners.remove(request);
+    }
+
+    /**
+     *
+     */
+    private ExchangeListener ensureListener(HttpServletRequest request) {
+        ExchangeListener listener = listeners.get(request);
+        
+        if (listener == null) {
+            synchronized (this) {
+                listener = listeners.get(request);
+                if (listener == null) {
+                    Console.traceln(Level.FINEST, "creating exchange listener for " + request);
+                    listener = new ExchangeListener(exchangeHandler); 
+                    listeners.put(request, listener);
+                }
+            }
+        }
+
+        return listener;
+    }
+
+    /**
+     * <p>
+     * internal timer task used for detecting session timeouts of clients
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    public class ListenerMonitorTimerTask extends TimerTask {
+
+        /* (non-Javadoc)
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            synchronized (ExchangeListenerManager.this) {
+                List<HttpServletRequest> timeoutRequests = new ArrayList<HttpServletRequest>();
+                for (Map.Entry<HttpServletRequest, ExchangeListener> entry : listeners.entrySet()) {
+                    ExchangeListener listener = entry.getValue();
+                    
+                    if (System.currentTimeMillis() - listener.getLastUpdate() > SESSION_TIMEOUT) {
+                        timeoutRequests.add(entry.getKey());
+                    }
+                }
+                
+                for (HttpServletRequest request : timeoutRequests) {
+                    ExchangeListener listener = listeners.remove(request);
+                    listener.onFinish(Status.TIMEOUT);
+                }
+            }
+        }
+
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitorRemoteExchangeHandler.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitorRemoteExchangeHandler.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitorRemoteExchangeHandler.java	(revision 1374)
@@ -0,0 +1,202 @@
+//   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.httpmonitor.proxy;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response.CompleteListener;
+import org.eclipse.jetty.client.api.Result;
+import org.eclipse.jetty.client.util.OutputStreamContentProvider;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorException;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.HttpExchange;
+import de.ugoe.cs.autoquest.httpmonitor.exchange.ObjectFactory;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class HttpMonitorRemoteExchangeHandler
+    implements CompleteListener, HttpMonitorExchangeHandler, HttpMonitorComponent
+{
+
+    /** */
+    private HttpClient httpClient;
+    
+    /** */
+    private String httpMonitorServer;
+    
+    /** */
+    private int httpMonitorPort;
+
+    /** */
+    private Set<Request> openRequests = new HashSet<Request>();
+    
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param httpMonitorServer2
+     * @param httpMonitorPort2
+     */
+    public HttpMonitorRemoteExchangeHandler(String httpMonitorServer, int httpMonitorPort) {
+        this.httpMonitorServer = httpMonitorServer;
+        this.httpMonitorPort = httpMonitorPort;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#init()
+     */
+    @Override
+    public void init() throws IllegalStateException, HttpMonitorException {
+        httpClient = createHttpClient();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#start()
+     */
+    @Override
+    public void start() throws IllegalStateException, HttpMonitorException {
+        try {
+            httpClient.start();
+            httpClient.getContentDecoderFactories().clear();
+        }
+        catch (Exception e) {
+            throw new HttpMonitorException("could not start client for HTTP-Monitor", e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent#stop()
+     */
+    @Override
+    public void stop() {
+        if (httpClient != null) {
+            try {
+                httpClient.stop();
+            }
+            catch (Exception e) {
+                Console.traceln(Level.WARNING, "could not stop client for HTTP-Monitor");
+                Console.logException(e);
+            }
+        }
+        
+        httpClient = null;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler#handleHttpExchange()
+     */
+    @Override
+    public void handleHttpExchange(HttpExchange httpExchange) {
+        // send the exchange to the server and wait for completion
+        synchronized (openRequests) {
+            Request httpMonitorRequest = httpClient.newRequest(httpMonitorServer, httpMonitorPort);
+            httpMonitorRequest.method(HttpMethod.POST);
+            httpMonitorRequest.version(HttpVersion.HTTP_1_1);
+
+            OutputStreamContentProvider out = new OutputStreamContentProvider();
+            httpMonitorRequest.content(out);
+            httpMonitorRequest.send(this);
+
+            try {
+                JAXBContext jaxbContext =
+                        JAXBContext.newInstance(HttpExchange.class.getPackage().getName());
+                Marshaller marshaller = jaxbContext.createMarshaller();
+
+                OutputStreamWriter writer = new OutputStreamWriter(out.getOutputStream());
+                marshaller.marshal(new ObjectFactory().createHttpExchange(httpExchange), writer);
+
+                out.getOutputStream().close();
+            }
+            catch (JAXBException e) {
+                Console.printerrln("could not convert request and response to XML string: " + e);
+                Console.logException(e);
+            }
+            catch (IOException e) {
+                Console.printerrln
+                ("could not close the stream for sending data to the HTML monitor: " + e);
+                Console.logException(e);
+            }
+            
+            openRequests.add(httpMonitorRequest);
+            
+            try {
+                // wait for the request to be removed fromt the list asynchronously
+                while (openRequests.contains(httpMonitorRequest)) {
+                    openRequests.wait();
+                }
+            }
+            catch (InterruptedException e) {
+                // ignore, as this may only happen on system shutdown
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jetty.client.api.Response.CompleteListener#onComplete(Result)
+     */
+    @Override
+    public void onComplete(Result result) {
+        if (result.isFailed()) {
+            Console.traceln
+                (Level.WARNING, "could not log exchange correctly: " + result.getFailure());
+            Console.logException((Exception) result.getFailure());
+        }
+        
+        synchronized (openRequests) {
+            openRequests.remove(result.getRequest());
+            openRequests.notify();
+        }
+    }
+
+    /**
+     * 
+     */
+    private HttpClient createHttpClient() {
+        HttpClient client = new HttpClient();
+        
+        QueuedThreadPool executor = new QueuedThreadPool(10);
+        executor.setName("HttpMonitorClients");
+        client.setExecutor(executor);
+
+        client.setMaxConnectionsPerDestination(10000);
+        client.setIdleTimeout(30000);
+        client.setRequestBufferSize(1024*1024);
+        client.setResponseBufferSize(1024*1024);
+        
+        return client;
+    }
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxy.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxy.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxy.java	(revision 1374)
@@ -0,0 +1,230 @@
+//   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.httpmonitor.proxy;
+
+import javax.servlet.Servlet;
+
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorException;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorExchangeHandler;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorLogManager;
+import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorServer;
+import de.ugoe.cs.autoquest.httpmonitor.Runner;
+import de.ugoe.cs.autoquest.httpmonitor.ShutdownHook;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO comment
+ * The HTML monitor starts a web server ({@link HttpMonitorServer}) that receives log messages
+ * of the HTML monitor java script. These messages are logged using the
+ * {@link ExchangeListenerManager}. The class assures that on shutdown e.g. caused by CTRL-C the
+ * server and the log manager are stopped correctly.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class HttpMonitoringProxy implements HttpMonitorComponent {
+
+    /**
+     * the port on which the webserver shall listen.
+     */
+    private int port;
+    
+    /**
+     * the web server receiving the log messages
+     */
+    private HttpMonitorServer server;
+    
+    /**
+     * the web server receiving the log messages
+     */
+    private ExchangeListenerManager exchangeListenerManager;
+    
+    /**
+     * 
+     */
+    private HttpMonitorExchangeHandler exchangeHandler;
+    
+    /**
+     * the directory into which the log files shall be written
+     */
+    private String logFileBaseDir;
+
+    /**
+     * the thread needed to handle CTRL-C events
+     */
+    private Thread shutdownHook;
+
+    /** */
+    private String proxiedServer;
+    
+    /** */
+    private int proxiedPort;
+    
+    /** */
+    private String httpMonitorServer;
+    
+    /** */
+    private int httpMonitorPort;
+    
+    /**
+     * <p>
+     * initializes the monitor with the command line arguments. Those may be the log directory
+     * as first argument and the port to listen on as second
+     * </p>
+     *
+     * @param commandLineArguments the command line arguments when starting the monitor using
+     *                             the {@link Runner}
+     */
+    public HttpMonitoringProxy(String[] commandLineArguments) {
+        if (commandLineArguments.length != 4) {
+            Console.printerrln("invalid number of command line parameters. Three are required:");
+            Console.printerrln("  1. the port on which to listen");
+            Console.printerrln("  2. the server and port to be proxied (format \"host:port\")");
+            Console.printerrln
+                ("  3. variant a: the value \"local\" for logging recorded exchanges locally");
+            Console.printerrln
+                ("     variant b: the server and port of the HTTP monitor to send the recorded\n" +
+                 "                exchanges to (format \"host:port\")");
+            throw new IllegalArgumentException();
+        }
+        
+        this.logFileBaseDir = commandLineArguments[0];
+
+        try {
+            this.port = Integer.parseInt(commandLineArguments[1]);
+        }
+        catch (NumberFormatException e) {
+            Console.printerrln("invalid port specification " + commandLineArguments[1]);
+        }
+        Console.println("listening on port " + this.port);
+
+        proxiedServer = commandLineArguments[2];
+        
+        int index = proxiedServer.indexOf(':');
+        if (index > -1) {
+            try {
+                proxiedPort = Integer.parseInt(proxiedServer.substring(index + 1));
+            }
+            catch (NumberFormatException e) {
+                Console.printerrln
+                    ("invalid port specification " + proxiedServer.substring(index + 1));
+            }
+            
+            proxiedServer = proxiedServer.substring(0, index);
+        }
+        else {
+            proxiedPort = 80;
+        }
+        
+        Console.println("proxing " + proxiedServer + ":" + proxiedPort);
+        
+        httpMonitorServer = commandLineArguments[3];
+        
+        index = httpMonitorServer.indexOf(':');
+        if (index > -1) {
+            try {
+                httpMonitorPort = Integer.parseInt(httpMonitorServer.substring(index + 1));
+            }
+            catch (NumberFormatException e) {
+                Console.printerrln
+                    ("invalid port specification " + httpMonitorServer.substring(index + 1));
+            }
+            
+            httpMonitorServer = httpMonitorServer.substring(0, index);
+        }
+        else if ("local".equals(httpMonitorServer)) {
+            httpMonitorServer = null;
+        }
+        else {
+            httpMonitorPort = 80;
+        }
+        
+        if (httpMonitorServer != null) {
+            Console.println("sending log data to " + httpMonitorServer + ":" + httpMonitorPort);
+            exchangeHandler =
+                new HttpMonitorRemoteExchangeHandler(httpMonitorServer, httpMonitorPort);
+        }
+        else {
+            Console.println("storing logs locally into directory " + logFileBaseDir);
+            exchangeHandler = new HttpMonitorLogManager(logFileBaseDir);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#init()
+     */
+    @Override
+    public synchronized void init() throws HttpMonitorException {
+        if (server != null) {
+            throw new IllegalStateException("already initialized.");
+        }
+        
+        exchangeHandler.init();
+        
+        exchangeListenerManager = new ExchangeListenerManager(exchangeHandler);
+        exchangeListenerManager.init();
+        
+        Servlet servlet =
+            new HttpMonitoringProxyServlet(proxiedServer, proxiedPort, exchangeListenerManager);
+        server = new HttpMonitorServer(port, servlet);
+        server.init();
+      
+        shutdownHook = new Thread
+            (new ShutdownHook(server, exchangeListenerManager, exchangeHandler));
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#start()
+     */
+    @Override
+    public synchronized void start() {
+        if ((exchangeHandler == null) || (exchangeListenerManager == null) || (server == null)) {
+            throw new IllegalStateException("not initialized.");
+        }
+        
+        try {
+            Runtime.getRuntime().addShutdownHook(shutdownHook);
+            exchangeHandler.start();
+            exchangeListenerManager.start();
+            server.start();
+        }
+        catch (HttpMonitorException e) {
+            Console.printerrln("could not start HTTP monitoring proxy: " + e);
+            Console.logException(e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.htmlmonitor.HttpMonitorComponent#stop()
+     */
+    @Override
+    public synchronized void stop() {
+        if ((exchangeHandler == null) || (exchangeListenerManager == null) || (server == null)) {
+            throw new IllegalStateException("not initialized.");
+        }
+        
+        Runtime.getRuntime().removeShutdownHook(shutdownHook);
+        server.stop();
+        exchangeListenerManager.stop();
+        exchangeHandler.stop();
+        
+        server = null;
+        exchangeListenerManager = null;
+        exchangeHandler = null;
+    }
+
+}
Index: /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxyServlet.java
===================================================================
--- /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxyServlet.java	(revision 1374)
+++ /trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxyServlet.java	(revision 1374)
@@ -0,0 +1,233 @@
+//   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.httpmonitor.proxy;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.api.ContentProvider;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.proxy.ProxyServlet;
+
+import de.ugoe.cs.autoquest.httpmonitor.exchange.Status;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO document
+ * the servlet deployed in the web server that receives all client messages and returns the client
+ * java script. The messages are parsed, validated, and forwarded to the provided message listener.
+ * If a message is not valid, it is discarded. If an event in a message is not valid, it is
+ * discarded. Messages are only received via the POST HTTP method. The GET HTTP method is only
+ * implemented for returning the client java script.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class HttpMonitoringProxyServlet extends ProxyServlet {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /** */
+    private String proxiedServer;
+    
+    /** */
+    private int proxiedPort;
+
+    /** */
+    private ExchangeListenerManager exchangeListenerManager;
+    
+    /**
+     * <p>
+     * initializes the servlet with the message listener to which all events shall be forwarded
+     * </p>
+     *
+     * @param messageListener the message listener that shall receive all client events
+     */
+    HttpMonitoringProxyServlet(String                  proxiedServer,
+                               int                     proxiedPort,
+                               ExchangeListenerManager exchangeListenerManager)
+    {
+        this.proxiedServer = proxiedServer;
+        this.proxiedPort = proxiedPort;
+        this.exchangeListenerManager = exchangeListenerManager;
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jetty.proxy.ProxyServlet#rewriteURI(javax.servlet.http.HttpServletRequest)
+     */
+    @Override
+    protected URI rewriteURI(HttpServletRequest request) {
+        try {
+            return new URI(request.getScheme(), null, proxiedServer, proxiedPort,
+                           request.getPathTranslated(), request.getQueryString(), null);
+        }
+        catch (URISyntaxException e) {
+            Console.printerrln("could not rewrite URI: " + e);
+            Console.logException(e);
+            return null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jetty.proxy.ProxyServlet#customizeProxyRequest(org.eclipse.jetty.client.api.Request, javax.servlet.http.HttpServletRequest)
+     */
+    @Override
+    protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request) {
+        super.customizeProxyRequest(proxyRequest, request);
+        
+        exchangeListenerManager.onRequest(request);
+        proxyRequest.content(new DubbingContentProvider(request, proxyRequest.getContent()));
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jetty.proxy.ProxyServlet#onResponseContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.eclipse.jetty.client.api.Response, byte[], int, int)
+     */
+    @Override
+    protected void onResponseContent(HttpServletRequest  request,
+                                     HttpServletResponse response,
+                                     Response            proxyResponse,
+                                     byte[]              buffer,
+                                     int                 offset,
+                                     int                 length)
+        throws IOException
+    {
+        super.onResponseContent(request, response, proxyResponse, buffer, offset, length);
+        
+        exchangeListenerManager.onResponseContent(request, ByteBuffer.wrap(buffer, offset, length));
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jetty.proxy.ProxyServlet#onResponseSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.eclipse.jetty.client.api.Response)
+     */
+    @Override
+    protected void onResponseSuccess(HttpServletRequest  request,
+                                     HttpServletResponse response,
+                                     Response            proxyResponse)
+    {
+        exchangeListenerManager.onResponse(request, response);
+        exchangeListenerManager.onFinish(request, Status.SUCCESS);
+        
+        super.onResponseSuccess(request, response, proxyResponse);
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jetty.proxy.ProxyServlet#onResponseFailure(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.eclipse.jetty.client.api.Response, java.lang.Throwable)
+     */
+    @Override
+    protected void onResponseFailure(HttpServletRequest  request,
+                                     HttpServletResponse response,
+                                     Response            proxyResponse,
+                                     Throwable           failure)
+    {
+        exchangeListenerManager.onResponse(request, response);
+        exchangeListenerManager.onFinish(request, Status.FAILURE);
+        
+        super.onResponseFailure(request, response, proxyResponse, failure);
+    }
+
+    /**
+     *
+     */
+    private class DubbingContentProvider implements ContentProvider {
+
+        /** */
+        private HttpServletRequest request;
+        
+        /** */
+        private ContentProvider delegate;
+
+        /**
+         *
+         */
+        public DubbingContentProvider(HttpServletRequest request, ContentProvider delegate) {
+            this.request = request;
+            this.delegate = delegate;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Iterable#iterator()
+         */
+        @Override
+        public Iterator<ByteBuffer> iterator() {
+            return new DubbingByteBufferIterator(request, delegate.iterator());
+        }
+
+        /* (non-Javadoc)
+         * @see org.eclipse.jetty.client.api.ContentProvider#getLength()
+         */
+        @Override
+        public long getLength() {
+            return delegate.getLength();
+        }
+
+    }
+
+    /**
+     *
+     */
+    public class DubbingByteBufferIterator implements Iterator<ByteBuffer> {
+
+        /** */
+        private HttpServletRequest request;
+        
+        /** */
+        private Iterator<ByteBuffer> delegate;
+        
+        /**
+         *
+         */
+        public DubbingByteBufferIterator(HttpServletRequest request, Iterator<ByteBuffer> delegate) {
+            this.request = request;
+            this.delegate = delegate;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Iterator#hasNext()
+         */
+        @Override
+        public boolean hasNext() {
+            return delegate.hasNext();
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Iterator#next()
+         */
+        @Override
+        public ByteBuffer next() {
+            ByteBuffer next = delegate.next();
+            exchangeListenerManager.onRequestContent(request, next.duplicate());
+            return next;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Iterator#remove()
+         */
+        @Override
+        public void remove() {
+            delegate.remove();
+        }
+
+    }
+
+}
