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

Last change on this file since 41 was 41, checked in by sherbold, 13 years ago

+ Added support for LOWORD/HIWORD usage when generating the LPARAM and WPARAM of single messages (sequences not yet supported)

File size: 25.2 KB
Line 
1package de.ugoe.cs.eventbench;
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.data.WindowTree;
22import de.ugoe.cs.eventbench.data.WindowTreeNode;
23import de.ugoe.cs.eventbench.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                        isMatch = true;
148                        messageStorage = new HashMap<String, Object>();
149                        sequenceIterator = sequence.listIterator();
150                        List<Element> ruleChildrenMsg = currentRule.getChildren("msg",
151                                        rulesNamespace);
152
153                        int i = 0;
154                        while (isMatch && i < ruleChildrenMsg.size()) {
155                                Element messageElement = ruleChildrenMsg.get(i);
156                                if ("true".equals(messageElement.getAttributeValue("multiple"))) {
157                                        Element nextMessageElement = null;
158                                        if (i + 1 < ruleChildrenMsg.size()) {
159                                                nextMessageElement = ruleChildrenMsg.get(i + 1);
160                                        }
161                                        try {
162                                                isMatch = matchMultipleMessages(messageElement,
163                                                                nextMessageElement);
164                                        } catch (InvalidParameterException e) {
165                                                Console.printerrln(e.getMessage());
166                                        }
167                                } else {
168                                        try {
169                                                isMatch = matchSingleMessage(messageElement);
170                                        } catch (InvalidParameterException e) {
171                                                Console.printerrln(e.getMessage());
172                                        }
173                                }
174                                i++;
175                        }
176                        if (isMatch) {
177                                List<Element> ruleChildren = currentRule.getChildren();
178                                for (Element genMsgElement : ruleChildren) {
179                                        if (genMsgElement.getName().equals("genMsg")) {
180                                                try {
181                                                        generateReplayMessage(genMsgElement);
182                                                } catch (InvalidParameterException e) {
183                                                        Console.printerrln(e.getMessage());
184                                                        currentToken.invalidateReplay();
185                                                }
186                                        } else if (genMsgElement.getName().equals("genMsgSeq")) {
187                                                try {
188                                                        generateReplaySequence(genMsgElement);
189                                                        currentToken.invalidateReplay();
190                                                } catch (InvalidParameterException e) {
191                                                        Console.printerrln(e.getMessage());
192                                                        currentToken.invalidateReplay();
193                                                }
194                                        }
195                                }
196                                Element idinfoElement = currentRule.getChild("idinfo",
197                                                rulesNamespace);
198                                if (idinfoElement != null) {
199                                        // cannot be empty if document is valid
200                                        List<Element> valueElements = idinfoElement.getChildren();
201                                        currentToken.setIdInfo(getTermValue(null,
202                                                        valueElements.get(0)));
203                                }
204                                Console.traceln(currentRule.getAttributeValue("name")
205                                                + currentToken.getIdInfo() + " matched");
206                        } else {
207                                currentToken = null;
208                        }
209                }
210                if (!isMatch) {
211                        Console.traceln("no match found for sequence: "
212                                        + sequence.toString());
213                }
214                return currentToken;
215        }
216
217        private boolean createSequenceLParam(
218                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
219                        int constMsgType, Element termElement)
220                        throws NoSuchElementException {
221                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
222                if (termElement.getName().equals("seqValue")) {
223                        String obj = termElement.getAttributeValue("seqObj");
224                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
225                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
226                                throw new InvalidParameterException(
227                                                "Failure generating replay sequence for rule "
228                                                                + currentRuleName
229                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts.");
230                        }
231                        for (WindowsMessage msg : seqVar) {
232                                WindowsMessage currentSeqMsg = getCurrentSeqMsg(
233                                                generatedMessageSeq, msgsGenerated, constMsgType,
234                                                seqIterator);
235                                String paramValueStr = msg.getParameter(termElement
236                                                .getAttributeValue("param"));
237                                int paramValue = 0;
238                                try {
239                                        paramValue = Integer.parseInt(paramValueStr);
240                                        currentSeqMsg.setLPARAM(paramValue);
241                                } catch (NumberFormatException e) {
242                                        currentSeqMsg.setLPARAMasWindowDesc(paramValueStr);
243                                }
244                        }
245                        if (seqIterator.hasNext()) {
246                                // the first seq-var has a different number of elements than the
247                                // current one
248                                throw new NoSuchElementException();
249                        }
250                        msgsGenerated = true;
251                } else { // const value
252                        int paramValue = Integer.parseInt(getTermValue(null, termElement));
253                        while (seqIterator.hasNext()) {
254                                seqIterator.next().setLPARAM(paramValue);
255                        }
256                }
257                return msgsGenerated;
258        }
259
260        private boolean createSequenceTarget(
261                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
262                        int constMsgType, Element termElement)
263                        throws NoSuchElementException {
264                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
265                if (termElement.getName().equals("seqValue")) {
266                        String obj = termElement.getAttributeValue("seqObj");
267                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
268                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
269                                throw new InvalidParameterException(
270                                                "Failure generating replay sequence for rule "
271                                                                + currentRuleName
272                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts.");
273                        }
274                        for (WindowsMessage msg : seqVar) {
275                                WindowsMessage currentSeqMsg = getCurrentSeqMsg(
276                                                generatedMessageSeq, msgsGenerated, constMsgType,
277                                                seqIterator);
278                                String targetString = msg.getParameter(termElement
279                                                .getAttributeValue("param"));
280                                currentSeqMsg.setXmlWindowDescription(targetString);
281                        }
282                        msgsGenerated = true;
283                } else { // const value
284                        throw new AssertionError("target must be a sequence variable!");
285                        /*
286                         * If target would not be a variable, the message-elements could not
287                         * yet be created and the whole sequence might be broken. If this is
288                         * to be changed, createSequenceLParam and createSequenceWParam need
289                         * to be addepted, too.
290                         */
291                }
292                return msgsGenerated;
293        }
294
295        private boolean createSequenceWParam(
296                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
297                        int constMsgType, Element termElement)
298                        throws NoSuchElementException {
299                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
300                if (termElement.getName().equals("seqValue")) {
301                        String obj = termElement.getAttributeValue("seqObj");
302                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
303                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
304                                throw new InvalidParameterException(
305                                                "Failure generating replay sequence for rule "
306                                                                + currentRuleName
307                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts.");
308                        }
309                        for (WindowsMessage msg : seqVar) {
310                                WindowsMessage currentSeqMsg = getCurrentSeqMsg(
311                                                generatedMessageSeq, msgsGenerated, constMsgType,
312                                                seqIterator);
313                                String paramValueStr = msg.getParameter(termElement
314                                                .getAttributeValue("param"));
315                                int paramValue = 0;
316                                try {
317                                        paramValue = Integer.parseInt(paramValueStr);
318                                        currentSeqMsg.setWPARAM(paramValue);
319                                } catch (NumberFormatException e) {
320                                        currentSeqMsg.setWPARAMasWindowDesc(paramValueStr);
321                                }
322                        }
323                        if (seqIterator.hasNext()) {
324                                // the first seq-var has a different number of elements than the
325                                // current one
326                                throw new NoSuchElementException();
327                        }
328                        msgsGenerated = true;
329                } else { // const value
330                        int paramValue = Integer.parseInt(getTermValue(null, termElement));
331                        while (seqIterator.hasNext()) {
332                                seqIterator.next().setWPARAM(paramValue);
333                        }
334                }
335                return msgsGenerated;
336        }
337
338        @SuppressWarnings("unchecked")
339        private boolean evalEqualRestrictions(WindowsMessage currentMessage,
340                        Element messageElement) {
341                boolean isMatch = true;
342                for (Element childElement : (List<Element>) messageElement.getChildren(
343                                "equals", rulesNamespace)) {
344                        List<Element> termElements = childElement.getChildren();
345                        // the size 2 of termElements is guaranteed by the XML schema
346                        String value1 = getTermValue(currentMessage, termElements.get(0));
347                        String value2 = getTermValue(currentMessage, termElements.get(1));
348                        if (value1 == null || value2 == null) {
349                                isMatch = false;
350                        } else {
351                                isMatch = isMatch && value1.equals(value2);
352                        }
353                }
354                for (Element childElement : (List<Element>) messageElement.getChildren(
355                                "equalsSeq", rulesNamespace)) {
356                        List<Element> termElements = childElement.getChildren();
357                        List<String> values1 = getTermValueSeq(currentMessage,
358                                        termElements.get(0));
359                        List<String> values2 = getTermValueSeq(currentMessage,
360                                        termElements.get(0));
361                        if (values1 == null || values2 == null) {
362                                isMatch = false;
363                        } else {
364                                isMatch = isMatch && values1.equals(values2);
365                        }
366                }
367                return isMatch;
368        }
369
370        @SuppressWarnings("unchecked")
371        private void generateReplayMessage(Element genMsgElement) {
372                List<Element> genMsgChildren = genMsgElement.getChildren();
373                WindowsMessage generatedMessage = null;
374                if (genMsgChildren.size() == 1) { // replay stored message without
375                                                                                        // change
376                        String obj = genMsgChildren.get(0).getAttributeValue("obj");
377                        generatedMessage = getStoredMessageVariable(null, obj);
378                } else { // generate message according to the rule
379                        for (Element genMsgChild : genMsgChildren) {
380                                Element termElement = (Element) genMsgChild.getChildren()
381                                                .get(0);
382                                if (genMsgChild.getName().equals("type")) {
383                                        try {
384                                                int msgType = Integer.parseInt(getTermValue(null,
385                                                                termElement));
386                                                generatedMessage = new WindowsMessage(msgType);
387                                        } catch (NumberFormatException e) {
388                                                throw new InvalidParameterException(
389                                                                "Failure generating replay sequence for rule "
390                                                                                + currentRuleName
391                                                                                + ": Defined type is not an integer.");
392                                        }
393                                } else if (genMsgChild.getName().equals("target")) {
394                                        String targetString = getTermValue(null, termElement);
395                                        generatedMessage.setXmlWindowDescription(targetString);
396                                } else if (genMsgChild.getName().equals("LPARAM")) {
397                                        String paramValueStr = getTermValue(null, termElement);
398                                        long paramValue = 0;
399                                        Element loword = genMsgChild.getChild("LOWORD", rulesNamespace);
400                                        if( loword!=null ) {
401                                                paramValue = loHiWord(genMsgChild);
402                                        } else {
403                                                try {
404                                                        paramValue = Integer.parseInt(paramValueStr);
405                                                        generatedMessage.setLPARAM(paramValue);
406                                                } catch (NumberFormatException e) {
407                                                        generatedMessage.setLPARAMasWindowDesc(paramValueStr);
408                                                }
409                                        }
410                                } else if (genMsgChild.getName().equals("WPARAM")) {
411                                        String paramValueStr = getTermValue(null, termElement);
412                                        long paramValue = 0;
413                                        Element loword = genMsgChild.getChild("LOWORD", rulesNamespace);
414                                        if( loword!=null ) {
415                                                paramValue = loHiWord(genMsgChild);
416                                        } else {
417                                                try {
418                                                        paramValue = Integer.parseInt(paramValueStr);
419                                                        generatedMessage.setWPARAM(paramValue);
420                                                } catch (NumberFormatException e) {
421                                                        generatedMessage.setWPARAMasWindowDesc(paramValueStr);
422                                                }
423                                        }
424                                }
425                        }
426                }
427                if (generatedMessage != null) {
428                        int delay = Integer.parseInt(genMsgElement
429                                        .getAttributeValue("delay"));
430                        generatedMessage.setDelay(delay);
431                } else {
432                        currentToken.invalidateReplay();
433                }
434                currentToken.addReplayEvent(generatedMessage);
435        }
436
437        @SuppressWarnings("unchecked")
438        private void generateReplaySequence(Element genMsgElement) {
439                List<Element> genMsgSeqChildren = genMsgElement.getChildren();
440                List<WindowsMessage> generatedMessageSeq = new LinkedList<WindowsMessage>();
441                if (genMsgSeqChildren.size() == 1) {
442                        String obj = genMsgSeqChildren.get(0).getAttributeValue("seqObj");
443                        generatedMessageSeq = getStoredSeqVariable(obj);
444                } else {
445                        boolean msgsGenerated = false;
446                        int constMsgType = 0;
447                        for (Element genMsgSeqChild : genMsgSeqChildren) {
448                                Element termElement = (Element) genMsgSeqChild.getChildren()
449                                                .get(0);
450                                if (genMsgSeqChild.getName().equals("type")) {
451                                        // note: cannot easily be extracted because of mulitple
452                                        // return values
453                                        if (termElement.getName().equals("seqValue")) {
454                                                String obj = termElement.getAttributeValue("seqObj");
455                                                List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
456                                                for (WindowsMessage msg : seqVar) {
457                                                        generatedMessageSeq.add(new WindowsMessage(msg
458                                                                        .getType()));
459                                                }
460                                                msgsGenerated = true;
461                                        } else { // constValue type
462                                                constMsgType = Integer.parseInt(getTermValue(null,
463                                                                termElement));
464                                        }
465                                } else if (genMsgSeqChild.getName().equals("target")) {
466                                        msgsGenerated = createSequenceTarget(generatedMessageSeq,
467                                                        msgsGenerated, constMsgType, termElement);
468                                } else if (genMsgSeqChild.getName().equals("LPARAM")) {
469                                        msgsGenerated = createSequenceLParam(generatedMessageSeq,
470                                                        msgsGenerated, constMsgType, termElement);
471                                } else if (genMsgSeqChild.getName().equals("WPARAM")) {
472                                        msgsGenerated = createSequenceWParam(generatedMessageSeq,
473                                                        msgsGenerated, constMsgType, termElement);
474                                }
475                        }
476                }
477                currentToken.addReplaySequence(generatedMessageSeq);
478        }
479
480        private WindowsMessage getCurrentSeqMsg(
481                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
482                        int constMsgType, Iterator<WindowsMessage> seqIterator) {
483                WindowsMessage currentSeqMsg = null;
484                if (msgsGenerated) {
485                        currentSeqMsg = seqIterator.next();
486                } else {
487                        currentSeqMsg = new WindowsMessage(constMsgType);
488                        generatedMessageSeq.add(currentSeqMsg);
489                }
490                return currentSeqMsg;
491        }
492
493        private WindowsMessage getStoredMessageVariable(
494                        WindowsMessage currentMessage, String obj)
495                        throws InvalidParameterException {
496                WindowsMessage varMessage = null;
497                if (obj.equals("this")) {
498                        if (currentMessage == null) {
499                                throw new InvalidParameterException(
500                                                "Failure obtaining term value for rule "
501                                                                + currentRuleName
502                                                                + ": \"this\" is not a valid name for generating runtime messages.");
503                        }
504                        varMessage = currentMessage;
505                } else {
506                        Object tmp = messageStorage.get(obj);
507                        if (tmp instanceof WindowsMessage) {
508                                varMessage = (WindowsMessage) tmp;
509                        } else {
510                                throw new InvalidParameterException(
511                                                "Failure obtaining term value for rule "
512                                                                + currentRuleName + ": No message \"" + obj
513                                                                + "\" stored.");
514                        }
515                }
516                return varMessage;
517        }
518
519        @SuppressWarnings("unchecked")
520        private List<WindowsMessage> getStoredSeqVariable(String obj)
521                        throws InvalidParameterException {
522                List<WindowsMessage> varMsgSeq = null;
523                Object tmp = messageStorage.get(obj);
524                if (tmp instanceof List<?>) {
525                        varMsgSeq = (List<WindowsMessage>) tmp;
526                } else {
527                        throw new InvalidParameterException(
528                                        "Failure obtaining term value for rule " + currentRuleName
529                                                        + ": No sequence \"" + obj + "\" store.");
530                }
531                return varMsgSeq;
532        }
533
534        private String getTermValue(WindowsMessage currentMessage,
535                        Element termElement) {
536                String value = null;
537                WindowsMessage varMessage = null;
538                if (termElement.getName().equals("constValue")) {
539                        value = termElement.getAttributeValue("value");
540                } else if (termElement.getName().equals("paramValue")) {
541                        String objectName = termElement.getAttributeValue("obj");
542                        varMessage = getStoredMessageVariable(currentMessage, objectName);
543                        if (varMessage != null) {
544                                String param = termElement.getAttributeValue("param");
545                                value = varMessage.getParameter(param);
546                        }
547                } else if (termElement.getName().equals("winInfoValue")) {
548                        String objectName = termElement.getAttributeValue("obj");
549                        varMessage = getStoredMessageVariable(currentMessage, objectName);
550                        if (varMessage != null) {
551                                String paramString = termElement.getAttributeValue("winParam");
552                                if (paramString.equals("class")) {
553                                        value = varMessage.getWindowClass();
554                                } else if (paramString.equals("resourceId")) {
555                                        value = "" + varMessage.getWindowResourceId();
556                                } else if (paramString.equals("hwnd")) {
557                                        value = "" + varMessage.getHwnd();
558                                } else if (paramString.equals("parentTarget")) {
559                                        String target = varMessage.getXmlWindowDescription();
560                                        int index = target.lastIndexOf("<");
561                                        if( index==0 ) {
562                                                Console.println("Trying to adress parent of top-level window! Replay probably invalid!");
563                                        }
564                                        value = target.substring(0, index);
565                                }
566                        }
567                } else if (termElement.getName().equals("msgInfoValue")) {
568                        String objectName = termElement.getAttributeValue("obj");
569                        varMessage = getStoredMessageVariable(currentMessage, objectName);
570                        if (varMessage != null) {
571                                String paramString = termElement.getAttributeValue("msgParam");
572                                if (paramString.equals("type")) {
573                                        value = "" + varMessage.getType();
574                                } else if (paramString.equals("target")) {
575                                        value = varMessage.getXmlWindowDescription();
576                                }
577                        }
578                }
579                return value;
580        }
581
582        private List<String> getTermValueSeq(WindowsMessage currentMessage,
583                        Element termElement) {
584                List<String> values = new LinkedList<String>();
585                if (termElement.getName().equals("seqValue")) {
586                        String obj = termElement.getAttributeValue("seqObj");
587                        String param = termElement.getAttributeValue("param");
588                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
589
590                        for (WindowsMessage msg : seqVar) {
591                                // msg.getParameter returns null, if parameter is not found,
592                                // therefore the List can contain null-values
593                                values.add(msg.getParameter(param));
594                        }
595                }
596                return values;
597        }
598
599        @SuppressWarnings("unchecked")
600        private void handleStorage(Element messageElement,
601                        WindowsMessage currentMessage) {
602                for (Element childElement : (List<Element>) messageElement.getChildren(
603                                "store", rulesNamespace)) {
604                        String identifier = childElement.getAttributeValue("var");
605                        messageStorage.put(identifier, currentMessage);
606                        resolveHwnd(currentMessage, childElement);
607                }
608                for (Element childElement : (List<Element>) messageElement.getChildren(
609                                "storeSeq", rulesNamespace)) {
610                        String identifier = childElement.getAttributeValue("varSeq");
611                        Object tmp = messageStorage.get(identifier);
612                        List<WindowsMessage> storedSequence;
613                        if (tmp == null || tmp instanceof WindowsMessage) {
614                                storedSequence = new LinkedList<WindowsMessage>();
615                                storedSequence.add(currentMessage);
616                                messageStorage.put(identifier, storedSequence);
617                        } else if (tmp instanceof List<?>) {
618                                storedSequence = (List<WindowsMessage>) tmp;
619                                storedSequence.add(currentMessage);
620                                messageStorage.put(identifier, storedSequence);
621                        }
622                        resolveHwnd(currentMessage, childElement);
623                }
624        }
625
626        private boolean matchMultipleMessages(Element messageElement,
627                        Element nextMessageElement) {
628                boolean isMatch = false;
629                boolean isCurrentMatch = false;
630                boolean nextMatchFound = false;
631                WindowsMessage currentMessage = null;
632                WindowsMessage nextMessage = null;
633
634                int type = Integer.parseInt(messageElement.getAttributeValue("type"));
635
636                int nextType = -1;
637                if (nextMessageElement != null) {
638                        nextType = Integer.parseInt(nextMessageElement
639                                        .getAttributeValue("type"));
640                }
641
642                while (!nextMatchFound && sequenceIterator.hasNext()) {
643                        currentMessage = sequenceIterator.next();
644                        if (type == currentMessage.getType()) {
645                                isCurrentMatch = evalEqualRestrictions(currentMessage,
646                                                messageElement);
647                                isMatch = isMatch || isCurrentMatch;
648
649                                if (isCurrentMatch) {
650                                        handleStorage(messageElement, currentMessage);
651                                        currentToken.setTarget(currentMessage
652                                                        .getXmlWindowDescription());
653                                        currentToken
654                                                        .setTargetShort(currentMessage.getParentNames());
655                                }
656                        }
657                        if (nextMessageElement != null && isMatch) {
658                                // peek next message to check if the sequence ends and the next
659                                // match is found
660                                if (!sequenceIterator.hasNext()) {
661                                        return false; // sequence is over, but not all messages are
662                                                                        // found
663                                }
664                                nextMessage = sequenceIterator.next();
665                                sequenceIterator.previous();
666
667                                if (nextType == nextMessage.getType()) {
668                                        nextMatchFound = evalEqualRestrictions(nextMessage,
669                                                        nextMessageElement);
670                                }
671
672                        }
673                }
674
675                return isMatch;
676        }
677
678        private boolean matchSingleMessage(Element messageElement) {
679                boolean isMatch = false;
680                WindowsMessage currentMessage = null;
681
682                int type = Integer.parseInt(messageElement.getAttributeValue("type"));
683
684                while (!isMatch && sequenceIterator.hasNext()) {
685                        // traverses the messages from the current position forward till a
686                        // message with the correct type is found
687                        currentMessage = sequenceIterator.next();
688                        if (type == currentMessage.getType()) {
689                                // message with the correct type found
690                                // eval child nodes for further matching/storing
691                                isMatch = evalEqualRestrictions(currentMessage, messageElement);
692
693                                // in case the message is a match, eval storage children
694                                if (isMatch) {
695                                        handleStorage(messageElement, currentMessage);
696                                        currentToken.setTarget(currentMessage
697                                                        .getXmlWindowDescription());
698                                        currentToken
699                                                        .setTargetShort(currentMessage.getParentNames());
700                                }
701                        }
702                }
703
704                return isMatch;
705        }
706
707        @SuppressWarnings("unchecked")
708        private void resolveHwnd(WindowsMessage currentMessage, Element childElement) {
709                List<Element> resolveElements = childElement.getChildren("resolveHwnd",
710                                rulesNamespace);
711                for (Element resolveElement : resolveElements) {
712                        String param = resolveElement.getAttributeValue("param");
713                        String storeParam = resolveElement.getAttributeValue("storeParam");
714                        int paramHwnd = Integer
715                                        .parseInt(currentMessage.getParameter(param));
716                        WindowTreeNode node = WindowTree.getInstance().find(paramHwnd);
717                        if (node != null) {
718                                currentMessage.addParameter(storeParam,
719                                                node.xmlRepresentation());
720                        }
721                }
722        }
723       
724        private long loHiWord(Element param) {
725                Element loword = param.getChild("LOWORD", rulesNamespace);
726                Element hiword = param.getChild("HIWORD", rulesNamespace);
727                String lowordStr = getTermValue(null, (Element) loword.getChildren().get(0));
728                String hiwordStr = getTermValue(null, (Element) hiword.getChildren().get(0));
729                return LOWORD(Integer.parseInt(lowordStr))+HIWORD(Integer.parseInt(hiwordStr));
730        }
731       
732        private static short LOWORD(long data) {
733                return (short) (data & 0xffff);
734        }
735
736        private static short HIWORD(long data) {
737                return (short) (data >> 16);
738        }
739
740}
Note: See TracBrowser for help on using the repository browser.