diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Ice/Initialize.cpp | 7 | ||||
-rw-r--r-- | cpp/src/Ice/PluginManagerI.cpp | 230 | ||||
-rw-r--r-- | cpp/src/Ice/PluginManagerI.h | 13 |
3 files changed, 177 insertions, 73 deletions
diff --git a/cpp/src/Ice/Initialize.cpp b/cpp/src/Ice/Initialize.cpp index 21ff3f62c80..e17e405bf7b 100644 --- a/cpp/src/Ice/Initialize.cpp +++ b/cpp/src/Ice/Initialize.cpp @@ -16,6 +16,7 @@ #include <Ice/StreamI.h> #include <Ice/LoggerI.h> #include <Ice/Instance.h> +#include <Ice/PluginManagerI.h> #include <IceUtil/Mutex.h> #include <IceUtil/MutexPtrLock.h> #include <IceUtil/StringConverter.h> @@ -351,6 +352,12 @@ Ice::setProcessLogger(const LoggerPtr& logger) processLogger = logger; } +void +Ice::registerPluginFactory(const std::string& name, PLUGIN_FACTORY factory, bool loadOnInitialize) +{ + PluginManagerI::registerPluginFactory(name, factory, loadOnInitialize); +} + InstancePtr IceInternal::getInstance(const CommunicatorPtr& communicator) { diff --git a/cpp/src/Ice/PluginManagerI.cpp b/cpp/src/Ice/PluginManagerI.cpp index 77076a13771..e43a8441cc2 100644 --- a/cpp/src/Ice/PluginManagerI.cpp +++ b/cpp/src/Ice/PluginManagerI.cpp @@ -13,7 +13,6 @@ #include <Ice/Communicator.h> #include <Ice/Properties.h> #include <Ice/LoggerUtil.h> -#include <Ice/Initialize.h> #include <Ice/Instance.h> #include <Ice/LocalException.h> @@ -23,7 +22,55 @@ using namespace IceInternal; const char * const Ice::PluginManagerI::_kindOfObject = "plugin"; -typedef Ice::Plugin* (*PLUGIN_FACTORY)(const CommunicatorPtr&, const string&, const StringSeq&); +namespace +{ + +map<string, PLUGIN_FACTORY>* factories = 0; +vector<string>* loadOnInitialization = 0; + +class PluginFactoryDestroy +{ +public: + + ~PluginFactoryDestroy() + { + delete factories; + factories = 0; + + delete loadOnInitialization; + loadOnInitialization = 0; + } +}; +PluginFactoryDestroy destroy; + +} + +void +Ice::PluginManagerI::registerPluginFactory(const std::string& name, PLUGIN_FACTORY factory, bool loadOnInit) +{ + if(factories == 0) + { + factories = new map<string, PLUGIN_FACTORY>(); + } + if(loadOnInitialization == 0) + { + loadOnInitialization = new vector<string>(); + } + + map<string, PLUGIN_FACTORY>::const_iterator p = factories->find(name); + if(p == factories->end()) + { + factories->insert(make_pair(name, factory)); + if(loadOnInit) + { + if(loadOnInitialization == 0) + { + loadOnInitialization = new vector<string>(); + } + loadOnInitialization->push_back(name); + } + } +} void Ice::PluginManagerI::initializePlugins() @@ -193,10 +240,48 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) StringSeq cmdArgs = argsToStringSeq(argc, argv); + const string prefix = "Ice.Plugin."; + PropertiesPtr properties = _communicator->getProperties(); + PropertyDict plugins = properties->getPropertiesForPrefix(prefix); + + // + // First, load static plugin factories which were setup to load on + // communicator initialization. If a matching plugin property is + // set, we load the plugin with the plugin specification. The + // entryPoint will be ignored but the rest of the plugin + // specification might be used. + // + if(loadOnInitialization) + { + for(vector<string>::const_iterator p = loadOnInitialization->begin(); p != loadOnInitialization->end(); ++p) + { + string property = prefix + *p; + PropertyDict::iterator r = plugins.find(property + ".cpp"); + if(r == plugins.end()) + { + r = plugins.find(property); + } + else + { + plugins.erase(property); + } + + if(r != plugins.end()) + { + loadPlugin(*p, r->second, cmdArgs); + plugins.erase(r); + } + else + { + loadPlugin(*p, "", cmdArgs); + } + } + } + // - // Load and initialize the plug-ins defined in the property set - // with the prefix "Ice.Plugin.". These properties should - // have the following format: + // Next, load and initialize the plug-ins defined in the property + // set with the prefix "Ice.Plugin.". These properties should have + // the following format: // // Ice.Plugin.name[.<language>]=entry_point [args] // @@ -204,10 +289,6 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) // specified plug-ins in the specified order, then load any // remaining plug-ins. // - const string prefix = "Ice.Plugin."; - PropertiesPtr properties = _communicator->getProperties(); - PropertyDict plugins = properties->getPropertiesForPrefix(prefix); - StringSeq loadOrder = properties->getPropertyAsList("Ice.PluginLoadOrder"); for(StringSeq::const_iterator p = loadOrder.begin(); p != loadOrder.end(); ++p) { @@ -220,14 +301,15 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) throw ex; } - PropertyDict::iterator r = plugins.find("Ice.Plugin." + name + ".cpp"); + string property = prefix + name; + PropertyDict::iterator r = plugins.find(property + ".cpp"); if(r == plugins.end()) { - r = plugins.find("Ice.Plugin." + name); + r = plugins.find(property); } else { - plugins.erase("Ice.Plugin." + name); + plugins.erase(property); } if(r != plugins.end()) @@ -270,7 +352,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) loadPlugin(name, p->second, cmdArgs); plugins.erase(p); - plugins.erase("Ice.Plugin." + name); + plugins.erase(prefix + name); } else { @@ -286,7 +368,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) // // Is there a .cpp entry? // - PropertyDict::iterator q = plugins.find("Ice.Plugin." + name + ".cpp"); + PropertyDict::iterator q = plugins.find(prefix + name + ".cpp"); if(q != plugins.end()) { plugins.erase(p); @@ -305,64 +387,91 @@ void Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, StringSeq& cmdArgs) { assert(_communicator); - // - // Split the entire property value into arguments. An entry point containing spaces - // must be enclosed in quotes. - // + + string entryPoint; StringSeq args; - try - { - args = IceUtilInternal::Options::split(pluginSpec); - } - catch(const IceUtilInternal::BadOptException& ex) + if(!pluginSpec.empty()) { - PluginInitializationException e(__FILE__, __LINE__); - e.reason = "invalid arguments for plug-in `" + name + "':\n" + ex.reason; - throw e; - } + // + // Split the entire property value into arguments. An entry point containing spaces + // must be enclosed in quotes. + // + try + { + args = IceUtilInternal::Options::split(pluginSpec); + } + catch(const IceUtilInternal::BadOptException& ex) + { + PluginInitializationException e(__FILE__, __LINE__); + e.reason = "invalid arguments for plug-in `" + name + "':\n" + ex.reason; + throw e; + } - assert(!args.empty()); + assert(!args.empty()); - // - // Shift the arguments. - // - const string entryPoint = args[0]; - args.erase(args.begin()); + // + // Shift the arguments. + // + entryPoint = args[0]; + args.erase(args.begin()); + + // + // Convert command-line options into properties. First we + // convert the options from the plug-in configuration, then + // we convert the options from the application command-line. + // + PropertiesPtr properties = _communicator->getProperties(); + args = properties->parseCommandLineOptions(name, args); + cmdArgs = properties->parseCommandLineOptions(name, cmdArgs); + } + + PluginPtr plugin; + PLUGIN_FACTORY factory = 0; + DynamicLibraryPtr library; // - // Convert command-line options into properties. First we - // convert the options from the plug-in configuration, then - // we convert the options from the application command-line. + // Always check the static plugin factory table first, it takes + // precedence over the the entryPoint specified in the plugin + // property value. // - PropertiesPtr properties = _communicator->getProperties(); - args = properties->parseCommandLineOptions(name, args); - cmdArgs = properties->parseCommandLineOptions(name, cmdArgs); + if(factories) + { + map<string, PLUGIN_FACTORY>::const_iterator p = factories->find(name); + if(p != factories->end()) + { + factory = p->second; + } + } // - // Load the entry point symbol. + // If we didn't find the factory, get the factory using the entry + // point symbol. // - PluginPtr plugin; - DynamicLibraryPtr library = new DynamicLibrary(); - DynamicLibrary::symbol_type sym = library->loadEntryPoint(entryPoint); - if(sym == 0) + if(!factory) { - ostringstream out; - string msg = library->getErrorMessage(); - out << "unable to load entry point `" << entryPoint << "'"; - if(!msg.empty()) + assert(!entryPoint.empty()); + library = new DynamicLibrary(); + DynamicLibrary::symbol_type sym = library->loadEntryPoint(entryPoint); + if(sym == 0) { - out << ": " + msg; + ostringstream out; + string msg = library->getErrorMessage(); + out << "unable to load entry point `" << entryPoint << "'"; + if(!msg.empty()) + { + out << ": " + msg; + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = out.str(); + throw ex; } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = out.str(); - throw ex; + factory = reinterpret_cast<PLUGIN_FACTORY>(sym); } // // Invoke the factory function. No exceptions can be raised // by the factory function because it's declared extern "C". // - PLUGIN_FACTORY factory = reinterpret_cast<PLUGIN_FACTORY>(sym); plugin = factory(_communicator, name, args); if(!plugin) { @@ -378,7 +487,10 @@ Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, St info.plugin = plugin; _plugins.push_back(info); - _libraries->add(library); + if(library) + { + _libraries->add(library); + } } Ice::PluginPtr @@ -393,13 +505,3 @@ Ice::PluginManagerI::findPlugin(const string& name) const } return 0; } - -void -IceInternal::loadPlugin(const Ice::CommunicatorPtr& communicator, - const string& name, - const string& pluginSpec, - Ice::StringSeq& cmdArgs) -{ - PluginManagerIPtr pluginManager = PluginManagerIPtr::dynamicCast(getInstance(communicator)->pluginManager()); - pluginManager->loadPlugin(name, pluginSpec, cmdArgs); -} diff --git a/cpp/src/Ice/PluginManagerI.h b/cpp/src/Ice/PluginManagerI.h index d70783e3cb4..ef9a1dd9275 100644 --- a/cpp/src/Ice/PluginManagerI.h +++ b/cpp/src/Ice/PluginManagerI.h @@ -18,20 +18,17 @@ #include <IceUtil/Mutex.h> #include <map> -namespace IceInternal -{ - -ICE_API void loadPlugin(const ::Ice::CommunicatorPtr&, const std::string&, const std::string&, Ice::StringSeq&); - -} - namespace Ice { +typedef Ice::Plugin* (*PLUGIN_FACTORY)(const ::Ice::CommunicatorPtr&, const std::string&, const ::Ice::StringSeq&); + class PluginManagerI : public PluginManager, public IceUtil::Mutex { public: + static void registerPluginFactory(const std::string&, PLUGIN_FACTORY, bool); + virtual void initializePlugins(); virtual StringSeq getPlugins(); virtual PluginPtr getPlugin(const std::string&); @@ -42,8 +39,6 @@ private: PluginManagerI(const CommunicatorPtr&, const IceInternal::DynamicLibraryListPtr&); friend class IceInternal::Instance; - friend void IceInternal::loadPlugin(const Ice::CommunicatorPtr&, const std::string&, const std::string&, - Ice::StringSeq&); void loadPlugins(int&, char*[]); void loadPlugin(const std::string&, const std::string&, StringSeq&); |