1 /*------------------------------------------------------------------------------
  2 Name:      TestSubId.java
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Demo code for a client using xmlBlaster
  6 ------------------------------------------------------------------------------*/
  7 package org.xmlBlaster.test.qos;
  8 
  9 import java.util.logging.Logger;
 10 import java.util.logging.Level;
 11 import org.xmlBlaster.util.Global;
 12 import org.xmlBlaster.client.qos.ConnectQos;
 13 import org.xmlBlaster.client.qos.ConnectReturnQos;
 14 import org.xmlBlaster.util.XmlBlasterException;
 15 import org.xmlBlaster.client.I_XmlBlasterAccess;
 16 import org.xmlBlaster.client.I_Callback;
 17 import org.xmlBlaster.client.key.UpdateKey;
 18 import org.xmlBlaster.client.qos.UpdateQos;
 19 import org.xmlBlaster.client.qos.SubscribeQos;
 20 import org.xmlBlaster.client.qos.EraseReturnQos;
 21 import org.xmlBlaster.util.MsgUnit;
 22 import org.xmlBlaster.util.def.Constants;
 23 
 24 import junit.framework.*;
 25 
 26 
 27 /**
 28  * This client tests the method subscribe() with a forced subscriptionId by the client
 29  * <br />
 30  * Invoke examples:<br />
 31  * <pre>
 32  *    java junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubId
 33  *    java junit.swingui.TestRunner org.xmlBlaster.test.qos.TestSubId
 34  * </pre>
 35  * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/engine.qos.subscribe.id.html">The engine.qos.subscribe.id requirement</a>
 36  */
 37 public class TestSubId extends TestCase implements I_Callback
 38 {
 39    private static String ME = "TestSubId";
 40    private final Global glob;
 41    private static Logger log = Logger.getLogger(TestSubId.class.getName());
 42 
 43    private boolean messageArrived = false;
 44 
 45    private String sentSubscribeId;
 46    private String subscribeId;
 47    private String oidExact = "HelloMessage";
 48    private String publishOid = "";
 49    private I_XmlBlasterAccess senderConnection;
 50    private String senderName;
 51    private String senderContent;
 52 
 53    private int numReceived = 0;         // error checking
 54    private final String contentMime = "text/xml";
 55    private final String contentMimeExtended = "1.0";
 56 
 57    private ConnectQos connectQos;
 58    private ConnectReturnQos connectReturnQos;
 59 
 60    /**
 61     * Constructs the TestSubId object.
 62     * <p />
 63     * @param testName  The name used in the test suite
 64     * @param loginName The name to login to the xmlBlaster
 65     */
 66    public TestSubId(Global glob, String testName, String loginName)
 67    {
 68       super(testName);
 69       this.glob = glob;
 70 
 71       this.senderName = loginName;
 72    }
 73 
 74 
 75    /**
 76     * Sets up the fixture.
 77     * <p />
 78     * Connect to xmlBlaster and login
 79     */
 80    protected void setUp()
 81    {
 82       try {
 83          senderConnection = glob.getXmlBlasterAccess(); // Find orb
 84          String passwd = "secret";
 85          connectQos = new ConnectQos(glob, senderName, passwd);
 86          connectReturnQos = senderConnection.connect(connectQos, this); // Login to xmlBlaster
 87       }
 88       catch (Exception e) {
 89           log.severe("Login failed: " + e.toString());
 90           e.printStackTrace();
 91           fail("Login failed: " + e.toString());
 92       }
 93    }
 94 
 95 
 96    /**
 97     * Tears down the fixture.
 98     * <p />
 99     * cleaning up .... erase() the previous message OID and logout
100     */
101    protected void tearDown()
102    {
103       String xmlKey = "<key oid='" + publishOid + "' queryType='EXACT'>\n" +
104                       "</key>";
105       try {
106          /*EraseReturnQos[] arr = */senderConnection.erase(xmlKey, "<qos/>");
107          //For illegal subid we wont erase anything
108          //assertEquals("Erase", 1, arr.length);
109       } catch(XmlBlasterException e) { fail("Erase XmlBlasterException: " + e.getMessage()); }
110 
111       senderConnection.disconnect(null);
112    }
113 
114 
115    /**
116     * Subscribe with a client side forced illegal subscriptionId
117     */
118    public void testIllegalSubscriptionId()
119    {
120       if (log.isLoggable(Level.FINE)) log.fine("Subscribing using XPath syntax ...");
121 
122       String xmlKey = "<key oid='" + oidExact + "' queryType='EXACT'>\n" +
123                       "</key>";
124       SubscribeQos sq = new SubscribeQos(glob);
125       int myCounter = 99;
126       try {
127          sentSubscribeId = Constants.SUBSCRIPTIONID_PREFIX +
128                   "client/someOtherUser/session/1" +
129                   "-" + myCounter;
130          sq.setSubscriptionId(sentSubscribeId);
131          senderConnection.subscribe(xmlKey, sq.toXml()).getSubscriptionId();
132          fail("Illegal subscriptionId should throw an exception");
133          
134       } catch(XmlBlasterException e) {
135          log.info("SUCCESS, got expected XmlBlasterException: " + e.getMessage());
136       }
137    }
138 
139 
140    /**
141     * Subscribe to message with EXACT oid
142     * <p />
143     * The returned subscribeId is checked
144     */
145    public void subscribeExact()
146    {
147       if (log.isLoggable(Level.FINE)) log.fine("Subscribing using XPath syntax ...");
148 
149       String xmlKey = "<key oid='" + oidExact + "' queryType='EXACT'>\n" +
150                       "</key>";
151       SubscribeQos sq = new SubscribeQos(glob);
152       int myCounter = 99;
153       try {
154          sentSubscribeId = Constants.SUBSCRIPTIONID_PREFIX +
155                   connectReturnQos.getSessionName().getRelativeName(true) +
156                   "-" + myCounter;
157          sq.setSubscriptionId(sentSubscribeId);
158          numReceived = 0;
159          this.subscribeId = null;
160          this.subscribeId = senderConnection.subscribe(xmlKey, sq.toXml()).getSubscriptionId();
161          assertEquals("Sent sentSubscribeId= " + sentSubscribeId + " The returned subscriptionId=" + subscribeId + " is wrong", sentSubscribeId, subscribeId);
162          log.info("Success: Subscribe on " + subscribeId + " done");
163          
164       } catch(XmlBlasterException e) {
165          log.warning("XmlBlasterException: " + e.getMessage());
166          fail("subscribe - XmlBlasterException: " + e.getMessage());
167       }
168       assertTrue("returned null subscribeId", subscribeId != null);
169       assertTrue("returned subscribeId is empty", 0 != subscribeId.length());
170    }
171 
172 
173    /**
174     * TEST: Construct a message and publish it.
175     * <p />
176     * The returned publishOid is checked
177     */
178    public void doPublish()
179    {
180       if (log.isLoggable(Level.FINE)) log.fine("Publishing a message ...");
181 
182       numReceived = 0;
183       String xmlKey = "<key oid='" + oidExact + "' contentMime='" + contentMime + "' contentMimeExtended='" + contentMimeExtended + "'>\n" +
184                       "</key>";
185       senderContent = "Yeahh, i'm the new content";
186       try {
187          MsgUnit msgUnit = new MsgUnit(xmlKey, senderContent.getBytes(), "<qos></qos>");
188          publishOid = senderConnection.publish(msgUnit).getKeyOid();
189          log.info("Success: Publishing done, returned oid=" + publishOid);
190       } catch(XmlBlasterException e) {
191          log.warning("XmlBlasterException: " + e.getMessage());
192          assertTrue("publish - XmlBlasterException: " + e.getMessage(), false);
193       }
194 
195       assertTrue("returned publishOid == null", publishOid != null);
196       assertTrue("returned publishOid", 0 != publishOid.length());
197       assertEquals("returned publishOid is wrong", oidExact, publishOid);
198    }
199 
200 
201    /**
202     * TEST: Construct a message and publish it,<br />
203     * the previous XPath subscription should match and send an update.
204     */
205    public void testPublishAfterSubscribe()
206    {
207       subscribeExact();
208       try { Thread.sleep(1000L); } catch( InterruptedException i) {}                                            // Wait some time for callback to arrive ...
209       assertEquals("numReceived after subscribe", 0, numReceived);  // there should be no Callback
210 
211       doPublish();
212       waitOnUpdate(5000L);
213       assertEquals("numReceived after publishing", 1, numReceived); // message arrived?
214 
215       // TODO test if it is possible to unsubscribe with the given subscribeId.
216       
217    }
218 
219    /**
220     * This is the callback method invoked from xmlBlaster
221     * delivering us a new asynchronous message. 
222     * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
223     */
224    public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
225    {
226       if (log.isLoggable(Level.FINER)) log.finer("Receiving update of a message ...");
227       log.info("sentSubscribeId=" + sentSubscribeId + ":" + updateQos.toXml());
228 
229       if (updateQos.isErased()) {
230          return "";
231       }
232 
233       numReceived += 1;
234 
235       // Wait that publish() returns and set 'publishOid' properly
236       try { Thread.sleep(200); } catch( InterruptedException i) {}
237 
238       assertEquals("Wrong sender", senderName, updateQos.getSender().getLoginName());
239       assertEquals("engine.qos.update.subscriptionId: Wrong subscriptionId", subscribeId, updateQos.getSubscriptionId());
240       assertEquals("Wrong oid of message returned", publishOid, updateKey.getOid());
241       assertEquals("Message content is corrupted", new String(senderContent), new String(content));
242       assertEquals("Message contentMime is corrupted", contentMime, updateKey.getContentMime());
243       assertEquals("Message contentMimeExtended is corrupted", contentMimeExtended, updateKey.getContentMimeExtended());
244 
245       messageArrived = true;
246       return "";
247    }
248 
249 
250    /**
251     * Little helper, waits until the variable 'messageArrive' is set
252     * to true, or returns when the given timeout occurs.
253     * @param timeout in milliseconds
254     */
255    private void waitOnUpdate(final long timeout)
256    {
257       long pollingInterval = 50L;  // check every 0.05 seconds
258       if (timeout < 50)  pollingInterval = timeout / 10L;
259       long sum = 0L;
260       while (!messageArrived) {
261          try {
262             Thread.sleep(pollingInterval);
263          }
264          catch( InterruptedException i)
265          {}
266          sum += pollingInterval;
267          if (sum > timeout) {
268             log.warning("Timeout of " + timeout + " occurred");
269             break;
270          }
271       }
272       messageArrived = false;
273    }
274 
275 
276    /**
277     * Method is used by TestRunner to load these tests
278     */
279    public static Test suite()
280    {
281        TestSuite suite= new TestSuite();
282        String loginName = "Tim";
283        suite.addTest(new TestSubId(new Global(), "testIllegalSubscriptionId", loginName));
284        suite.addTest(new TestSubId(new Global(), "testPublishAfterSubscribe", loginName));
285        return suite;
286    }
287 
288 
289    /**
290     * Invoke: java org.xmlBlaster.test.qos.TestSubId
291     * @deprecated Use the TestRunner from the testsuite to run it:<p />
292     * <pre>   java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubId</pre>
293     */
294    public static void main(String args[])
295    {
296       Global glob = new Global();
297       if (glob.init(args) != 0) {
298          System.err.println(ME + ": Init failed");
299          System.exit(1);
300       }
301       TestSubId testSub = new TestSubId(glob, "TestSubId", "Tim");
302       testSub.setUp();
303       testSub.testPublishAfterSubscribe();
304       testSub.tearDown();
305    }
306 }


syntax highlighted by Code2HTML, v. 0.9.1