1 /*-----------------------------------------------------------------------------
  2 Name:      EmbeddedServer.cpp
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Testing the Timeout Features
  6 -----------------------------------------------------------------------------*/
  7 
  8 #include <util/EmbeddedServer.h>
  9 #include <util/Global.h>
 10 #include <util/lexical_cast.h>
 11 
 12 namespace org { namespace xmlBlaster { namespace util {
 13 
 14 using namespace std;
 15 using namespace org::xmlBlaster::util;
 16 using namespace org::xmlBlaster::util::qos;
 17 using namespace org::xmlBlaster::util::qos::address;
 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 
 23 EmbeddedServerRunner::EmbeddedServerRunner(EmbeddedServer& owner) : ME("EmbeddedServerRunner"), owner_(owner)
 24 {
 25 }
 26 
 27 void EmbeddedServerRunner::run()
 28 {  
 29 #if !defined(WINCE)
 30    if (owner_.log_.call()) owner_.log_.call(ME, "::run");
 31 
 32    if (owner_.isRunning_) {
 33       owner_.log_.warn(ME, "the current server is already running. ignoring the start command.");
 34       return;
 35    }
 36 /* currently commented out (could give problems if multithreading not supported)
 37    if (isSomeServerResponding()) {
 38       log_.error(ME, "an external server is already running. Please shut it down");
 39       return;
 40    }
 41 */
 42    string cmdLine = string("java ") + owner_.jvmArguments_ + " org.xmlBlaster.Main " + owner_.applArguments_;
 43    owner_.log_.info(ME, "starting the embedded server with command line: '" + cmdLine + "'");
 44    if (system(NULL)) {
 45       try {
 46          owner_.isRunning_ = true;
 47          int ret = system(cmdLine.c_str());
 48          owner_.log_.info(ME, "the embedded server with command line: '" + cmdLine + "' has been stopped, return code is: " + lexical_cast<std::string>(ret));
 49          owner_.isRunning_ = false;
 50       }
 51       catch (exception& ex) {
 52          owner_.log_.error(ME,string("could not start the server: ") + ex.what());
 53          owner_.isRunning_ = false;
 54       }
 55       catch (...) {
 56          owner_.log_.error(ME,"could not start the server: an unknown exception occured");
 57          owner_.isRunning_ = false;
 58       }
 59    }
 60    else {
 61       owner_.log_.error(ME, "could not start the embedded server: your OS does not have a command processor, plase start your server manually");
 62       owner_.isRunning_ = false;
 63    }
 64 #endif //!defined(WINCE)
 65 }
 66 
 67 
 68 EmbeddedServer::EmbeddedServer(Global& glob, const string& jvmArguments, const string& applArguments, XmlBlasterAccess* externalAccess) 
 69    : ME("EmbeddedServer"), 
 70      global_(glob), 
 71      log_(glob.getLog("org.xmlBlaster.util"))
 72 {
 73    isRunning_      = false;
 74    applArguments_  = applArguments;
 75    jvmArguments_   = jvmArguments;
 76    externalAccess_ = externalAccess; 
 77    runner_         = NULL;
 78 }
 79 
 80 EmbeddedServer::~EmbeddedServer()
 81 {
 82    log_.call(ME, "destructor");
 83    // don't try to stop it with the borrowed external connection here since it could be a 
 84    // failsafe connection (which would queue this publish in case it is already disconnected)
 85    externalAccess_ = NULL;
 86    stop(false, false);
 87    log_.trace(ME, "destructor: stopped the server");
 88 }
 89 
 90 bool EmbeddedServer::start(bool blockUntilUp)
 91 {
 92    if (log_.call()) log_.call(ME, "start");
 93 
 94    if (runner_) return false;
 95    runner_ = new EmbeddedServerRunner(*this);
 96         const bool detached = false;
 97    bool ret  = runner_->start(detached);
 98    if (ret && blockUntilUp) {
 99       if (log_.trace()) log_.trace(ME, "start: setting up for a client connection");
100       bool isConnected = false;
101       int count = 0;
102       while (!isConnected && count < 60) {
103          if (log_.trace()) log_.trace(ME, "start: establishing a connection: trial nr. '" + lexical_cast<std::string>(count) + "'");
104          try {
105             count++;
106             XmlBlasterAccess conn(global_);
107             ConnectQos connQos(global_, "embeddedKiller", "secret");
108             Address *address = new Address(global_);
109             address->setDelay(0);
110             connQos.setAddress(address);
111             // to be sure not to store the kill msg in a client queue ...
112             conn.connect(connQos, NULL);
113             log_.trace(ME, "successfully connected to the embedded server");
114             conn.disconnect(DisconnectQos(global_));
115             log_.trace(ME, "successfully disconnected from the embedded server");
116             isConnected = true;
117          }
118          catch (XmlBlasterException& ex) {
119             if (log_.trace()) log_.trace(ME, "exception occurred when connecting: " + ex.toXml());
120             if ( !ex.isCommunication() ) throw ex;
121             if (log_.trace()) log_.trace(ME, "the exception occurred was a communication exception (connection not established yet). Will retry (sleep for 2 sec)");
122             Thread::sleepSecs(2);
123          }
124          count++;
125       }
126       if (!isConnected) {
127          log_.error(ME, "maximum number of retrials to establish a connection failed ");
128          throw XmlBlasterException(COMMUNICATION_NOCONNECTION, ME, " start: could not establish a connection to the embedded server");
129       }
130 
131    }
132    return ret;
133 }
134 
135 bool EmbeddedServer::stop(bool shutdownExternal, bool warnIfNotRunning)
136 {
137    if (log_.call()) log_.call(ME, "stop");
138    if (!isRunning_ && !shutdownExternal) {
139       if (warnIfNotRunning)
140          log_.warn(ME, "the current embedded server is not running. Ignoring this 'stop' command");
141       return false;
142    }
143 
144    PublishKey key(global_);
145    key.setOid("__cmd:?exit=0");
146    PublishQos qos(global_);
147    MessageUnit msgUnit(key, "0", qos);
148 
149    XmlBlasterAccess conn(global_);
150    try {
151       ConnectQos connQos(global_, "embeddedKiller", "secret");
152       // to be sure not to store the kill msg in a client queue ...
153       Address *address = new Address(global_);
154       address->setDelay(0);
155       connQos.setAddress(address);
156       conn.connect(connQos, NULL);
157    }
158    catch (XmlBlasterException& ex) {
159       if ( ex.isCommunication() ) {
160          log_.warn(ME, "there is no server responding, ignoring this 'stop' command");
161          return false;
162       }
163       throw ex;
164    }
165    conn.publish(msgUnit);
166 
167    if (log_.trace()) log_.trace(ME, "stop: going to join the threads");
168    if (runner_) runner_->join();
169 
170    delete runner_;
171    runner_ = NULL;
172    if (log_.trace()) log_.trace(ME, "stop completed");
173    return true;
174 }
175 
176 
177 bool EmbeddedServer::isSomeServerResponding() const
178 {
179    try {
180       SessionQos sessionQos(global_);
181       sessionQos.setAbsoluteName("embeddedTester");
182       ConnectQos connQos(global_, "embeddedTester", "secret");
183       connQos.setSessionQos(sessionQos);
184       if (externalAccess_) {
185          externalAccess_->connect(connQos, NULL);
186       }
187       else {
188          XmlBlasterAccess conn(global_);
189          conn.connect(connQos, NULL);
190       }
191       return true;
192    }
193    catch (XmlBlasterException& ex) {
194       if (ex.isCommunication()) {
195          return false;
196       }
197       throw ex; // then it is another exception
198    }
199 }
200 
201 
202 }}}
203 
204 
205 #ifdef _XMLBLASTER_CLASSTEST
206 
207 using namespace std;
208 using namespace org::xmlBlaster::util;
209 
210 
211 int main(int args, char* argv[])
212 {
213    Global& glob = Global::getInstance();
214    glob.initialize(args, argv);
215   
216    EmbeddedServer server(glob, ""); // , "-info false -error false -warn false");
217    server.start();
218    Thread::sleepSecs(10);
219    server.stop();
220    Thread::sleepSecs(10);
221    server.start();
222    Thread::sleepSecs(10);
223 
224    return 0;
225 }
226 
227 #endif


syntax highlighted by Code2HTML, v. 0.9.1