00001 /*------------------------------------------------------------------------------ 00002 Name: Global.cpp 00003 Project: xmlBlaster.org 00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 00005 Comment: Create unique timestamp 00006 Version: $Id: Global.cpp 15992 2007-02-11 12:29:40Z ruff $ 00007 ------------------------------------------------------------------------------*/ 00008 #include <client/protocol/CbServerPluginManager.h> 00009 #include <util/dispatch/DispatchManager.h> 00010 #include <util/Timeout.h> 00011 #include <algorithm> 00012 #include <util/lexical_cast.h> 00013 #include <util/Global.h> 00014 00015 // For usage(): 00016 #include <util/qos/address/Address.h> 00017 #include <util/qos/address/CallbackAddress.h> 00018 #include <util/qos/storage/MsgUnitStoreProperty.h> 00019 #include <util/qos/storage/ClientQueueProperty.h> 00020 #include <util/qos/storage/CbQueueProperty.h> 00021 #if defined(XMLBLASTER_MSXML_PLUGIN) 00022 # error Implement Microsoft XML parser for /DXMLBLASTER_MSXML_PLUGIN 00023 #else // XMLBLASTER_XERCES_PLUGIN 00024 # include <util/parser/Sax2XercesParser.h> 00025 #endif 00026 #ifdef COMPILE_SOCKET_PLUGIN 00027 # include <client/protocol/socket/SocketDriver.h> 00028 #endif 00029 #ifdef COMPILE_CORBA_PLUGIN 00030 # include <client/protocol/corba/CorbaDriver.h> 00031 #endif 00032 #ifdef XMLBLASTER_COMPILE_LOG4CPLUS_PLUGIN 00033 # include<util/Log4cplus.h> 00034 #endif 00035 00036 #if !defined(XMLBLASTER_NO_RCSID) 00037 /* 00038 Add the exact version of the C++ client library, this is for examination 00039 with for example the UNIX 'strings' command only. 00040 If it makes problem just set -DXMLBLASTER_NO_RCSID 00041 */ 00042 # if defined(__GNUC__) || defined(__ICC) 00043 // To support query state with 'ident libxmlBlasterClient.so' or 'what libxmlBlasterClient.so' 00044 // or 'strings libxmlBlasterClient.so | grep Global.cpp' 00045 static const char *rcsid_GlobalCpp __attribute__ ((unused)) = "@(#) $Id: Global.cpp 15992 2007-02-11 12:29:40Z ruff $ xmlBlaster @version@ #@revision.number@"; 00046 # elif defined(__SUNPRO_CC) 00047 static const char *rcsid_GlobalCpp = "@(#) $Id: Global.cpp 15992 2007-02-11 12:29:40Z ruff $ xmlBlaster @version@ #@revision.number@"; 00048 # endif 00049 #endif 00050 00051 namespace org { namespace xmlBlaster { namespace util { 00052 //#if __GNUC__ == 2 || defined(__sun) 00053 #if __GNUC__ == 2 || defined(__SUNPRO_CC) 00054 //#if __GNUC__ == 2 00055 // Problems with g++ 2.95.3 and template<> 00056 #else 00057 00058 template<> std::string lexical_cast(bool arg) 00059 { 00060 return (arg) ? XMLBLASTER_TRUE : XMLBLASTER_FALSE; // "true", "false" 00061 } 00063 template<> const char * lexical_cast(bool arg) 00064 { 00065 return (arg) ? XMLBLASTER_TRUE.c_str() : XMLBLASTER_FALSE.c_str(); 00066 } 00067 00068 template<> bool lexical_cast(std::string arg) 00069 { 00070 return arg == "1" || arg == XMLBLASTER_TRUE || arg == "TRUE"; // "true" 00071 } 00072 00073 template<> bool lexical_cast(const char* arg) 00074 { 00075 return lexical_cast<bool>(std::string(arg)); 00076 } 00077 00078 00083 template<> std::string lexical_cast(std::string arg) 00084 { 00085 return arg; 00086 } 00087 00088 #endif 00089 using namespace std; 00090 using namespace org::xmlBlaster::util::dispatch; 00091 using namespace org::xmlBlaster::client::protocol; 00092 00093 Global::Global() : ME("Global"), pingerMutex_(), sessionName_(0) 00094 { 00095 cbServerPluginManager_ = 0; 00096 pingTimer_ = 0; 00097 dispatchManager_ = 0; 00098 copy(); 00099 property_ = new Property(); 00100 isInitialized_ = false; 00101 00102 if(global_ == NULL) 00103 global_ = this; 00104 } 00105 00106 void Global::copy() 00107 { 00108 args_ = 0 ; 00109 argv_ = NULL; 00110 property_ = NULL; 00111 pingTimer_ = NULL; 00112 dispatchManager_ = NULL; 00113 cbServerPluginManager_ = NULL; 00114 id_ = ""; 00115 } 00116 00117 /* 00118 Global::Global(const Global& global) : ME("Global") 00119 { 00120 args_ = global.args_; 00121 argv_ = global.argv_; 00122 } 00123 */ 00124 00125 Global& Global::operator =(const Global &) 00126 { 00127 copy(); 00128 return *this; 00129 } 00130 00131 00132 Global::~Global() 00133 { 00134 try { 00135 delete property_; 00136 delete cbServerPluginManager_; 00137 delete pingTimer_; 00138 delete dispatchManager_; 00139 } 00140 catch (...) { 00141 } 00142 try { 00143 if (this != global_) { 00144 global_->destroyInstance(this->getInstanceName()); 00145 } 00146 else { 00147 globalRefMap_.clear(); 00148 globalMap_.clear(); 00149 } 00150 } 00151 catch (...) { 00152 } 00153 } 00154 00155 Global *Global::global_ = NULL; 00156 Global::GlobalRefMap Global::globalRefMap_; 00157 Global::GlobalMap Global::globalMap_; 00158 thread::Mutex Global::globalMutex_; 00159 00160 //----------------- 00161 // Global.cpp modification 00162 Global& Global::getInstance(string name) 00163 { 00164 if (name == "" || name == "default") { 00165 if (global_ == NULL) { 00166 global_ = new Global(); 00167 Object_Lifetime_Manager::instance()->manage_object(Constants::XB_GLOBAL_KEY, global_); // if not pre-allocated. 00168 } 00169 return *global_; 00170 } 00171 00172 GlobalMap::iterator iter = globalMap_.find(name); 00173 if (iter != globalMap_.end()) { 00174 Global* glP = (*iter).second; 00175 return *glP; 00176 } 00177 00178 throw XmlBlasterException(USER_ILLEGALARGUMENT, 00179 "UNKNOWN NODE", 00180 string("Global::getInstance"), 00181 "The Global instance '" + name + "' is not known"); 00182 } 00183 00184 GlobalRef Global::createInstance(const string& name, const Property::MapType *propertyMapP, bool holdReferenceCount) 00185 { 00186 if (name == "") { 00187 throw XmlBlasterException(USER_ILLEGALARGUMENT, 00188 "UNKNOWN NODE", 00189 string("Global::createInstance"), 00190 "Please call createInstance with none empty name argument"); 00191 } 00192 if (name == "default") { 00193 throw XmlBlasterException(USER_ILLEGALARGUMENT, 00194 "UNKNOWN NODE", 00195 string("Global::createInstance"), 00196 "Please call getInstance to access the 'default' Global instance"); 00197 } 00198 00199 thread::Lock lock(globalMutex_); 00200 00201 { 00202 GlobalRefMap::iterator iter = globalRefMap_.find(name); 00203 if (iter != globalRefMap_.end()) { 00204 GlobalRef gr = (*iter).second; 00205 return gr; 00206 } 00207 } 00208 { 00209 GlobalMap::iterator iter = globalMap_.find(name); 00210 if (iter != globalMap_.end()) { 00211 //Global* glP = (*iter).second; 00212 throw XmlBlasterException(USER_ILLEGALARGUMENT, 00213 "UNKNOWN NODE", 00214 string("Global::createInstance"), 00215 "Please call getInstance to access the '" + name + "' Global instance"); 00216 } 00217 } 00218 00219 if (holdReferenceCount) { 00220 GlobalRef globRef = GlobalRef(new Global()); 00221 globRef->instanceName_ = name; 00222 if (propertyMapP != NULL) { 00223 globRef->initialize(*propertyMapP); 00224 } 00225 GlobalRefMap::value_type el(name, globRef); 00226 globalRefMap_.insert(el); 00227 return globRef; 00228 } 00229 else { 00230 Global* glP = new Global(); 00231 glP->instanceName_ = name; 00232 if (propertyMapP != NULL) { 00233 glP->initialize(*propertyMapP); 00234 } 00235 GlobalMap::value_type el(name, glP); 00236 globalMap_.insert(el); 00237 return GlobalRef(glP); 00238 } 00239 } 00240 00241 const string& Global::getInstanceName() 00242 { 00243 if (this->instanceName_ == "" && this == global_) { 00244 this->instanceName_ = "default"; 00245 } 00246 return this->instanceName_; 00247 } 00248 00249 bool Global::containsInstance(const std::string &name) 00250 { 00251 bool ret = globalRefMap_.count(name) != 0; 00252 if (ret) { 00253 return true; 00254 } 00255 return globalMap_.count(name) != 0; 00256 } 00257 00258 bool Global::destroyInstance(const std::string &name) 00259 { 00260 if (name == "") { 00261 return false; 00262 } 00263 if (name == "default") { 00264 throw XmlBlasterException(USER_ILLEGALARGUMENT, 00265 "UNKNOWN NODE", 00266 string("Global::destroyInstance"), 00267 "The 'default' Global instance is handled by the life time manager and can't be destroyed manually"); 00268 } 00269 thread::Lock lock(globalMutex_); 00270 { 00271 bool ret = globalRefMap_.count(name) != 0; 00272 if (ret) { 00273 globalRefMap_.erase(name); 00274 //cout << "DEBUG ONLY: " << name << " RefSize=" + lexical_cast<std::string>(globalRefMap_.size()) << 00275 // " Size=" + lexical_cast<std::string>(globalMap_.size()) << endl; 00276 return ret; 00277 } 00278 } 00279 { 00280 bool ret = globalMap_.count(name) != 0; 00281 if (ret) { 00282 globalMap_.erase(name); 00283 //cout << "DEBUG ONLY: " << name << " Size=" + lexical_cast<std::string>(globalMap_.size()) << 00284 // " RefSize=" + lexical_cast<std::string>(globalRefMap_.size()) << endl; 00285 return ret; 00286 } 00287 } 00288 return false; 00289 } 00290 00291 Global& Global::initialize(int args, const char * const argv[]) 00292 { 00293 if (isInitialized_) { 00294 getLog("org.xmlBlaster.util").warn(ME, "::initialize: the global is already initialized. Ignoring this initialization"); 00295 return *this; 00296 } 00297 args_ = args; 00298 argv_ = argv; 00299 if (property_ != NULL) delete property_; 00300 property_ = NULL; 00301 property_ = new Property(args, argv); 00302 property_->loadPropertyFile(); // load xmlBlaster.properties 00303 isInitialized_ = true; 00304 return *this; 00305 } 00306 00307 Global& Global::initialize(const Property::MapType &propertyMap) 00308 { 00309 if (isInitialized_) { 00310 getLog("org.xmlBlaster.util").warn(ME, "::initialize: the global is already initialized. Ignoring this initialization"); 00311 return *this; 00312 } 00313 args_ = 0; 00314 argv_ = 0; 00315 if (property_ != NULL) delete property_; 00316 property_ = NULL; 00317 property_ = new Property(propertyMap); 00318 property_->loadPropertyFile(); // load xmlBlaster.properties 00319 isInitialized_ = true; 00320 return *this; 00321 } 00322 00323 void Global::fillArgs(ArgsStruct_T &args) 00324 { 00325 if (property_ == 0) { 00326 args.argc = 0; 00327 args.argv = 0; 00328 return; 00329 } 00330 const Property::MapType &prmap = property_->getPropertyMap(); 00331 args.argc = 2*prmap.size()+1; 00332 args.argv = new char *[args.argc]; 00333 00334 string execName = (argv_ != 0 && args_ > 0) ? argv_[0] : "xmlBlasterClient"; 00335 args.argv[0] = new char[execName.length()+1]; 00336 strcpy(args.argv[0],execName.c_str()); 00337 int i = 1; 00338 Property::MapType::const_iterator ipm; 00339 for (ipm = prmap.begin(); ipm != prmap.end(); ++ipm) { 00340 args.argv[i] = new char[(*ipm).first.size()+2]; 00341 *(args.argv[i]) = '-'; 00342 strcpy(args.argv[i]+1, (*ipm).first.c_str()); i++; 00343 args.argv[i] = new char[(*ipm).second.size()+1]; 00344 strcpy(args.argv[i], (*ipm).second.c_str()); i++; 00345 } 00346 } 00347 00348 void Global::freeArgs(ArgsStruct_T &args) 00349 { 00350 for (size_t i=0; i<args.argc; i++) 00351 delete [] args.argv[i]; 00352 delete [] args.argv; 00353 args.argc = 0; 00354 } 00355 00356 bool Global::wantsHelp() 00357 { 00358 return getProperty().getBoolProperty("help", false, false) || 00359 getProperty().getBoolProperty("-help", false, false) || 00360 getProperty().getBoolProperty("h", false, false) || 00361 getProperty().getBoolProperty("?", false, false); 00362 } 00363 00364 string &Global::getVersion() 00365 { 00366 static string version = "@version@"; // is replaced by ant / build.xml to e.g. "0.901" 00367 return version; 00368 } 00369 00370 string &Global::getRevisionNumber() 00371 { 00372 static string revisionNumber = "@revision.number@"; // is replaced by ant / build.xml to subversions revision number, e.g. "1207" 00373 if (revisionNumber.find("@",0) != 0 && revisionNumber!=string("${revision.number}")) 00374 return revisionNumber; 00375 return getVersion(); 00376 } 00377 00378 string &Global::getReleaseId() 00379 { 00380 if (Global::getVersion() == Global::getRevisionNumber()) 00381 return Global::getVersion(); 00382 static string releaseId = Global::getVersion() + " #" + Global::getRevisionNumber(); 00383 return releaseId; 00384 } 00385 00386 string &Global::getBuildTimestamp() 00387 { 00388 static string timestamp = "@build.timestamp@"; // is replaced by ant / build.xml to e.g. "03/20/2003 10:22 PM"; 00389 return timestamp; 00390 } 00391 00392 string& Global::getCompiler() 00393 { 00394 static string cppCompiler = "@cpp.compiler@"; // is replaced by ant / build.xml to e.g. "g++"; 00395 return cppCompiler; 00396 } 00397 00398 00402 string& Global::getDefaultProtocol() 00403 { 00404 # if COMPILE_SOCKET_PLUGIN 00405 static string defaultProtocol = Constants::SOCKET; 00406 # elif COMPILE_CORBA_PLUGIN 00407 static string defaultProtocol = Constants::IOR; 00408 # else 00409 log_.error(ME, "Missing protocol in getDefaultProtocol(), please set COMPILE_CORBA_PLUGIN or COMPILE_SOCKET_PLUGIN on compilation"); 00410 # endif 00411 return defaultProtocol; 00412 } 00413 00414 Property& Global::getProperty() const 00415 { 00416 if (property_ == NULL) 00417 throw XmlBlasterException(USER_CONFIGURATION, 00418 "UNKNOWN NODE", 00419 ME + string("::getProperty"), "Please call initialize to init Property"); 00420 return *property_; 00421 } 00422 00423 string Global::usage() 00424 { 00425 string sb; 00426 sb += "\n"; 00427 sb += "\nXmlBlaster C++ client " + Global::getReleaseId() + " compiled at " + Global::getBuildTimestamp() + " with " + Global::getCompiler(); 00428 sb += "\n"; 00429 //# if COMPILE_SOCKET_PLUGIN && COMPILE_CORBA_PLUGIN 00430 sb += "\n -protocol SOCKET | IOR"; 00431 sb += "\n IOR for CORBA, SOCKET for our native protocol."; 00432 sb += "\n"; 00433 //# endif 00434 # ifdef COMPILE_SOCKET_PLUGIN 00435 sb += org::xmlBlaster::client::protocol::socket::SocketDriver::usage(); 00436 sb += "\n -logLevel ERROR | WARN | INFO | TRACE | DUMP [WARN]"; 00437 sb += "\n NOTE: Switch on C++ logging simultaneously to see the traces"; 00438 sb += "\n as the C logging is redirected to the C++ logging library\n"; 00439 sb += "\n"; 00440 # endif 00441 # ifdef COMPILE_CORBA_PLUGIN 00442 sb += org::xmlBlaster::client::protocol::corba::CorbaDriver::usage(); 00443 sb += "\n"; 00444 # endif 00445 # if defined(XMLBLASTER_MSXML_PLUGIN) 00446 # error Implement Microsoft XML parser for /DXMLBLASTER_MSXML_PLUGIN 00447 # else // XMLBLASTER_XERCES_PLUGIN 00448 sb += org::xmlBlaster::util::parser::Sax2Parser::usage(); 00449 sb += "\n"; 00450 # endif 00451 sb += org::xmlBlaster::util::qos::SessionQos::usage(); 00452 sb += "\n"; 00453 sb += org::xmlBlaster::util::qos::address::Address(Global::getInstance()).usage(); 00454 sb += "\n"; 00455 sb += org::xmlBlaster::util::qos::storage::ClientQueueProperty::usage(); 00456 sb += "\n"; 00457 //sb += org::xmlBlaster::util::qos::storage::MsgUnitStoreProperty::usage(); 00458 //sb += "\n"; 00459 sb += org::xmlBlaster::util::qos::address::CallbackAddress(Global::getInstance()).usage(); 00460 sb += "\n"; 00461 sb += org::xmlBlaster::util::qos::storage::CbQueueProperty::usage(); 00462 sb += "\n"; 00463 const I_Log& ll = getInstance().getLog(); 00464 sb += ll.usage(); 00465 return sb; 00466 /* 00467 StringBuffer sb = new StringBuffer(4028); 00468 sb.append(org.xmlBlaster.client.XmlBlasterAccess.usage(this)); 00469 sb.append(logUsage()); 00470 return sb.toString(); 00471 */ 00472 } 00473 00474 LogManager& Global::getLogManager() 00475 { 00476 return logManager_; 00477 } 00478 00479 I_Log& Global::getLog(const string &logName) 00480 { 00481 try { 00482 # if XMLBLASTER_COMPILE_LOG4CPLUS_PLUGIN==1 00483 static bool first = true; 00484 if (first) { 00485 logManager_.setLogFactory("log4cplus", new Log4cplusFactory()); 00486 logManager_.initialize(getProperty().getPropertyMap()); 00487 first = false; 00488 } 00489 return logManager_.getLogFactory().getLog(logName); 00490 # else 00491 return logManager_.getLogFactory().getLog(logName); // Use our default Log.cpp 00492 # endif 00493 } 00494 catch(...) { 00495 throw XmlBlasterException(INTERNAL_UNKNOWN, "UNKNOWN NODE", ME + string("::getLog() failed to setup logging configuration")); 00496 } 00497 } 00498 00499 int Global::getArgs() 00500 { 00501 return args_; 00502 } 00503 00504 const char * const* Global::getArgc() 00505 { 00506 return argv_; 00507 } 00508 00509 string Global::getLocalIP() const 00510 { 00511 // change this to a better way later ... 00512 return string("127.0.0.1"); 00513 } 00514 00515 string Global::getBootstrapHostname() const 00516 { 00517 return getProperty().getStringProperty(string("bootstrapHostname"), getLocalIP()); 00518 /* URL: 00519 string bootstrapHostname = getProperty().getStringProperty(string("bootstrapHostname"), getLocalIP()); 00520 int bootstrapPort = getProperty().getIntProperty(string("bootstrapPort"), Constants::XMLBLASTER_PORT); 00521 return "http://" + bootstrapHostname + ":" + lexical_cast<std::string>(bootstrapPort); 00522 */ 00523 } 00524 00525 string Global::getCbHostname() const 00526 { 00527 // std::cout << "Global::getCbHostname implementation is not finished" << std::endl; 00528 return getProperty().getStringProperty(string("bootstrapHostname"), getLocalIP()); 00529 } 00530 00531 CbServerPluginManager& Global::getCbServerPluginManager() 00532 { 00533 if (cbServerPluginManager_ == NULL) { 00534 cbServerPluginManager_ = new CbServerPluginManager(*this); 00535 } 00536 return *cbServerPluginManager_; 00537 } 00538 00539 DispatchManager& Global::getDispatchManager() 00540 { 00541 if (dispatchManager_ == NULL) { 00542 dispatchManager_ = new DispatchManager(*this); 00543 } 00544 return *dispatchManager_; 00545 } 00546 00547 Timeout& Global::getPingTimer() 00548 { 00549 if (pingTimer_) return *pingTimer_; 00550 thread::Lock lock(pingerMutex_); 00551 { // this is synchronized. Test again if meanwhile it has been set ... 00552 getLog("org.xmlBlaster.util").trace(ME, "::getPingTimer: creating the singleton 'ping timer'"); 00553 if (pingTimer_) return *pingTimer_; 00554 pingTimer_ = new Timeout(*this, string("ping timer")); 00555 return *pingTimer_; 00556 } 00557 } 00558 00559 const string& Global::getBoolAsString(bool val) 00560 { 00561 return (val) ? XMLBLASTER_TRUE : XMLBLASTER_FALSE; 00562 // return lexical_cast<std::string>(val); 00563 // gcc complains: warning: returning reference to temporary 00564 } 00565 00566 void Global::setSessionName(SessionNameRef sessionName) 00567 { 00568 sessionName_ = sessionName; 00569 } 00570 00571 SessionNameRef Global::getSessionName() const 00572 { 00573 return sessionName_; 00574 } 00575 00576 00583 string Global::getId() const 00584 { 00585 return id_; 00586 } 00587 00588 string Global::getImmutableId() const 00589 { 00590 return immutableId_; 00591 } 00592 00593 string Global::getStrippedId() const 00594 { 00595 return getStrippedString(id_); 00596 } 00597 00598 string Global::getStrippedImmutableId() const 00599 { 00600 return getStrippedString(immutableId_); 00601 } 00602 00603 string Global::getStrippedString(const string& text) const 00604 { 00605 string ret = text; 00606 string::iterator 00607 ref = remove(ret.begin(), ret.end(), '/'); // StringHelper.replaceAll(text, "/", ""); 00608 replace(ret.begin(), ref, '.', '_'); // StringHelper.replaceAll(strippedId, ".", "_"); 00609 replace(ret.begin(), ref, ':', '_'); // StringHelper.replaceAll(strippedId, ":", "_"); 00610 ref = remove(ret.begin(), ref, '\\'); // StringHelper.replaceAll(strippedId, "\\", ""); 00611 ret.erase(ref, ret.end()); 00612 return ret; 00613 } 00614 00615 void Global::setId(const string& id) 00616 { 00617 id_ = id; 00618 resetInstanceId(); 00619 } 00620 00621 void Global::setImmutableId(const string& id) 00622 { 00623 immutableId_ = id; 00624 } 00625 00626 void Global::resetInstanceId() { 00627 thread::Lock lock(globalMutex_); 00628 instanceId_ = ""; 00629 } 00630 00631 std::string Global::getInstanceId() const { 00632 if (instanceId_ == "") { 00633 thread::Lock lock(globalMutex_); 00634 if (instanceId_ == "") { 00635 Timestamp timestamp = TimestampFactory::getInstance().getTimestamp(); 00636 //ContextNode node(this, "instanceId", 00637 // lexical_cast<std::string>(timestamp), getContextNode()); 00638 instanceId_ = getId() + "/instanceId/" + lexical_cast<std::string>(timestamp); 00639 } 00640 } 00641 return instanceId_; 00642 } 00643 00644 std::string waitOnKeyboardHit(const std::string &str) 00645 { 00646 char ptr[256]; 00647 std::string retStr; 00648 00649 // Flush input stream 00650 while (true) { 00651 cout.flush(); 00652 size_t ret = std::cin.rdbuf()->in_avail(); 00653 if (ret == 0) break; 00654 std::cin.getline(ptr,255,'\n'); 00655 } 00656 00657 // Request input 00658 if (str != "") 00659 std::cout << str; 00660 00661 // Read input, ignore newlines 00662 *ptr = 0; 00663 bool first=true; 00664 while (true) { 00665 std::cin.getline(ptr,255,'\n'); 00666 if (strlen(ptr)) 00667 retStr = ptr; 00668 else { 00669 if (str != "" && !first) 00670 std::cout << str; 00671 } 00672 first = false; 00673 00674 size_t ret = std::cin.rdbuf()->in_avail(); 00675 if (ret == 0 && retStr != "") { 00676 return retStr; 00677 } 00678 } 00679 } 00680 00681 }}} // namespace 00682