1 /*-----------------------------------------------------------------------------
  2 Name:      TestRequestResponse.cpp
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Demo code for a client using xmlBlaster
  6            build -DexeName=TestRequestResponse cpp-test-single
  7 -----------------------------------------------------------------------------*/
  8 #include "TestSuite.h"
  9 #include <iostream>
 10 
 11 /**
 12  * This client tests the request/reply pattern
 13  */
 14 
 15 using namespace std;
 16 using namespace org::xmlBlaster::util;
 17 using namespace org::xmlBlaster::util::qos;
 18 using namespace org::xmlBlaster::util::thread;
 19 using namespace org::xmlBlaster::client;
 20 using namespace org::xmlBlaster::client::qos;
 21 using namespace org::xmlBlaster::client::key;
 22 using namespace org::xmlBlaster::authentication;
 23 
 24 namespace org { namespace xmlBlaster { namespace test {
 25 
 26 /**
 27  * Callback implementation of the receiver client. 
 28  */
 29 class ReceiverCallback : public I_Callback {
 30 private:
 31    XmlBlasterAccess &receiver_;
 32    string name_;
 33    I_Log& log_;
 34 
 35 public:
 36    ReceiverCallback(XmlBlasterAccess &receiver, I_Log& log, const string& name) : receiver_(receiver), log_(log) {
 37       name_ = name;
 38    }
 39 
 40    string update(const string &sessionId,
 41                UpdateKey &updateKey,
 42                const unsigned char * /*content*/, long /*contentSize*/,
 43                UpdateQos &updateQos) 
 44    {
 45       log_.info("update", string("Receiving update on callback '") + name_ + "' of message oid=" +
 46                 updateKey.getOid() + " state=" + updateQos.getState() +
 47                 " authentication sessionId=" + sessionId + " ...");
 48 
 49       //if (updateKey.isInternal()) return "";
 50       if (updateQos.isErased()) return "";
 51       
 52       try {
 53          string tempTopicOid = updateQos.getClientProperty(Constants::JMS_REPLY_TO, string("")); // __jms:JMSReplyTo
 54          log_.info("update", name_+": Got request, using topic '" + tempTopicOid + "' for response");
 55 
 56          // Send reply back ...
 57          PublishKey pk(receiver_.getGlobal(), tempTopicOid, "text/plain", "1.0");
 58          PublishQos pq(receiver_.getGlobal());
 59          MessageUnit msgUnit(pk, "On doubt no ultimate truth, my dear.", pq);
 60          PublishReturnQos retQos = receiver_.publish(msgUnit);
 61          log_.info("update", name_+": Published reply message using temporary topic " + retQos.getKeyOid());
 62       }
 63       catch (XmlBlasterException &e) {
 64          log_.error("update", string(name_)+": Sending reply to " + updateQos.getSender()->getAbsoluteName() + " failed: " + e.getMessage());
 65       }
 66       return "<qos><state id='OK'/></qos>";
 67    }
 68 };
 69 
 70 
 71 class TestRequestResponse: public TestSuite, public virtual I_Callback 
 72 {
 73 private:
 74    bool   messageArrived_;      // = false;
 75    string subscribeOid_;
 76    string publishOid_;          // = "dummy";
 77    string senderName_;
 78    string receiverName_;        // sender/receiver is here the same client
 79    ConnectReturnQos returnQos_;
 80    ReceiverCallback *cbReceiver;
 81 
 82    GlobalRef globalReceiver_;
 83    XmlBlasterAccess receiver_;
 84 
 85    /**
 86     * Constructs the TestRequestResponse object.
 87     * <p />
 88     * @param testName  The name used in the test suite
 89     * @param loginName The name to login to the xmlBlaster
 90     */
 91  public:
 92    TestRequestResponse(int args, char *argc[], const string &senderName, const string &receiverName)
 93       : TestSuite(args, argc, "TestRequestResponse"),
 94         returnQos_(global_),
 95         globalReceiver_(global_.createInstance("receiverGlobal")),
 96    receiver_(globalReceiver_)
 97    {
 98       globalReceiver_->initialize(args, argc);
 99       senderName_          = senderName;
100       receiverName_        = receiverName;
101       publishOid_          = "dummy";
102       cbReceiver = new ReceiverCallback(receiver_, log_, "callbackReceiver");
103    }
104 
105    virtual ~TestRequestResponse() 
106    {
107       delete cbReceiver;
108    }
109 
110    /**
111     * Sets up the fixture. <p />
112     * Connect to xmlBlaster and login
113     */
114    void setUp() 
115    {
116       log_.info(ME, "Trying to connect to xmlBlaster with C++ client lib " + Global::getVersion() + " from " + Global::getBuildTimestamp());
117       TestSuite::setUp();
118       const string passwd = "secret";
119       try {
120          ConnectQos connQos(global_, senderName_);
121          returnQos_ = connection_.connect(connQos, this);
122          log_.info(ME, string("connected '") + senderName_ + "'");
123       }
124       catch (XmlBlasterException &e) {
125          log_.error(ME, string("Login failed: ") + e.toXml());
126          usage();
127          assert(0);
128       }
129 
130       try {
131          ConnectQos connQos(receiver_.getGlobal(), receiverName_);
132          returnQos_ = receiver_.connect(connQos, cbReceiver);
133          log_.info(ME, string("connected '") + receiverName_ + "'");
134       }
135       catch (XmlBlasterException &e) {
136          log_.error(ME, string("Login failed: ") + e.toXml());
137          usage();
138          assert(0);
139       }
140    }
141 
142 
143    /**
144     * Tears down the fixture. <p />
145     * cleaning up .... erase() the previous message OID and logout
146     */
147    void tearDown() 
148    {
149       log_.info(ME, "Cleaning up test");
150       connection_.disconnect(DisconnectQos(global_));
151       receiver_.disconnect(DisconnectQos(receiver_.getGlobal()));
152       TestSuite::tearDown();
153    }
154 
155    /**
156     * TEST
157     */
158    void testRequest() 
159    {
160       if (log_.trace()) log_.trace(ME, "Publishing a message (old style) ...");
161       PublishKey pubKey(global_, "requestForEnlightenment");
162       PublishQos pubQos(global_);
163       Destination destination(global_, receiverName_);
164       pubQos.addDestination(destination);
165       MessageUnit msgUnit(pubKey, "Tell me the truth!", pubQos);
166       try {
167          std::vector<org::xmlBlaster::util::MessageUnit> replies = 
168        connection_.request(msgUnit, 6000, 1);
169     assertEquals(log_, ME, 1, replies.size(), "missing response");
170          log_.info(ME, senderName_+": Got " + lexical_cast<string>(replies.size()) + " reply :\n" + replies[0].toXml());
171          log_.info(ME, replies[0].getContentStr() + " size=" + lexical_cast<string>(replies[0].getContentLen()));
172     assertEquals(log_, ME, "On doubt no ultimate truth, my dear.", replies[0].getContentStr(), "response from a wise man");
173       }
174       catch(XmlBlasterException &e) {
175          log_.warn(ME, string("XmlBlasterException: ")+e.toXml());
176          assert(0);
177       }
178    }
179 
180    string update(const string &sessionId,
181                UpdateKey &updateKey,
182                const unsigned char *content, long contentSize,
183                UpdateQos &updateQos) 
184    {
185       log_.error(ME, string("Unexpected receiving update of message oid=") +
186                 updateKey.getOid() + " state=" + updateQos.getState() +
187                 " authentication sessionId=" + sessionId + " ...");
188       return "<qos><state id='OK'/></qos>";
189    }
190 
191 
192    /**
193     * Little helper, waits until the variable 'messageArrive' is set
194     * to true, or returns when the given timeout occurs.
195     * @param timeout in milliseconds
196     */
197 private:
198    void usage() const
199    {
200       TestSuite::usage();
201       log_.plain(ME, "----------------------------------------------------------");
202       log_.plain(ME, "Testing C++ request/reply pattern");
203       log_.plain(ME, "Usage:");
204       XmlBlasterAccess::usage();
205       log_.usage();
206       log_.plain(ME, "Example:");
207       log_.plain(ME, "   TestRequestResponse -trace true");
208       log_.plain(ME, "----------------------------------------------------------");
209    }
210 };
211 
212 }}} // namespace
213 
214 using namespace org::xmlBlaster::test;
215 
216 int main(int args, char *argc[]) 
217 {
218    try {
219       org::xmlBlaster::util::Object_Lifetime_Manager::init();
220       TestRequestResponse testReq(args, argc, "TheDesperate", "TheKnowing");
221  
222       testReq.setUp();
223       testReq.testRequest();
224       testReq.tearDown();
225 
226       Thread::sleepSecs(1);
227    }
228    catch (XmlBlasterException& ex) {
229       std::cout << ex.toXml() << std::endl;
230    }
231    catch (bad_exception& ex) {
232       cout << "bad_exception: " << ex.what() << endl;
233    }
234    catch (exception& ex) {
235       cout << " exception: " << ex.what() << endl;
236    }
237    catch (string& ex) {
238       cout << "string: " << ex << endl;
239    }
240    catch (char* ex) {
241       cout << "char* :  " << ex << endl;
242    }
243 
244    catch (...)
245    {
246       cout << "unknown exception occured" << endl;
247       XmlBlasterException e(INTERNAL_UNKNOWN, "main", "main thread");
248       cout << e.toXml() << endl;
249    }
250 
251    org::xmlBlaster::util::Object_Lifetime_Manager::fini();
252    return 0;
253 }


syntax highlighted by Code2HTML, v. 0.9.1