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

Last change on this file since 106 was 77, checked in by sherbold, 14 years ago

+ introduced de.ugoe.cs.eventbench.windows.WindowsEvent?

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