package de.ugoe.cs.eventbench.jfc; import java.awt.event.FocusEvent; import java.awt.event.MouseEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.security.InvalidParameterException; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import de.ugoe.cs.eventbench.jfc.data.JFCEvent; import de.ugoe.cs.util.console.Console; /** *

* This class provides functionality to parse XML log files generated by the * JFCMonitor of EventBench. The result of parsing a file is a collection of * event sequences. *

* * @author Steffen Herbold * @version 1.0 */ public class JFCLogParser extends DefaultHandler { /** *

* Collection of event sequences that is contained in the log file, which is * parsed. *

*/ private Collection> sequences; /** *

* Internal handle to the event that is currently being parsed. *

*/ private JFCEvent currentEvent; /** *

* Internal handle to the event sequence that is currently being parsed. *

*/ private List currentSequence = null; /** *

* Internally used string to build a string representing a component-node. *

*/ private String componentString; /** *

* Enumeration to differentiate if a parameter belongs to an event, a source * or the parent of a source. *

* * @author Steffen Herbold * @version 1.0 */ private enum ParamSource { EVENT, SOURCE, PARENT, COMPONENT }; /** *

* Specifies whether the parameters that are currently being read belong the * the event, the source or the parent. *

*/ ParamSource paramSource = null; private Collection eventFilter; /** *

* Constructor. Creates a new JFCLogParser with a default event filter. * This ignores focus events, mouse pressed, and mouse released events. *

*/ public JFCLogParser() { sequences = new LinkedList>(); currentSequence = new LinkedList(); setupDefaultEventFilter(); } /** *

* Constructor. Creates a new JFCLogParser with a specific event filter. * The events in the provided collection are ignored by the parser. * As events, the constants of the different event classes must be used. * E.g. creating a collection and putting * MouseEvent.MOUSE_PRESSED will cause the parser to ignore * all mouse pressed events. If the provided collection is null, no event * is ignored. *

* * @param ignoredEvents the events to be ignored by the parser, can be null */ public JFCLogParser(Collection ignoredEvents) { sequences = new LinkedList>(); currentSequence = new LinkedList(); eventFilter = ignoredEvents; } /** *

* creates a default event filter that ignores focus changes, mouse pressed * and mouse released events. *

*/ private void setupDefaultEventFilter() { eventFilter = new HashSet(); eventFilter.add(MouseEvent.MOUSE_PRESSED); eventFilter.add(MouseEvent.MOUSE_RELEASED); eventFilter.add(FocusEvent.FOCUS_GAINED); } /** *

* Returns the collection of event sequences that is obtained from parsing * log files. *

* * @return collection of event sequences */ public Collection> getSequences() { return sequences; } /* * (non-Javadoc) * * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, * java.lang.String, java.lang.String, org.xml.sax.Attributes) */ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { if (qName.equals("sessions")) { currentSequence = new LinkedList(); } if (qName.equals("newsession")) { Console.traceln("start of session"); if (currentSequence != null && !currentSequence.isEmpty()) { sequences.add(currentSequence); } currentSequence = new LinkedList(); } else if (qName.equals("event")) { int eventId = Integer.parseInt(atts.getValue("id")); if ((eventFilter == null) || (!eventFilter.contains(eventId))) { currentEvent = new JFCEvent(atts.getValue("id")); paramSource = ParamSource.EVENT; } } else if (currentEvent != null) { if (qName.equals("param")) { if (paramSource == ParamSource.EVENT) { currentEvent.addParameter(atts.getValue("name"), atts.getValue("value")); } else if (paramSource == ParamSource.SOURCE) { currentEvent.addSourceInformation(atts.getValue("name"), atts.getValue("value")); } else if (paramSource == ParamSource.PARENT) { currentEvent.addParentInformation(atts.getValue("name"), atts.getValue("value")); } else if (paramSource == ParamSource.COMPONENT) { componentString += "'" + atts.getValue("value") + "',"; } } else if (qName.equals("source")) { paramSource = ParamSource.SOURCE; } else if (qName.equals("parent")) { paramSource = ParamSource.PARENT; } else if (qName.equals("component")) { paramSource = ParamSource.COMPONENT; componentString = "["; } } } /* * (non-Javadoc) * * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, * java.lang.String, java.lang.String) */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("sessions")) { if (currentSequence != null && !currentSequence.isEmpty()) { sequences.add(currentSequence); } currentSequence = null; } else if (currentEvent != null) { if (qName.equals("event")) { currentSequence.add(currentEvent); currentEvent = null; } else if (qName.equals("source")) { paramSource = ParamSource.EVENT; } else if (qName.equals("parent")) { paramSource = ParamSource.SOURCE; } else if (qName.equals("component")) { paramSource.equals(ParamSource.SOURCE); currentEvent.extendTarget(componentString.substring(0, componentString.length() - 1) + "]"); } } } /** *

* Parses a log file written by the JFCMonitor and creates a collection of * event sequences. *

* * @param filename * name and path of the log file */ public void parseFile(String filename) { if (filename == null) { throw new InvalidParameterException("filename must not be null"); } SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setValidating(true); SAXParser saxParser = null; InputSource inputSource = null; try { saxParser = spf.newSAXParser(); inputSource = new InputSource(new InputStreamReader( new FileInputStream(filename), "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } if (inputSource != null) { inputSource.setSystemId("file://" + new File(filename).getAbsolutePath()); try { if (saxParser == null) { throw new RuntimeException("SAXParser creation failed"); } saxParser.parse(inputSource, this); } catch (SAXParseException e) { Console.printerrln("Failure parsing file in line " + e.getLineNumber() + ", column " + e.getColumnNumber() + "."); e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }