summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2006-04-26 03:22:49 +0000
committerMark Spruiell <mes@zeroc.com>2006-04-26 03:22:49 +0000
commitd24b35ce1f999f86c6f856821d51f4adf72c76e6 (patch)
treeb1d1dbe50724a4d42ce1e46622aa49fde0a5492d /cpp
parentuse two stages for plugin initialization; refactoring to remove Context (diff)
downloadice-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.def4
-rw-r--r--cpp/doc/Properties.sgml73
-rw-r--r--cpp/include/IceSSL/Plugin.h26
-rw-r--r--cpp/slice/Ice/Plugin.ice26
-rw-r--r--cpp/src/Ice/PluginManagerI.cpp63
-rw-r--r--cpp/src/Ice/PluginManagerI.h3
-rw-r--r--cpp/src/Ice/PropertyNames.cpp6
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/test/IceSSL/configuration/AllTests.cpp30
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&)
{