source: trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/windows/MFCLogParser.java @ 403

Last change on this file since 403 was 403, checked in by sherbold, 12 years ago
  • improved handling of empty MFC sessions
File size: 7.7 KB
RevLine 
[52]1package de.ugoe.cs.eventbench.windows;
[1]2
3import java.io.File;
[45]4import java.io.FileInputStream;
[1]5import java.io.FileNotFoundException;
6import java.io.IOException;
[45]7import java.io.InputStreamReader;
8import java.io.UnsupportedEncodingException;
[1]9import java.security.InvalidParameterException;
[203]10import java.util.Collection;
[1]11import java.util.LinkedList;
12import java.util.List;
13import java.util.SortedMap;
14import java.util.TreeMap;
15
16import javax.xml.parsers.ParserConfigurationException;
17import javax.xml.parsers.SAXParser;
18import javax.xml.parsers.SAXParserFactory;
19
20import org.xml.sax.Attributes;
21import org.xml.sax.InputSource;
22import org.xml.sax.SAXException;
23import org.xml.sax.SAXParseException;
24import org.xml.sax.helpers.DefaultHandler;
25
[52]26import de.ugoe.cs.eventbench.windows.data.WindowTree;
[198]27import de.ugoe.cs.eventbench.windows.data.WindowsEvent;
[52]28import de.ugoe.cs.eventbench.windows.data.WindowsMessage;
[1]29import de.ugoe.cs.util.StringTools;
30import de.ugoe.cs.util.console.Console;
31
[171]32/**
33 * <p>
34 * This class provides functionality to parse XML log files generated by the
35 * MFCUsageMonitor of EventBench. The result of parsing a file is a collection
36 * of event sequences. It uses the {@link SequenceSplitter} and the
37 * {@link EventGenerator} as well as custom defined {@link MessageHandler} for
38 * the parsing.
39 * </p>
40 *
41 * @author Steffen Herbold
42 * @version 1.0
43 */
[297]44public class MFCLogParser extends DefaultHandler {
[171]45
46        /**
47         * <p>
48         * If a custom message handler is used, this field contains its handle.
49         * Otherwise this field is {@code null}.
50         * </p>
51         */
[1]52        private MessageHandler currentHandler;
[171]53
54        /**
55         * <p>
56         * Handle to the message that is currently parsed.
57         * </p>
58         */
[1]59        private WindowsMessage currentMessage;
[171]60
61        /**
62         * <p>
[297]63         * {@link SequenceSplitter} instance used by the {@link MFCLogParser}.
[171]64         * </p>
65         */
[1]66        private SequenceSplitter sequenceSplitter;
[171]67
68        /**
69         * <p>
70         * Collection of event sequences that is contained in the log file, which is
71         * parsed.
72         * </p>
73         */
[203]74        private Collection<List<WindowsEvent>> sequences;
[171]75
76        /**
77         * <p>
78         * Debugging variable that allows the analysis which message type occurs how
79         * often in the log file. Can be used to enhance the message filter.
80         * </p>
81         */
[1]82        private SortedMap<Integer, Integer> typeCounter;
[171]83
84        /**
85         * <p>
86         * Debugging variable that enables the counting of the occurrences of each
87         * message. Used in combination with {@link #typeCounter}.
88         * </p>
89         */
[1]90        private boolean countMessageOccurences;
[171]91
92        /**
93         * <p>
94         * Constructor. Creates a new LogParser that does not count message
95         * occurrences.
96         * </p>
97         */
[297]98        public MFCLogParser() {
[1]99                this(false);
100        }
[171]101
102        /**
103         * <p>
104         * Constructor. Creates a new LogParser.
105         * </p>
106         *
107         * @param countMessageOccurences
108         *            if true, the occurrences of each message type in the log is
109         *            counted.
110         */
[297]111        public MFCLogParser(boolean countMessageOccurences) {
[1]112                sequenceSplitter = new SequenceSplitter();
[77]113                sequences = new LinkedList<List<WindowsEvent>>();
[1]114                currentHandler = null;
115                this.countMessageOccurences = countMessageOccurences;
[171]116                if (countMessageOccurences) {
[1]117                        typeCounter = new TreeMap<Integer, Integer>();
118                }
[171]119
[1]120        }
[171]121
122        /**
123         * <p>
124         * Returns the collection of event sequences that is obtained from parsing
125         * log files.
126         * </p>
127         *
128         * @return collection of event sequences
129         */
[203]130        public Collection<List<WindowsEvent>> getSequences() {
[1]131                return sequences;
132        }
[171]133
134        /*
135         * (non-Javadoc)
136         *
137         * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
138         * java.lang.String, java.lang.String, org.xml.sax.Attributes)
139         */
[1]140        @Override
[171]141        public void startElement(String uri, String localName, String qName,
142                        Attributes atts) throws SAXException {
143                if (qName.equals("session")) {
[1]144                        Console.traceln("start of session");
145                        sequenceSplitter = new SequenceSplitter();
[171]146                } else if (qName.equals("msg")) {
[1]147                        String msgType = atts.getValue("type");
148                        int msgInt = -1;
149                        try {
150                                msgInt = Integer.parseInt(msgType);
[171]151
152                                if (countMessageOccurences) {
[1]153                                        Integer currentCount = typeCounter.get(msgInt);
[171]154                                        if (currentCount == null) {
[1]155                                                typeCounter.put(msgInt, 1);
156                                        } else {
[171]157                                                typeCounter.put(msgInt, currentCount + 1);
[1]158                                        }
159                                }
[171]160
161                                if (msgInt == MessageDefs.WM_CREATE) {
[1]162                                        currentHandler = new HandlerCreate();
163                                        currentHandler.onStartElement();
[171]164                                } else if (msgInt == MessageDefs.WM_DESTROY) {
[1]165                                        currentHandler = new HandlerDestroy();
166                                        currentHandler.onStartElement();
[171]167                                } else if (msgInt == MessageDefs.WM_SETTEXT) {
[1]168                                        currentHandler = new HandlerSetText();
169                                        currentHandler.onStartElement();
170                                } else {
171                                        currentMessage = new WindowsMessage(msgInt);
172                                }
[171]173                        } catch (NumberFormatException e) {
[4]174                                Console.printerrln("Invalid message type: type not a number");
[1]175                                e.printStackTrace();
176                        }
[171]177                } else if (qName.equals("param")) {
178                        if (currentHandler != null) {
179                                currentHandler.onParameter(atts.getValue("name"),
180                                                atts.getValue("value"));
[1]181                        } else {
[171]182                                currentMessage.addParameter(atts.getValue("name"),
183                                                atts.getValue("value"));
[1]184                        }
185                }
186        }
[171]187
188        /*
189         * (non-Javadoc)
190         *
191         * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
192         * java.lang.String, java.lang.String)
193         */
[1]194        @Override
[171]195        public void endElement(String uri, String localName, String qName)
196                        throws SAXException {
197                if (qName.equals("msg")) {
198                        if (currentHandler != null) {
[1]199                                currentHandler.onEndElement();
200                                currentHandler = null;
201                        } else {
202                                try {
203                                        currentMessage.setTarget(WindowTree.getInstance());
204                                        sequenceSplitter.addMessage(currentMessage);
205                                } catch (InvalidParameterException e) {
[171]206                                        Console.traceln(e.getMessage() + " WindowsMessage "
207                                                        + currentMessage + " ignored.");
208                                }
[1]209                        }
[171]210                } else if (qName.equals("session")) {
[1]211                        sequenceSplitter.endSession();
[403]212                        List<WindowsEvent> seq = sequenceSplitter.getSequence();
213                        if( seq!=null && !seq.isEmpty() ) {
214                                sequences.add(seq);
215                        }
[1]216                        Console.traceln("end of session");
217                }
218        }
[171]219
220        /**
221         * <p>
[297]222         * Parses a given log file created by the MFCMonitor and adds its contents
223         * to the collection of event sequences.
[171]224         * </p>
225         *
226         * @param filename
227         *            name and path of the log file
228         */
[1]229        public void parseFile(String filename) {
[171]230                if (filename == null) {
[1]231                        throw new InvalidParameterException("filename must not be null");
232                }
[171]233
[1]234                SAXParserFactory spf = SAXParserFactory.newInstance();
235                spf.setValidating(true);
[171]236
[1]237                SAXParser saxParser = null;
238                InputSource inputSource = null;
239                try {
240                        saxParser = spf.newSAXParser();
[171]241                        inputSource = new InputSource(new InputStreamReader(
242                                        new FileInputStream(filename), "UTF-16"));
[45]243                } catch (UnsupportedEncodingException e) {
244                        e.printStackTrace();
[1]245                } catch (ParserConfigurationException e) {
246                        e.printStackTrace();
247                } catch (SAXException e) {
248                        e.printStackTrace();
249                } catch (FileNotFoundException e) {
250                        e.printStackTrace();
251                }
[171]252                if (inputSource != null) {
253                        inputSource.setSystemId("file://"
254                                        + new File(filename).getAbsolutePath());
255                        try {
256                                if (saxParser == null) {
257                                        throw new RuntimeException("SAXParser creation failed");
258                                }
[1]259                                saxParser.parse(inputSource, this);
[171]260                        } catch (SAXParseException e) {
261                                Console.printerrln("Failure parsing file in line "
262                                                + e.getLineNumber() + ", column " + e.getColumnNumber()
263                                                + ".");
264                                e.printStackTrace();
[1]265                        } catch (SAXException e) {
266                                e.printStackTrace();
267                        } catch (IOException e) {
268                                e.printStackTrace();
269                        }
270                }
[171]271                if (countMessageOccurences) {
[1]272                        Console.println("Message statistics:");
[171]273                        Console.println(typeCounter.toString()
274                                        .replace(" ", StringTools.ENDLINE)
275                                        .replaceAll("[\\{\\}]", ""));
[1]276                }
277        }
278}
Note: See TracBrowser for help on using the repository browser.