00001 /*----------------------------------------------------------------------------- 00002 Name: EmbeddedServer.cpp 00003 Project: xmlBlaster.org 00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 00005 Comment: Testing the Timeout Features 00006 -----------------------------------------------------------------------------*/ 00007 00008 #include <util/EmbeddedServer.h> 00009 #include <util/Global.h> 00010 #include <util/lexical_cast.h> 00011 00012 namespace org { namespace xmlBlaster { namespace util { 00013 00014 using namespace std; 00015 using namespace org::xmlBlaster::util; 00016 using namespace org::xmlBlaster::util::qos; 00017 using namespace org::xmlBlaster::util::qos::address; 00018 using namespace org::xmlBlaster::util::thread; 00019 using namespace org::xmlBlaster::client; 00020 using namespace org::xmlBlaster::client::qos; 00021 using namespace org::xmlBlaster::client::key; 00022 00023 EmbeddedServerRunner::EmbeddedServerRunner(EmbeddedServer& owner) : ME("EmbeddedServerRunner"), owner_(owner) 00024 { 00025 } 00026 00027 void EmbeddedServerRunner::run() 00028 { 00029 #if !defined(WINCE) 00030 if (owner_.log_.call()) owner_.log_.call(ME, "::run"); 00031 00032 if (owner_.isRunning_) { 00033 owner_.log_.warn(ME, "the current server is already running. ignoring the start command."); 00034 return; 00035 } 00036 /* currently commented out (could give problems if multithreading not supported) 00037 if (isSomeServerResponding()) { 00038 log_.error(ME, "an external server is already running. Please shut it down"); 00039 return; 00040 } 00041 */ 00042 string cmdLine = string("java ") + owner_.jvmArguments_ + " org.xmlBlaster.Main " + owner_.applArguments_; 00043 owner_.log_.info(ME, "starting the embedded server with command line: '" + cmdLine + "'"); 00044 if (system(NULL)) { 00045 try { 00046 owner_.isRunning_ = true; 00047 int ret = system(cmdLine.c_str()); 00048 owner_.log_.info(ME, "the embedded server with command line: '" + cmdLine + "' has been stopped, return code is: " + lexical_cast<std::string>(ret)); 00049 owner_.isRunning_ = false; 00050 } 00051 catch (exception& ex) { 00052 owner_.log_.error(ME,string("could not start the server: ") + ex.what()); 00053 owner_.isRunning_ = false; 00054 } 00055 catch (...) { 00056 owner_.log_.error(ME,"could not start the server: an unknown exception occured"); 00057 owner_.isRunning_ = false; 00058 } 00059 } 00060 else { 00061 owner_.log_.error(ME, "could not start the embedded server: your OS does not have a command processor, plase start your server manually"); 00062 owner_.isRunning_ = false; 00063 } 00064 #endif 00065 } 00066 00067 00068 EmbeddedServer::EmbeddedServer(Global& glob, const string& jvmArguments, const string& applArguments, XmlBlasterAccess* externalAccess) 00069 : ME("EmbeddedServer"), 00070 global_(glob), 00071 log_(glob.getLog("org.xmlBlaster.util")) 00072 { 00073 isRunning_ = false; 00074 applArguments_ = applArguments; 00075 jvmArguments_ = jvmArguments; 00076 externalAccess_ = externalAccess; 00077 runner_ = false; 00078 } 00079 00080 EmbeddedServer::~EmbeddedServer() 00081 { 00082 log_.call(ME, "destructor"); 00083 // don't try to stop it with the borrowed external connection here since it could be a 00084 // failsafe connection (which would queue this publish in case it is already disconnected) 00085 externalAccess_ = NULL; 00086 stop(false, false); 00087 log_.trace(ME, "destructor: stopped the server"); 00088 } 00089 00090 bool EmbeddedServer::start(bool blockUntilUp) 00091 { 00092 if (log_.call()) log_.call(ME, "start"); 00093 00094 if (runner_) return false; 00095 runner_ = new EmbeddedServerRunner(*this); 00096 const bool detached = false; 00097 bool ret = runner_->start(detached); 00098 if (ret && blockUntilUp) { 00099 if (log_.trace()) log_.trace(ME, "start: setting up for a client connection"); 00100 bool isConnected = false; 00101 int count = 0; 00102 while (!isConnected && count < 60) { 00103 if (log_.trace()) log_.trace(ME, "start: establishing a connection: trial nr. '" + lexical_cast<std::string>(count) + "'"); 00104 try { 00105 count++; 00106 XmlBlasterAccess conn(global_); 00107 ConnectQos connQos(global_, "embeddedKiller", "secret"); 00108 Address *address = new Address(global_); 00109 address->setDelay(0); 00110 connQos.setAddress(address); 00111 // to be sure not to store the kill msg in a client queue ... 00112 conn.connect(connQos, NULL); 00113 log_.trace(ME, "successfully connected to the embedded server"); 00114 conn.disconnect(DisconnectQos(global_)); 00115 log_.trace(ME, "successfully disconnected from the embedded server"); 00116 isConnected = true; 00117 } 00118 catch (XmlBlasterException& ex) { 00119 if (log_.trace()) log_.trace(ME, "exception occurred when connecting: " + ex.toXml()); 00120 if ( !ex.isCommunication() ) throw ex; 00121 if (log_.trace()) log_.trace(ME, "the exception occurred was a communication exception (connection not established yet). Will retry (sleep for 2 sec)"); 00122 Thread::sleepSecs(2); 00123 } 00124 count++; 00125 } 00126 if (!isConnected) { 00127 log_.error(ME, "maximum number of retrials to establish a connection failed "); 00128 throw XmlBlasterException(COMMUNICATION_NOCONNECTION, ME, " start: could not establish a connection to the embedded server"); 00129 } 00130 00131 } 00132 return ret; 00133 } 00134 00135 bool EmbeddedServer::stop(bool shutdownExternal, bool warnIfNotRunning) 00136 { 00137 if (log_.call()) log_.call(ME, "stop"); 00138 if (!isRunning_ && !shutdownExternal) { 00139 if (warnIfNotRunning) 00140 log_.warn(ME, "the current embedded server is not running. Ignoring this 'stop' command"); 00141 return false; 00142 } 00143 00144 PublishKey key(global_); 00145 key.setOid("__cmd:?exit=0"); 00146 PublishQos qos(global_); 00147 MessageUnit msgUnit(key, "0", qos); 00148 00149 XmlBlasterAccess conn(global_); 00150 try { 00151 ConnectQos connQos(global_, "embeddedKiller", "secret"); 00152 // to be sure not to store the kill msg in a client queue ... 00153 Address *address = new Address(global_); 00154 address->setDelay(0); 00155 connQos.setAddress(address); 00156 conn.connect(connQos, NULL); 00157 } 00158 catch (XmlBlasterException& ex) { 00159 if ( ex.isCommunication() ) { 00160 log_.warn(ME, "there is no server responding, ignoring this 'stop' command"); 00161 return false; 00162 } 00163 throw ex; 00164 } 00165 conn.publish(msgUnit); 00166 00167 if (log_.trace()) log_.trace(ME, "stop: going to join the threads"); 00168 if (runner_) runner_->join(); 00169 00170 delete runner_; 00171 runner_ = NULL; 00172 if (log_.trace()) log_.trace(ME, "stop completed"); 00173 return true; 00174 } 00175 00176 00177 bool EmbeddedServer::isSomeServerResponding() const 00178 { 00179 try { 00180 SessionQos sessionQos(global_); 00181 sessionQos.setAbsoluteName("embeddedTester"); 00182 ConnectQos connQos(global_, "embeddedTester", "secret"); 00183 connQos.setSessionQos(sessionQos); 00184 if (externalAccess_) { 00185 externalAccess_->connect(connQos, NULL); 00186 } 00187 else { 00188 XmlBlasterAccess conn(global_); 00189 conn.connect(connQos, NULL); 00190 } 00191 return true; 00192 } 00193 catch (XmlBlasterException& ex) { 00194 if (ex.isCommunication()) { 00195 return false; 00196 } 00197 throw ex; // then it is another exception 00198 } 00199 } 00200 00201 00202 }}} 00203 00204 00205 #ifdef _XMLBLASTER_CLASSTEST 00206 00207 using namespace std; 00208 using namespace org::xmlBlaster::util; 00209 00210 00211 int main(int args, char* argv[]) 00212 { 00213 Global& glob = Global::getInstance(); 00214 glob.initialize(args, argv); 00215 00216 EmbeddedServer server(glob, ""); // , "-info false -error false -warn false"); 00217 server.start(); 00218 Thread::sleepSecs(10); 00219 server.stop(); 00220 Thread::sleepSecs(10); 00221 server.start(); 00222 Thread::sleepSecs(10); 00223 00224 return 0; 00225 } 00226 00227 #endif 00228