diff options
author | Mark Spruiell <mes@zeroc.com> | 2006-04-26 03:22:49 +0000 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2006-04-26 03:22:49 +0000 |
commit | d24b35ce1f999f86c6f856821d51f4adf72c76e6 (patch) | |
tree | b1d1dbe50724a4d42ce1e46622aa49fde0a5492d /cpp | |
parent | use two stages for plugin initialization; refactoring to remove Context (diff) | |
download | ice-d24b35ce1f999f86c6f856821d51f4adf72c76e6.tar.bz2 ice-d24b35ce1f999f86c6f856821d51f4adf72c76e6.tar.xz ice-d24b35ce1f999f86c6f856821d51f4adf72c76e6.zip |
use two stages for plugin initialization
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/config/PropertyNames.def | 4 | ||||
-rw-r--r-- | cpp/doc/Properties.sgml | 73 | ||||
-rw-r--r-- | cpp/include/IceSSL/Plugin.h | 26 | ||||
-rw-r--r-- | cpp/slice/Ice/Plugin.ice | 26 | ||||
-rw-r--r-- | cpp/src/Ice/PluginManagerI.cpp | 63 | ||||
-rw-r--r-- | cpp/src/Ice/PluginManagerI.h | 3 | ||||
-rw-r--r-- | cpp/src/Ice/PropertyNames.cpp | 6 | ||||
-rw-r--r-- | cpp/src/Ice/PropertyNames.h | 2 | ||||
-rw-r--r-- | cpp/test/IceSSL/configuration/AllTests.cpp | 30 |
9 files changed, 167 insertions, 66 deletions
diff --git a/cpp/config/PropertyNames.def b/cpp/config/PropertyNames.def index a396bccac5c..576d02d46a6 100644 --- a/cpp/config/PropertyNames.def +++ b/cpp/config/PropertyNames.def @@ -126,6 +126,7 @@ Ice: Default.Protocol Default.Router GC.Interval + InitPlugins Logger.Timestamp MessageSizeMax MonitorConnections @@ -294,13 +295,10 @@ IceSSL: CertAuthDir CertAuthFile CertFile - Certs - CertsPassword CheckCertName CheckCRL Ciphers DefaultDir - DelayInit DH.<any> EntropyDaemon ImportCert.<any>.<any> diff --git a/cpp/doc/Properties.sgml b/cpp/doc/Properties.sgml index 1236bf24dd7..bccac484fae 100644 --- a/cpp/doc/Properties.sgml +++ b/cpp/doc/Properties.sgml @@ -654,25 +654,37 @@ Ice.Plugin.<replaceable>name</replaceable>=<replaceable>entry_point [args]</repl Defines a plugin to be installed during communicator initialization. </para> <para> -In C++, <replaceable>entry_point</replaceable> has the form +<variablelist><title>Platform Notes</title> +<varlistentry><term>C++</term> +<listitem> +<para> +The value of <replaceable>entry_point</replaceable> has the form <literal>basename[,version]:function</literal>. The <literal>basename</literal> and optional <literal>version</literal> components are used to construct the name of a DLL or shared library. If no version is supplied, the &Ice; version is used. The <literal>function</literal> component is the name of a function with -C linkage. For example, the entry point <literal>MyPlugin,2.3:create</literal> -would imply a shared library name of <literal>libMyPlugin.so.2.3</literal> -on Unix and <literal>MyPlugin23.dll</literal> on Windows. Furthermore, +C linkage. For example, the entry point <literal>MyPlugin,3.1:create</literal> +would imply a shared library name of <literal>libMyPlugin.so.3.1</literal> +on Unix and <literal>MyPlugin31.dll</literal> on Windows. Furthermore, if &Ice; is built on Windows with debugging, a <literal>d</literal> is -automatically appended to the version (e.g., <literal>MyPlugin23d.dll</literal>). +automatically appended to the version (e.g., <literal>MyPlugin31d.dll</literal>). </para> +</listitem> +</varlistentry> +<varlistentry><term>Java</term> +<listitem> <para> -In Java, <replaceable>entry_point</replaceable> is the name of a class that +The value of <replaceable>entry_point</replaceable> is the name of a class that must implement the <literal>Ice.PluginFactory</literal> interface. Any arguments that follow the class name are passed to the <literal>create</literal> method. </para> +</listitem> +</varlistentry> +<varlistentry><term>.NET</term> +<listitem> <para> -In C# and Visual Basic, <replaceable>entry_point</replaceable> has the form +The value of <replaceable>entry_point</replaceable> has the form <literal>assembly:class</literal>. The assembly can be the full assembly name, such as <literal>myplugin, Version=0.0.0.0, Culture=neutral</literal>, or an assembly DLL name such as <literal>myplugin.dll</literal>. The specified @@ -680,10 +692,14 @@ class must implement the <literal>Ice.PluginFactory</literal> interface. Any arguments that follow the class name are passed to the <literal>create</literal> method. </para> +</listitem> +</varlistentry> +</variablelist> +</para> </section> </section> -<section><title>Ice.PluginLoadOrder</title> +<section id="Ice.PluginLoadOrder"><title>Ice.PluginLoadOrder</title> <section><title>Synopsis</title> <synopsis> Ice.PluginLoadOrder=<replaceable>names</replaceable> @@ -702,6 +718,28 @@ order. </section> </section> +<section id="Ice.InitPlugins"><title>Ice.InitPlugins</title> +<section><title>Synopsis</title> +<synopsis> +Ice.InitPlugins=<replaceable>num</replaceable> +</synopsis> +</section> +<section> +<title>Description</title> +<para> +If <replaceable>num</replaceable> is a value greater than zero, the +Ice run time automatically initializes the plugins it has loaded. +The order in which plugins are loaded and initialized is determined +by <link linkend="Ice.PluginLoadOrder">Ice.PluginLoadOrder</link>. +An application may need to set this property to zero in order to +interact directly with a plugin after it has been loaded but before +it is initialized. In this case, the application must invoke +<literal>initializePlugins</literal> on the plugin manager to complete +the initialization process. If not defined, the default value is 1. +</para> +</section> +</section> + </section> <!-- ********************************************************************** --> @@ -1757,25 +1795,6 @@ information. </section> </section> -<section id="IceSSL.DelayInit"><title>IceSSL.DelayInit</title> -<section><title>Synopsis</title> -<synopsis> -IceSSL.DelayInit=<replaceable>num</replaceable> -</synopsis> -</section> -<section> -<title>Description</title> -<para> -If <replaceable>num</replaceable> is a value greater than zero, IceSSL -delays its initialization and waits for the application to indicate -when initialization should proceed. This provides the application with -an opportunity to install callbacks or perform other pre-initialization -steps, such as prompting the user for a password. See the Ice manual -for more information. -</para> -</section> -</section> - <section id="IceSSL.DH"><title>IceSSL.DH.<replaceable>bits</replaceable></title> <section><title>Synopsis</title> <synopsis> diff --git a/cpp/include/IceSSL/Plugin.h b/cpp/include/IceSSL/Plugin.h index 1c4c9a95182..aec6a21c143 100644 --- a/cpp/include/IceSSL/Plugin.h +++ b/cpp/include/IceSSL/Plugin.h @@ -339,13 +339,21 @@ class Plugin : public Ice::Plugin public: // - // Initialize the IceSSL plugin. An application may supply its own - // SSL_CTX objects to configure the SSL contexts for client - // (outgoing) and server (incoming) connections. If an argument is - // nonzero, the plugin skips its normal property-based - // configuration. + // Establish the OpenSSL context. This must be done before the + // plugin is initialized, therefore the application must define + // the property Ice.InitPlugins=0, set the context, and finally + // invoke initializePlugins on the PluginManager. + // + // When the application supplies its own OpenSSL context, the + // plugin skips its normal property-based configuration. // - virtual void initialize(SSL_CTX* context = 0) = 0; + virtual void setContext(SSL_CTX*) = 0; + + // + // Obtain the SSL context. Use caution when modifying this value. + // Changes made to this value have no effect on existing connections. + // + virtual SSL_CTX* getContext() = 0; // // Establish the certificate verifier object. This should be done @@ -358,12 +366,6 @@ public: // the plugin is initialized. // virtual void setPasswordPrompt(const PasswordPromptPtr&) = 0; - - // - // Obtain the SSL context. If you need to customize the context, - // you should do it before any SSL connections are established. - // - virtual SSL_CTX* context() = 0; }; typedef IceUtil::Handle<Plugin> PluginPtr; diff --git a/cpp/slice/Ice/Plugin.ice b/cpp/slice/Ice/Plugin.ice index 17616487e12..79b4ca0e2e1 100644 --- a/cpp/slice/Ice/Plugin.ice +++ b/cpp/slice/Ice/Plugin.ice @@ -18,11 +18,22 @@ module Ice * A communicator plugin. A plugin generally adds a feature to a * communicator, such as support for a protocol. * + * The communicator loads its plugins in two stages: the first stage + * creates the plugins, and the second stage invokes [initialize] on + * each one. + * **/ local interface Plugin { /** * + * Perform any necessary initialization steps. + * + **/ + void initialize(); + + /** + * * Called when the communicator is being destroyed. * **/ @@ -39,6 +50,21 @@ local interface PluginManager { /** * + * Initialize the configured plugins. The communicator automatically initializes + * the plugins by default, but an application may need to interact directly with + * a plugin prior to initialization. In this case, the application must set + * <literal>Ice.InitPlugins=0</literal> and then invoke [initializePlugins] + * manually. The plugins are initialized in the order in which they are loaded. + * If a plugin raises an exception during initialization, the communicator + * invokes destroy on the plugins that have already been initialized. + * + * @throws InitializationException Raised if the plugins have already been initialized. + * + **/ + void initializePlugins(); + + /** + * * Obtain a plugin by name. * * @param name The plugin's name. diff --git a/cpp/src/Ice/PluginManagerI.cpp b/cpp/src/Ice/PluginManagerI.cpp index 7d65df2234c..c5cf4648f0e 100644 --- a/cpp/src/Ice/PluginManagerI.cpp +++ b/cpp/src/Ice/PluginManagerI.cpp @@ -19,10 +19,55 @@ using namespace std; using namespace Ice; using namespace IceInternal; -const char * const Ice::PluginManagerI::_kindOfObject = "plug-in"; +const char * const Ice::PluginManagerI::_kindOfObject = "plugin"; typedef Ice::Plugin* (*PLUGIN_FACTORY)(const CommunicatorPtr&, const string&, const StringSeq&); +void +Ice::PluginManagerI::initializePlugins() +{ + if(_initialized) + { + InitializationException ex(__FILE__, __LINE__); + ex.reason = "plugins already initialized"; + throw ex; + } + + // + // Invoke initialize() on the plugins, in the order they were loaded. + // + vector<PluginPtr> initializedPlugins; + try + { + for(vector<PluginPtr>::iterator p = _initOrder.begin(); p != _initOrder.end(); ++p) + { + (*p)->initialize(); + initializedPlugins.push_back(*p); + } + } + catch(...) + { + // + // Destroy the plugins that have been successfully initialized, in the + // reverse order. + // + for(vector<PluginPtr>::reverse_iterator p = initializedPlugins.rbegin(); p != initializedPlugins.rend(); ++p) + { + try + { + (*p)->destroy(); + } + catch(...) + { + // Ignore. + } + } + throw; + } + + _initialized = true; +} + PluginPtr Ice::PluginManagerI::getPlugin(const string& name) { @@ -88,7 +133,8 @@ Ice::PluginManagerI::destroy() Ice::PluginManagerI::PluginManagerI(const CommunicatorPtr& communicator, const DynamicLibraryListPtr& libraries) : _communicator(communicator), - _libraries(libraries) + _libraries(libraries), + _initialized(false) { } @@ -115,7 +161,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) PropertyDict plugins = properties->getPropertiesForPrefix(prefix); string loadOrder = properties->getProperty("Ice.PluginLoadOrder"); - string::size_type beg = 0;
+ string::size_type beg = 0; if(!loadOrder.empty()) { const string delim = ", \t\n"; @@ -169,6 +215,16 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[]) } stringSeqToArgs(cmdArgs, argc, argv); + + // + // An application can set Ice.InitPlugins=0 if it wants to postpone + // initialization until after it has interacted directly with the + // plugins. + // + if(properties->getPropertyAsIntWithDefault("Ice.InitPlugins", 1) > 0) + { + initializePlugins(); + } } void @@ -253,4 +309,5 @@ Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, St _libraries->add(library); _plugins[name] = plugin; + _initOrder.push_back(plugin); } diff --git a/cpp/src/Ice/PluginManagerI.h b/cpp/src/Ice/PluginManagerI.h index 7b766f95eb8..5a5460c2427 100644 --- a/cpp/src/Ice/PluginManagerI.h +++ b/cpp/src/Ice/PluginManagerI.h @@ -25,6 +25,7 @@ class PluginManagerI : public PluginManager, public IceUtil::Mutex { public: + virtual void initializePlugins(); virtual PluginPtr getPlugin(const std::string&); virtual void addPlugin(const std::string&, const PluginPtr&); virtual void destroy(); @@ -41,6 +42,8 @@ private: IceInternal::DynamicLibraryListPtr _libraries; std::map<std::string, PluginPtr> _plugins; + std::vector<PluginPtr> _initOrder; + bool _initialized; static const char * const _kindOfObject; }; diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp index 2d58eef25f6..002e9720f4a 100644 --- a/cpp/src/Ice/PropertyNames.cpp +++ b/cpp/src/Ice/PropertyNames.cpp @@ -7,7 +7,7 @@ // // ********************************************************************** -// Generated by makeprops.py from file `../config/PropertyNames.def', Mon Apr 17 10:30:14 2006 +// Generated by makeprops.py from file `../config/PropertyNames.def', Tue Apr 25 16:28:52 2006 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -28,6 +28,7 @@ const char* IceInternal::PropertyNames::IceProps[] = "Ice.Default.Protocol", "Ice.Default.Router", "Ice.GC.Interval", + "Ice.InitPlugins", "Ice.Logger.Timestamp", "Ice.MessageSizeMax", "Ice.MonitorConnections", @@ -208,13 +209,10 @@ const char* IceInternal::PropertyNames::IceSSLProps[] = "IceSSL.CertAuthDir", "IceSSL.CertAuthFile", "IceSSL.CertFile", - "IceSSL.Certs", - "IceSSL.CertsPassword", "IceSSL.CheckCertName", "IceSSL.CheckCRL", "IceSSL.Ciphers", "IceSSL.DefaultDir", - "IceSSL.DelayInit", "IceSSL.DH.*", "IceSSL.EntropyDaemon", "IceSSL.ImportCert.*.*", diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h index 98446db0f6a..9f72cdaad0d 100644 --- a/cpp/src/Ice/PropertyNames.h +++ b/cpp/src/Ice/PropertyNames.h @@ -7,7 +7,7 @@ // // ********************************************************************** -// Generated by makeprops.py from file `../config/PropertyNames.def', Mon Apr 17 10:30:14 2006 +// Generated by makeprops.py from file `../config/PropertyNames.def', Tue Apr 25 16:28:52 2006 // IMPORTANT: Do not edit this file -- any edits made here will be lost! diff --git a/cpp/test/IceSSL/configuration/AllTests.cpp b/cpp/test/IceSSL/configuration/AllTests.cpp index ae47f324d43..22254f58e65 100644 --- a/cpp/test/IceSSL/configuration/AllTests.cpp +++ b/cpp/test/IceSSL/configuration/AllTests.cpp @@ -157,7 +157,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir) { InitializationData initData; initData.properties = createClientProps(defaultHost); - initData.properties->setProperty("IceSSL.DelayInit", "1"); + initData.properties->setProperty("Ice.InitPlugins", "0"); CommunicatorPtr comm = initialize(argc, argv, initData); ObjectPrx p = comm->stringToProxy("dummy:ssl -p 9999"); try @@ -178,13 +178,12 @@ allTests(const CommunicatorPtr& communicator, const string& testDir) { InitializationData initData; initData.properties = createClientProps(defaultHost); - initData.properties->setProperty("IceSSL.DelayInit", "1"); + initData.properties->setProperty("Ice.InitPlugins", "0"); initData.properties->setProperty("IceSSL.Ciphers", "ADH"); initData.properties->setProperty("IceSSL.VerifyPeer", "0"); CommunicatorPtr comm = initialize(argc, argv, initData); - IceSSL::PluginPtr plugin = IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); - test(plugin); - plugin->initialize(); + PluginManagerPtr pm = comm->getPluginManager(); + pm->initializePlugins(); ObjectPrx obj = comm->stringToProxy(factoryRef); test(obj); Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(obj); @@ -486,8 +485,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir) initData.properties->setProperty("IceSSL.Ciphers", "ADH"); initData.properties->setProperty("IceSSL.VerifyPeer", "0"); CommunicatorPtr comm = initialize(argc, argv, initData); - IceSSL::PluginPtr plugin = - IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); + IceSSL::PluginPtr plugin = IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); test(plugin); CertificateVerifierIPtr verifier = new CertificateVerifierI; plugin->setCertificateVerifier(verifier); @@ -550,8 +548,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir) initData.properties->setProperty("IceSSL.KeyFile", "c_rsa_nopass_ca1_priv.pem"); initData.properties->setProperty("IceSSL.VerifyPeer", "0"); CommunicatorPtr comm = initialize(argc, argv, initData); - IceSSL::PluginPtr plugin = - IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); + IceSSL::PluginPtr plugin = IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); test(plugin); CertificateVerifierIPtr verifier = new CertificateVerifierI; plugin->setCertificateVerifier(verifier); @@ -779,14 +776,14 @@ allTests(const CommunicatorPtr& communicator, const string& testDir) initData.properties->setProperty("IceSSL.DefaultDir", defaultDir); initData.properties->setProperty("IceSSL.CertFile", "c_rsa_pass_ca1_pub.pem"); initData.properties->setProperty("IceSSL.KeyFile", "c_rsa_pass_ca1_priv.pem"); - initData.properties->setProperty("IceSSL.DelayInit", "1"); + initData.properties->setProperty("Ice.InitPlugins", "0"); CommunicatorPtr comm = initialize(argc, argv, initData); - IceSSL::PluginPtr plugin = - IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); + PluginManagerPtr pm = comm->getPluginManager(); + IceSSL::PluginPtr plugin = IceSSL::PluginPtr::dynamicCast(pm->getPlugin("IceSSL")); test(plugin); PasswordPromptIPtr prompt = new PasswordPromptI("client"); plugin->setPasswordPrompt(prompt); - plugin->initialize(); + pm->initializePlugins(); test(prompt->count() == 1); Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(comm->stringToProxy(factoryRef)); test(fact); @@ -815,15 +812,16 @@ allTests(const CommunicatorPtr& communicator, const string& testDir) initData.properties->setProperty("IceSSL.CertFile", "c_rsa_pass_ca1_pub.pem"); initData.properties->setProperty("IceSSL.KeyFile", "c_rsa_pass_ca1_priv.pem"); initData.properties->setProperty("IceSSL.PasswordRetryMax", "4"); - initData.properties->setProperty("IceSSL.DelayInit", "1"); + initData.properties->setProperty("Ice.InitPlugins", "0"); comm = initialize(argc, argv, initData); - plugin = IceSSL::PluginPtr::dynamicCast(comm->getPluginManager()->getPlugin("IceSSL")); + pm = comm->getPluginManager(); + plugin = IceSSL::PluginPtr::dynamicCast(pm->getPlugin("IceSSL")); test(plugin); prompt = new PasswordPromptI("invalid"); plugin->setPasswordPrompt(prompt); try { - plugin->initialize(); + pm->initializePlugins(); } catch(const PluginInitializationException&) { |