// // Copyright (c) ZeroC, Inc. All rights reserved. // #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace Ice; using namespace IceInternal; namespace { IceUtil::Mutex* globalMutex = 0; Ice::LoggerPtr processLogger; class Init { public: Init() { globalMutex = new IceUtil::Mutex; } ~Init() { delete globalMutex; globalMutex = 0; } }; Init init; } StringSeq Ice::argsToStringSeq(int argc, const char* const argv[]) { StringSeq result; for(int i = 0; i < argc; i++) { result.push_back(argv[i]); } return result; } #ifdef _WIN32 StringSeq Ice::argsToStringSeq(int /*argc*/, const wchar_t* const argv[]) { // // Don't need to use a wide string converter argv is expected to // come from Windows API. // const StringConverterPtr converter = getProcessStringConverter(); StringSeq args; for(int i = 0; argv[i] != 0; i++) { args.push_back(wstringToString(argv[i], converter)); } return args; } #endif void Ice::stringSeqToArgs(const StringSeq& args, int& argc, const char* argv[]) { // // Shift all elements in argv which are present in args to the // beginning of argv. We record the original value of argc so // that we can know later if we've shifted the array. // const int argcOrig = argc; int i = 0; while(i < argc) { if(find(args.begin(), args.end(), argv[i]) == args.end()) { for(int j = i; j < argc - 1; j++) { argv[j] = argv[j + 1]; } --argc; } else { ++i; } } // // Make sure that argv[argc] == 0, the ISO C++ standard requires this. // We can only do this if we've shifted the array, otherwise argv[argc] // may point to an invalid address. // if(argv && argcOrig != argc) { argv[argc] = 0; } } #ifdef _WIN32 void Ice::stringSeqToArgs(const StringSeq& args, int& argc, const wchar_t* argv[]) { // // Don't need to use a wide string converter argv is expected to // come from Windows API. // const StringConverterPtr converter = getProcessStringConverter(); // // Shift all elements in argv which are present in args to the // beginning of argv. We record the original value of argc so // that we can know later if we've shifted the array. // const int argcOrig = argc; int i = 0; while(i < argc) { if(find(args.begin(), args.end(), wstringToString(argv[i], converter)) == args.end()) { for(int j = i; j < argc - 1; j++) { argv[j] = argv[j + 1]; } --argc; } else { ++i; } } // // Make sure that argv[argc] == 0, the ISO C++ standard requires this. // We can only do this if we've shifted the array, otherwise argv[argc] // may point to an invalid address. // if(argv && argcOrig != argc) { argv[argc] = 0; } } #endif PropertiesPtr Ice::createProperties() { return ICE_MAKE_SHARED(PropertiesI); } PropertiesPtr Ice::createProperties(StringSeq& args, const PropertiesPtr& defaults) { return ICE_MAKE_SHARED(PropertiesI, args, defaults); } PropertiesPtr Ice::createProperties(int& argc, const char* argv[], const PropertiesPtr& defaults) { StringSeq args = argsToStringSeq(argc, argv); PropertiesPtr properties = createProperties(args, defaults); stringSeqToArgs(args, argc, argv); return properties; } #ifdef _WIN32 PropertiesPtr Ice::createProperties(int& argc, const wchar_t* argv[], const PropertiesPtr& defaults) { StringSeq args = argsToStringSeq(argc, argv); PropertiesPtr properties = createProperties(args, defaults); stringSeqToArgs(args, argc, argv); return properties; } #endif #ifdef ICE_CPP11_MAPPING Ice::ThreadHookPlugin::ThreadHookPlugin(const CommunicatorPtr& communicator, function threadStart, function threadStop) { if(communicator == nullptr) { throw PluginInitializationException(__FILE__, __LINE__, "Communicator cannot be null"); } IceInternal::InstancePtr instance = IceInternal::getInstance(communicator); instance->setThreadHook(std::move(threadStart), std::move(threadStop)); } #else Ice::ThreadHookPlugin::ThreadHookPlugin(const CommunicatorPtr& communicator, const ThreadNotificationPtr& threadHook) { if(communicator == 0) { throw PluginInitializationException(__FILE__, __LINE__, "Communicator cannot be null"); } IceInternal::InstancePtr instance = IceInternal::getInstance(communicator); instance->setThreadHook(threadHook); } #endif void Ice::ThreadHookPlugin::initialize() { } void Ice::ThreadHookPlugin::destroy() { } namespace { inline void checkIceVersion(int version) { #ifndef ICE_IGNORE_VERSION # if ICE_INT_VERSION % 100 > 50 // // Beta version: exact match required // if(ICE_INT_VERSION != version) { throw VersionMismatchException(__FILE__, __LINE__); } # else // // Major and minor version numbers must match. // if(ICE_INT_VERSION / 100 != version / 100) { throw VersionMismatchException(__FILE__, __LINE__); } // // Reject beta caller // if(version % 100 > 50) { throw VersionMismatchException(__FILE__, __LINE__); } // // The caller's patch level cannot be greater than library's patch level. (Patch level changes are // backward-compatible, but not forward-compatible.) // if(version % 100 > ICE_INT_VERSION % 100) { throw VersionMismatchException(__FILE__, __LINE__); } # endif #endif } } Ice::CommunicatorPtr Ice::initialize(int& argc, const char* argv[], const InitializationData& initializationData, int version) { checkIceVersion(version); InitializationData initData = initializationData; initData.properties = createProperties(argc, argv, initData.properties); CommunicatorIPtr communicator = CommunicatorI::create(initData); communicator->finishSetup(argc, argv); return communicator; } Ice::CommunicatorPtr Ice::initialize(int& argc, const char* argv[], ICE_CONFIG_FILE_STRING configFile, int version) { InitializationData initData; initData.properties = createProperties(); initData.properties->load(configFile); return initialize(argc, argv, initData, version); } #ifdef _WIN32 Ice::CommunicatorPtr Ice::initialize(int& argc, const wchar_t* argv[], const InitializationData& initializationData, int version) { Ice::StringSeq args = argsToStringSeq(argc, argv); CommunicatorPtr communicator = initialize(args, initializationData, version); stringSeqToArgs(args, argc, argv); return communicator; } Ice::CommunicatorPtr Ice::initialize(int& argc, const wchar_t* argv[], ICE_CONFIG_FILE_STRING configFile, int version) { InitializationData initData; initData.properties = createProperties(); initData.properties->load(configFile); return initialize(argc, argv, initData, version); } #endif Ice::CommunicatorPtr Ice::initialize(StringSeq& args, const InitializationData& initializationData, int version) { IceInternal::ArgVector av(args); CommunicatorPtr communicator = initialize(av.argc, av.argv, initializationData, version); args = argsToStringSeq(av.argc, av.argv); return communicator; } Ice::CommunicatorPtr Ice::initialize(StringSeq& args, ICE_CONFIG_FILE_STRING configFile, int version) { InitializationData initData; initData.properties = createProperties(); initData.properties->load(configFile); return initialize(args, initData, version); } Ice::CommunicatorPtr Ice::initialize(const InitializationData& initData, int version) { // // We can't simply call the other initialize() because this one does NOT read // the config file, while the other one always does. // checkIceVersion(version); CommunicatorIPtr communicator = CommunicatorI::create(initData); int argc = 0; const char* argv[] = { 0 }; communicator->finishSetup(argc, argv); return communicator; } Ice::CommunicatorPtr Ice::initialize(ICE_CONFIG_FILE_STRING configFile, int version) { InitializationData initData; initData.properties = createProperties(); initData.properties->load(configFile); return initialize(initData, version); } LoggerPtr Ice::getProcessLogger() { IceUtilInternal::MutexPtrLock lock(globalMutex); if(processLogger == ICE_NULLPTR) { // // TODO: Would be nice to be able to use process name as prefix by default. // processLogger = ICE_MAKE_SHARED(LoggerI, "", "", true); } return processLogger; } void Ice::setProcessLogger(const LoggerPtr& logger) { IceUtilInternal::MutexPtrLock lock(globalMutex); processLogger = logger; } void Ice::registerPluginFactory(const std::string& name, PluginFactory factory, bool loadOnInitialize) { IceUtilInternal::MutexPtrLock lock(globalMutex); PluginManagerI::registerPluginFactory(name, factory, loadOnInitialize); } // // CommunicatorHolder // Ice::CommunicatorHolder::CommunicatorHolder() { } #ifdef ICE_CPP11_MAPPING Ice::CommunicatorHolder::CommunicatorHolder(shared_ptr communicator) : _communicator(std::move(communicator)) { } Ice::CommunicatorHolder& Ice::CommunicatorHolder::operator=(shared_ptr communicator) { if(_communicator) { _communicator->destroy(); } _communicator = std::move(communicator); return *this; } Ice::CommunicatorHolder& Ice::CommunicatorHolder::operator=(CommunicatorHolder&& other) noexcept { if(_communicator) { _communicator->destroy(); } _communicator = std::move(other._communicator); return *this; } #else // C++98 mapping Ice::CommunicatorHolder::CommunicatorHolder(int& argc, const char* argv[], const InitializationData& initData, int version) : _communicator(initialize(argc, argv, initData, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(int& argc, char* argv[], const InitializationData& initData, int version) : _communicator(initialize(argc, argv, initData, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(int& argc, const char* argv[], const char* configFile, int version) : _communicator(initialize(argc, argv, configFile, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(int& argc, char* argv[], const char* configFile, int version) : _communicator(initialize(argc, argv, configFile, version)) { } # ifdef _WIN32 Ice::CommunicatorHolder::CommunicatorHolder(int& argc, const wchar_t* argv[], const InitializationData& initData, int version) : _communicator(initialize(argc, argv, initData, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(int& argc, wchar_t* argv[], const InitializationData& initData, int version) : _communicator(initialize(argc, argv, initData, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(int& argc, const wchar_t* argv[], const char* configFile, int version) : _communicator(initialize(argc, argv, configFile, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(int& argc, wchar_t* argv[], const char* configFile, int version) : _communicator(initialize(argc, argv, configFile, version)) { } # endif Ice::CommunicatorHolder::CommunicatorHolder(StringSeq& args, const InitializationData& initData, int version) : _communicator(initialize(args, initData, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(StringSeq& args, const char* configFile, int version) : _communicator(initialize(args, configFile, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(const InitializationData& initData, int version) : _communicator(initialize(initData, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(const char* configFile, int version) : _communicator(initialize(configFile, version)) { } Ice::CommunicatorHolder::CommunicatorHolder(const CommunicatorPtr& communicator) : _communicator(communicator) { } Ice::CommunicatorHolder& Ice::CommunicatorHolder::operator=(const CommunicatorPtr& communicator) { if(_communicator) { _communicator->destroy(); } _communicator = communicator; return *this; } #endif Ice::CommunicatorHolder::~CommunicatorHolder() { if(_communicator) { _communicator->destroy(); } } Ice::CommunicatorHolder::operator bool() const { return _communicator != ICE_NULLPTR; } const Ice::CommunicatorPtr& Ice::CommunicatorHolder::communicator() const { return _communicator; } const Ice::CommunicatorPtr& Ice::CommunicatorHolder::operator->() const { return _communicator; } Ice::CommunicatorPtr Ice::CommunicatorHolder::release() { #ifdef ICE_CPP11_MAPPING return std::move(_communicator); #else CommunicatorPtr result; result.swap(_communicator); return result; #endif } InstancePtr IceInternal::getInstance(const CommunicatorPtr& communicator) { CommunicatorIPtr p = ICE_DYNAMIC_CAST(::Ice::CommunicatorI, communicator); assert(p); return p->_instance; } IceUtil::TimerPtr IceInternal::getInstanceTimer(const CommunicatorPtr& communicator) { CommunicatorIPtr p = ICE_DYNAMIC_CAST(::Ice::CommunicatorI, communicator); assert(p); return p->_instance->timer(); } Identity Ice::stringToIdentity(const string& s) { Identity ident; // // Find unescaped separator; note that the string may contain an escaped // backslash before the separator. // string::size_type slash = string::npos; string::size_type pos = 0; while((pos = s.find('/', pos)) != string::npos) { string::size_type escapes = 0; while(static_cast(pos - escapes) > 0 && s[pos - escapes - 1] == '\\') { escapes++; } // // We ignore escaped escapes // if(escapes % 2 == 0) { if(slash == string::npos) { slash = pos; } else { // // Extra unescaped slash found. // throw IdentityParseException(__FILE__, __LINE__, "unescaped '/' in identity `" + s + "'"); } } pos++; } if(slash == string::npos) { try { ident.name = unescapeString(s, 0, s.size(), "/"); } catch(const IceUtil::IllegalArgumentException& ex) { throw IdentityParseException(__FILE__, __LINE__, "invalid identity name `" + s + "': " + ex.reason()); } } else { try { ident.category = unescapeString(s, 0, slash, "/"); } catch(const IceUtil::IllegalArgumentException& ex) { throw IdentityParseException(__FILE__, __LINE__, "invalid category in identity `" + s + "': " + ex.reason()); } if(slash + 1 < s.size()) { try { ident.name = unescapeString(s, slash + 1, s.size(), "/"); } catch(const IceUtil::IllegalArgumentException& ex) { throw IdentityParseException(__FILE__, __LINE__, "invalid name in identity `" + s + "': " + ex.reason()); } } } return ident; } string Ice::identityToString(const Identity& ident, ToStringMode toStringMode) { if(ident.category.empty()) { return escapeString(ident.name, "/", toStringMode); } else { return escapeString(ident.category, "/", toStringMode) + '/' + escapeString(ident.name, "/", toStringMode); } }