// 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.text.DecimalFormat; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.xml.sax.SAXException; import de.ugoe.cs.util.StringTools; import de.ugoe.cs.util.console.Console; /** *

* TODO comment *

* * @author Fabian Glaser, Patrick Harms * @version 1.0 * */ public class HTMLLogCompressor extends AbstractDefaultLogParser { /** * */ private PrintWriter outputWriter; /** * the GUI elements, that were already logged and need therefore not be logged again into * the same file */ private Set loggedGUIElementIds = new HashSet(); /** * the events that were read */ private List sortedEvents = new LinkedList(); /** * */ public void compressFilesInDirectory(String directory) { if (directory == null) { throw new IllegalArgumentException("directory must not be null"); } compressFilesInDirectory(new File(directory)); } /** * */ public void compressFilesInDirectory(File directory) { if (directory == null) { throw new IllegalArgumentException("directory must not be null"); } if (!directory.exists()) { throw new IllegalArgumentException("directory must denote an existing directory"); } if (!directory.isDirectory()) { throw new IllegalArgumentException("directory must denote a directory"); } File[] files = directory.listFiles(); if ((files == null) || (files.length == 0)) { Console.println("directory is empty"); return; } File outFile = null; int logFileIndex = -1; do { outFile = new File(directory, getLogFileName(directory.getName(), logFileIndex)); logFileIndex++; } while (outFile.exists()); List compressedFiles = new LinkedList(); try { FileOutputStream fis = new FileOutputStream(outFile); outputWriter = new PrintWriter(new OutputStreamWriter(fis, "UTF-8")); outputWriter.println(""); outputWriter.println(""); loggedGUIElementIds.clear(); sortedEvents.clear(); for (File file : files) { if (file.isFile()) { try { super.parseFile(file); Console.println("compressed " + file); compressedFiles.add(file); } catch (Exception e) { Console.printerrln("could not parse and compress file " + file); } } } for (EventEntry event : sortedEvents) { event.dump(); } outputWriter.println(""); outputWriter.flush(); } catch (FileNotFoundException e) { Console.printerrln("could not create compressed file " + outFile); compressedFiles.clear(); } catch (UnsupportedEncodingException e) { // this should never happen e.printStackTrace(); compressedFiles.clear(); } finally { if (outputWriter != null) { outputWriter.close(); outputWriter = null; } } for (File file : compressedFiles) { if (!file.delete()) { Console.printerrln("could not delete compressed file " + file); } } if (outFile.exists()) { File finalOutFile = null; logFileIndex = -1; do { logFileIndex++; finalOutFile = new File(directory, getLogFileName(directory.getName(), logFileIndex)); } while (finalOutFile.exists()); outFile.renameTo(finalOutFile); Console.println("created " + finalOutFile); } } /* (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 parameters) throws SAXException { if (!loggedGUIElementIds.contains(id)) { outputWriter.print(""); for (Map.Entry param : parameters.entrySet()) { dumpParam(param.getKey(), param.getValue()); } outputWriter.println(""); loggedGUIElementIds.add(id); } return true; } /* (non-Javadoc) * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleEvent(java.lang.String, java.util.Map) */ @Override protected boolean handleEvent(String type, Map 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); } return true; } /** *

* 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. *

* * @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(" "); } /** *

* 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. "htmlmonitor_12345_001.log". *

* * @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(String clientId, int index) { String result = "htmlmonitor_" + clientId; if (index >= 0) { result += "_" + new DecimalFormat("000" ).format(index); } result += ".log"; return result; } /** * */ private class EventEntry { /** * */ private String type; /** * */ private Map parameters; /** * */ private long timestamp; /** *

* TODO: comment *

* * @param type * @param parameters * @param timestamp */ private EventEntry(String type, Map parameters, long timestamp) { this.type = type; this.parameters = parameters; this.timestamp = timestamp; } /** * */ private void dump() { outputWriter.print(""); for (Map.Entry param : parameters.entrySet()) { dumpParam(param.getKey(), param.getValue()); } outputWriter.println(""); } } }