source: trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/windows/LogParser.java @ 171

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