source: trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/windows/EventGenerator.java @ 67

Last change on this file since 67 was 58, checked in by sherbold, 13 years ago
  • modified de.ugoe.cs.eventbench.ReplayGenerator? to use de.ugoe.cs.eventbench.IReplayDecorator interface to write headers and footers
  • added decorator MFCReplayDecorator for writing MFC replay header and footer
File size: 25.3 KB
Line 
1package de.ugoe.cs.eventbench.windows;
2
3import java.io.IOException;
4import java.security.InvalidParameterException;
5import java.util.HashMap;
6import java.util.Iterator;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.ListIterator;
10import java.util.Map;
11import java.util.NoSuchElementException;
12
13import org.jdom.Document;
14import org.jdom.Element;
15import org.jdom.JDOMException;
16import org.jdom.Namespace;
17import org.jdom.input.SAXBuilder;
18
19import de.ugoe.cs.eventbench.data.Event;
20import de.ugoe.cs.eventbench.data.ReplayableEvent;
21import de.ugoe.cs.eventbench.windows.data.WindowTree;
22import de.ugoe.cs.eventbench.windows.data.WindowTreeNode;
23import de.ugoe.cs.eventbench.windows.data.WindowsMessage;
24import de.ugoe.cs.util.console.Console;
25
26/**
27 * <p>
28 * Translates sequences of windows messages into events that can be used by the
29 * Logalyzer core libraries for usage analysis.
30 * </p>
31 *
32 * @author Steffen Herbold
33 *
34 */
35public class EventGenerator {
36
37        /**
38         * <p>
39         * Helper method that fetches the document node of an XML file.
40         * </p>
41         *
42         * @param filename
43         *            name of the XML file
44         * @return the document node
45         */
46        private static Document getDocument(String filename) {
47                SAXBuilder builder = new SAXBuilder();
48                Document doc = null;
49
50                try {
51                        doc = builder.build(filename);
52                        rulesNamespace = Namespace.getNamespace("ul:rules");
53                } catch (JDOMException e) {
54                        System.err.println("Invalid rules file.");
55                        e.printStackTrace();
56                } catch (IOException e) {
57                        System.err.println("Invalid rules file.");
58                        e.printStackTrace();
59                }
60
61                return doc;
62        }
63
64        /**
65         * <p>
66         * Name and path of the XML files containing the rules.
67         * </p>
68         */
69        private String rulesFile;
70
71        /**
72         * <p>
73         * Iterator used for the current sequence.
74         * </p>
75         */
76        private ListIterator<WindowsMessage> sequenceIterator;
77
78        /**
79         * <p>
80         * Token that is currently being generated.
81         * </p>
82         */
83        private ReplayableEvent<WindowsMessage> currentToken;
84
85        /**
86         * <p>
87         * Reference to the ul:rules namespace.
88         * </p>
89         */
90        private static Namespace rulesNamespace;
91
92        /**
93         * <p>
94         * The name of the rule that is currently being evaluated.
95         * </p>
96         */
97        private String currentRuleName;
98
99        /**
100         * <p>
101         * Internal message storage. Used to implement the
102         * <code>{@literal <store>}</code> and <code>{@literal <storeSeq>}</code>
103         * tags.
104         * </p>
105         */
106        private Map<String, Object> messageStorage;
107
108        /**
109         * <p>
110         * Creates a new EventGenerator. Sets "rules/rules.xml" as default file for
111         * the rules.
112         * </p>
113         */
114        public EventGenerator() {
115                rulesFile = "rules/rules.xml";
116        }
117
118        /**
119         * <p>
120         * Tries to match the rules to the given sequence to generate an
121         * {@link Event}.
122         * </p>
123         * <p>
124         * The rules are matched the order, in which they are defined in the XML
125         * file. Therefore, the order of the rules in the file defines priorities,
126         * when multiple rules could be matched to the same sequence.
127         * </p>
128         *
129         * @param sequence
130         *            sequence of message for which an event will be generated
131         * @return event that matches the messages; null, if no rule can be matched
132         */
133        @SuppressWarnings("unchecked")
134        public Event<WindowsMessage> generateEvent(List<WindowsMessage> sequence) {
135                Document rulesDoc = getDocument(rulesFile);
136                Element rulesRoot = rulesDoc.getRootElement();
137
138                List<Element> ruleElements = rulesRoot.getChildren("rule",
139                                rulesNamespace);
140
141                boolean isMatch = false;
142
143                for (int ruleIndex = 0; ruleIndex < ruleElements.size() && !isMatch; ruleIndex++) {
144                        Element currentRule = ruleElements.get(ruleIndex);
145                        currentRuleName = currentRule.getAttributeValue("name");
146                        currentToken = new ReplayableEvent<WindowsMessage>(currentRuleName);
147                        currentToken.setDecorator(MFCReplayDecorator.getInstance());
148                        isMatch = true;
149                        messageStorage = new HashMap<String, Object>();
150                        sequenceIterator = sequence.listIterator();
151                        List<Element> ruleChildrenMsg = currentRule.getChildren("msg",
152                                        rulesNamespace);
153
154                        int i = 0;
155                        while (isMatch && i < ruleChildrenMsg.size()) {
156                                Element messageElement = ruleChildrenMsg.get(i);
157                                if ("true".equals(messageElement.getAttributeValue("multiple"))) {
158                                        Element nextMessageElement = null;
159                                        if (i + 1 < ruleChildrenMsg.size()) {
160                                                nextMessageElement = ruleChildrenMsg.get(i + 1);
161                                        }
162                                        try {
163                                                isMatch = matchMultipleMessages(messageElement,
164                                                                nextMessageElement);
165                                        } catch (InvalidParameterException e) {
166                                                Console.printerrln(e.getMessage());
167                                        }
168                                } else {
169                                        try {
170                                                isMatch = matchSingleMessage(messageElement);
171                                        } catch (InvalidParameterException e) {
172                                                Console.printerrln(e.getMessage());
173                                        }
174                                }
175                                i++;
176                        }
177                        if (isMatch) {
178                                List<Element> ruleChildren = currentRule.getChildren();
179                                for (Element genMsgElement : ruleChildren) {
180                                        if (genMsgElement.getName().equals("genMsg")) {
181                                                try {
182                                                        generateReplayMessage(genMsgElement);
183                                                } catch (InvalidParameterException e) {
184                                                        Console.printerrln(e.getMessage());
185                                                        currentToken.invalidateReplay();
186                                                }
187                                        } else if (genMsgElement.getName().equals("genMsgSeq")) {
188                                                try {
189                                                        generateReplaySequence(genMsgElement);
190                                                        currentToken.invalidateReplay();
191                                                } catch (InvalidParameterException e) {
192                                                        Console.printerrln(e.getMessage());
193                                                        currentToken.invalidateReplay();
194                                                }
195                                        }
196                                }
197                                Element idinfoElement = currentRule.getChild("idinfo",
198                                                rulesNamespace);
199                                if (idinfoElement != null) {
200                                        // cannot be empty if document is valid
201                                        List<Element> valueElements = idinfoElement.getChildren();
202                                        currentToken.setIdInfo(getTermValue(null,
203                                                        valueElements.get(0)));
204                                }
205                                Console.traceln(currentRule.getAttributeValue("name")
206                                                + currentToken.getIdInfo() + " matched");
207                        } else {
208                                currentToken = null;
209                        }
210                }
211                if (!isMatch) {
212                        Console.traceln("no match found for sequence: "
213                                        + sequence.toString());
214                }
215                return currentToken;
216        }
217
218        private boolean createSequenceLParam(
219                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
220                        int constMsgType, Element termElement)
221                        throws NoSuchElementException {
222                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
223                if (termElement.getName().equals("seqValue")) {
224                        String obj = termElement.getAttributeValue("seqObj");
225                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
226                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
227                                throw new InvalidParameterException(
228                                                "Failure generating replay sequence for rule "
229                                                                + currentRuleName
230                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts.");
231                        }
232                        for (WindowsMessage msg : seqVar) {
233                                WindowsMessage currentSeqMsg = getCurrentSeqMsg(
234                                                generatedMessageSeq, msgsGenerated, constMsgType,
235                                                seqIterator);
236                                String paramValueStr = msg.getParameter(termElement
237                                                .getAttributeValue("param"));
238                                int paramValue = 0;
239                                try {
240                                        paramValue = Integer.parseInt(paramValueStr);
241                                        currentSeqMsg.setLPARAM(paramValue);
242                                } catch (NumberFormatException e) {
243                                        currentSeqMsg.setLPARAMasWindowDesc(paramValueStr);
244                                }
245                        }
246                        if (seqIterator.hasNext()) {
247                                // the first seq-var has a different number of elements than the
248                                // current one
249                                throw new NoSuchElementException();
250                        }
251                        msgsGenerated = true;
252                } else { // const value
253                        int paramValue = Integer.parseInt(getTermValue(null, termElement));
254                        while (seqIterator.hasNext()) {
255                                seqIterator.next().setLPARAM(paramValue);
256                        }
257                }
258                return msgsGenerated;
259        }
260
261        private boolean createSequenceTarget(
262                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
263                        int constMsgType, Element termElement)
264                        throws NoSuchElementException {
265                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
266                if (termElement.getName().equals("seqValue")) {
267                        String obj = termElement.getAttributeValue("seqObj");
268                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
269                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
270                                throw new InvalidParameterException(
271                                                "Failure generating replay sequence for rule "
272                                                                + currentRuleName
273                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts.");
274                        }
275                        for (WindowsMessage msg : seqVar) {
276                                WindowsMessage currentSeqMsg = getCurrentSeqMsg(
277                                                generatedMessageSeq, msgsGenerated, constMsgType,
278                                                seqIterator);
279                                String targetString = msg.getParameter(termElement
280                                                .getAttributeValue("param"));
281                                currentSeqMsg.setXmlWindowDescription(targetString);
282                        }
283                        msgsGenerated = true;
284                } else { // const value
285                        throw new AssertionError("target must be a sequence variable!");
286                        /*
287                         * If target would not be a variable, the message-elements could not
288                         * yet be created and the whole sequence might be broken. If this is
289                         * to be changed, createSequenceLParam and createSequenceWParam need
290                         * to be addepted, too.
291                         */
292                }
293                return msgsGenerated;
294        }
295
296        private boolean createSequenceWParam(
297                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
298                        int constMsgType, Element termElement)
299                        throws NoSuchElementException {
300                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
301                if (termElement.getName().equals("seqValue")) {
302                        String obj = termElement.getAttributeValue("seqObj");
303                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
304                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
305                                throw new InvalidParameterException(
306                                                "Failure generating replay sequence for rule "
307                                                                + currentRuleName
308                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts.");
309                        }
310                        for (WindowsMessage msg : seqVar) {
311                                WindowsMessage currentSeqMsg = getCurrentSeqMsg(
312                                                generatedMessageSeq, msgsGenerated, constMsgType,
313                                                seqIterator);
314                                String paramValueStr = msg.getParameter(termElement
315                                                .getAttributeValue("param"));
316                                int paramValue = 0;
317                                try {
318                                        paramValue = Integer.parseInt(paramValueStr);
319                                        currentSeqMsg.setWPARAM(paramValue);
320                                } catch (NumberFormatException e) {
321                                        currentSeqMsg.setWPARAMasWindowDesc(paramValueStr);
322                                }
323                        }
324                        if (seqIterator.hasNext()) {
325                                // the first seq-var has a different number of elements than the
326                                // current one
327                                throw new NoSuchElementException();
328                        }
329                        msgsGenerated = true;
330                } else { // const value
331                        int paramValue = Integer.parseInt(getTermValue(null, termElement));
332                        while (seqIterator.hasNext()) {
333                                seqIterator.next().setWPARAM(paramValue);
334                        }
335                }
336                return msgsGenerated;
337        }
338
339        @SuppressWarnings("unchecked")
340        private boolean evalEqualRestrictions(WindowsMessage currentMessage,
341                        Element messageElement) {
342                boolean isMatch = true;
343                for (Element childElement : (List<Element>) messageElement.getChildren(
344                                "equals", rulesNamespace)) {
345                        List<Element> termElements = childElement.getChildren();
346                        // the size 2 of termElements is guaranteed by the XML schema
347                        String value1 = getTermValue(currentMessage, termElements.get(0));
348                        String value2 = getTermValue(currentMessage, termElements.get(1));
349                        if (value1 == null || value2 == null) {
350                                isMatch = false;
351                        } else {
352                                isMatch = isMatch && value1.equals(value2);
353                        }
354                }
355                for (Element childElement : (List<Element>) messageElement.getChildren(
356                                "equalsSeq", rulesNamespace)) {
357                        List<Element> termElements = childElement.getChildren();
358                        List<String> values1 = getTermValueSeq(currentMessage,
359                                        termElements.get(0));
360                        List<String> values2 = getTermValueSeq(currentMessage,
361                                        termElements.get(0));
362                        if (values1 == null || values2 == null) {
363                                isMatch = false;
364                        } else {
365                                isMatch = isMatch && values1.equals(values2);
366                        }
367                }
368                return isMatch;
369        }
370
371        @SuppressWarnings("unchecked")
372        private void generateReplayMessage(Element genMsgElement) {
373                List<Element> genMsgChildren = genMsgElement.getChildren();
374                WindowsMessage generatedMessage = null;
375                if (genMsgChildren.size() == 1) { // replay stored message without
376                                                                                        // change
377                        String obj = genMsgChildren.get(0).getAttributeValue("obj");
378                        generatedMessage = getStoredMessageVariable(null, obj);
379                } else { // generate message according to the rule
380                        for (Element genMsgChild : genMsgChildren) {
381                                Element termElement = (Element) genMsgChild.getChildren()
382                                                .get(0);
383                                if (genMsgChild.getName().equals("type")) {
384                                        try {
385                                                int msgType = Integer.parseInt(getTermValue(null,
386                                                                termElement));
387                                                generatedMessage = new WindowsMessage(msgType);
388                                        } catch (NumberFormatException e) {
389                                                throw new InvalidParameterException(
390                                                                "Failure generating replay sequence for rule "
391                                                                                + currentRuleName
392                                                                                + ": Defined type is not an integer.");
393                                        }
394                                } else if (genMsgChild.getName().equals("target")) {
395                                        String targetString = getTermValue(null, termElement);
396                                        generatedMessage.setXmlWindowDescription(targetString);
397                                } else if (genMsgChild.getName().equals("LPARAM")) {
398                                        String paramValueStr = getTermValue(null, termElement);
399                                        long paramValue = 0;
400                                        Element loword = genMsgChild.getChild("LOWORD", rulesNamespace);
401                                        if( loword!=null ) {
402                                                paramValue = loHiWord(genMsgChild);
403                                                generatedMessage.setLPARAM(paramValue);
404                                        } else {
405                                                try {
406                                                        paramValue = Integer.parseInt(paramValueStr);
407                                                        generatedMessage.setLPARAM(paramValue);
408                                                } catch (NumberFormatException e) {
409                                                        generatedMessage.setLPARAMasWindowDesc(paramValueStr);
410                                                }
411                                        }
412                                } else if (genMsgChild.getName().equals("WPARAM")) {
413                                        String paramValueStr = getTermValue(null, termElement);
414                                        long paramValue = 0;
415                                        Element loword = genMsgChild.getChild("LOWORD", rulesNamespace);
416                                        if( loword!=null ) {
417                                                paramValue = loHiWord(genMsgChild);
418                                                generatedMessage.setWPARAM(paramValue);
419                                        } else {
420                                                try {
421                                                        paramValue = Integer.parseInt(paramValueStr);
422                                                        generatedMessage.setWPARAM(paramValue);
423                                                } catch (NumberFormatException e) {
424                                                        generatedMessage.setWPARAMasWindowDesc(paramValueStr);
425                                                }
426                                        }
427                                }
428                        }
429                }
430                if (generatedMessage != null) {
431                        int delay = Integer.parseInt(genMsgElement
432                                        .getAttributeValue("delay"));
433                        generatedMessage.setDelay(delay);
434                } else {
435                        currentToken.invalidateReplay();
436                }
437                currentToken.addReplayEvent(generatedMessage);
438        }
439
440        @SuppressWarnings("unchecked")
441        private void generateReplaySequence(Element genMsgElement) {
442                List<Element> genMsgSeqChildren = genMsgElement.getChildren();
443                List<WindowsMessage> generatedMessageSeq = new LinkedList<WindowsMessage>();
444                if (genMsgSeqChildren.size() == 1) {
445                        String obj = genMsgSeqChildren.get(0).getAttributeValue("seqObj");
446                        generatedMessageSeq = getStoredSeqVariable(obj);
447                } else {
448                        boolean msgsGenerated = false;
449                        int constMsgType = 0;
450                        for (Element genMsgSeqChild : genMsgSeqChildren) {
451                                Element termElement = (Element) genMsgSeqChild.getChildren()
452                                                .get(0);
453                                if (genMsgSeqChild.getName().equals("type")) {
454                                        // note: cannot easily be extracted because of mulitple
455                                        // return values
456                                        if (termElement.getName().equals("seqValue")) {
457                                                String obj = termElement.getAttributeValue("seqObj");
458                                                List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
459                                                for (WindowsMessage msg : seqVar) {
460                                                        generatedMessageSeq.add(new WindowsMessage(msg
461                                                                        .getType()));
462                                                }
463                                                msgsGenerated = true;
464                                        } else { // constValue type
465                                                constMsgType = Integer.parseInt(getTermValue(null,
466                                                                termElement));
467                                        }
468                                } else if (genMsgSeqChild.getName().equals("target")) {
469                                        msgsGenerated = createSequenceTarget(generatedMessageSeq,
470                                                        msgsGenerated, constMsgType, termElement);
471                                } else if (genMsgSeqChild.getName().equals("LPARAM")) {
472                                        msgsGenerated = createSequenceLParam(generatedMessageSeq,
473                                                        msgsGenerated, constMsgType, termElement);
474                                } else if (genMsgSeqChild.getName().equals("WPARAM")) {
475                                        msgsGenerated = createSequenceWParam(generatedMessageSeq,
476                                                        msgsGenerated, constMsgType, termElement);
477                                }
478                        }
479                }
480                currentToken.addReplaySequence(generatedMessageSeq);
481        }
482
483        private WindowsMessage getCurrentSeqMsg(
484                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
485                        int constMsgType, Iterator<WindowsMessage> seqIterator) {
486                WindowsMessage currentSeqMsg = null;
487                if (msgsGenerated) {
488                        currentSeqMsg = seqIterator.next();
489                } else {
490                        currentSeqMsg = new WindowsMessage(constMsgType);
491                        generatedMessageSeq.add(currentSeqMsg);
492                }
493                return currentSeqMsg;
494        }
495
496        private WindowsMessage getStoredMessageVariable(
497                        WindowsMessage currentMessage, String obj)
498                        throws InvalidParameterException {
499                WindowsMessage varMessage = null;
500                if (obj.equals("this")) {
501                        if (currentMessage == null) {
502                                throw new InvalidParameterException(
503                                                "Failure obtaining term value for rule "
504                                                                + currentRuleName
505                                                                + ": \"this\" is not a valid name for generating runtime messages.");
506                        }
507                        varMessage = currentMessage;
508                } else {
509                        Object tmp = messageStorage.get(obj);
510                        if (tmp instanceof WindowsMessage) {
511                                varMessage = (WindowsMessage) tmp;
512                        } else {
513                                throw new InvalidParameterException(
514                                                "Failure obtaining term value for rule "
515                                                                + currentRuleName + ": No message \"" + obj
516                                                                + "\" stored.");
517                        }
518                }
519                return varMessage;
520        }
521
522        @SuppressWarnings("unchecked")
523        private List<WindowsMessage> getStoredSeqVariable(String obj)
524                        throws InvalidParameterException {
525                List<WindowsMessage> varMsgSeq = null;
526                Object tmp = messageStorage.get(obj);
527                if (tmp instanceof List<?>) {
528                        varMsgSeq = (List<WindowsMessage>) tmp;
529                } else {
530                        throw new InvalidParameterException(
531                                        "Failure obtaining term value for rule " + currentRuleName
532                                                        + ": No sequence \"" + obj + "\" store.");
533                }
534                return varMsgSeq;
535        }
536
537        private String getTermValue(WindowsMessage currentMessage,
538                        Element termElement) {
539                String value = null;
540                WindowsMessage varMessage = null;
541                if (termElement.getName().equals("constValue")) {
542                        value = termElement.getAttributeValue("value");
543                } else if (termElement.getName().equals("paramValue")) {
544                        String objectName = termElement.getAttributeValue("obj");
545                        varMessage = getStoredMessageVariable(currentMessage, objectName);
546                        if (varMessage != null) {
547                                String param = termElement.getAttributeValue("param");
548                                value = varMessage.getParameter(param);
549                        }
550                } else if (termElement.getName().equals("winInfoValue")) {
551                        String objectName = termElement.getAttributeValue("obj");
552                        varMessage = getStoredMessageVariable(currentMessage, objectName);
553                        if (varMessage != null) {
554                                String paramString = termElement.getAttributeValue("winParam");
555                                if (paramString.equals("class")) {
556                                        value = varMessage.getWindowClass();
557                                } else if (paramString.equals("resourceId")) {
558                                        value = "" + varMessage.getWindowResourceId();
559                                } else if (paramString.equals("hwnd")) {
560                                        value = "" + varMessage.getHwnd();
561                                } else if (paramString.equals("parentTarget")) {
562                                        String target = varMessage.getXmlWindowDescription();
563                                        int index = target.lastIndexOf("<");
564                                        if( index==0 ) {
565                                                Console.println("Trying to adress parent of top-level window! Replay probably invalid!");
566                                        }
567                                        value = target.substring(0, index);
568                                }
569                        }
570                } else if (termElement.getName().equals("msgInfoValue")) {
571                        String objectName = termElement.getAttributeValue("obj");
572                        varMessage = getStoredMessageVariable(currentMessage, objectName);
573                        if (varMessage != null) {
574                                String paramString = termElement.getAttributeValue("msgParam");
575                                if (paramString.equals("type")) {
576                                        value = "" + varMessage.getType();
577                                } else if (paramString.equals("target")) {
578                                        value = varMessage.getXmlWindowDescription();
579                                }
580                        }
581                }
582                return value;
583        }
584
585        private List<String> getTermValueSeq(WindowsMessage currentMessage,
586                        Element termElement) {
587                List<String> values = new LinkedList<String>();
588                if (termElement.getName().equals("seqValue")) {
589                        String obj = termElement.getAttributeValue("seqObj");
590                        String param = termElement.getAttributeValue("param");
591                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
592
593                        for (WindowsMessage msg : seqVar) {
594                                // msg.getParameter returns null, if parameter is not found,
595                                // therefore the List can contain null-values
596                                values.add(msg.getParameter(param));
597                        }
598                }
599                return values;
600        }
601
602        @SuppressWarnings("unchecked")
603        private void handleStorage(Element messageElement,
604                        WindowsMessage currentMessage) {
605                for (Element childElement : (List<Element>) messageElement.getChildren(
606                                "store", rulesNamespace)) {
607                        String identifier = childElement.getAttributeValue("var");
608                        messageStorage.put(identifier, currentMessage);
609                        resolveHwnd(currentMessage, childElement);
610                }
611                for (Element childElement : (List<Element>) messageElement.getChildren(
612                                "storeSeq", rulesNamespace)) {
613                        String identifier = childElement.getAttributeValue("varSeq");
614                        Object tmp = messageStorage.get(identifier);
615                        List<WindowsMessage> storedSequence;
616                        if (tmp == null || tmp instanceof WindowsMessage) {
617                                storedSequence = new LinkedList<WindowsMessage>();
618                                storedSequence.add(currentMessage);
619                                messageStorage.put(identifier, storedSequence);
620                        } else if (tmp instanceof List<?>) {
621                                storedSequence = (List<WindowsMessage>) tmp;
622                                storedSequence.add(currentMessage);
623                                messageStorage.put(identifier, storedSequence);
624                        }
625                        resolveHwnd(currentMessage, childElement);
626                }
627        }
628
629        private boolean matchMultipleMessages(Element messageElement,
630                        Element nextMessageElement) {
631                boolean isMatch = false;
632                boolean isCurrentMatch = false;
633                boolean nextMatchFound = false;
634                WindowsMessage currentMessage = null;
635                WindowsMessage nextMessage = null;
636
637                int type = Integer.parseInt(messageElement.getAttributeValue("type"));
638
639                int nextType = -1;
640                if (nextMessageElement != null) {
641                        nextType = Integer.parseInt(nextMessageElement
642                                        .getAttributeValue("type"));
643                }
644
645                while (!nextMatchFound && sequenceIterator.hasNext()) {
646                        currentMessage = sequenceIterator.next();
647                        if (type == currentMessage.getType()) {
648                                isCurrentMatch = evalEqualRestrictions(currentMessage,
649                                                messageElement);
650                                isMatch = isMatch || isCurrentMatch;
651
652                                if (isCurrentMatch) {
653                                        handleStorage(messageElement, currentMessage);
654                                        currentToken.setTarget(currentMessage
655                                                        .getXmlWindowDescription());
656                                        currentToken
657                                                        .setTargetShort(currentMessage.getParentNames());
658                                }
659                        }
660                        if (nextMessageElement != null && isMatch) {
661                                // peek next message to check if the sequence ends and the next
662                                // match is found
663                                if (!sequenceIterator.hasNext()) {
664                                        return false; // sequence is over, but not all messages are
665                                                                        // found
666                                }
667                                nextMessage = sequenceIterator.next();
668                                sequenceIterator.previous();
669
670                                if (nextType == nextMessage.getType()) {
671                                        nextMatchFound = evalEqualRestrictions(nextMessage,
672                                                        nextMessageElement);
673                                }
674
675                        }
676                }
677
678                return isMatch;
679        }
680
681        private boolean matchSingleMessage(Element messageElement) {
682                boolean isMatch = false;
683                WindowsMessage currentMessage = null;
684
685                int type = Integer.parseInt(messageElement.getAttributeValue("type"));
686
687                while (!isMatch && sequenceIterator.hasNext()) {
688                        // traverses the messages from the current position forward till a
689                        // message with the correct type is found
690                        currentMessage = sequenceIterator.next();
691                        if (type == currentMessage.getType()) {
692                                // message with the correct type found
693                                // eval child nodes for further matching/storing
694                                isMatch = evalEqualRestrictions(currentMessage, messageElement);
695
696                                // in case the message is a match, eval storage children
697                                if (isMatch) {
698                                        handleStorage(messageElement, currentMessage);
699                                        currentToken.setTarget(currentMessage
700                                                        .getXmlWindowDescription());
701                                        currentToken
702                                                        .setTargetShort(currentMessage.getParentNames());
703                                }
704                        }
705                }
706
707                return isMatch;
708        }
709
710        @SuppressWarnings("unchecked")
711        private void resolveHwnd(WindowsMessage currentMessage, Element childElement) {
712                List<Element> resolveElements = childElement.getChildren("resolveHwnd",
713                                rulesNamespace);
714                for (Element resolveElement : resolveElements) {
715                        String param = resolveElement.getAttributeValue("param");
716                        String storeParam = resolveElement.getAttributeValue("storeParam");
717                        int paramHwnd = Integer
718                                        .parseInt(currentMessage.getParameter(param));
719                        WindowTreeNode node = WindowTree.getInstance().find(paramHwnd);
720                        if (node != null) {
721                                currentMessage.addParameter(storeParam,
722                                                node.xmlRepresentation());
723                        }
724                }
725        }
726       
727        private long loHiWord(Element param) {
728                Element loword = param.getChild("LOWORD", rulesNamespace);
729                Element hiword = param.getChild("HIWORD", rulesNamespace);
730                String lowordStr = getTermValue(null, (Element) loword.getChildren().get(0));
731                String hiwordStr = getTermValue(null, (Element) hiword.getChildren().get(0));
732                return MAKEPARAM(Short.parseShort(lowordStr), Short.parseShort(hiwordStr));
733        }
734       
735        private static int MAKEPARAM(short loword, short hiword) {
736                return loword| ((int) hiword) << Short.SIZE;
737        }
738
739}
Note: See TracBrowser for help on using the repository browser.