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

Last change on this file since 54 was 52, checked in by sherbold, 14 years ago
  • refactored translation layer features for Windows MFC into seperate packages de.ugoe.cs.eventbench.windows.*
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.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                        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                                                generatedMessage.setLPARAM(paramValue);
403                                        } else {
404                                                try {
405                                                        paramValue = Integer.parseInt(paramValueStr);
406                                                        generatedMessage.setLPARAM(paramValue);
407                                                } catch (NumberFormatException e) {
408                                                        generatedMessage.setLPARAMasWindowDesc(paramValueStr);
409                                                }
410                                        }
411                                } else if (genMsgChild.getName().equals("WPARAM")) {
412                                        String paramValueStr = getTermValue(null, termElement);
413                                        long paramValue = 0;
414                                        Element loword = genMsgChild.getChild("LOWORD", rulesNamespace);
415                                        if( loword!=null ) {
416                                                paramValue = loHiWord(genMsgChild);
417                                                generatedMessage.setWPARAM(paramValue);
418                                        } else {
419                                                try {
420                                                        paramValue = Integer.parseInt(paramValueStr);
421                                                        generatedMessage.setWPARAM(paramValue);
422                                                } catch (NumberFormatException e) {
423                                                        generatedMessage.setWPARAMasWindowDesc(paramValueStr);
424                                                }
425                                        }
426                                }
427                        }
428                }
429                if (generatedMessage != null) {
430                        int delay = Integer.parseInt(genMsgElement
431                                        .getAttributeValue("delay"));
432                        generatedMessage.setDelay(delay);
433                } else {
434                        currentToken.invalidateReplay();
435                }
436                currentToken.addReplayEvent(generatedMessage);
437        }
438
439        @SuppressWarnings("unchecked")
440        private void generateReplaySequence(Element genMsgElement) {
441                List<Element> genMsgSeqChildren = genMsgElement.getChildren();
442                List<WindowsMessage> generatedMessageSeq = new LinkedList<WindowsMessage>();
443                if (genMsgSeqChildren.size() == 1) {
444                        String obj = genMsgSeqChildren.get(0).getAttributeValue("seqObj");
445                        generatedMessageSeq = getStoredSeqVariable(obj);
446                } else {
447                        boolean msgsGenerated = false;
448                        int constMsgType = 0;
449                        for (Element genMsgSeqChild : genMsgSeqChildren) {
450                                Element termElement = (Element) genMsgSeqChild.getChildren()
451                                                .get(0);
452                                if (genMsgSeqChild.getName().equals("type")) {
453                                        // note: cannot easily be extracted because of mulitple
454                                        // return values
455                                        if (termElement.getName().equals("seqValue")) {
456                                                String obj = termElement.getAttributeValue("seqObj");
457                                                List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
458                                                for (WindowsMessage msg : seqVar) {
459                                                        generatedMessageSeq.add(new WindowsMessage(msg
460                                                                        .getType()));
461                                                }
462                                                msgsGenerated = true;
463                                        } else { // constValue type
464                                                constMsgType = Integer.parseInt(getTermValue(null,
465                                                                termElement));
466                                        }
467                                } else if (genMsgSeqChild.getName().equals("target")) {
468                                        msgsGenerated = createSequenceTarget(generatedMessageSeq,
469                                                        msgsGenerated, constMsgType, termElement);
470                                } else if (genMsgSeqChild.getName().equals("LPARAM")) {
471                                        msgsGenerated = createSequenceLParam(generatedMessageSeq,
472                                                        msgsGenerated, constMsgType, termElement);
473                                } else if (genMsgSeqChild.getName().equals("WPARAM")) {
474                                        msgsGenerated = createSequenceWParam(generatedMessageSeq,
475                                                        msgsGenerated, constMsgType, termElement);
476                                }
477                        }
478                }
479                currentToken.addReplaySequence(generatedMessageSeq);
480        }
481
482        private WindowsMessage getCurrentSeqMsg(
483                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
484                        int constMsgType, Iterator<WindowsMessage> seqIterator) {
485                WindowsMessage currentSeqMsg = null;
486                if (msgsGenerated) {
487                        currentSeqMsg = seqIterator.next();
488                } else {
489                        currentSeqMsg = new WindowsMessage(constMsgType);
490                        generatedMessageSeq.add(currentSeqMsg);
491                }
492                return currentSeqMsg;
493        }
494
495        private WindowsMessage getStoredMessageVariable(
496                        WindowsMessage currentMessage, String obj)
497                        throws InvalidParameterException {
498                WindowsMessage varMessage = null;
499                if (obj.equals("this")) {
500                        if (currentMessage == null) {
501                                throw new InvalidParameterException(
502                                                "Failure obtaining term value for rule "
503                                                                + currentRuleName
504                                                                + ": \"this\" is not a valid name for generating runtime messages.");
505                        }
506                        varMessage = currentMessage;
507                } else {
508                        Object tmp = messageStorage.get(obj);
509                        if (tmp instanceof WindowsMessage) {
510                                varMessage = (WindowsMessage) tmp;
511                        } else {
512                                throw new InvalidParameterException(
513                                                "Failure obtaining term value for rule "
514                                                                + currentRuleName + ": No message \"" + obj
515                                                                + "\" stored.");
516                        }
517                }
518                return varMessage;
519        }
520
521        @SuppressWarnings("unchecked")
522        private List<WindowsMessage> getStoredSeqVariable(String obj)
523                        throws InvalidParameterException {
524                List<WindowsMessage> varMsgSeq = null;
525                Object tmp = messageStorage.get(obj);
526                if (tmp instanceof List<?>) {
527                        varMsgSeq = (List<WindowsMessage>) tmp;
528                } else {
529                        throw new InvalidParameterException(
530                                        "Failure obtaining term value for rule " + currentRuleName
531                                                        + ": No sequence \"" + obj + "\" store.");
532                }
533                return varMsgSeq;
534        }
535
536        private String getTermValue(WindowsMessage currentMessage,
537                        Element termElement) {
538                String value = null;
539                WindowsMessage varMessage = null;
540                if (termElement.getName().equals("constValue")) {
541                        value = termElement.getAttributeValue("value");
542                } else if (termElement.getName().equals("paramValue")) {
543                        String objectName = termElement.getAttributeValue("obj");
544                        varMessage = getStoredMessageVariable(currentMessage, objectName);
545                        if (varMessage != null) {
546                                String param = termElement.getAttributeValue("param");
547                                value = varMessage.getParameter(param);
548                        }
549                } else if (termElement.getName().equals("winInfoValue")) {
550                        String objectName = termElement.getAttributeValue("obj");
551                        varMessage = getStoredMessageVariable(currentMessage, objectName);
552                        if (varMessage != null) {
553                                String paramString = termElement.getAttributeValue("winParam");
554                                if (paramString.equals("class")) {
555                                        value = varMessage.getWindowClass();
556                                } else if (paramString.equals("resourceId")) {
557                                        value = "" + varMessage.getWindowResourceId();
558                                } else if (paramString.equals("hwnd")) {
559                                        value = "" + varMessage.getHwnd();
560                                } else if (paramString.equals("parentTarget")) {
561                                        String target = varMessage.getXmlWindowDescription();
562                                        int index = target.lastIndexOf("<");
563                                        if( index==0 ) {
564                                                Console.println("Trying to adress parent of top-level window! Replay probably invalid!");
565                                        }
566                                        value = target.substring(0, index);
567                                }
568                        }
569                } else if (termElement.getName().equals("msgInfoValue")) {
570                        String objectName = termElement.getAttributeValue("obj");
571                        varMessage = getStoredMessageVariable(currentMessage, objectName);
572                        if (varMessage != null) {
573                                String paramString = termElement.getAttributeValue("msgParam");
574                                if (paramString.equals("type")) {
575                                        value = "" + varMessage.getType();
576                                } else if (paramString.equals("target")) {
577                                        value = varMessage.getXmlWindowDescription();
578                                }
579                        }
580                }
581                return value;
582        }
583
584        private List<String> getTermValueSeq(WindowsMessage currentMessage,
585                        Element termElement) {
586                List<String> values = new LinkedList<String>();
587                if (termElement.getName().equals("seqValue")) {
588                        String obj = termElement.getAttributeValue("seqObj");
589                        String param = termElement.getAttributeValue("param");
590                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
591
592                        for (WindowsMessage msg : seqVar) {
593                                // msg.getParameter returns null, if parameter is not found,
594                                // therefore the List can contain null-values
595                                values.add(msg.getParameter(param));
596                        }
597                }
598                return values;
599        }
600
601        @SuppressWarnings("unchecked")
602        private void handleStorage(Element messageElement,
603                        WindowsMessage currentMessage) {
604                for (Element childElement : (List<Element>) messageElement.getChildren(
605                                "store", rulesNamespace)) {
606                        String identifier = childElement.getAttributeValue("var");
607                        messageStorage.put(identifier, currentMessage);
608                        resolveHwnd(currentMessage, childElement);
609                }
610                for (Element childElement : (List<Element>) messageElement.getChildren(
611                                "storeSeq", rulesNamespace)) {
612                        String identifier = childElement.getAttributeValue("varSeq");
613                        Object tmp = messageStorage.get(identifier);
614                        List<WindowsMessage> storedSequence;
615                        if (tmp == null || tmp instanceof WindowsMessage) {
616                                storedSequence = new LinkedList<WindowsMessage>();
617                                storedSequence.add(currentMessage);
618                                messageStorage.put(identifier, storedSequence);
619                        } else if (tmp instanceof List<?>) {
620                                storedSequence = (List<WindowsMessage>) tmp;
621                                storedSequence.add(currentMessage);
622                                messageStorage.put(identifier, storedSequence);
623                        }
624                        resolveHwnd(currentMessage, childElement);
625                }
626        }
627
628        private boolean matchMultipleMessages(Element messageElement,
629                        Element nextMessageElement) {
630                boolean isMatch = false;
631                boolean isCurrentMatch = false;
632                boolean nextMatchFound = false;
633                WindowsMessage currentMessage = null;
634                WindowsMessage nextMessage = null;
635
636                int type = Integer.parseInt(messageElement.getAttributeValue("type"));
637
638                int nextType = -1;
639                if (nextMessageElement != null) {
640                        nextType = Integer.parseInt(nextMessageElement
641                                        .getAttributeValue("type"));
642                }
643
644                while (!nextMatchFound && sequenceIterator.hasNext()) {
645                        currentMessage = sequenceIterator.next();
646                        if (type == currentMessage.getType()) {
647                                isCurrentMatch = evalEqualRestrictions(currentMessage,
648                                                messageElement);
649                                isMatch = isMatch || isCurrentMatch;
650
651                                if (isCurrentMatch) {
652                                        handleStorage(messageElement, currentMessage);
653                                        currentToken.setTarget(currentMessage
654                                                        .getXmlWindowDescription());
655                                        currentToken
656                                                        .setTargetShort(currentMessage.getParentNames());
657                                }
658                        }
659                        if (nextMessageElement != null && isMatch) {
660                                // peek next message to check if the sequence ends and the next
661                                // match is found
662                                if (!sequenceIterator.hasNext()) {
663                                        return false; // sequence is over, but not all messages are
664                                                                        // found
665                                }
666                                nextMessage = sequenceIterator.next();
667                                sequenceIterator.previous();
668
669                                if (nextType == nextMessage.getType()) {
670                                        nextMatchFound = evalEqualRestrictions(nextMessage,
671                                                        nextMessageElement);
672                                }
673
674                        }
675                }
676
677                return isMatch;
678        }
679
680        private boolean matchSingleMessage(Element messageElement) {
681                boolean isMatch = false;
682                WindowsMessage currentMessage = null;
683
684                int type = Integer.parseInt(messageElement.getAttributeValue("type"));
685
686                while (!isMatch && sequenceIterator.hasNext()) {
687                        // traverses the messages from the current position forward till a
688                        // message with the correct type is found
689                        currentMessage = sequenceIterator.next();
690                        if (type == currentMessage.getType()) {
691                                // message with the correct type found
692                                // eval child nodes for further matching/storing
693                                isMatch = evalEqualRestrictions(currentMessage, messageElement);
694
695                                // in case the message is a match, eval storage children
696                                if (isMatch) {
697                                        handleStorage(messageElement, currentMessage);
698                                        currentToken.setTarget(currentMessage
699                                                        .getXmlWindowDescription());
700                                        currentToken
701                                                        .setTargetShort(currentMessage.getParentNames());
702                                }
703                        }
704                }
705
706                return isMatch;
707        }
708
709        @SuppressWarnings("unchecked")
710        private void resolveHwnd(WindowsMessage currentMessage, Element childElement) {
711                List<Element> resolveElements = childElement.getChildren("resolveHwnd",
712                                rulesNamespace);
713                for (Element resolveElement : resolveElements) {
714                        String param = resolveElement.getAttributeValue("param");
715                        String storeParam = resolveElement.getAttributeValue("storeParam");
716                        int paramHwnd = Integer
717                                        .parseInt(currentMessage.getParameter(param));
718                        WindowTreeNode node = WindowTree.getInstance().find(paramHwnd);
719                        if (node != null) {
720                                currentMessage.addParameter(storeParam,
721                                                node.xmlRepresentation());
722                        }
723                }
724        }
725       
726        private long loHiWord(Element param) {
727                Element loword = param.getChild("LOWORD", rulesNamespace);
728                Element hiword = param.getChild("HIWORD", rulesNamespace);
729                String lowordStr = getTermValue(null, (Element) loword.getChildren().get(0));
730                String hiwordStr = getTermValue(null, (Element) hiword.getChildren().get(0));
731                return MAKEPARAM(Short.parseShort(lowordStr), Short.parseShort(hiwordStr));
732        }
733       
734        private static int MAKEPARAM(short loword, short hiword) {
735                return loword| ((int) hiword) << Short.SIZE;
736        }
737
738}
Note: See TracBrowser for help on using the repository browser.