1 /*------------------------------------------------------------------------------
  2 Name:      TestResultSetToXmlConverter.java
  3 Project:   org.xmlBlasterProject:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 ------------------------------------------------------------------------------*/
  6 package org.xmlBlaster.test.contrib.dbwatcher;
  7 
  8 import java.io.IOException;
  9 import java.io.InputStream;
 10 import java.util.prefs.Preferences;
 11 
 12 
 13 import junit.framework.TestCase;
 14 import org.custommonkey.xmlunit.XMLTestCase;
 15 import org.xmlBlaster.contrib.I_Info;
 16 import org.xmlBlaster.contrib.I_Update;
 17 import org.xmlBlaster.contrib.db.DbPool;
 18 import org.xmlBlaster.contrib.db.I_DbPool;
 19 import org.xmlBlaster.contrib.dbwatcher.DbWatcher;
 20 import org.xmlBlaster.contrib.dbwatcher.Info;
 21 import org.xmlBlaster.contrib.dbwatcher.detector.I_ChangeDetector;
 22 import org.xmlBlaster.contrib.dbwatcher.mom.XmlBlasterPublisher;
 23 import org.xmlBlaster.test.contrib.TestUtils;
 24 
 25 import java.util.logging.Logger;
 26 
 27 import java.util.Map;
 28 import java.util.HashMap;
 29 
 30 /**
 31  * Test basic functionality. 
 32  * <p> 
 33  * To run most of the tests you need to have a databse (for example Oracle)
 34  * and XmlBlaster up and running.
 35  * </p>
 36  * <p>
 37  * The connection configuration (url, password etc.) is configured
 38  * as JVM property or in {@link #createTest(I_Info, Map)} and
 39  * {@link #setUpDbPool(I_Info)}
 40  * </p> 
 41  *
 42  * @see DbWatcher
 43  * @author Marcel Ruff
 44  */
 45 public class TestResultSetToXmlConverter extends XMLTestCase {
 46     private static Logger log = Logger.getLogger(TestResultSetToXmlConverter.class.getName());
 47     private Preferences prefs;
 48     private I_Info info;
 49     private I_DbPool dbPool;
 50     private Map updateMap = new HashMap(); // collects received update messages
 51     private DbWatcher processor;
 52 
 53     /**
 54      * Start the test. 
 55      * <pre>
 56      * java -Ddb.password=secret junit.swingui.TestRunner -noloading org.xmlBlaster.test.contrib.dbwatcher.TestResultSetToXmlConverter
 57      * </pre>
 58      * @param args Command line settings
 59      */
 60     public static void main(String[] args) {
 61         junit.swingui.TestRunner.run(TestResultSetToXmlConverter.class);
 62     }
 63 
 64     /**
 65      * Default ctor. 
 66      */
 67     public TestResultSetToXmlConverter() {
 68     }
 69 
 70    /**
 71     * Constructor for TestResultSetToXmlConverter.
 72     * @param arg0
 73     */
 74     public TestResultSetToXmlConverter(String arg0) {
 75        super(arg0);
 76     }
 77 
 78     /**
 79      * Configure database access. 
 80      * @see TestCase#setUp()
 81      */
 82    protected void setUp() throws Exception {
 83       super.setUp();
 84       this.prefs = Preferences.userRoot();
 85       this.prefs.clear();
 86       this.info = new Info(this.prefs);
 87       
 88       this.dbPool = setUpDbPool(info);
 89       try {
 90          this.dbPool.update("DROP TABLE TEST_POLL");
 91       } catch(Exception e) {
 92          log.warning(e.toString()); 
 93       }
 94       
 95       this.processor = null;
 96    }
 97    
 98    /**
 99     * Creates a database pooling instance and puts it to info. 
100     * @param info The configuration
101     * @return The created pool
102     */
103    public static DbPool setUpDbPool(I_Info info) {
104       String driverClass = System.getProperty("jdbc.drivers", "org.hsqldb.jdbcDriver:oracle.jdbc.driver.OracleDriver:com.microsoft.jdbc.sqlserver.SQLServerDriver:org.postgresql.Driver");
105       ////System.setProperty("jdbc.drivers", driverClass);
106 
107       /*
108       String dbUrl = System.getProperty("db.url", "jdbc:oracle:thin:@localhost:1521:orcl");
109       String dbUser = System.getProperty("db.user", "system");
110       String dbPassword = System.getProperty("db.password", "");
111       */
112       
113       String dbUrl = System.getProperty("db.url", "jdbc:oracle:thin:@desktop:1521:test");
114       String dbUser = System.getProperty("db.user", "system");
115       String dbPassword = System.getProperty("db.password", "frifra20");
116       
117       //String fs = System.getProperty("file.separator");
118       //String dbUrl = "jdbc:hsqldb:"+System.getProperty("user.home")+fs+"tmp"+fs+"testpoll";
119       //String dbUser = "sa";
120       //String dbPassword = "";
121 
122       info.put("jdbc.drivers", driverClass);
123       info.put("db.url", dbUrl);
124       info.put("db.user", dbUser);
125       info.put("db.password", dbPassword);
126         
127       DbPool dbPool = new DbPool();
128       dbPool.init(info);
129       info.putObject("db.pool", dbPool);
130       
131       return dbPool;
132    }
133 
134    /**
135     * Creates a DbWatcher instance and listens on MoM messages. 
136     * @param info Configuration
137     * @param updateMap The map for received messages
138     * @return A new DbWatcher
139     * @throws Exception
140     */
141    public static DbWatcher createTest(I_Info info, final Map updateMap) throws Exception {
142       /*
143       // Configure the MoM
144       this.prefs.put("mom.connectQos", 
145                      "<qos>" +
146                      " <securityService type='htpasswd' version='1.0'>" +
147                      "   <![CDATA[" + 
148                      "   <user>michele</user>" +
149                      "   <passwd>secret</passwd>" +
150                      "   ]]>" +
151                      " </securityService>" +
152                      " <session name='joe/3'/>'" +
153                      " <address type='SOCKET'>" +
154                      "   socket://192.168.110.10:7607" +
155                      " </address>" +
156                      " </qos>");
157       System.setProperty("protocol", "SOCKET");
158       System.setProperty("protocol/socket/hostname", "192.168.110.10");
159       */
160 
161       DbWatcher pc = new DbWatcher(info);
162       XmlBlasterPublisher mom = (XmlBlasterPublisher)pc.getMom();
163       mom.subscribe("XPATH://key", new I_Update() {
164          public void update(String topic, java.io.InputStream is, Map attrMap) {
165             log.info("Received '" + topic + "' from MoM");
166             try {
167                writeToFile(topic, new String(TestUtils.getContent(is)));
168             }
169             catch (Exception e) {
170                // Ignore   
171             }
172             updateMap.put(topic, is);
173          }
174       });
175       
176       try { Thread.sleep(1000); } catch(Exception e) { /* Ignore */ }
177       updateMap.clear(); // Ignore any existing topics
178 
179       pc.startAlertProducers();
180       
181       return pc;
182    }
183 
184    /*
185     * @see TestCase#tearDown()
186     */
187    protected void tearDown() throws Exception {
188       super.tearDown();
189        
190       if (this.processor != null) {
191          this.processor.shutdown();
192          this.processor = null;
193       }
194        
195       if (this.dbPool != null) {
196          try {
197             this.dbPool.update("DROP TABLE TEST_POLL");
198          } catch(Exception e) {
199             log.warning(e.toString()); 
200          }
201          this.dbPool.shutdown();
202       }
203    }
204 
205    /**
206     * If the table does not exist we expect a null ResultSet
207     * @throws Exception Any type is possible
208     */
209    public final void testTableStates() throws Exception {
210       log.info("Start testTableStates()");
211 
212       this.prefs.put("converter.rootName", "myRootTag");
213       this.prefs.put("db.queryMeatStatement", "");
214       this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
215       this.prefs.put("changeDetector.groupColName", ""); // !!! Tests without grouping
216       this.prefs.put("converter.addMeta", ""+true);
217       this.prefs.put("changeDetector.detectStatement", "SELECT colKey, col1, col2, ICAO_ID FROM TEST_POLL");
218       this.prefs.put("mom.topicName", "db.change.event.TEST_POLL");
219       
220       this.processor = createTest(new Info(prefs), this.updateMap);
221       I_ChangeDetector changeDetector = processor.getChangeDetector();
222       
223       for (int i=0; i<2; i++) {
224          log.info("Testing no table ...");
225          changeDetector.checkAgain(null);
226          sleep(500);
227          assertEquals("Number of message is wrong", 0, this.updateMap.size());
228       }
229 
230       {
231       log.info("Now testing an empty table ...");
232       this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
233       changeDetector.checkAgain(null);
234       sleep(500);
235       assertEquals("Number of message is wrong", 1, this.updateMap.size());
236       String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
237       assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
238       assertXpathNotExists("/myRootTag/row[@num='0']", xml);
239       assertXpathEvaluatesTo("CREATE", "/myRootTag/desc/command/text()", xml);
240       this.updateMap.clear();
241 
242       writeToFile("db.change.event.CREATE", xml);
243 
244       changeDetector.checkAgain(null);
245       sleep(500);
246       assertEquals("Number of message is wrong", 0, this.updateMap.size());
247       }
248 
249       {
250       log.info("Insert one row");
251       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('1.1', '<Bla', '9000', 'EDDI')");
252       changeDetector.checkAgain(null);
253       sleep(500);
254       assertEquals("Number of message is wrong", 1, this.updateMap.size());
255       String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
256       assertNotNull("xml returned is null", xml);
257       // TODO: We deliver a "UPDATE" because of the CREATE md5: Is it easy possible to detect the INSERT?
258       assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
259       assertXpathEvaluatesTo("<Bla", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
260       this.updateMap.clear();
261 
262       writeToFile("db.change.event.INSERT", xml);
263 
264       changeDetector.checkAgain(null);
265       sleep(500);
266       assertEquals("Number of message is wrong", 0, this.updateMap.size());
267       }
268             
269       {
270          log.info("Update one row");
271          this.dbPool.update("UPDATE TEST_POLL SET col1='BXXX' WHERE ICAO_ID='EDDI'");
272          changeDetector.checkAgain(null);
273          sleep(500);
274          assertEquals("Number of message is wrong", 1, this.updateMap.size());
275          String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
276          assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
277          assertXpathEvaluatesTo("BXXX", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
278          this.updateMap.clear();
279 
280          writeToFile("db.change.event.UPDATE", xml);
281 
282          changeDetector.checkAgain(null);
283          sleep(500);
284          assertEquals("Number of message is wrong", 0, this.updateMap.size());
285       }
286 
287       {
288          log.info("Delete one row");
289          this.dbPool.update("DELETE FROM TEST_POLL WHERE ICAO_ID='EDDI'");
290          changeDetector.checkAgain(null);
291          sleep(500);
292          assertEquals("Number of message is wrong", 1, this.updateMap.size());
293          String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
294          // TODO: We deliver "UPDATE" instead of DELETE:
295          assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
296          assertXpathNotExists("/myRootTag/row[@num='0']", xml);
297          this.updateMap.clear();
298 
299          writeToFile("db.change.event.DELETE", xml);
300 
301          changeDetector.checkAgain(null);
302          sleep(500);
303          assertEquals("Number of message is wrong", 0, this.updateMap.size());
304       }
305 
306       {
307          log.info("Drop a table");
308          this.dbPool.update("DROP TABLE TEST_POLL");
309          changeDetector.checkAgain(null);
310          sleep(500);
311          assertEquals("Number of message is wrong", 1, this.updateMap.size());
312          String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
313          assertXpathEvaluatesTo("DROP", "/myRootTag/desc/command/text()", xml);
314          assertXpathNotExists("/myRootTag/row[@num='0']", xml);
315          this.updateMap.clear();
316 
317          writeToFile("db.change.event.DROP", xml);
318 
319          changeDetector.checkAgain(null);
320          sleep(500);
321          assertEquals("Number of message is wrong", 0, this.updateMap.size());
322       }
323 
324       log.info("SUCCESS");
325    }
326 
327    /**
328     * @throws Exception Any type is possible
329     */
330    public final void testNULLcol() throws Exception {
331       log.info("Start testNULLcol()");
332 
333       this.prefs.put("converter.rootName", "myRootTag");
334       this.prefs.put("db.queryMeatStatement", "");
335       this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
336       this.prefs.put("changeDetector.groupColName", ""); // !!! Tests without grouping
337       this.prefs.put("converter.addMeta", ""+true);
338       this.prefs.put("changeDetector.detectStatement", "SELECT colKey, col1, col2, ICAO_ID FROM TEST_POLL");
339       this.prefs.put("mom.topicName", "db.change.event.TEST_POLL");
340 
341       this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
342       //this.dbPool.update("INSERT INTO TEST_POLL (colKey, col1, col2) VALUES ('2.0', 'XXX', '2000')");
343       this.dbPool.update("INSERT INTO TEST_POLL (colKey) VALUES ('2.0')");
344       
345       this.processor = createTest(new Info(prefs), this.updateMap);
346       I_ChangeDetector changeDetector = processor.getChangeDetector();
347       
348       changeDetector.checkAgain(null);
349       sleep(500);
350       assertEquals("Number of message is wrong", 1, this.updateMap.size());
351       String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
352       assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
353       assertXpathEvaluatesTo("2", "/myRootTag/row[@num='0']/col[@name='COLKEY']/text()", xml);
354       assertXpathEvaluatesTo("", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
355       assertXpathEvaluatesTo("", "/myRootTag/row[@num='0']/col[@name='COL2']/text()", xml);
356       assertXpathEvaluatesTo("", "/myRootTag/row[@num='0']/col[@name='ICAO_ID']/text()", xml);
357 
358       log.info("SUCCESS");
359    }
360 
361    private void sleep(long millis) {
362       try { Thread.sleep(millis); } catch(Exception e) { /* Ignore */ }
363    }
364    
365    /**
366     * If the table does not exist we expect a null ResultSet
367     * @throws Exception Any type is possible
368     */
369    public final void testQueryMeatTableStates() throws Exception {
370       log.info("Start testQueryMeatTableStates()");
371 
372       this.prefs.put("converter.rootName", "myRootTag");
373       this.prefs.put("db.queryMeatStatement", "select 'Bla-'||COLKEY from TEST_POLL");
374       this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
375       this.prefs.put("changeDetector.groupColName", ""); // !!! Tests without grouping
376       this.prefs.put("converter.addMeta", ""+true);
377       this.prefs.put("changeDetector.detectStatement", "SELECT colKey, col1, col2, ICAO_ID FROM TEST_POLL");
378       this.prefs.put("mom.topicName", "db.change.event.TEST_POLL");
379       
380       this.processor = createTest(new Info(prefs), this.updateMap);
381       I_ChangeDetector changeDetector = processor.getChangeDetector();
382       
383       for (int i=0; i<2; i++) {
384          log.info("Testing no table ...");
385          changeDetector.checkAgain(null);
386          sleep(500);
387          assertEquals("Number of message is wrong", 0, this.updateMap.size());
388       }
389 
390       {
391       log.info("Now testing an empty table ...");
392       this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
393       changeDetector.checkAgain(null);
394       sleep(500);
395       assertEquals("Number of message is wrong", 1, this.updateMap.size());
396       String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
397       assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
398       assertXpathNotExists("/myRootTag/row[@num='0']", xml);
399       assertXpathEvaluatesTo("CREATE", "/myRootTag/desc/command/text()", xml);
400       this.updateMap.clear();
401 
402       changeDetector.checkAgain(null);
403       sleep(500);
404       assertEquals("Number of message is wrong", 0, this.updateMap.size());
405       }
406 
407       {
408       log.info("Insert one row");
409       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('1.1', '<Bla', '9000', 'EDDI')");
410       changeDetector.checkAgain(null);
411       sleep(500);
412       assertEquals("Number of message is wrong", 1, this.updateMap.size());
413       String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
414       assertNotNull("xml returned is null", xml);
415       assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
416       //assertXpathEvaluatesTo("Bla-1,1", "/myRootTag/row[@num='0']/col[@name='BLA-||COLKEY']/text()", xml);
417       assertTrue(xml.indexOf("Bla-1.1") != -1);
418       this.updateMap.clear();
419 
420       writeToFile("db.change.event.INSERT", xml);
421 
422       changeDetector.checkAgain(null);
423       sleep(500);
424       assertEquals("Number of message is wrong", 0, this.updateMap.size());
425       }
426             
427       {
428          log.info("Update one row");
429          this.dbPool.update("UPDATE TEST_POLL SET colKey='4.44' WHERE ICAO_ID='EDDI'");
430          changeDetector.checkAgain(null);
431          sleep(500);
432          assertEquals("Number of message is wrong", 1, this.updateMap.size());
433          String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
434          assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
435          //assertXpathEvaluatesTo("Bla-4.44", "/myRootTag/row[@num='0']/col[@name='BLA-||COLKEY']/text()", xml);
436          assertTrue(xml.indexOf("Bla-4.44") != -1);
437          this.updateMap.clear();
438 
439          writeToFile("db.change.event.UPDATE", xml);
440 
441          changeDetector.checkAgain(null);
442          sleep(500);
443          assertEquals("Number of message is wrong", 0, this.updateMap.size());
444       }
445 
446       {
447          log.info("Delete one row");
448          this.dbPool.update("DELETE FROM TEST_POLL WHERE ICAO_ID='EDDI'");
449          changeDetector.checkAgain(null);
450          sleep(500);
451          assertEquals("Number of message is wrong", 1, this.updateMap.size());
452          String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
453          assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
454          assertXpathNotExists("/myRootTag/row[@num='0']", xml);
455          this.updateMap.clear();
456 
457          writeToFile("db.change.event.DELETE", xml);
458 
459          changeDetector.checkAgain(null);
460          sleep(500);
461          assertEquals("Number of message is wrong", 0, this.updateMap.size());
462       }
463 
464       {
465          log.info("Drop a table");
466          this.dbPool.update("DROP TABLE TEST_POLL");
467          changeDetector.checkAgain(null);
468          sleep(500);
469          assertEquals("Number of message is wrong", 1, this.updateMap.size());
470          String xml = (String)this.updateMap.get("db.change.event.TEST_POLL");
471          assertXpathEvaluatesTo("DROP", "/myRootTag/desc/command/text()", xml);
472          assertXpathNotExists("/myRootTag/row[@num='0']", xml);
473          this.updateMap.clear();
474 
475          writeToFile("db.change.event.DROP", xml);
476 
477          changeDetector.checkAgain(null);
478          sleep(500);
479          assertEquals("Number of message is wrong", 0, this.updateMap.size());
480       }
481 
482       log.info("SUCCESS");
483    }
484 
485    /**
486     * Test synchronous all possible table changes.
487     * We drive two test, one with meat and one as content less event messages.
488     * @throws Exception Any type is possible
489     */
490    public final void testGroupedQueryMeatTableStates() throws Exception {
491       log.info("Start testGroupedQueryMeatTableStates()");
492 
493       this.prefs.put("converter.rootName", "myRootTag");
494       this.prefs.put("db.queryMeatStatement", "select ICAO_ID, 'Bla-'||COLKEY from TEST_POLL where ICAO_ID='${groupColValue}'");
495       this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
496       this.prefs.put("changeDetector.groupColName", "ICAO_ID");
497       this.prefs.put("converter.addMeta", ""+true);
498       this.prefs.put("changeDetector.detectStatement", "SELECT colKey, col1, col2, ICAO_ID FROM TEST_POLL ORDER BY ICAO_ID");
499       this.prefs.put("mom.topicName", "db.change.event.${groupColValue}");
500       
501       boolean hasConverter = false;
502       for (int run=0; run<2; run++) {
503          if (run == 0) {
504             this.prefs.put("converter.class", "");
505          }
506          else {        
507             if (this.processor != null) this.processor.shutdown();
508             this.prefs.put("converter.class", "org.xmlBlaster.contrib.dbwatcher.convert.ResultSetToXmlConverter");
509             hasConverter = true;
510          }
511          this.processor = createTest(new Info(prefs), this.updateMap);
512          I_ChangeDetector changeDetector = processor.getChangeDetector();
513 
514          for (int i=0; i<2; i++) {
515             log.info("Testing no table ...");
516             changeDetector.checkAgain(null);
517             sleep(500);
518             assertEquals("Number of message is wrong", 0, this.updateMap.size());
519          }
520 
521          {
522          log.info("Now testing an empty table ...");
523          this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
524          changeDetector.checkAgain(null);
525          sleep(500);
526          assertEquals("Number of message is wrong", 1, this.updateMap.size());
527          String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
528          assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
529          if (hasConverter) {
530             assertXpathNotExists("/myRootTag/row[@num='0']", xml);
531             assertXpathEvaluatesTo("CREATE", "/myRootTag/desc/command/text()", xml);
532          }
533          this.updateMap.clear();
534 
535          writeToFile("db.change.event.CREATE", xml);
536 
537          changeDetector.checkAgain(null);
538          sleep(500);
539          assertEquals("Number of message is wrong", 0, this.updateMap.size());
540          }
541 
542          {
543          log.info("Insert one row");
544          this.dbPool.update("INSERT INTO TEST_POLL VALUES ('1.1', '<Bla', '9000', 'EDDI')");
545          changeDetector.checkAgain(null);
546          sleep(500);
547          assertEquals("Number of message is wrong", 1, this.updateMap.size());
548          String xml = (String)this.updateMap.get("db.change.event.EDDI");
549          assertNotNull("No db.change.event.EDDI message has arrived", xml);
550          if (hasConverter) {
551             assertXpathEvaluatesTo("INSERT", "/myRootTag/desc/command/text()", xml);
552             assertTrue(xml.indexOf("Bla-1.1") != -1);
553          }
554          this.updateMap.clear();
555 
556          writeToFile("db.change.event.INSERT", xml);
557 
558          changeDetector.checkAgain(null);
559          sleep(500);
560          assertEquals("Number of message is wrong", 0, this.updateMap.size());
561          }
562                
563          {
564             log.info("Update one row");
565             this.dbPool.update("UPDATE TEST_POLL SET col1='BXXX' WHERE ICAO_ID='EDDI'");
566             changeDetector.checkAgain(null);
567             sleep(500);
568             assertEquals("Number of message is wrong", 1, this.updateMap.size());
569             String xml = (String)this.updateMap.get("db.change.event.EDDI");
570             assertNotNull("No db.change.event.EDDI message has arrived", xml);
571             if (hasConverter) {
572                assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
573                assertFalse(xml.indexOf("BXXX") != -1); // col is not in queryMeatStatement
574             }
575             this.updateMap.clear();
576 
577             writeToFile("db.change.event.UPDATE", xml);
578 
579             changeDetector.checkAgain(null);
580             sleep(500);
581             assertEquals("Number of message is wrong", 0, this.updateMap.size());
582          }
583 
584          {
585             log.info("Delete one row");
586             this.dbPool.update("DELETE FROM TEST_POLL WHERE ICAO_ID='EDDI'");
587             changeDetector.checkAgain(null);
588             sleep(500);
589             assertEquals("Number of message is wrong", 1, this.updateMap.size());
590             String xml = (String)this.updateMap.get("db.change.event.EDDI");
591             assertNotNull("No db.change.event.EDDI message has arrived", xml);
592             if (hasConverter) {
593                assertXpathEvaluatesTo("DELETE", "/myRootTag/desc/command/text()", xml);
594                assertXpathNotExists("/myRootTag/row[@num='0']", xml);
595             }
596             this.updateMap.clear();
597 
598             writeToFile("db.change.event.DELETE", xml);
599 
600             changeDetector.checkAgain(null);
601             sleep(500);
602             assertEquals("Number of message is wrong", 0, this.updateMap.size());
603          }
604 
605          {
606             log.info("Drop a table");
607             this.dbPool.update("DROP TABLE TEST_POLL");
608             changeDetector.checkAgain(null);
609             sleep(500);
610             assertEquals("Number of message is wrong", 1, this.updateMap.size());
611             String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
612             assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
613             if (hasConverter) {
614                assertXpathEvaluatesTo("DROP", "/myRootTag/desc/command/text()", xml);
615                assertXpathNotExists("/myRootTag/row[@num='0']", xml);
616             }
617             this.updateMap.clear();
618 
619             writeToFile("db.change.event.DROP", xml);
620 
621             changeDetector.checkAgain(null);
622             sleep(500);
623             assertEquals("Number of message is wrong", 0, this.updateMap.size());
624          }
625 
626       }
627       log.info("SUCCESS");
628    }
629 
630    /**
631     * Test synchronous all possible table changes.
632     * We drive two test, one with meat and one as content less event messages.
633     * If the table does not exist we expect a null ResultSet
634     * @throws Exception Any type is possible
635     */
636    public final void testGroupedTableStates() throws Exception {
637       log.info("Start testGroupedTableStates()");
638 
639       this.prefs.put("converter.rootName", "myRootTag");
640       this.prefs.put("db.queryMeatStatement", "");
641       this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
642       this.prefs.put("changeDetector.groupColName", "ICAO_ID");
643       this.prefs.put("converter.addMeta", ""+true);
644       this.prefs.put("changeDetector.detectStatement", "SELECT colKey, col1, col2, ICAO_ID FROM TEST_POLL ORDER BY ICAO_ID");
645       this.prefs.put("mom.topicName", "db.change.event.${groupColValue}");
646       
647       boolean hasConverter = false;
648       for (int run=0; run<2; run++) {
649          if (run == 0) {
650             this.prefs.put("converter.class", "");
651          }
652          else {        
653             this.processor.shutdown();
654             this.prefs.put("converter.class", "org.xmlBlaster.contrib.dbwatcher.convert.ResultSetToXmlConverter");
655             hasConverter = true;
656          }
657          this.processor = createTest(new Info(prefs), this.updateMap);
658          I_ChangeDetector changeDetector = processor.getChangeDetector();
659 
660          for (int i=0; i<2; i++) {
661             log.info("Testing no table ...");
662             changeDetector.checkAgain(null);
663             sleep(500);
664             assertEquals("Number of message is wrong", 0, this.updateMap.size());
665          }
666 
667          {
668          log.info("Now testing an empty table ...");
669          this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
670          changeDetector.checkAgain(null);
671          sleep(500);
672          assertEquals("Number of message is wrong", 1, this.updateMap.size());
673          String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
674          assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
675          if (hasConverter) {
676             assertXpathNotExists("/myRootTag/row[@num='0']", xml);
677             assertXpathEvaluatesTo("CREATE", "/myRootTag/desc/command/text()", xml);
678          }
679          this.updateMap.clear();
680 
681          writeToFile("db.change.event.CREATE", xml);
682 
683          changeDetector.checkAgain(null);
684          sleep(500);
685          assertEquals("Number of message is wrong", 0, this.updateMap.size());
686          }
687 
688          {
689          log.info("Insert one row");
690          this.dbPool.update("INSERT INTO TEST_POLL VALUES ('1.1', '<Bla', '9000', 'EDDI')");
691          changeDetector.checkAgain(null);
692          sleep(500);
693          assertEquals("Number of message is wrong", 1, this.updateMap.size());
694          String xml = (String)this.updateMap.get("db.change.event.EDDI");
695          assertNotNull("No db.change.event.EDDI message has arrived", xml);
696          if (hasConverter) {
697             assertXpathEvaluatesTo("INSERT", "/myRootTag/desc/command/text()", xml);
698             assertXpathEvaluatesTo("<Bla", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
699          }
700          this.updateMap.clear();
701 
702          writeToFile("db.change.event.INSERT", xml);
703 
704          changeDetector.checkAgain(null);
705          sleep(500);
706          assertEquals("Number of message is wrong", 0, this.updateMap.size());
707          }
708                
709          {
710             log.info("Update one row");
711             this.dbPool.update("UPDATE TEST_POLL SET col1='BXXX' WHERE ICAO_ID='EDDI'");
712             changeDetector.checkAgain(null);
713             sleep(500);
714             assertEquals("Number of message is wrong", 1, this.updateMap.size());
715             String xml = (String)this.updateMap.get("db.change.event.EDDI");
716             assertNotNull("No db.change.event.EDDI message has arrived", xml);
717             if (hasConverter) {
718                assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
719                assertXpathEvaluatesTo("BXXX", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
720             }
721             this.updateMap.clear();
722 
723             writeToFile("db.change.event.UPDATE", xml);
724 
725             changeDetector.checkAgain(null);
726             sleep(500);
727             assertEquals("Number of message is wrong", 0, this.updateMap.size());
728          }
729 
730          {
731             log.info("Delete one row");
732             this.dbPool.update("DELETE FROM TEST_POLL WHERE ICAO_ID='EDDI'");
733             changeDetector.checkAgain(null);
734             sleep(500);
735             assertEquals("Number of message is wrong", 1, this.updateMap.size());
736             String xml = (String)this.updateMap.get("db.change.event.EDDI");
737             assertNotNull("No db.change.event.EDDI message has arrived", xml);
738             if (hasConverter) {
739                assertXpathEvaluatesTo("DELETE", "/myRootTag/desc/command/text()", xml);
740                assertXpathNotExists("/myRootTag/row[@num='0']", xml);
741             }
742             this.updateMap.clear();
743 
744             writeToFile("db.change.event.DELETE", xml);
745 
746             changeDetector.checkAgain(null);
747             sleep(500);
748             assertEquals("Number of message is wrong", 0, this.updateMap.size());
749          }
750 
751          {
752             log.info("Drop a table");
753             this.dbPool.update("DROP TABLE TEST_POLL");
754             changeDetector.checkAgain(null);
755             sleep(500);
756             assertEquals("Number of message is wrong", 1, this.updateMap.size());
757             String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
758             assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
759             if (hasConverter) {
760                assertXpathEvaluatesTo("DROP", "/myRootTag/desc/command/text()", xml);
761                assertXpathNotExists("/myRootTag/row[@num='0']", xml);
762             }
763             this.updateMap.clear();
764 
765             writeToFile("db.change.event.DROP", xml);
766 
767             changeDetector.checkAgain(null);
768             sleep(500);
769             assertEquals("Number of message is wrong", 0, this.updateMap.size());
770          }
771       }
772       log.info("SUCCESS");
773    }
774 
775    /**
776     * Test one round trip, the message content is created on the fly.  
777     * You need a running database and a running xmlBlaster server.
778     * @throws Exception
779     */
780    public final void testRoundTripWithImplicitMeat() throws Exception {
781       log.info("Start testRoundTripWithImplicitMeat()");
782 
783       this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10), col1 VARCHAR(20), col2 VARCHAR(20), ICAO_ID VARCHAR(10))");
784       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('1', '<Bla', 'Blub', 'EDDI')");
785       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('2', 'Lol<', 'Lal', 'EDDF')");
786       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('3', 'Cl&&i', 'Clo', 'EDDP')");
787       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('4', 'Bl]]>Bl', 'BBBB', 'EDDI')");
788       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('5', 'BOO', 'BIII', 'EDDI')");
789       
790       this.prefs.put("converter.rootName", "myRootTag");
791       this.prefs.put("db.queryMeatStatement", "");
792       this.prefs.put("alertScheduler.pollInterval", "500");
793       this.prefs.put("changeDetector.groupColName", "ICAO_ID");
794       this.prefs.put("changeDetector.detectStatement", "SELECT col1, col2, ICAO_ID FROM TEST_POLL ORDER BY ICAO_ID");
795       this.prefs.put("mom.topicName", "db.change.event.${groupColValue}");
796       
797       this.processor = createTest(new Info(prefs), this.updateMap);
798 
799       {
800       log.info("Testing startup events ...");
801       try { Thread.sleep(1500); } catch(Exception e) { /* Ignore */ }
802       assertEquals("Number of message is wrong", 3, this.updateMap.size());
803       String xml = (String)this.updateMap.get("db.change.event.EDDP");
804       assertNotNull("No db.change.event.EDDP message has arrived", xml);
805       assertXpathEvaluatesTo("EDDP", "/myRootTag/desc/ident/text()", xml);
806       assertXpathEvaluatesTo("Cl&&i", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
807       assertXpathNotExists("/myRootTag/row[@num='1']", xml);
808       
809       xml = (String)this.updateMap.get("db.change.event.EDDI");
810       writeToFile("db.change.event.EDDI", xml);
811       assertXpathEvaluatesTo("3", "count(/myRootTag/desc/colname)", xml);
812       assertXpathEvaluatesTo("EDDI", "/myRootTag/desc/ident/text()", xml);
813       assertXpathEvaluatesTo("1", "count(/myRootTag/desc)", xml);
814       assertXpathEvaluatesTo("3", "count(/myRootTag/row)", xml);
815       assertXpathEvaluatesTo("<Bla", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
816       
817       this.updateMap.clear();
818       }
819       
820       {      
821       log.info("Testing change event ...");
822       this.dbPool.update("UPDATE TEST_POLL SET col1='BXXX' WHERE ICAO_ID='EDDP'");
823       try { Thread.sleep(1500); } catch(Exception e) { /* Ignore */ }
824       String xml = (String)this.updateMap.get("db.change.event.EDDP");
825       assertNotNull("No db.change.event.EDDP message has arrived", xml);
826       assertEquals("Number of message is wrong", 1, this.updateMap.size());
827       assertXpathEvaluatesTo("BXXX", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
828       assertXpathNotExists("/myRootTag/row[@num='1']", xml);
829       this.updateMap.clear();
830       }
831       
832       {
833          log.info("Drop a table with entries");
834          this.dbPool.update("DROP TABLE TEST_POLL");
835          try { Thread.sleep(1500); } catch(Exception e) { /* Ignore */ }
836          assertEquals("Number of message is wrong", 3, this.updateMap.size());
837          /*
838          String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
839          assertXpathEvaluatesTo("DROP", "/myRootTag/desc/command/text()", xml);
840          assertXpathNotExists("/myRootTag/row[@num='0']", xml);
841          */
842          this.updateMap.clear();
843          //writeToFile("db.change.event.DROP", xml);
844       }
845       try { Thread.sleep(1000); } catch(Exception e) { /* Ignore */ }
846       
847       log.info("SUCCESS");
848    }
849 
850    /**
851     * Test one round trip, the message content is empty sending an event only.  
852     * You need a running database and a running xmlBlaster server.
853     * @throws Exception
854     */
855    public final void testRoundTripWithoutMeat() throws Exception {
856       log.info("Start testRoundTripWithoutMeat()");
857 
858       this.dbPool.update("CREATE TABLE TEST_POLL (colKey NUMBER(10), col1 VARCHAR(20), col2 VARCHAR(20), ICAO_ID VARCHAR(10))");
859       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('1', '<Bla', 'Blub', 'EDDI')");
860       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('2', 'Lol<', 'Lal', 'EDDF')");
861       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('3', 'Cl&&i', 'Clo', 'EDDP')");
862       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('4', 'Bl]]>Bl', 'BBBB', 'EDDI')");
863       this.dbPool.update("INSERT INTO TEST_POLL VALUES ('5', 'BOO', 'BIII', 'EDDI')");
864       
865       this.prefs.put("converter.rootName", "myRootTag");
866       this.prefs.put("db.queryMeatStatement", "");
867       this.prefs.put("alertScheduler.pollInterval", "500");
868       this.prefs.put("changeDetector.groupColName", "ICAO_ID");
869       this.prefs.put("changeDetector.detectStatement", "SELECT col1, col2, ICAO_ID FROM TEST_POLL ORDER BY ICAO_ID");
870       this.prefs.put("mom.topicName", "db.change.event.${groupColValue}");
871       this.prefs.put("converter.class", ""); // No change detector class !
872       
873       this.processor = createTest(new Info(prefs), this.updateMap);
874 
875       {
876       log.info("Testing startup events ...");
877       try { Thread.sleep(1500); } catch(Exception e) { /* Ignore */ }
878       assertEquals("Number of message is wrong", 3, this.updateMap.size());
879       String xml = (String)this.updateMap.get("db.change.event.EDDP");
880       assertNotNull("No db.change.event.EDDP message has arrived", xml);
881       assertEquals("No content expected", "", xml);
882       this.updateMap.clear();
883       }
884       
885       {      
886       log.info("Testing change event ...");
887       this.dbPool.update("UPDATE TEST_POLL SET col1='BXXX' WHERE ICAO_ID='EDDP'");
888       try { Thread.sleep(1500); } catch(Exception e) { /* Ignore */ }
889       String xml = (String)this.updateMap.get("db.change.event.EDDP");
890       assertNotNull("No db.change.event.EDDP message has arrived", xml);
891       assertEquals("No content expected", "", xml);
892       assertEquals("Number of message is wrong", 1, this.updateMap.size());
893       this.updateMap.clear();
894       }
895       
896       {
897          log.info("Drop a table with entries");
898          this.dbPool.update("DROP TABLE TEST_POLL");
899          try { Thread.sleep(1500); } catch(Exception e) { /* Ignore */ }
900          assertEquals("Number of message is wrong", 3, this.updateMap.size());
901          this.updateMap.clear();
902       }
903       
904       log.info("SUCCESS");
905    }
906 
907    /**
908     * Dump to file. 
909     * @param topic The file name body
910     * @param xml The file content
911     * @throws Exception IOException
912     */
913    public static void writeToFile(String topic, String xml) throws Exception {
914       java.io.File f = new java.io.File(System.getProperty("java.io.tmpdir")+System.getProperty("file.separator")+topic+".xml");
915       java.io.FileOutputStream to = new java.io.FileOutputStream(f);
916       to.write(xml.getBytes());
917       to.close();
918    }
919 }


syntax highlighted by Code2HTML, v. 0.9.1