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