Index: /trunk/autoquest-plugin-html/pom.xml
===================================================================
--- /trunk/autoquest-plugin-html/pom.xml	(revision 1241)
+++ /trunk/autoquest-plugin-html/pom.xml	(revision 1242)
@@ -37,4 +37,9 @@
             <version>${project.parent.version}</version>
         </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.7</version>
+        </dependency>
     </dependencies>
     <build>
Index: /trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/HTMLLogTextInputPseudomizer.java
===================================================================
--- /trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/HTMLLogTextInputPseudomizer.java	(revision 1242)
+++ /trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/HTMLLogTextInputPseudomizer.java	(revision 1242)
@@ -0,0 +1,354 @@
+//   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.plugin.html;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.codec.binary.Base64;
+import org.xml.sax.SAXException;
+
+import de.ugoe.cs.util.StringTools;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ * @version 1.0
+ * 
+ */
+public class HTMLLogTextInputPseudomizer extends AbstractDefaultLogParser {
+    
+    /**
+     * <p>
+     * The output writer into which the pseudomized variant of the log file is written
+     * </p>
+     */
+    private PrintWriter outputWriter;
+    
+    /**
+     * <p>
+     * The set of text input fields found in the GUI model
+     * </p>
+     */
+    private Set<String> textInputFieldIds = new HashSet<String>();
+    
+    /**
+     * <p>
+     * the events that were read
+     * </p>
+     */
+    private List<EventEntry> sortedEvents = new LinkedList<EventEntry>();
+
+    /**
+     * <p>
+     * called to pseudomize all text inputs in the given log file. The method reuses 
+     * {@link #pseudomizeFile(File)}.
+     * </p>
+     * 
+     * @param file the log file in which the text inputs must be pseudomized
+     */
+    public void pseudomizeFile(String file) {
+        if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+
+        pseudomizeFile(new File(file));
+    }
+
+    /**
+     * <p>
+     * called to pseudomize all text inputs in the given log file. The given file is read
+     * completely. All GUI elements are written to an output file as they are. All events are
+     * written to an output file as they are, as well, as long as they do not represent test inputs.
+     * If they are text input events, the entered text is replaced by its hash value for
+     * pseudomizing the text input. Finally, the original log file is deleted and replaced by
+     * the pseudomized variant. Log files, which are already pseudomized, stay untouched.
+     * </p>
+     * 
+     * @param file the log file in which the text inputs must be pseudomized
+     */
+    public void pseudomizeFile(File file) {
+        if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+        
+        if (!file.exists()) {
+            throw new IllegalArgumentException("file must denote an existing file");
+        }
+        
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("file must denote a file");
+        }
+        
+        File outFile = new File(file.getParentFile(), file.getName() + "_tmp");
+        boolean parsingFailed = false;
+        
+        try {
+            FileOutputStream fis = new FileOutputStream(outFile);
+            outputWriter = new PrintWriter(new OutputStreamWriter(fis, "UTF-8"));
+            outputWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+            outputWriter.println("<session>");
+
+            textInputFieldIds.clear();
+            sortedEvents.clear();
+            
+            try {
+                super.parseFile(file);
+            }
+            catch (SAXException e) {
+                parsingFailed = true;
+            }
+            
+            for (EventEntry event : sortedEvents) {
+                event.dump();
+            }
+            
+            outputWriter.println("</session>");
+            outputWriter.flush();
+        }
+        catch (FileNotFoundException e) {
+            Console.printerrln("could not create pseudomized file " + outFile);
+        }
+        catch (UnsupportedEncodingException e) {
+            // this should never happen
+            e.printStackTrace();
+        }
+        finally {
+            if (outputWriter != null) {
+                outputWriter.close();
+                outputWriter = null;
+            }
+        }
+        
+        if (!parsingFailed && outFile.exists()) {
+            if (!file.delete()) {
+                Console.printerrln("could not delete pseudomized file " + file);
+            }
+            else if (!outFile.renameTo(file)) {
+                Console.printerrln
+                    ("could not rename pseudomized file to original file name " + file);
+            }            
+            else {
+                Console.println("pseudomized file " + file);
+            }
+        }
+        else {
+            if (!outFile.delete()) {
+                Console.printerrln("could not delete temporary file " + outFile);
+            }
+        }
+    }
+    
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#parseFile(java.lang.String)
+     */
+    @Override
+    public void parseFile(String filename) {
+        throw new IllegalStateException("this method must not be called externally");
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#parseFile(java.io.File)
+     */
+    @Override
+    public void parseFile(File file) {
+        throw new IllegalStateException("this method must not be called externally");
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleGUIElement(String, Map)
+     */
+    @Override
+    protected boolean handleGUIElement(String id, Map<String, String> parameters)
+        throws SAXException
+    {
+        outputWriter.print("<component id=\"");
+        outputWriter.print(id);
+        outputWriter.println("\">");
+        
+        for (Map.Entry<String, String> param : parameters.entrySet()) {
+            dumpParam(param.getKey(), param.getValue());
+            
+            if ("tagname".equals(param.getKey()) && "input_text".equals(param.getValue())) {
+                textInputFieldIds.add(id);
+            }
+        }
+            
+        outputWriter.println("</component>");
+        
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleEvent(String,Map)
+     */
+    @Override
+    protected boolean handleEvent(String type, Map<String, String> parameters) throws SAXException {
+        String timestampStr = parameters.get("timestamp");
+        
+        long timestamp = Long.MAX_VALUE;
+        
+        if (timestampStr != null) {
+            timestamp = Long.parseLong(timestampStr);
+        }
+        
+        EventEntry newEvent = new EventEntry(type, parameters, timestamp);
+        
+        boolean added = false;
+        for (int i = 0; i < sortedEvents.size(); i++) {
+            if (sortedEvents.get(i).timestamp > newEvent.timestamp) {
+                sortedEvents.add(i, newEvent);
+                added = true;
+                break;
+            }
+        }
+        
+        if (!added) {
+            sortedEvents.add(newEvent);
+        }
+        
+        if ("onchange".equals(type)) {
+            String targetId = parameters.get("target");
+        
+            if ((targetId != null) && textInputFieldIds.contains(targetId)) {
+                String value = parameters.get("selectedValue");
+                
+                if (!value.endsWith("==")) {
+                    try {
+                        MessageDigest md = MessageDigest.getInstance("SHA-512");
+                        md.update(value.getBytes("UTF-8"));
+                        value =  Base64.encodeBase64String(md.digest());
+                    }
+                    catch (UnsupportedEncodingException e) {
+                        throw new IllegalStateException("Java VM does not support this code");
+                    }
+                    catch (NoSuchAlgorithmException e) {
+                        throw new IllegalStateException("Java VM does not support this code");
+                    }
+                }
+                
+                parameters.put("selectedValue", value);
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * <p>
+     * dumps a parameter with the given name and value to the log file. The result is a
+     * tag named param with a name attribute and a value attribute. The value is transformed
+     * to a String if it is no String already. Furthermore, an XML entity replacement is performed
+     * if required.
+     * </p>
+     *
+     * @param name  the name of the parameter to be dumped
+     * @param value the value of the parameter to be dumped
+     */
+    private void dumpParam(String name, Object value) {
+        if (value == null) {
+            return;
+        }
+        
+        String val;
+        
+        if (value instanceof String) {
+            val = (String) value;
+        }
+        else {
+            val = String.valueOf(value);
+        }
+        
+        outputWriter.print(" <param name=\"");
+        outputWriter.print(name);
+        outputWriter.print("\" value=\"");
+        outputWriter.print(StringTools.xmlEntityReplacement(val));
+        outputWriter.println("\"/>");
+    }
+
+
+    /**
+     * <p>
+     * this class is used internally for storing events in a sorted list together with the
+     * timestamps, being the sort criteria. 
+     * </p>
+     */
+    private class EventEntry {
+        
+        /**
+         * <p>
+         * the type of the event
+         * </p>
+         */
+        private String type;
+        
+        /**
+         * <p>
+         * the parameters of the event
+         * </p>
+         */
+        private Map<String, String> parameters;
+        
+        /**
+         * <p>
+         * the timestamp of the event
+         * </p>
+         */
+        private long timestamp;
+
+        /**
+         * <p>
+         * creates a new event entry with event type, parameters and the timestamp
+         * </p>
+         */
+        private EventEntry(String type, Map<String, String> parameters, long timestamp) {
+            this.type = type;
+            this.parameters = parameters;
+            this.timestamp = timestamp;
+        }
+        
+        /**
+         * <p>
+         * convenience method for dumping the event into the compressed log file
+         * </p>
+         */
+        private void dump() {
+            outputWriter.print("<event type=\"");
+            outputWriter.print(type);
+            outputWriter.println("\">");
+            
+            for (Map.Entry<String, String> param : parameters.entrySet()) {
+                dumpParam(param.getKey(), param.getValue());
+            }
+            
+            outputWriter.println("</event>");
+        }
+    }
+}
Index: /trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/commands/CMDpseudomizeHTMLTextInputs.java
===================================================================
--- /trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/commands/CMDpseudomizeHTMLTextInputs.java	(revision 1242)
+++ /trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/commands/CMDpseudomizeHTMLTextInputs.java	(revision 1242)
@@ -0,0 +1,87 @@
+//   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.plugin.html.commands;
+
+import java.io.File;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.plugin.html.HTMLLogTextInputPseudomizer;
+import de.ugoe.cs.util.console.Command;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ * @version 1.0
+ */
+public class CMDpseudomizeHTMLTextInputs implements Command {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
+     */
+    @Override
+    public void run(List<Object> parameters) {
+        String path;
+
+        try {
+            path = (String) parameters.get(0);
+        }
+        catch (Exception e) {
+            throw new IllegalArgumentException("illegal parameters provided: " + e);
+        }
+
+        File directory = new File(path);
+        if (!directory.isDirectory()) {
+            Console.printerrln(path + " is not a directory");
+            return;
+        }
+
+        pseudomizeTextInputsInDirectory(directory);
+
+    }
+
+    /**
+     * 
+     */
+    private void pseudomizeTextInputsInDirectory(File directory) {
+        if (directory.isDirectory()) {
+            File[] children = directory.listFiles();
+            
+            for (File child : children) {
+                pseudomizeTextInputsInDirectory(child);
+            }
+        }
+        else if (directory.isFile()) {
+            HTMLLogTextInputPseudomizer pseudomizer = new HTMLLogTextInputPseudomizer();
+            pseudomizer.pseudomizeFile(directory);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#help()
+     */
+    @Override
+    public String help() {
+        return "pseudomizeHTMLTextInputs <directory>";
+    }
+
+}
