Ignore:
Timestamp:
09/09/11 06:23:36 (13 years ago)
Author:
sherbold
Message:
  • code documentation and formatting
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/windows/EventGenerator.java

    r141 r171  
    1717import org.jdom.input.SAXBuilder; 
    1818 
     19import de.ugoe.cs.eventbench.data.Event; 
    1920import de.ugoe.cs.eventbench.windows.data.WindowTree; 
    2021import de.ugoe.cs.eventbench.windows.data.WindowTreeNode; 
     
    2425/** 
    2526 * <p> 
    26  * Translates sequences of windows messages into events that can be used by the 
    27  * Logalyzer core libraries for usage analysis. 
     27 * Translates sequences of windows messages into {@link WindowsEvent}s that can 
     28 * be used by the EventBench core libraries. 
    2829 * </p> 
    2930 *  
    3031 * @author Steffen Herbold 
    31  *  
     32 * @version 1.0 
    3233 */ 
    3334public class EventGenerator { 
     
    214215        } 
    215216 
    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!"); 
     217        // //////////////////////////////////////////////////////////// 
     218        // Helper functions for matching of events, i.e., msg-nodes // 
     219        // //////////////////////////////////////////////////////////// 
     220 
     221        /** 
     222         * <p> 
     223         * Handles msg-nodes where multiple is not true, i.e., not a sequences. 
     224         * </p> 
     225         *  
     226         * @param messageElement 
     227         *            {@link Element} representing the msg-node 
     228         * @return true, if a match is found; false otherwise 
     229         */ 
     230        private boolean matchSingleMessage(Element messageElement) { 
     231                boolean isMatch = false; 
     232                WindowsMessage currentMessage = null; 
     233 
     234                int type = Integer.parseInt(messageElement.getAttributeValue("type")); 
     235 
     236                while (!isMatch && sequenceIterator.hasNext()) { 
    284237                        /* 
    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. 
     238                         * traverses the messages from the current position forward till a 
     239                         * message with the correct type is found 
    289240                         */ 
    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  
     241                        currentMessage = sequenceIterator.next(); 
     242                        if (type == currentMessage.getType()) { 
     243                                // message with the correct type found 
     244                                // eval child nodes for further matching/storing 
     245                                isMatch = evalEqualRestrictions(currentMessage, messageElement); 
     246 
     247                                // in case the message is a match, eval storage children 
     248                                if (isMatch) { 
     249                                        handleStorage(messageElement, currentMessage); 
     250                                        currentToken.setTarget(currentMessage 
     251                                                        .getXmlWindowDescription()); 
     252                                        currentToken 
     253                                                        .setTargetShort(currentMessage.getParentNames()); 
     254                                } 
     255                        } 
     256                } 
     257 
     258                return isMatch; 
     259        } 
     260 
     261        /** 
     262         * <p> 
     263         * Handles msg-nodes where multiple is true, i.e., sequences. Requires 
     264         * knowledge about the next msg-node to determine the end of the sequence. 
     265         * </p> 
     266         *  
     267         * @param messageElement 
     268         *            {@link Element} representing the msg-node 
     269         * @param nextMessageElement 
     270         *            {@link Element} representing the next msg-node; {@code null} 
     271         *            if the current node is the last one 
     272         * @return true, if a sequence is matched; false otherwise 
     273         */ 
     274        private boolean matchMultipleMessages(Element messageElement, 
     275                        Element nextMessageElement) { 
     276                boolean isMatch = false; 
     277                boolean isCurrentMatch = false; 
     278                boolean nextMatchFound = false; 
     279                WindowsMessage currentMessage = null; 
     280                WindowsMessage nextMessage = null; 
     281 
     282                int type = Integer.parseInt(messageElement.getAttributeValue("type")); 
     283 
     284                int nextType = -1; 
     285                if (nextMessageElement != null) { 
     286                        nextType = Integer.parseInt(nextMessageElement 
     287                                        .getAttributeValue("type")); 
     288                } 
     289 
     290                while (!nextMatchFound && sequenceIterator.hasNext()) { 
     291                        currentMessage = sequenceIterator.next(); 
     292                        if (type == currentMessage.getType()) { 
     293                                isCurrentMatch = evalEqualRestrictions(currentMessage, 
     294                                                messageElement); 
     295                                isMatch = isMatch || isCurrentMatch; 
     296 
     297                                if (isCurrentMatch) { 
     298                                        handleStorage(messageElement, currentMessage); 
     299                                        currentToken.setTarget(currentMessage 
     300                                                        .getXmlWindowDescription()); 
     301                                        currentToken 
     302                                                        .setTargetShort(currentMessage.getParentNames()); 
     303                                } 
     304                        } 
     305                        if (nextMessageElement != null && isMatch) { 
     306                                // peek next message to check if the sequence ends and the next 
     307                                // match is found 
     308                                if (!sequenceIterator.hasNext()) { 
     309                                        return false; // sequence is over, but not all messages are 
     310                                                                        // found 
     311                                } 
     312                                nextMessage = sequenceIterator.next(); 
     313                                sequenceIterator.previous(); 
     314 
     315                                if (nextType == nextMessage.getType()) { 
     316                                        nextMatchFound = evalEqualRestrictions(nextMessage, 
     317                                                        nextMessageElement); 
     318                                } 
     319 
     320                        } 
     321                } 
     322 
     323                return isMatch; 
     324        } 
     325 
     326        /** 
     327         * <p> 
     328         * Handles equals-nodes. 
     329         * </p> 
     330         *  
     331         * @param currentMessage 
     332         *            {@link Element} representing the msg-node the equals-node 
     333         *            belongs to 
     334         * @param messageElement 
     335         *            {@link Element} representing the equals-node to be evaluated 
     336         * @return true, if constraint is fulfilled; false otherwise 
     337         */ 
    337338        @SuppressWarnings("unchecked") 
    338339        private boolean evalEqualRestrictions(WindowsMessage currentMessage, 
     
    354355                                "equalsSeq", rulesNamespace)) { 
    355356                        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)); 
     357                        List<String> values1 = getTermValueSeq(termElements.get(0)); 
     358                        List<String> values2 = getTermValueSeq(termElements.get(0)); 
    360359                        if (values1 == null || values2 == null) { 
    361360                                isMatch = false; 
     
    367366        } 
    368367 
     368        /** 
     369         * <p> 
     370         * Handles store-nodes and storeSeq-nodes. 
     371         * </p> 
     372         *  
     373         * @param messageElement 
     374         *            {@link Element} representing the msg-node that is currently 
     375         *            being evaluated 
     376         * @param currentMessage 
     377         *            current message in the message sequence that is matched; this 
     378         *            is the message that is stored 
     379         */ 
     380        @SuppressWarnings("unchecked") 
     381        private void handleStorage(Element messageElement, 
     382                        WindowsMessage currentMessage) { 
     383                for (Element childElement : (List<Element>) messageElement.getChildren( 
     384                                "store", rulesNamespace)) { 
     385                        String identifier = childElement.getAttributeValue("var"); 
     386                        messageStorage.put(identifier, currentMessage); 
     387                        resolveHwnd(currentMessage, childElement); 
     388                } 
     389                for (Element childElement : (List<Element>) messageElement.getChildren( 
     390                                "storeSeq", rulesNamespace)) { 
     391                        String identifier = childElement.getAttributeValue("varSeq"); 
     392                        Object tmp = messageStorage.get(identifier); 
     393                        List<WindowsMessage> storedSequence; 
     394                        if (tmp == null || tmp instanceof WindowsMessage) { 
     395                                storedSequence = new LinkedList<WindowsMessage>(); 
     396                                storedSequence.add(currentMessage); 
     397                                messageStorage.put(identifier, storedSequence); 
     398                        } else if (tmp instanceof List<?>) { 
     399                                storedSequence = (List<WindowsMessage>) tmp; 
     400                                storedSequence.add(currentMessage); 
     401                                messageStorage.put(identifier, storedSequence); 
     402                        } 
     403                        resolveHwnd(currentMessage, childElement); 
     404                } 
     405        } 
     406 
     407        /** 
     408         * <p> 
     409         * Resolves a parameter that contains a HWND of a message to the target 
     410         * string of the HWND and stores it. 
     411         * </p> 
     412         *  
     413         * @param currentMessage 
     414         *            message whose HWND is resolved 
     415         * @param childElement 
     416         *            child element of the store node that represents the resolve 
     417         */ 
     418        @SuppressWarnings("unchecked") 
     419        private void resolveHwnd(WindowsMessage currentMessage, Element childElement) { 
     420                List<Element> resolveElements = childElement.getChildren("resolveHwnd", 
     421                                rulesNamespace); 
     422                for (Element resolveElement : resolveElements) { 
     423                        String param = resolveElement.getAttributeValue("param"); 
     424                        String storeParam = resolveElement.getAttributeValue("storeParam"); 
     425                        int paramHwnd = Integer 
     426                                        .parseInt(currentMessage.getParameter(param)); 
     427                        WindowTreeNode node = WindowTree.getInstance().find(paramHwnd); 
     428                        if (node != null) { 
     429                                currentMessage.addParameter(storeParam, 
     430                                                node.xmlRepresentation()); 
     431                        } 
     432                } 
     433        } 
     434 
     435        // ///////////////////////////////////////////////////// 
     436        // Helper functions for generating the replay, i.e., 
     437        // parsing of genMsg und genMsgSeq-nodes 
     438        // ///////////////////////////////////////////////////// 
     439 
     440        /** 
     441         * <p> 
     442         * Handles genMsg-nodes and adds the replay to the {@link Event} that is 
     443         * generated. 
     444         * </p> 
     445         *  
     446         * @param genMsgElement 
     447         *            {@link Element} representing the genMsg-node 
     448         */ 
    369449        @SuppressWarnings("unchecked") 
    370450        private void generateReplayMessage(Element genMsgElement) { 
     
    396476                                        String paramValueStr = getTermValue(null, termElement); 
    397477                                        long paramValue = 0; 
    398                                         Element loword = genMsgChild.getChild("LOWORD", rulesNamespace); 
    399                                         if( loword!=null ) { 
     478                                        Element loword = genMsgChild.getChild("LOWORD", 
     479                                                        rulesNamespace); 
     480                                        if (loword != null) { 
    400481                                                paramValue = loHiWord(genMsgChild); 
    401482                                                generatedMessage.setLPARAM(paramValue); 
     
    405486                                                        generatedMessage.setLPARAM(paramValue); 
    406487                                                } catch (NumberFormatException e) { 
    407                                                         generatedMessage.setLPARAMasWindowDesc(paramValueStr); 
     488                                                        generatedMessage 
     489                                                                        .setLPARAMasWindowDesc(paramValueStr); 
    408490                                                } 
    409491                                        } 
     
    411493                                        String paramValueStr = getTermValue(null, termElement); 
    412494                                        long paramValue = 0; 
    413                                         Element loword = genMsgChild.getChild("LOWORD", rulesNamespace); 
    414                                         if( loword!=null ) { 
     495                                        Element loword = genMsgChild.getChild("LOWORD", 
     496                                                        rulesNamespace); 
     497                                        if (loword != null) { 
    415498                                                paramValue = loHiWord(genMsgChild); 
    416499                                                generatedMessage.setWPARAM(paramValue); 
     
    420503                                                        generatedMessage.setWPARAM(paramValue); 
    421504                                                } catch (NumberFormatException e) { 
    422                                                         generatedMessage.setWPARAMasWindowDesc(paramValueStr); 
     505                                                        generatedMessage 
     506                                                                        .setWPARAMasWindowDesc(paramValueStr); 
    423507                                                } 
    424508                                        } 
     
    436520        } 
    437521 
     522        /** 
     523         * Handles genMsgSeq-nodes and adds the replay to the {@link Event} that is 
     524         * generated.</p> 
     525         *  
     526         * @param genMsgElement 
     527         *            {@link Element} representing the genMsgSeq-node. 
     528         */ 
    438529        @SuppressWarnings("unchecked") 
    439530        private void generateReplaySequence(Element genMsgElement) { 
     
    479570        } 
    480571 
     572        /** 
     573         * <p> 
     574         * Creates the targets for replay sequences generated with genMsgSeq-nodes. 
     575         * </p> 
     576         *  
     577         * @param generatedMessageSeq 
     578         *            list of the messages that is being generated 
     579         * @param msgsGenerated 
     580         *            boolean stating if the list of messages is already generated 
     581         *            or if the generation has to be handles by this method 
     582         * @param constMsgType 
     583         *            a constant message type that is used for message generation, 
     584         *            in case the list of message is generated by this method 
     585         * @param termElement 
     586         *            {@link Element} representing the term-node describing the 
     587         *            target 
     588         * @return true, if the list of message is generated after calling this 
     589         *         method; false otherwise 
     590         * @throws NoSuchElementException 
     591         *             thrown if the seqVar referred to in the termElement contains 
     592         *             a different number of messages than is contained in 
     593         *             messageSeq 
     594         */ 
     595        private boolean createSequenceTarget( 
     596                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated, 
     597                        int constMsgType, Element termElement) 
     598                        throws NoSuchElementException { 
     599                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator(); 
     600                if (termElement.getName().equals("seqValue")) { 
     601                        String obj = termElement.getAttributeValue("seqObj"); 
     602                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj); 
     603                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) { 
     604                                throw new InvalidParameterException( 
     605                                                "Failure generating replay sequence for rule " 
     606                                                                + currentRuleName 
     607                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts."); 
     608                        } 
     609                        for (WindowsMessage msg : seqVar) { 
     610                                WindowsMessage currentSeqMsg = getCurrentSeqMsg( 
     611                                                generatedMessageSeq, msgsGenerated, constMsgType, 
     612                                                seqIterator); 
     613                                String targetString = msg.getParameter(termElement 
     614                                                .getAttributeValue("param")); 
     615                                currentSeqMsg.setXmlWindowDescription(targetString); 
     616                        } 
     617                        msgsGenerated = true; 
     618                } else { // const value 
     619                        throw new AssertionError("target must be a sequence variable!"); 
     620                        /* 
     621                         * If target would not be a variable, the message-elements could not 
     622                         * yet be created and the whole sequence might be broken. If this is 
     623                         * to be changed, createSequenceLParam and createSequenceWParam need 
     624                         * to be addepted, too. 
     625                         */ 
     626                } 
     627                return msgsGenerated; 
     628        } 
     629 
     630        /** 
     631         * <p> 
     632         * Creates the LPARAMs for replay sequences generated with genMsgSeq-nodes. 
     633         * </p> 
     634         *  
     635         * @param generatedMessageSeq 
     636         *            list of the messages that is being generated 
     637         * @param msgsGenerated 
     638         *            boolean stating if the list of messages is already generated 
     639         *            or if the generation has to be handles by this method 
     640         * @param constMsgType 
     641         *            a constant message type that is used for message generation, 
     642         *            in case the list of message is generated by this method 
     643         * @param termElement 
     644         *            {@link Element} representing the term-node describing the 
     645         *            LPARAM 
     646         * @return true, if the list of message is generated after calling this 
     647         *         method; false otherwise 
     648         * @throws NoSuchElementException 
     649         *             thrown if the seqVar referred to in the termElement contains 
     650         *             a different number of messages than is contained in 
     651         *             messageSeq 
     652         */ 
     653        private boolean createSequenceLParam( 
     654                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated, 
     655                        int constMsgType, Element termElement) 
     656                        throws NoSuchElementException { 
     657                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator(); 
     658                if (termElement.getName().equals("seqValue")) { 
     659                        String obj = termElement.getAttributeValue("seqObj"); 
     660                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj); 
     661                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) { 
     662                                throw new InvalidParameterException( 
     663                                                "Failure generating replay sequence for rule " 
     664                                                                + currentRuleName 
     665                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts."); 
     666                        } 
     667                        for (WindowsMessage msg : seqVar) { 
     668                                WindowsMessage currentSeqMsg = getCurrentSeqMsg( 
     669                                                generatedMessageSeq, msgsGenerated, constMsgType, 
     670                                                seqIterator); 
     671                                String paramValueStr = msg.getParameter(termElement 
     672                                                .getAttributeValue("param")); 
     673                                int paramValue = 0; 
     674                                try { 
     675                                        paramValue = Integer.parseInt(paramValueStr); 
     676                                        currentSeqMsg.setLPARAM(paramValue); 
     677                                } catch (NumberFormatException e) { 
     678                                        currentSeqMsg.setLPARAMasWindowDesc(paramValueStr); 
     679                                } 
     680                        } 
     681                        if (seqIterator.hasNext()) { 
     682                                // the first seq-var has a different number of elements than the 
     683                                // current one 
     684                                throw new NoSuchElementException(); 
     685                        } 
     686                        msgsGenerated = true; 
     687                } else { // const value 
     688                        int paramValue = Integer.parseInt(getTermValue(null, termElement)); 
     689                        while (seqIterator.hasNext()) { 
     690                                seqIterator.next().setLPARAM(paramValue); 
     691                        } 
     692                } 
     693                return msgsGenerated; 
     694        } 
     695 
     696        /** 
     697         * <p> 
     698         * Creates the WPARAMs for replay sequences generated with genMsgSeq-nodes. 
     699         * </p> 
     700         *  
     701         * @param generatedMessageSeq 
     702         *            list of the messages that is being generated 
     703         * @param msgsGenerated 
     704         *            boolean stating if the list of messages is already generated 
     705         *            or if the generation has to be handles by this method 
     706         * @param constMsgType 
     707         *            a constant message type that is used for message generation, 
     708         *            in case the list of message is generated by this method 
     709         * @param termElement 
     710         *            {@link Element} representing the term-node describing the 
     711         *            WPARAM 
     712         * @return true, if the list of message is generated after calling this 
     713         *         method; false otherwise 
     714         * @throws NoSuchElementException 
     715         *             thrown if the seqVar referred to in the termElement contains 
     716         *             a different number of messages than is contained in 
     717         *             messageSeq 
     718         */ 
     719        private boolean createSequenceWParam( 
     720                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated, 
     721                        int constMsgType, Element termElement) 
     722                        throws NoSuchElementException { 
     723                Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator(); 
     724                if (termElement.getName().equals("seqValue")) { 
     725                        String obj = termElement.getAttributeValue("seqObj"); 
     726                        List<WindowsMessage> seqVar = getStoredSeqVariable(obj); 
     727                        if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) { 
     728                                throw new InvalidParameterException( 
     729                                                "Failure generating replay sequence for rule " 
     730                                                                + currentRuleName 
     731                                                                + ": One or more of the sequence variables used to generate a sequence have different lenghts."); 
     732                        } 
     733                        for (WindowsMessage msg : seqVar) { 
     734                                WindowsMessage currentSeqMsg = getCurrentSeqMsg( 
     735                                                generatedMessageSeq, msgsGenerated, constMsgType, 
     736                                                seqIterator); 
     737                                String paramValueStr = msg.getParameter(termElement 
     738                                                .getAttributeValue("param")); 
     739                                int paramValue = 0; 
     740                                try { 
     741                                        paramValue = Integer.parseInt(paramValueStr); 
     742                                        currentSeqMsg.setWPARAM(paramValue); 
     743                                } catch (NumberFormatException e) { 
     744                                        currentSeqMsg.setWPARAMasWindowDesc(paramValueStr); 
     745                                } 
     746                        } 
     747                        if (seqIterator.hasNext()) { 
     748                                // the first seq-var has a different number of elements than the 
     749                                // current one 
     750                                throw new NoSuchElementException(); 
     751                        } 
     752                        msgsGenerated = true; 
     753                } else { // const value 
     754                        int paramValue = Integer.parseInt(getTermValue(null, termElement)); 
     755                        while (seqIterator.hasNext()) { 
     756                                seqIterator.next().setWPARAM(paramValue); 
     757                        } 
     758                } 
     759                return msgsGenerated; 
     760        } 
     761 
     762        /** 
     763         * <p> 
     764         * If a message sequence is already generated, i.e., msgsGenerated is true, 
     765         * the seqIterator is used to iterate through these messages and return the 
     766         * current one. If the message sequence is not yet generated, i.e., 
     767         * msgsGenerated is false, the message sequence is generated on the fly 
     768         * during each call of this message and the newly generated messages are 
     769         * returned. 
     770         * </p> 
     771         *  
     772         * @param generatedMessageSeq 
     773         *            message sequence 
     774         * @param msgsGenerated 
     775         *            indicates if generatedMessageSeq is already generated or has 
     776         *            to be generated on the fly by this method 
     777         * @param constMsgType 
     778         *            type of the message to be used for message generation 
     779         * @param seqIterator 
     780         *            iterates through an already generated message sequence; must 
     781         *            not be {@code null}, if msgsGenerated is true 
     782         * @return current message 
     783         */ 
    481784        private WindowsMessage getCurrentSeqMsg( 
    482785                        List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated, 
     
    492795        } 
    493796 
     797        // //////////////////////////// 
     798        // General helper functions // 
     799        // //////////////////////////// 
     800 
     801        /** 
     802         * <p> 
     803         * Retrieves a message from the storage for, e.g., comparison or replay. 
     804         * "this" is used to refer to the current message. 
     805         * </p> 
     806         *  
     807         * @param currentMessage 
     808         *            current message during the parsing; passed to handle "this" 
     809         * @param obj 
     810         *            object identifier in the storage 
     811         * @return message retrieved from the storage 
     812         * @throws InvalidParameterException 
     813         *             thrown in case of invalid uses of "this" or if no message 
     814         *             with the identifier obj is found in the storage 
     815         */ 
    494816        private WindowsMessage getStoredMessageVariable( 
    495817                        WindowsMessage currentMessage, String obj) 
     
    518840        } 
    519841 
     842        /** 
     843         * <p> 
     844         * Retrieves a stored message sequence from the storage. 
     845         * </p> 
     846         *  
     847         * @param obj 
     848         *            object identifier in the storage 
     849         * @return message sequence retrieved from the storage 
     850         * @throws InvalidParameterException 
     851         *             thrown if no message sequences with the identifier obj is 
     852         *             found in the storage 
     853         */ 
    520854        @SuppressWarnings("unchecked") 
    521855        private List<WindowsMessage> getStoredSeqVariable(String obj) 
     
    533867        } 
    534868 
     869        /** 
     870         * <p> 
     871         * Handles term-nodes and returns the value of the described term. 
     872         * </p> 
     873         *  
     874         * @param currentMessage 
     875         *            current message during the parsing; required to resolve 
     876         *            references to "this" in a term 
     877         * @param termElement 
     878         *            {@link Element} representing the term node 
     879         * @return value of the term or {@code null} of the term node could not be 
     880         *         evaluated 
     881         */ 
    535882        private String getTermValue(WindowsMessage currentMessage, 
    536883                        Element termElement) { 
     
    560907                                        String target = varMessage.getXmlWindowDescription(); 
    561908                                        int index = target.lastIndexOf("<"); 
    562                                         if( index==0 ) { 
     909                                        if (index == 0) { 
    563910                                                Console.println("Trying to adress parent of top-level window! Replay probably invalid!"); 
    564911                                        } 
     
    583930        } 
    584931 
    585         private List<String> getTermValueSeq(WindowsMessage currentMessage, 
    586                         Element termElement) { 
     932        /** 
     933         * <p> 
     934         * Handles term-nodes contained by equalSeq nodes. 
     935         * </p> 
     936         *  
     937         * @param termElement 
     938         *            {@link Element} representing the term-node 
     939         * @return list of values of the term 
     940         */ 
     941        private List<String> getTermValueSeq(Element termElement) { 
    587942                List<String> values = new LinkedList<String>(); 
    588943                if (termElement.getName().equals("seqValue")) { 
     
    600955        } 
    601956 
    602         @SuppressWarnings("unchecked") 
    603         private void handleStorage(Element messageElement, 
    604                         WindowsMessage currentMessage) { 
    605                 for (Element childElement : (List<Element>) messageElement.getChildren( 
    606                                 "store", rulesNamespace)) { 
    607                         String identifier = childElement.getAttributeValue("var"); 
    608                         messageStorage.put(identifier, currentMessage); 
    609                         resolveHwnd(currentMessage, childElement); 
    610                 } 
    611                 for (Element childElement : (List<Element>) messageElement.getChildren( 
    612                                 "storeSeq", rulesNamespace)) { 
    613                         String identifier = childElement.getAttributeValue("varSeq"); 
    614                         Object tmp = messageStorage.get(identifier); 
    615                         List<WindowsMessage> storedSequence; 
    616                         if (tmp == null || tmp instanceof WindowsMessage) { 
    617                                 storedSequence = new LinkedList<WindowsMessage>(); 
    618                                 storedSequence.add(currentMessage); 
    619                                 messageStorage.put(identifier, storedSequence); 
    620                         } else if (tmp instanceof List<?>) { 
    621                                 storedSequence = (List<WindowsMessage>) tmp; 
    622                                 storedSequence.add(currentMessage); 
    623                                 messageStorage.put(identifier, storedSequence); 
    624                         } 
    625                         resolveHwnd(currentMessage, childElement); 
    626                 } 
    627         } 
    628  
    629         private boolean matchMultipleMessages(Element messageElement, 
    630                         Element nextMessageElement) { 
    631                 boolean isMatch = false; 
    632                 boolean isCurrentMatch = false; 
    633                 boolean nextMatchFound = false; 
    634                 WindowsMessage currentMessage = null; 
    635                 WindowsMessage nextMessage = null; 
    636  
    637                 int type = Integer.parseInt(messageElement.getAttributeValue("type")); 
    638  
    639                 int nextType = -1; 
    640                 if (nextMessageElement != null) { 
    641                         nextType = Integer.parseInt(nextMessageElement 
    642                                         .getAttributeValue("type")); 
    643                 } 
    644  
    645                 while (!nextMatchFound && sequenceIterator.hasNext()) { 
    646                         currentMessage = sequenceIterator.next(); 
    647                         if (type == currentMessage.getType()) { 
    648                                 isCurrentMatch = evalEqualRestrictions(currentMessage, 
    649                                                 messageElement); 
    650                                 isMatch = isMatch || isCurrentMatch; 
    651  
    652                                 if (isCurrentMatch) { 
    653                                         handleStorage(messageElement, currentMessage); 
    654                                         currentToken.setTarget(currentMessage 
    655                                                         .getXmlWindowDescription()); 
    656                                         currentToken 
    657                                                         .setTargetShort(currentMessage.getParentNames()); 
    658                                 } 
    659                         } 
    660                         if (nextMessageElement != null && isMatch) { 
    661                                 // peek next message to check if the sequence ends and the next 
    662                                 // match is found 
    663                                 if (!sequenceIterator.hasNext()) { 
    664                                         return false; // sequence is over, but not all messages are 
    665                                                                         // found 
    666                                 } 
    667                                 nextMessage = sequenceIterator.next(); 
    668                                 sequenceIterator.previous(); 
    669  
    670                                 if (nextType == nextMessage.getType()) { 
    671                                         nextMatchFound = evalEqualRestrictions(nextMessage, 
    672                                                         nextMessageElement); 
    673                                 } 
    674  
    675                         } 
    676                 } 
    677  
    678                 return isMatch; 
    679         } 
    680  
    681         private boolean matchSingleMessage(Element messageElement) { 
    682                 boolean isMatch = false; 
    683                 WindowsMessage currentMessage = null; 
    684  
    685                 int type = Integer.parseInt(messageElement.getAttributeValue("type")); 
    686  
    687                 while (!isMatch && sequenceIterator.hasNext()) { 
    688                         // traverses the messages from the current position forward till a 
    689                         // message with the correct type is found 
    690                         currentMessage = sequenceIterator.next(); 
    691                         if (type == currentMessage.getType()) { 
    692                                 // message with the correct type found 
    693                                 // eval child nodes for further matching/storing 
    694                                 isMatch = evalEqualRestrictions(currentMessage, messageElement); 
    695  
    696                                 // in case the message is a match, eval storage children 
    697                                 if (isMatch) { 
    698                                         handleStorage(messageElement, currentMessage); 
    699                                         currentToken.setTarget(currentMessage 
    700                                                         .getXmlWindowDescription()); 
    701                                         currentToken 
    702                                                         .setTargetShort(currentMessage.getParentNames()); 
    703                                 } 
    704                         } 
    705                 } 
    706  
    707                 return isMatch; 
    708         } 
    709  
    710         @SuppressWarnings("unchecked") 
    711         private void resolveHwnd(WindowsMessage currentMessage, Element childElement) { 
    712                 List<Element> resolveElements = childElement.getChildren("resolveHwnd", 
    713                                 rulesNamespace); 
    714                 for (Element resolveElement : resolveElements) { 
    715                         String param = resolveElement.getAttributeValue("param"); 
    716                         String storeParam = resolveElement.getAttributeValue("storeParam"); 
    717                         int paramHwnd = Integer 
    718                                         .parseInt(currentMessage.getParameter(param)); 
    719                         WindowTreeNode node = WindowTree.getInstance().find(paramHwnd); 
    720                         if (node != null) { 
    721                                 currentMessage.addParameter(storeParam, 
    722                                                 node.xmlRepresentation()); 
    723                         } 
    724                 } 
    725         } 
    726          
     957        /** 
     958         * <p> 
     959         * Handles LOWORD and HIWORD child nodes of LPARAM and WPARAM nodes. The 
     960         * returned value is the LPARAM/WPARAM value based on the LOWORD and HIWORD. 
     961         * </p> 
     962         *  
     963         * @param param 
     964         *            {@link Element} representing the LPARAM/WPARAM node 
     965         * @return value of the LPARAM/WPARAM 
     966         */ 
    727967        private long loHiWord(Element param) { 
    728968                Element loword = param.getChild("LOWORD", rulesNamespace); 
    729969                Element hiword = param.getChild("HIWORD", rulesNamespace); 
    730                 String lowordStr = getTermValue(null, (Element) loword.getChildren().get(0)); 
    731                 String hiwordStr = getTermValue(null, (Element) hiword.getChildren().get(0)); 
    732                 return MAKEPARAM(Short.parseShort(lowordStr), Short.parseShort(hiwordStr)); 
    733         } 
    734          
     970                String lowordStr = getTermValue(null, (Element) loword.getChildren() 
     971                                .get(0)); 
     972                String hiwordStr = getTermValue(null, (Element) hiword.getChildren() 
     973                                .get(0)); 
     974                return MAKEPARAM(Short.parseShort(lowordStr), 
     975                                Short.parseShort(hiwordStr)); 
     976        } 
     977 
     978        /** 
     979         * <p> 
     980         * Takes to short integers and combines them into the high and low order 
     981         * bits of an integer. 
     982         * </p> 
     983         *  
     984         * @param loword 
     985         *            low word 
     986         * @param hiword 
     987         *            high word 
     988         * @return combined integer 
     989         */ 
    735990        private static int MAKEPARAM(short loword, short hiword) { 
    736                 return loword| ((int) hiword) << Short.SIZE; 
     991                return loword | ((int) hiword) << Short.SIZE; 
    737992        } 
    738993 
Note: See TracChangeset for help on using the changeset viewer.