summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2012-08-16 15:58:01 +0200
committerJose <jose@zeroc.com>2012-08-16 15:58:01 +0200
commit0b82edbd44b61ab36592f73728e76d1fd11a3aa2 (patch)
tree8f8a0b6d5cb22a95dfc4b2c257d0eb7c0fe62c9b
parentICE-4820 - Service class public API (diff)
downloadice-0b82edbd44b61ab36592f73728e76d1fd11a3aa2.tar.bz2
ice-0b82edbd44b61ab36592f73728e76d1fd11a3aa2.tar.xz
ice-0b82edbd44b61ab36592f73728e76d1fd11a3aa2.zip
ICE-4609 - Add ability to load shared library with full path
- C++/Java now also support to load Services and Plugins from a full path, this was already supported by .NET - Fixed the parsing of plug-in arguments to correct split the arguments - Fixed Plugin manager destroy C++/Java/C#, the plugin must are now destroyed in initialization reverse order as documented.
-rwxr-xr-xcpp/allTests.py1
-rw-r--r--cpp/src/Ice/DynamicLibrary.cpp58
-rw-r--r--cpp/src/Ice/PluginManagerI.cpp119
-rw-r--r--cpp/src/Ice/PluginManagerI.h14
-rw-r--r--cpp/src/IceBox/ServiceManagerI.cpp99
-rw-r--r--cpp/test/Ice/Makefile3
-rw-r--r--cpp/test/Ice/Makefile.mak1
-rw-r--r--cpp/test/Ice/plugin/.depend1
-rw-r--r--cpp/test/Ice/plugin/.depend.mak1
-rw-r--r--cpp/test/Ice/plugin/.gitignore7
-rw-r--r--cpp/test/Ice/plugin/Client.cpp187
-rw-r--r--cpp/test/Ice/plugin/Makefile51
-rw-r--r--cpp/test/Ice/plugin/Makefile.mak68
-rw-r--r--cpp/test/Ice/plugin/Plugin.cpp404
-rw-r--r--cpp/test/Ice/plugin/plugins/.gitignore0
-rwxr-xr-xcpp/test/Ice/plugin/run.py25
-rw-r--r--cpp/test/WinRT/TestSuite/MainPage.xaml.cpp3
-rwxr-xr-xcs/allTests.py1
-rw-r--r--cs/src/Ice/PluginManagerI.cs182
-rw-r--r--cs/src/IceBox/ServiceManagerI.cs120
-rw-r--r--cs/test/Ice/Makefile3
-rw-r--r--cs/test/Ice/Makefile.mak3
-rw-r--r--cs/test/Ice/plugin/.depend0
-rw-r--r--cs/test/Ice/plugin/.depend.mak0
-rw-r--r--cs/test/Ice/plugin/BasePlugin.cs44
-rw-r--r--cs/test/Ice/plugin/BasePluginFail.cs48
-rw-r--r--cs/test/Ice/plugin/Client.cs179
-rw-r--r--cs/test/Ice/plugin/Makefile41
-rw-r--r--cs/test/Ice/plugin/Makefile.mak38
-rw-r--r--cs/test/Ice/plugin/PluginFactory.cs64
-rw-r--r--cs/test/Ice/plugin/PluginInitializeFailException.cs15
-rw-r--r--cs/test/Ice/plugin/PluginInitializeFailFactory.cs37
-rw-r--r--cs/test/Ice/plugin/PluginOneFactory.cs36
-rw-r--r--cs/test/Ice/plugin/PluginOneFailFactory.cs56
-rw-r--r--cs/test/Ice/plugin/PluginThreeFactory.cs36
-rw-r--r--cs/test/Ice/plugin/PluginThreeFailFactory.cs47
-rw-r--r--cs/test/Ice/plugin/PluginTwoFactory.cs36
-rw-r--r--cs/test/Ice/plugin/PluginTwoFailFactory.cs56
-rwxr-xr-xcs/test/Ice/plugin/client.exe.config6
-rw-r--r--cs/test/Ice/plugin/plugins/.gitignore0
-rwxr-xr-xcs/test/Ice/plugin/run.py30
-rwxr-xr-xjava/allTests.py1
-rw-r--r--java/build.xml10
-rw-r--r--java/src/Ice/PluginManagerI.java248
-rw-r--r--java/src/IceBox/ServiceManagerI.java166
-rw-r--r--java/src/IceInternal/Instance.java2
-rw-r--r--java/src/IceInternal/Util.java1
-rw-r--r--java/test/Ice/plugin/Client.java197
-rw-r--r--java/test/Ice/plugin/plugins/BasePlugin.java41
-rw-r--r--java/test/Ice/plugin/plugins/BasePluginFail.java45
-rw-r--r--java/test/Ice/plugin/plugins/PluginFactory.java73
-rw-r--r--java/test/Ice/plugin/plugins/PluginInitializeFailException.java18
-rw-r--r--java/test/Ice/plugin/plugins/PluginInitializeFailFactory.java39
-rw-r--r--java/test/Ice/plugin/plugins/PluginOneFactory.java39
-rw-r--r--java/test/Ice/plugin/plugins/PluginOneFailFactory.java64
-rw-r--r--java/test/Ice/plugin/plugins/PluginThreeFactory.java39
-rw-r--r--java/test/Ice/plugin/plugins/PluginThreeFailFactory.java55
-rw-r--r--java/test/Ice/plugin/plugins/PluginTwoFactory.java39
-rw-r--r--java/test/Ice/plugin/plugins/PluginTwoFailFactory.java64
-rwxr-xr-xjava/test/Ice/plugin/run.py29
60 files changed, 2939 insertions, 351 deletions
diff --git a/cpp/allTests.py b/cpp/allTests.py
index f124bf519bd..d3107df594f 100755
--- a/cpp/allTests.py
+++ b/cpp/allTests.py
@@ -66,6 +66,7 @@ tests = [
("Ice/defaultServant", ["core"]),
("Ice/defaultValue", ["core"]),
("Ice/invoke", ["core", "novc6"]),
+ ("Ice/plugin", ["core"]),
("Ice/hash", ["once"]),
("IceSSL/configuration", ["once", "novalgrind"]), # valgrind doesn't work well with openssl
("IceBox/configuration", ["core", "noipv6", "novc6", "nomingw"]),
diff --git a/cpp/src/Ice/DynamicLibrary.cpp b/cpp/src/Ice/DynamicLibrary.cpp
index 5b690df5f2b..ab724a9847a 100644
--- a/cpp/src/Ice/DynamicLibrary.cpp
+++ b/cpp/src/Ice/DynamicLibrary.cpp
@@ -50,7 +50,28 @@ IceInternal::DynamicLibrary::~DynamicLibrary()
IceInternal::DynamicLibrary::symbol_type
IceInternal::DynamicLibrary::loadEntryPoint(const string& entryPoint, bool useIceVersion)
{
+
+#ifdef _WIN32
+ bool isFilePath = entryPoint.find('\\') != string::npos || entryPoint.find('/') != string::npos;
+#else
+ bool isFilePath = entryPoint.find('/') != string::npos;
+#endif
+
string::size_type colon = entryPoint.rfind(':');
+
+#ifdef _WIN32
+ const string driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if(colon == 1 && driveLetters.find(entryPoint[0]) != string::npos &&
+ (entryPoint[2] == '\\' || entryPoint[2] == '/'))
+ {
+ //
+ // The only colon we found is in the drive specification, as in "C:\MyDir".
+ // This means the function name is missing.
+ //
+ colon = string::npos;
+ }
+#endif
+
string::size_type comma = entryPoint.find(',');
if(colon == string::npos || colon == entryPoint.size() - 1 ||
(comma != string::npos && (comma > colon || comma == colon - 1)))
@@ -58,9 +79,22 @@ IceInternal::DynamicLibrary::loadEntryPoint(const string& entryPoint, bool useIc
_err = "invalid entry point format `" + entryPoint + "'";
return 0;
}
+
string libSpec = entryPoint.substr(0, colon);
string funcName = entryPoint.substr(colon + 1);
- string libName, version, debug;
+ string libPath, libName, version, debug;
+
+ if(isFilePath)
+ {
+#ifdef _WIN32
+ string::size_type separator = entryPoint.find_last_of("/\\");
+#else
+ string::size_type separator = entryPoint.rfind('/');
+#endif
+ libPath = libSpec.substr(0, separator + 1);
+ libSpec = libSpec.substr(separator + 1);
+ }
+
if(comma == string::npos)
{
libName = libSpec;
@@ -70,7 +104,7 @@ IceInternal::DynamicLibrary::loadEntryPoint(const string& entryPoint, bool useIc
int minorVersion = (ICE_INT_VERSION / 100) - majorVersion * 100;
ostringstream os;
os << majorVersion * 10 + minorVersion;
-
+
int patchVersion = ICE_INT_VERSION % 100;
if(patchVersion > 50)
{
@@ -89,10 +123,10 @@ IceInternal::DynamicLibrary::loadEntryPoint(const string& entryPoint, bool useIc
version = libSpec.substr(comma + 1);
}
- string lib;
+ string lib = libPath;
#ifdef _WIN32
- lib = libName;
+ lib += libName;
# ifdef COMPSUFFIX
//
@@ -114,13 +148,13 @@ IceInternal::DynamicLibrary::loadEntryPoint(const string& entryPoint, bool useIc
lib += ".dll";
#elif defined(__APPLE__)
- lib = "lib" + libName;
- if(!version.empty())
+ lib += "lib" + libName;
+ if(!version.empty())
{
lib += "." + version;
}
#elif defined(__hpux)
- lib = "lib" + libName;
+ lib += "lib" + libName;
if(!version.empty())
{
lib += "." + version;
@@ -130,14 +164,14 @@ IceInternal::DynamicLibrary::loadEntryPoint(const string& entryPoint, bool useIc
lib += ".sl";
}
#elif defined(_AIX)
- lib = "lib" + libName + ".a(lib" + libName + ".so";
+ lib += "lib" + libName + ".a(lib" + libName + ".so";
if(!version.empty())
{
lib += "." + version;
}
lib += ")";
#else
- lib = "lib" + libName + ".so";
+ lib += "lib" + libName + ".so";
if(!version.empty())
{
lib += "." + version;
@@ -217,16 +251,16 @@ IceInternal::DynamicLibrary::getSymbol(const string& name)
#else
symbol_type result = dlsym(_hnd, name.c_str());
#endif
-
+
if(result == 0)
{
//
// Remember the most recent error in _err.
//
#ifdef _WIN32
- _err = IceUtilInternal::lastErrorToString();
+ _err = IceUtilInternal::lastErrorToString();
#else
- const char* err = dlerror();
+ const char* err = dlerror();
if(err)
{
_err = err;
diff --git a/cpp/src/Ice/PluginManagerI.cpp b/cpp/src/Ice/PluginManagerI.cpp
index 513a3036ea6..bb2bcd37959 100644
--- a/cpp/src/Ice/PluginManagerI.cpp
+++ b/cpp/src/Ice/PluginManagerI.cpp
@@ -7,6 +7,7 @@
//
// **********************************************************************
+#include <IceUtil/Options.h>
#include <Ice/PluginManagerI.h>
#include <Ice/DynamicLibrary.h>
#include <Ice/Communicator.h>
@@ -40,10 +41,10 @@ Ice::PluginManagerI::initializePlugins()
vector<PluginPtr> initializedPlugins;
try
{
- for(vector<PluginPtr>::iterator p = _initOrder.begin(); p != _initOrder.end(); ++p)
+ for(PluginInfoList::iterator p = _plugins.begin(); p != _plugins.end(); ++p)
{
- (*p)->initialize();
- initializedPlugins.push_back(*p);
+ p->plugin->initialize();
+ initializedPlugins.push_back(p->plugin);
}
}
catch(...)
@@ -75,10 +76,9 @@ Ice::PluginManagerI::getPlugins()
IceUtil::Mutex::Lock sync(*this);
StringSeq names;
- map<string, PluginPtr>::iterator r;
- for(r = _plugins.begin(); r != _plugins.end(); ++r)
+ for(PluginInfoList::iterator p = _plugins.begin(); p != _plugins.end(); ++p)
{
- names.push_back((*r).first);
+ names.push_back(p->name);
}
return names;
}
@@ -93,10 +93,10 @@ Ice::PluginManagerI::getPlugin(const string& name)
throw CommunicatorDestroyedException(__FILE__, __LINE__);
}
- map<string, PluginPtr>::const_iterator r = _plugins.find(name);
- if(r != _plugins.end())
+ PluginPtr p = findPlugin(name);
+ if(p)
{
- return (*r).second;
+ return p;
}
NotRegisteredException ex(__FILE__, __LINE__);
@@ -115,15 +115,18 @@ Ice::PluginManagerI::addPlugin(const string& name, const PluginPtr& plugin)
throw CommunicatorDestroyedException(__FILE__, __LINE__);
}
- map<string, PluginPtr>::const_iterator r = _plugins.find(name);
- if(r != _plugins.end())
+ if(findPlugin(name))
{
AlreadyRegisteredException ex(__FILE__, __LINE__);
ex.kindOfObject = _kindOfObject;
ex.id = name;
throw ex;
}
- _plugins[name] = plugin;
+
+ PluginInfo info;
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.push_back(info);
}
void
@@ -135,40 +138,44 @@ Ice::PluginManagerI::destroy()
{
if(_initialized)
{
- map<string, PluginPtr>::iterator r;
- for(r = _plugins.begin(); r != _plugins.end(); ++r)
+
+ //
+ // Destroy the plug-ins that have been successfully initialized, in the
+ // reverse order.
+ //
+ for(PluginInfoList::reverse_iterator p = _plugins.rbegin(); p != _plugins.rend(); ++p)
{
try
{
- r->second->destroy();
- r->second = 0;
+ p->plugin->destroy();
}
catch(const std::exception& ex)
{
Warning out(getProcessLogger());
- out << "unexpected exception raised by plug-in `" << r->first << "' destruction:\n" << ex.what();
+ out << "unexpected exception raised by plug-in `" << p->name << "' destruction:\n" << ex.what();
}
catch(const std::string& str)
{
Warning out(getProcessLogger());
- out << "unexpected exception raised by plug-in `" << r->first << "' destruction:\n" << str;
+ out << "unexpected exception raised by plug-in `" << p->name << "' destruction:\n" << str;
}
catch(const char* msg)
{
Warning out(getProcessLogger());
- out << "unexpected exception raised by plug-in `" << r->first << "' destruction:\n" << msg;
+ out << "unexpected exception raised by plug-in `" << p->name << "' destruction:\n" << msg;
}
catch(...)
{
Warning out(getProcessLogger());
- out << "unexpected exception raised by plug-in `" << r->first << "' destruction";
+ out << "unexpected exception raised by plug-in `" << p->name << "' destruction";
}
}
}
-
+
_communicator = 0;
}
+ _plugins.clear();
_libraries = 0;
}
@@ -206,7 +213,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[])
{
string name = *p;
- if(_plugins.find(name) != _plugins.end())
+ if(findPlugin(name))
{
PluginInitializationException ex(__FILE__, __LINE__);
ex.reason = "plug-in `" + name + "' already loaded";
@@ -239,7 +246,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[])
//
// Load any remaining plug-ins that weren't specified in PluginLoadOrder.
//
-
+
while(!plugins.empty())
{
PropertyDict::iterator p = plugins.begin();
@@ -262,7 +269,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[])
name = name.substr(0, dotPos);
loadPlugin(name, p->second, cmdArgs);
plugins.erase(p);
-
+
plugins.erase("Ice.Plugin." + name);
}
else
@@ -273,7 +280,7 @@ Ice::PluginManagerI::loadPlugins(int& argc, char* argv[])
dotPos = string::npos;
}
}
-
+
if(dotPos == string::npos)
{
//
@@ -299,36 +306,29 @@ Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, St
{
assert(_communicator);
//
- // Separate the entry point from the arguments.
+ // Split the entire property value into arguments. An entry point containing spaces
+ // must be enclosed in quotes.
//
- string entryPoint;
StringSeq args;
- const string delim = " \t\n";
- string::size_type pos = pluginSpec.find_first_of(delim);
- if(pos == string::npos)
+ try
{
- entryPoint = pluginSpec;
+ args = IceUtilInternal::Options::split(pluginSpec);
}
- else
+ catch(const IceUtilInternal::BadOptException& ex)
{
- entryPoint = pluginSpec.substr(0, pos);
- string::size_type beg = pluginSpec.find_first_not_of(delim, pos);
- while(beg != string::npos)
- {
- string::size_type end = pluginSpec.find_first_of(delim, beg);
- if(end == string::npos)
- {
- args.push_back(pluginSpec.substr(beg));
- beg = end;
- }
- else
- {
- args.push_back(pluginSpec.substr(beg, end - beg));
- beg = pluginSpec.find_first_not_of(delim, end);
- }
- }
+ PluginInitializationException e(__FILE__, __LINE__);
+ e.reason = "invalid arguments for plug-in `" + name + "':\n" + ex.reason;
+ throw e;
}
+ assert(!args.empty());
+
+ //
+ // Shift the arguments.
+ //
+ const string entryPoint = args[0];
+ args.erase(args.begin());
+
//
// Convert command-line options into properties. First we
// convert the options from the plug-in configuration, then
@@ -373,15 +373,30 @@ Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, St
throw e;
}
- _plugins[name] = plugin;
- _initOrder.push_back(plugin);
+ PluginInfo info;
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.push_back(info);
_libraries->add(library);
}
+Ice::PluginPtr
+Ice::PluginManagerI::findPlugin(const string& name) const
+{
+ for(PluginInfoList::const_iterator p = _plugins.begin(); p != _plugins.end(); ++p)
+ {
+ if(name == p->name)
+ {
+ return p->plugin;
+ }
+ }
+ return 0;
+}
+
void
-IceInternal::loadPlugin(const Ice::CommunicatorPtr& communicator,
- const string& name,
+IceInternal::loadPlugin(const Ice::CommunicatorPtr& communicator,
+ const string& name,
const string& pluginSpec,
Ice::StringSeq& cmdArgs)
{
diff --git a/cpp/src/Ice/PluginManagerI.h b/cpp/src/Ice/PluginManagerI.h
index ecb73fa3a43..a7b7578ebaa 100644
--- a/cpp/src/Ice/PluginManagerI.h
+++ b/cpp/src/Ice/PluginManagerI.h
@@ -41,17 +41,25 @@ private:
PluginManagerI(const CommunicatorPtr&, const IceInternal::DynamicLibraryListPtr&);
friend class IceInternal::Instance;
- friend void IceInternal::loadPlugin(const Ice::CommunicatorPtr&, const std::string&, const std::string&,
+ 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&);
+ PluginPtr findPlugin(const std::string&) const;
+
CommunicatorPtr _communicator;
IceInternal::DynamicLibraryListPtr _libraries;
- std::map<std::string, PluginPtr> _plugins;
- std::vector<PluginPtr> _initOrder;
+ struct PluginInfo
+ {
+ std::string name;
+ PluginPtr plugin;
+ };
+ typedef std::vector<PluginInfo> PluginInfoList;
+
+ PluginInfoList _plugins;
bool _initialized;
static const char * const _kindOfObject;
};
diff --git a/cpp/src/IceBox/ServiceManagerI.cpp b/cpp/src/IceBox/ServiceManagerI.cpp
index 60f0959dcb5..f91e9cd8da2 100644
--- a/cpp/src/IceBox/ServiceManagerI.cpp
+++ b/cpp/src/IceBox/ServiceManagerI.cpp
@@ -22,18 +22,18 @@ using namespace std;
typedef IceBox::Service* (*SERVICE_FACTORY)(CommunicatorPtr);
-namespace
+namespace
{
class PropertiesAdminI : public PropertiesAdmin
{
public:
-
+
PropertiesAdminI(const PropertiesPtr& properties) :
_properties(properties)
{
}
-
+
virtual string getProperty(const string& name, const Current&)
{
return _properties->getProperty(name);
@@ -43,10 +43,10 @@ public:
{
return _properties->getPropertiesForPrefix(prefix);
}
-
+
private:
- const PropertiesPtr _properties;
+ const PropertiesPtr _properties;
};
struct StartServiceInfo
@@ -56,28 +56,28 @@ struct StartServiceInfo
name = service;
//
- // Separate the entry point from the arguments.
+ // Split the entire property value into arguments. An entry point containing spaces
+ // must be enclosed in quotes.
//
- string::size_type pos = value.find_first_of(" \t\n");
- if(pos == string::npos)
+ try
{
- entryPoint = value;
+ args = IceUtilInternal::Options::split(value);
}
- else
+ catch(const IceUtilInternal::BadOptException& ex)
{
- entryPoint = value.substr(0, pos);
- try
- {
- args = IceUtilInternal::Options::split(value.substr(pos + 1));
- }
- catch(const IceUtilInternal::BadOptException& ex)
- {
- FailureException e(__FILE__, __LINE__);
- e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.reason;
- throw e;
- }
+ PluginInitializationException e(__FILE__, __LINE__);
+ e.reason = "invalid arguments for service `" + name + "':\n" + ex.reason;
+ throw e;
}
+ assert(!args.empty());
+
+ //
+ // Shift the arguments.
+ //
+ entryPoint = args[0];
+ args.erase(args.begin());
+
for(Ice::StringSeq::const_iterator p = serverArgs.begin(); p != serverArgs.end(); ++p)
{
if(p->find("--" + name + ".") == 0)
@@ -92,10 +92,9 @@ struct StartServiceInfo
Ice::StringSeq args;
};
-
}
-IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) :
+IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) :
_communicator(communicator),
_pendingStatusChanges(false),
_traceServiceObserver(0),
@@ -169,7 +168,7 @@ IceBox::ServiceManagerI::startService(const string& name, const Current&)
Warning out(_logger);
out << "ServiceManager: unknown exception in start for service " << info.name;
}
-
+
{
IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
@@ -290,7 +289,7 @@ IceBox::ServiceManagerI::addObserver(const ServiceObserverPrx& observer, const I
{
Trace out(_logger, "IceBox.ServiceObserver");
out << "Added service observer " << _communicator->proxyToString(observer);
- }
+ }
vector<string> activeServices;
for(vector<ServiceInfo>::iterator p = _services.begin(); p != _services.end(); ++p)
@@ -301,7 +300,7 @@ IceBox::ServiceManagerI::addObserver(const ServiceObserverPrx& observer, const I
activeServices.push_back(info.name);
}
}
-
+
if(activeServices.size() > 0)
{
observer->begin_servicesStarted(activeServices, _observerCompletedCB);
@@ -345,7 +344,7 @@ IceBox::ServiceManagerI::start()
//
// IceBox.Service.Foo=entry_point [args]
//
- // We parse the service properties specified in IceBox.LoadOrder
+ // We parse the service properties specified in IceBox.LoadOrder
// first, then the ones from remaining services.
//
const string prefix = "IceBox.Service.";
@@ -369,7 +368,7 @@ IceBox::ServiceManagerI::start()
{
servicesInfo.push_back(StartServiceInfo(p->first.substr(prefix.size()), p->second, _argv));
}
-
+
//
// Check if some services are using the shared communicator in which
// case we create the shared communicator now with a property set which
@@ -416,12 +415,12 @@ IceBox::ServiceManagerI::start()
{
initData.properties->setProperty(r->first, r->second);
}
-
+
//
- // Parse <service>.* command line options (the Ice command line options
+ // Parse <service>.* command line options (the Ice command line options
// were parsed by the createProperties above)
//
- q->args = initData.properties->parseCommandLineOptions(q->name, q->args);
+ q->args = initData.properties->parseCommandLineOptions(q->name, q->args);
}
_sharedCommunicator = initialize(initData);
}
@@ -462,7 +461,7 @@ IceBox::ServiceManagerI::start()
//
// Add a Properties facet for each service
- //
+ //
for(vector<ServiceInfo>::iterator r = _services.begin(); r != _services.end(); ++r)
{
const ServiceInfo& info = *r;
@@ -470,7 +469,7 @@ IceBox::ServiceManagerI::start()
_communicator->addAdminFacet(new PropertiesAdminI(communicator->getProperties()),
"IceBox.Service." + info.name + ".Properties");
}
-
+
_communicator->getAdmin();
}
catch(const ObjectAdapterDeactivatedException&)
@@ -611,7 +610,7 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
communicator = _sharedCommunicator;
}
else
- {
+ {
//
// Create the service properties. We use the communicator properties as the default
// properties if IceBox.InheritProperties is set.
@@ -627,25 +626,25 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
initData.properties = createProperties(info.args, initData.properties);
//
- // Next, parse the service "<service>.*" command line options (the Ice command
+ // Next, parse the service "<service>.*" command line options (the Ice command
// line options were parsed by the createProperties above)
//
info.args = initData.properties->parseCommandLineOptions(service, info.args);
}
-
+
//
// Clone the logger to assign a new prefix.
//
initData.logger = _logger->cloneWithPrefix(initData.properties->getProperty("Ice.ProgramName"));
-
+
//
- // Remaining command line options are passed to the communicator. This is
+ // Remaining command line options are passed to the communicator. This is
// necessary for Ice plug-in properties (e.g.: IceSSL).
//
info.communicator = initialize(info.args, initData);
communicator = info.communicator;
}
-
+
//
// Start the service.
//
@@ -656,8 +655,8 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint,
//
// There is no need to notify the observers since the 'start all'
- // (that indirectly calls this function) occurs before the creation of
- // the Server Admin object, and before the activation of the main
+ // (that indirectly calls this function) occurs before the creation of
+ // the Server Admin object, and before the activation of the main
// object adapter (so before any observer can be registered)
//
}
@@ -750,7 +749,7 @@ IceBox::ServiceManagerI::stopAll()
vector<string> stoppedServices;
//
- // First, for each service, we call stop on the service and flush its database environment to
+ // First, for each service, we call stop on the service and flush its database environment to
// the disk.
//
for(p = _services.rbegin(); p != _services.rend(); ++p)
@@ -782,7 +781,7 @@ IceBox::ServiceManagerI::stopAll()
for(p = _services.rbegin(); p != _services.rend(); ++p)
{
ServiceInfo& info = *p;
-
+
try
{
_communicator->removeAdminFacet("IceBox.Service." + info.name + ".Properties");
@@ -815,9 +814,9 @@ IceBox::ServiceManagerI::stopAll()
}
//
- // Release the service, the service communicator and then the library. The order is important,
+ // Release the service, the service communicator and then the library. The order is important,
// the service must be released before destroying the communicator so that the communicator
- // leak detector doesn't report potential leaks, and the communicator must be destroyed before
+ // leak detector doesn't report potential leaks, and the communicator must be destroyed before
// the library is released since the library will destroy its global state.
//
try
@@ -850,7 +849,7 @@ IceBox::ServiceManagerI::stopAll()
out << ex;
}
}
-
+
try
{
info.library = 0;
@@ -915,7 +914,7 @@ IceBox::ServiceManagerI::servicesStopped(const vector<string>& services, const s
void
IceBox::ServiceManagerI::observerRemoved(const ServiceObserverPrx& observer, const std::exception& ex)
-{
+{
if(_traceServiceObserver >= 1)
{
//
@@ -929,8 +928,8 @@ IceBox::ServiceManagerI::observerRemoved(const ServiceObserverPrx& observer, con
out << "Removed service observer " << _communicator->proxyToString(observer)
<< "\nafter catching " << ex.what();
}
- }
-}
+ }
+}
Ice::PropertiesPtr
IceBox::ServiceManagerI::createServiceProperties(const string& service)
@@ -946,7 +945,7 @@ IceBox::ServiceManagerI::createServiceProperties(const string& service)
{
properties = createProperties();
}
-
+
string programName = communicatorProperties->getProperty("Ice.ProgramName");
if(programName.empty())
{
diff --git a/cpp/test/Ice/Makefile b/cpp/test/Ice/Makefile
index 15092758312..ea2d27fe5fa 100644
--- a/cpp/test/Ice/Makefile
+++ b/cpp/test/Ice/Makefile
@@ -42,7 +42,8 @@ SUBDIRS = proxy \
defaultValue \
threadPoolPriority \
invoke \
- properties
+ properties \
+ plugin
$(EVERYTHING)::
@for subdir in $(SUBDIRS); \
diff --git a/cpp/test/Ice/Makefile.mak b/cpp/test/Ice/Makefile.mak
index eaa8112b30a..dfd91c1bda1 100644
--- a/cpp/test/Ice/Makefile.mak
+++ b/cpp/test/Ice/Makefile.mak
@@ -29,6 +29,7 @@ SUBDIRS = proxy \
retry \
timeout \
udp \
+ plugin \
stream
!if "$(WINRT)" != "yes"
diff --git a/cpp/test/Ice/plugin/.depend b/cpp/test/Ice/plugin/.depend
new file mode 100644
index 00000000000..1d479e875ec
--- /dev/null
+++ b/cpp/test/Ice/plugin/.depend
@@ -0,0 +1 @@
+Plugin$(OBJEXT): Plugin.cpp $(includedir)/Ice/Ice.h $(includedir)/Ice/Initialize.h $(includedir)/Ice/CommunicatorF.h $(includedir)/Ice/LocalObjectF.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/Ice/Handle.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/IceUtil/ScopedArray.h $(includedir)/Ice/UndefSysMacros.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Proxy.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsync.h $(includedir)/IceUtil/Monitor.h $(includedir)/IceUtil/Cond.h $(includedir)/IceUtil/Timer.h $(includedir)/IceUtil/Thread.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/InstanceF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/BasicStream.h $(includedir)/Ice/ObjectFactoryF.h $(includedir)/Ice/Buffer.h $(includedir)/Ice/Protocol.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/Object.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/LoggerF.h $(includedir)/Ice/StatsF.h $(includedir)/Ice/Dispatcher.h $(includedir)/Ice/StringConverter.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/BuiltinSequences.h $(includedir)/Ice/Stream.h $(includedir)/IceUtil/Unicode.h $(includedir)/Ice/LocalException.h $(includedir)/Ice/Properties.h $(includedir)/Ice/Outgoing.h $(includedir)/Ice/Incoming.h $(includedir)/Ice/ServantLocatorF.h $(includedir)/Ice/ServantManagerF.h $(includedir)/Ice/Direct.h $(includedir)/Ice/Logger.h $(includedir)/Ice/LoggerUtil.h $(includedir)/Ice/Stats.h $(includedir)/Ice/Communicator.h $(includedir)/Ice/RouterF.h $(includedir)/Ice/LocatorF.h $(includedir)/Ice/PluginF.h $(includedir)/Ice/ImplicitContextF.h $(includedir)/Ice/CommunicatorAsync.h $(includedir)/Ice/ObjectFactory.h $(includedir)/Ice/ObjectAdapter.h $(includedir)/Ice/FacetMap.h $(includedir)/Ice/Endpoint.h $(includedir)/Ice/ServantLocator.h $(includedir)/Ice/IncomingAsync.h $(includedir)/Ice/Process.h $(includedir)/Ice/Application.h $(includedir)/Ice/Connection.h $(includedir)/Ice/ConnectionAsync.h $(includedir)/Ice/Functional.h $(includedir)/IceUtil/Functional.h $(includedir)/Ice/ImplicitContext.h $(includedir)/Ice/Locator.h $(includedir)/Ice/FactoryTableInit.h $(includedir)/Ice/FactoryTable.h $(includedir)/Ice/UserExceptionFactory.h $(includedir)/Ice/ProcessF.h $(includedir)/Ice/Router.h $(includedir)/Ice/DispatchInterceptor.h $(includedir)/Ice/IconvStringConverter.h ../../include/TestCommon.h
diff --git a/cpp/test/Ice/plugin/.depend.mak b/cpp/test/Ice/plugin/.depend.mak
new file mode 100644
index 00000000000..e02b2718caf
--- /dev/null
+++ b/cpp/test/Ice/plugin/.depend.mak
@@ -0,0 +1 @@
+Plugin$(OBJEXT): Plugin.cpp "$(includedir)/Ice/Ice.h" "$(includedir)/Ice/Initialize.h" "$(includedir)/Ice/CommunicatorF.h" "$(includedir)/Ice/LocalObjectF.h" "$(includedir)/IceUtil/Shared.h" "$(includedir)/IceUtil/Config.h" "$(includedir)/Ice/Handle.h" "$(includedir)/IceUtil/Handle.h" "$(includedir)/IceUtil/Exception.h" "$(includedir)/Ice/Config.h" "$(includedir)/Ice/ProxyF.h" "$(includedir)/Ice/ProxyHandle.h" "$(includedir)/Ice/ObjectF.h" "$(includedir)/Ice/Exception.h" "$(includedir)/Ice/LocalObject.h" "$(includedir)/IceUtil/ScopedArray.h" "$(includedir)/Ice/UndefSysMacros.h" "$(includedir)/Ice/PropertiesF.h" "$(includedir)/Ice/Proxy.h" "$(includedir)/IceUtil/Mutex.h" "$(includedir)/IceUtil/Lock.h" "$(includedir)/IceUtil/ThreadException.h" "$(includedir)/IceUtil/Time.h" "$(includedir)/IceUtil/MutexProtocol.h" "$(includedir)/Ice/ProxyFactoryF.h" "$(includedir)/Ice/ConnectionIF.h" "$(includedir)/Ice/RequestHandlerF.h" "$(includedir)/Ice/EndpointIF.h" "$(includedir)/Ice/EndpointF.h" "$(includedir)/Ice/EndpointTypes.h" "$(includedir)/Ice/ObjectAdapterF.h" "$(includedir)/Ice/ReferenceF.h" "$(includedir)/Ice/OutgoingAsync.h" "$(includedir)/IceUtil/Monitor.h" "$(includedir)/IceUtil/Cond.h" "$(includedir)/IceUtil/Timer.h" "$(includedir)/IceUtil/Thread.h" "$(includedir)/Ice/OutgoingAsyncF.h" "$(includedir)/Ice/InstanceF.h" "$(includedir)/Ice/Current.h" "$(includedir)/Ice/ConnectionF.h" "$(includedir)/Ice/Identity.h" "$(includedir)/Ice/BasicStream.h" "$(includedir)/Ice/ObjectFactoryF.h" "$(includedir)/Ice/Buffer.h" "$(includedir)/Ice/Protocol.h" "$(includedir)/Ice/StreamF.h" "$(includedir)/Ice/Object.h" "$(includedir)/Ice/GCShared.h" "$(includedir)/Ice/GCCountMap.h" "$(includedir)/Ice/IncomingAsyncF.h" "$(includedir)/Ice/LoggerF.h" "$(includedir)/Ice/StatsF.h" "$(includedir)/Ice/Dispatcher.h" "$(includedir)/Ice/StringConverter.h" "$(includedir)/Ice/Plugin.h" "$(includedir)/Ice/BuiltinSequences.h" "$(includedir)/Ice/Stream.h" "$(includedir)/IceUtil/Unicode.h" "$(includedir)/Ice/LocalException.h" "$(includedir)/Ice/Properties.h" "$(includedir)/Ice/Outgoing.h" "$(includedir)/Ice/Incoming.h" "$(includedir)/Ice/ServantLocatorF.h" "$(includedir)/Ice/ServantManagerF.h" "$(includedir)/Ice/Direct.h" "$(includedir)/Ice/Logger.h" "$(includedir)/Ice/LoggerUtil.h" "$(includedir)/Ice/Stats.h" "$(includedir)/Ice/Communicator.h" "$(includedir)/Ice/RouterF.h" "$(includedir)/Ice/LocatorF.h" "$(includedir)/Ice/PluginF.h" "$(includedir)/Ice/ImplicitContextF.h" "$(includedir)/Ice/CommunicatorAsync.h" "$(includedir)/Ice/ObjectFactory.h" "$(includedir)/Ice/ObjectAdapter.h" "$(includedir)/Ice/FacetMap.h" "$(includedir)/Ice/Endpoint.h" "$(includedir)/Ice/ServantLocator.h" "$(includedir)/Ice/IncomingAsync.h" "$(includedir)/Ice/Process.h" "$(includedir)/Ice/Application.h" "$(includedir)/Ice/Connection.h" "$(includedir)/Ice/ConnectionAsync.h" "$(includedir)/Ice/Functional.h" "$(includedir)/IceUtil/Functional.h" "$(includedir)/Ice/ImplicitContext.h" "$(includedir)/Ice/Locator.h" "$(includedir)/Ice/FactoryTableInit.h" "$(includedir)/Ice/FactoryTable.h" "$(includedir)/Ice/UserExceptionFactory.h" "$(includedir)/Ice/ProcessF.h" "$(includedir)/Ice/Router.h" "$(includedir)/Ice/DispatchInterceptor.h" "$(includedir)/Ice/IconvStringConverter.h" ../../include/TestCommon.h
diff --git a/cpp/test/Ice/plugin/.gitignore b/cpp/test/Ice/plugin/.gitignore
new file mode 100644
index 00000000000..a86ad423f93
--- /dev/null
+++ b/cpp/test/Ice/plugin/.gitignore
@@ -0,0 +1,7 @@
+// Generated by makegitignore.py
+
+// IMPORTANT: Do not edit this file -- any edits made here will be lost!
+client
+plugins/libTestPlugin.so.3.4.2
+plugins/libTestPlugin.so.34
+plugins/libTestPlugin.so
diff --git a/cpp/test/Ice/plugin/Client.cpp b/cpp/test/Ice/plugin/Client.cpp
new file mode 100644
index 00000000000..a54ec9e65c2
--- /dev/null
+++ b/cpp/test/Ice/plugin/Client.cpp
@@ -0,0 +1,187 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <Ice/Ice.h>
+#include <TestCommon.h>
+
+using namespace std;
+
+DEFINE_TEST("client")
+
+namespace
+{
+
+class MyPlugin : public Ice::Plugin
+{
+
+public:
+
+ MyPlugin() :
+ _initialized(false),
+ _destroyed(false)
+ {
+ }
+
+ bool
+ isInitialized() const
+ {
+ return _initialized;
+ }
+
+ bool
+ isDestroyed() const
+ {
+ return _destroyed;
+ }
+
+ void
+ initialize()
+ {
+ _initialized = true;
+ }
+
+ void
+ destroy()
+ {
+ _destroyed = true;
+ }
+
+ ~MyPlugin()
+ {
+ test(_initialized);
+ test(_destroyed);
+ }
+
+private:
+
+ const Ice::CommunicatorPtr _communicator;
+ bool _initialized;
+ bool _destroyed;
+};
+typedef IceUtil::Handle<MyPlugin> MyPluginPtr;
+
+}
+
+int
+main(int argc, char* argv[])
+{
+ int status = EXIT_SUCCESS;
+ Ice::CommunicatorPtr communicator;
+
+ cout << "testing a simple plug-in... " << flush;
+ try
+ {
+ Ice::InitializationData initData;
+ initData.properties = Ice::createProperties(argc, argv);
+ initData.properties->setProperty("Ice.Plugin.Test",
+ "plugins/TestPlugin:createPlugin 'C:\\Program Files\\' --DatabasePath "
+ "'C:\\Program Files\\Application\\db'" );
+ communicator = Ice::initialize(argc, argv, initData);
+ communicator->destroy();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
+ cout << "ok" << endl;
+
+ cout << "testing a simple plug-in that fails to initialize... " << flush;
+ communicator = 0;
+ try
+ {
+ Ice::InitializationData initData;
+ initData.properties = Ice::createProperties(argc, argv);
+ initData.properties->setProperty("Ice.Plugin.Test", "plugins/TestPlugin:createPluginInitializeFail");
+ communicator = Ice::initialize(argc, argv, initData);
+ test(false);
+ }
+ catch(const std::exception& ex)
+ {
+ test(string(ex.what()) == "PluginInitializeFailExeption");
+ }
+ test(!communicator);
+ cout << "ok" << endl;
+
+ cout << "testing plug-in load order... " << flush;
+ try
+ {
+ Ice::InitializationData initData;
+ initData.properties = Ice::createProperties(argc, argv);
+ initData.properties->setProperty("Ice.Plugin.PluginOne", "plugins/TestPlugin:createPluginOne");
+ initData.properties->setProperty("Ice.Plugin.PluginTwo", "plugins/TestPlugin:createPluginTwo");
+ initData.properties->setProperty("Ice.Plugin.PluginThree", "plugins/TestPlugin:createPluginThree");
+ initData.properties->setProperty("Ice.PluginLoadOrder", "PluginOne, PluginTwo"); // Exclude PluginThree
+ communicator = Ice::initialize(argc, argv, initData);
+ communicator->destroy();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
+ cout << "ok" << endl;
+
+ cout << "testing plug-in manager... " << flush;
+ try
+ {
+ Ice::InitializationData initData;
+ initData.properties = Ice::createProperties(argc, argv);
+ initData.properties->setProperty("Ice.Plugin.PluginOne", "plugins/TestPlugin:createPluginOne");
+ initData.properties->setProperty("Ice.Plugin.PluginTwo", "plugins/TestPlugin:createPluginTwo");
+ initData.properties->setProperty("Ice.Plugin.PluginThree", "plugins/TestPlugin:createPluginThree");
+ initData.properties->setProperty("Ice.PluginLoadOrder", "PluginOne, PluginTwo");
+ initData.properties->setProperty("Ice.InitPlugins", "0");
+ communicator = Ice::initialize(argc, argv, initData);
+
+ Ice::PluginManagerPtr pm = communicator->getPluginManager();
+ test(pm->getPlugin("PluginOne"));
+ test(pm->getPlugin("PluginTwo"));
+ test(pm->getPlugin("PluginThree"));
+
+ MyPluginPtr p4 = new MyPlugin;
+ pm->addPlugin("PluginFour", p4);
+ test(pm->getPlugin("PluginFour"));
+
+ pm->initializePlugins();
+
+ test(p4->isInitialized());
+
+ communicator->destroy();
+
+ test(p4->isDestroyed());
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
+ cout << "ok" << endl;
+
+ cout << "testing destroy when a plug-in fails to initialize... " << flush;
+ communicator = 0;
+ try
+ {
+ Ice::InitializationData initData;
+ initData.properties = Ice::createProperties(argc, argv);
+ initData.properties->setProperty("Ice.Plugin.PluginOneFail", "plugins/TestPlugin:createPluginOneFail");
+ initData.properties->setProperty("Ice.Plugin.PluginTwoFail", "plugins/TestPlugin:createPluginTwoFail");
+ initData.properties->setProperty("Ice.Plugin.PluginThreeFail", "plugins/TestPlugin:createPluginThreeFail");
+ initData.properties->setProperty("Ice.PluginLoadOrder", "PluginOneFail, PluginTwoFail, PluginThreeFail");
+ communicator = Ice::initialize(argc, argv, initData);
+ }
+ catch(const std::exception& ex)
+ {
+ test(string(ex.what()) == "PluginInitializeFailExeption");
+ }
+ test(!communicator);
+ cout << "ok" << endl;
+
+ return status;
+}
diff --git a/cpp/test/Ice/plugin/Makefile b/cpp/test/Ice/plugin/Makefile
new file mode 100644
index 00000000000..446a4b7c8ac
--- /dev/null
+++ b/cpp/test/Ice/plugin/Makefile
@@ -0,0 +1,51 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ../../..
+
+PLUGINLIBFILENAME = $(call mklibfilename,TestPlugin,$(VERSION))
+PLUGINSONAME = $(call mksoname,TestPlugin,$(SOVERSION))
+PLUGINLIBNAME = $(call mklibname,TestPlugin)
+CLIENT = client
+PLUGINDIR = plugins
+
+TARGETS = $(CLIENT) $(call mklibtargets,$(PLUGINDIR)/$(PLUGINLIBFILENAME),$(PLUGINDIR)/$(PLUGINSONAME),$(PLUGINDIR)/$(PLUGINLIBNAME))
+
+COBJS = Client.o \
+
+POBJS = Plugin.o
+
+SRCS = $(COBJS:.o=.cpp) \
+ $(SOBJS:.o=.cpp) \
+ $(POBJS:.o=.cpp)
+
+LINKWITH := -lIceUtil -lIce
+
+include $(top_srcdir)/config/Make.rules
+
+CPPFLAGS := -I. -I../../include $(CPPFLAGS)
+
+$(CLIENT): $(COBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(COBJS) $(LIBS)
+
+$(PLUGINDIR)/$(PLUGINLIBFILENAME): $(POBJS)
+ rm -f $@
+ $(call mkshlib,$@,$(PLUGINSONAME),$(POBJS),$(LINKWITH))
+
+$(PLUGINDIR)/$(PLUGINSONAME): $(PLUGINDIR)/$(PLUGINLIBFILENAME)
+ rm -f $@
+ ln -s $(PLUGINLIBFILENAME) $@
+
+$(PLUGINDIR)/$(PLUGINLIBNAME): $(PLUGINDIR)/$(PLUGINSONAME)
+ rm -f $@
+ ln -s $(PLUGINSONAME) $@
+
+
+include .depend
diff --git a/cpp/test/Ice/plugin/Makefile.mak b/cpp/test/Ice/plugin/Makefile.mak
new file mode 100644
index 00000000000..c1baf6957f2
--- /dev/null
+++ b/cpp/test/Ice/plugin/Makefile.mak
@@ -0,0 +1,68 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..\..
+
+!if "$(WINRT)" != "yes"
+NAME_PREFIX =
+EXT = .exe
+!else
+NAME_PREFIX = Ice_plugin_
+EXT = .dll
+!endif
+
+CLIENT = $(NAME_PREFIX)client
+LIBNAME = TestPlugin$(LIBSUFFIX).lib
+DLLNAME = TestPlugin$(SOVERSION)$(LIBSUFFIX).dll
+PLUGINDIR = plugins
+
+TARGETS = $(CLIENT)$(EXT) $(PLUGINDIR)\$(LIBNAME) $(PLUGINDIR)\$(DLLNAME)
+
+COBJS = Client.obj
+
+POBJS = Plugin.obj
+
+SRCS = $(COBJS:.obj=.cpp) \
+ $(POBJS:.obj=.cpp)
+
+!include $(top_srcdir)/config/Make.rules.mak
+
+CPPFLAGS = -I. -I../../include $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+
+!if "$(GENERATE_PDB)" == "yes"
+CPDBFLAGS = /pdb:$(CLIENT).pdb
+PPDBFLAGS = /pdb:$(DLLNAME:.dll=.pdb)
+!endif
+
+!if "$(WINRT)" != "yes"
+LD_TESTFLAGS = $(LD_EXEFLAGS) $(SETARGV)
+!else
+LD_TESTFLAGS = $(LD_DLLFLAGS) /export:dllMain
+!endif
+
+LINKWITH = $(LIBS)
+
+$(PLUGINDIR)\$(LIBNAME): $(PLUGINDIR)\$(DLLNAME)
+
+$(PLUGINDIR)\$(DLLNAME): $(POBJS)
+ $(LINK) $(BASE):0x22000000 $(LD_DLLFLAGS) $(PDBFLAGS) $(POBJS) $(PREOUT)$@ $(PRELIBS)$(LINKWITH)
+ move $(PLUGINDIR)\$(DLLNAME:.dll=.lib) $(PLUGINDIR)\$(LIBNAME)
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#2 && del /q $@.manifest
+ @if exist $(PLUGINDIR)\$(DLLNAME:.dll=.exp) del /q $(PLUGINDIR)\$(DLLNAME:.dll=.exp)
+
+$(CLIENT)$(EXT): $(COBJS)
+ $(LINK) $(LD_TESTFLAGS) $(CPDBFLAGS) $(SETARGV) $(COBJS) $(PREOUT)$@ $(PRELIBS)$(LIBS)
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+clean::
+ del /q $(PLUGINDIR)\*.ilk $(PLUGINDIR)\*.pdb
+
+!include .depend.mak
diff --git a/cpp/test/Ice/plugin/Plugin.cpp b/cpp/test/Ice/plugin/Plugin.cpp
new file mode 100644
index 00000000000..0fc9cbad24d
--- /dev/null
+++ b/cpp/test/Ice/plugin/Plugin.cpp
@@ -0,0 +1,404 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <Ice/Ice.h>
+#include <TestCommon.h>
+
+using namespace std;
+
+namespace
+{
+
+class Plugin : public Ice::Plugin
+{
+
+public:
+
+ Plugin(const Ice::CommunicatorPtr& communicator, const Ice::StringSeq& args) :
+ _communicator(communicator),
+ _args(args),
+ _initialized(false),
+ _destroyed(false)
+ {
+ }
+
+ void
+ initialize()
+ {
+ _initialized = true;
+ test(_args.size() == 3);
+ test(_args[0] == "C:\\Program Files\\");
+ test(_args[1] == "--DatabasePath");
+ test(_args[2] == "C:\\Program Files\\Application\\db");
+ }
+
+ void
+ destroy()
+ {
+ _destroyed = true;
+ }
+
+ ~Plugin()
+ {
+ test(_initialized);
+ test(_destroyed);
+ }
+
+private:
+
+ const Ice::CommunicatorPtr _communicator;
+ Ice::StringSeq _args;
+ bool _initialized;
+ bool _destroyed;
+};
+
+class PluginInitializeFailExeption : public std::exception
+{
+
+public:
+
+ PluginInitializeFailExeption() throw() {}
+ virtual ~PluginInitializeFailExeption() throw() {}
+ virtual const char* what() const throw() { return "PluginInitializeFailExeption"; }
+};
+
+class PluginInitializeFail : public Ice::Plugin
+{
+
+public:
+
+ PluginInitializeFail(const Ice::CommunicatorPtr& communicator) :
+ _communicator(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ throw PluginInitializeFailExeption();
+ }
+
+ void
+ destroy()
+ {
+ test(false);
+ }
+
+private:
+
+ const Ice::CommunicatorPtr _communicator;
+};
+
+class BasePlugin;
+typedef IceUtil::Handle<BasePlugin> BasePluginPtr;
+
+class BasePlugin : public Ice::Plugin
+{
+
+public:
+
+ BasePlugin(const Ice::CommunicatorPtr& communicator) :
+ _communicator(communicator),
+ _initialized(false),
+ _destroyed(false)
+ {
+ }
+
+ bool
+ isInitialized() const
+ {
+ return _initialized;
+ }
+
+ bool
+ isDestroyed() const
+ {
+ return _destroyed;
+ }
+
+protected:
+
+ const Ice::CommunicatorPtr _communicator;
+ bool _initialized;
+ bool _destroyed;
+ BasePluginPtr _other;
+};
+
+
+class PluginOne : public BasePlugin
+{
+
+public:
+
+ PluginOne(const Ice::CommunicatorPtr& communicator) :
+ BasePlugin(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ _other = BasePluginPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginTwo"));
+ test(!_other->isInitialized());
+ _initialized = true;
+ }
+
+ void
+ destroy()
+ {
+ _destroyed = true;
+ test(_other->isDestroyed());
+ }
+};
+
+class PluginTwo : public BasePlugin
+{
+
+public:
+
+ PluginTwo(const Ice::CommunicatorPtr& communicator) :
+ BasePlugin(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ _initialized = true;
+ _other = BasePluginPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginOne"));
+ test(_other->isInitialized());
+ }
+
+ void
+ destroy()
+ {
+ _destroyed = true;
+ test(!_other->isDestroyed());
+ }
+};
+
+class PluginThree : public BasePlugin
+{
+
+public:
+
+ PluginThree(const Ice::CommunicatorPtr& communicator) :
+ BasePlugin(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ _initialized = true;
+ _other = BasePluginPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginTwo"));
+ test(_other->isInitialized());
+ }
+
+ void
+ destroy()
+ {
+ _destroyed = true;
+ test(!_other->isDestroyed());
+ }
+};
+
+class BasePluginFail;
+typedef IceUtil::Handle<BasePluginFail> BasePluginFailPtr;
+
+class BasePluginFail : public Ice::Plugin
+{
+
+public:
+
+ BasePluginFail(const Ice::CommunicatorPtr& communicator) :
+ _communicator(communicator),
+ _initialized(false),
+ _destroyed(false)
+ {
+ }
+
+ bool
+ isInitialized() const
+ {
+ return _initialized;
+ }
+
+ bool
+ isDestroyed() const
+ {
+ return _destroyed;
+ }
+
+protected:
+
+ const Ice::CommunicatorPtr _communicator;
+ bool _initialized;
+ bool _destroyed;
+ BasePluginFailPtr _one;
+ BasePluginFailPtr _two;
+ BasePluginFailPtr _three;
+};
+
+
+class PluginOneFail : public BasePluginFail
+{
+
+public:
+
+ PluginOneFail(const Ice::CommunicatorPtr& communicator) :
+ BasePluginFail(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ _two = BasePluginFailPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginTwoFail"));
+ test(!_two->isInitialized());
+ _three = BasePluginFailPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginThreeFail"));
+ test(!_three->isInitialized());
+ _initialized = true;
+ }
+
+ void
+ destroy()
+ {
+ test(_two->isDestroyed());
+ //
+ // Not destroyed because initialize fails.
+ //
+ test(!_three->isDestroyed());
+ _destroyed = true;
+ }
+
+ ~PluginOneFail()
+ {
+ test(_initialized);
+ test(_destroyed);
+ }
+};
+
+class PluginTwoFail : public BasePluginFail
+{
+
+public:
+
+ PluginTwoFail(const Ice::CommunicatorPtr& communicator) :
+ BasePluginFail(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ _initialized = true;
+ _one = BasePluginFailPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginOneFail"));
+ test(_one->isInitialized());
+ _three = BasePluginFailPtr::dynamicCast(_communicator->getPluginManager()->getPlugin("PluginThreeFail"));
+ test(!_three->isInitialized());
+ }
+
+ void
+ destroy()
+ {
+ _destroyed = true;
+ test(!_one->isDestroyed());
+ }
+
+ ~PluginTwoFail()
+ {
+ test(_initialized);
+ test(_destroyed);
+ }
+};
+
+class PluginThreeFail : public BasePluginFail
+{
+
+public:
+
+ PluginThreeFail(const Ice::CommunicatorPtr& communicator) :
+ BasePluginFail(communicator)
+ {
+ }
+
+ void
+ initialize()
+ {
+ throw PluginInitializeFailExeption();
+ }
+
+ void
+ destroy()
+ {
+ test(false);
+ }
+
+ ~PluginThreeFail()
+ {
+ test(!_initialized);
+ test(!_destroyed);
+ }
+};
+
+}
+
+extern "C"
+{
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPlugin(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq& args)
+{
+ return new Plugin(communicator, args);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginInitializeFail(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginInitializeFail(communicator);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginOne(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginOne(communicator);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginTwo(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginTwo(communicator);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginThree(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginThree(communicator);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginOneFail(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginOneFail(communicator);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginTwoFail(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginTwoFail(communicator);
+}
+
+ICE_DECLSPEC_EXPORT ::Ice::Plugin*
+createPluginThreeFail(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&)
+{
+ return new PluginThreeFail(communicator);
+}
+
+}
diff --git a/cpp/test/Ice/plugin/plugins/.gitignore b/cpp/test/Ice/plugin/plugins/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cpp/test/Ice/plugin/plugins/.gitignore
diff --git a/cpp/test/Ice/plugin/run.py b/cpp/test/Ice/plugin/run.py
new file mode 100755
index 00000000000..3c4472ca289
--- /dev/null
+++ b/cpp/test/Ice/plugin/run.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise "can't find toplevel directory!"
+sys.path.append(os.path.join(path[0]))
+from scripts import *
+
+client = os.path.join(os.getcwd(), "client")
+TestUtil.simpleTest(client)
+
diff --git a/cpp/test/WinRT/TestSuite/MainPage.xaml.cpp b/cpp/test/WinRT/TestSuite/MainPage.xaml.cpp
index 1b36c721576..becadead55f 100644
--- a/cpp/test/WinRT/TestSuite/MainPage.xaml.cpp
+++ b/cpp/test/WinRT/TestSuite/MainPage.xaml.cpp
@@ -301,7 +301,8 @@ static const TestCase allTest[] =
{"Ice\\stream", "Ice_stream_", "client.dll", 0, 0, 0},
{"Ice\\timeout", "Ice_timeout_", "client.dll", "server.dll", 0, 0 },
{"Ice\\udp", "Ice_udp_", "client.dll", "server.dll", 0, 0 },
- {"Ice\\hash", "Ice_hash_", "client.dll", 0, 0, 0}
+ {"Ice\\hash", "Ice_hash_", "client.dll", 0, 0, 0},
+ {"Ice\\plugin", "Ice_plugin_", "client.dll", 0, 0, 0}
};
class TestRunner : public IceUtil::Thread
diff --git a/cs/allTests.py b/cs/allTests.py
index 1a2e6093e62..813cf75456d 100755
--- a/cs/allTests.py
+++ b/cs/allTests.py
@@ -60,6 +60,7 @@ tests = [
("Ice/threadPoolPriority", ["core", "nomono", "nosilverlight"]),
("Ice/invoke", ["core"]),
("Ice/hash", ["once"]),
+ ("Ice/plugin", ["core"]),
("IceBox/configuration", ["core", "noipv6", "nosilverlight"]),
("Glacier2/router", ["service", "nosilverlight"]),
("Glacier2/sessionHelper", ["service", "nosilverlight"]),
diff --git a/cs/src/Ice/PluginManagerI.cs b/cs/src/Ice/PluginManagerI.cs
index 9e128ebf71d..81171a5639a 100644
--- a/cs/src/Ice/PluginManagerI.cs
+++ b/cs/src/Ice/PluginManagerI.cs
@@ -51,10 +51,10 @@ namespace Ice
ArrayList initializedPlugins = new ArrayList();
try
{
- foreach(Plugin p in _initOrder)
+ foreach(PluginInfo p in _plugins)
{
- p.initialize();
- initializedPlugins.Add(p);
+ p.plugin.initialize();
+ initializedPlugins.Add(p.plugin);
}
}
catch(System.Exception)
@@ -86,9 +86,9 @@ namespace Ice
lock(this)
{
ArrayList names = new ArrayList();
- foreach(DictionaryEntry entry in _plugins)
+ foreach(PluginInfo p in _plugins)
{
- names.Add(entry.Key);
+ names.Add(p.name);
}
return (string[])names.ToArray(typeof(string));
}
@@ -102,12 +102,13 @@ namespace Ice
{
throw new CommunicatorDestroyedException();
}
-
- Plugin p = (Plugin)_plugins[name];
+
+ Plugin p = findPlugin(name);
if(p != null)
{
return p;
}
+
NotRegisteredException ex = new NotRegisteredException();
ex.id = name;
ex.kindOfObject = _kindOfObject;
@@ -123,15 +124,19 @@ namespace Ice
{
throw new CommunicatorDestroyedException();
}
-
- if(_plugins.Contains(name))
+
+ if(findPlugin(name) != null)
{
AlreadyRegisteredException ex = new AlreadyRegisteredException();
ex.id = name;
ex.kindOfObject = _kindOfObject;
throw ex;
}
- _plugins[name] = plugin;
+
+ PluginInfo info = new PluginInfo();
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.Add(info);
}
}
@@ -143,39 +148,38 @@ namespace Ice
{
if(_initialized)
{
- foreach(DictionaryEntry entry in _plugins)
+ ArrayList plugins = (ArrayList)_plugins.Clone();
+ plugins.Reverse();
+ foreach(PluginInfo p in plugins)
{
try
{
- Plugin plugin = (Plugin)entry.Value;
- plugin.destroy();
+ p.plugin.destroy();
}
catch(System.Exception ex)
{
- Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" +
- entry.Key.ToString() + "' destruction:\n" +
- ex.ToString());
+ Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" +
+ p.name + "' destruction:\n" + ex.ToString());
}
}
}
-
+
_communicator = null;
}
}
}
-
+
public PluginManagerI(Communicator communicator)
{
_communicator = communicator;
- _plugins = new Hashtable();
- _initOrder = new ArrayList();
+ _plugins = new ArrayList();
_initialized = false;
}
public void loadPlugins(ref string[] cmdArgs)
{
Debug.Assert(_communicator != null);
-
+
//
// Load and initialize the plug-ins defined in the property set
// with the prefix "Ice.Plugin.". These properties should
@@ -204,7 +208,7 @@ namespace Ice
continue;
}
- if(_plugins.Contains(loadOrder[i]))
+ if(findPlugin(loadOrder[i]) != null)
{
PluginInitializationException e = new PluginInitializationException();
e.reason = "plug-in `" + loadOrder[i] + "' already loaded";
@@ -265,7 +269,7 @@ namespace Ice
loadPlugin(name, val, ref cmdArgs);
plugins.Remove(key);
plugins.Remove("Ice.Plugin." + name);
-
+
}
else
{
@@ -275,7 +279,7 @@ namespace Ice
dotPos = -1;
}
}
-
+
if(dotPos == -1)
{
plugins.Remove(key);
@@ -288,60 +292,43 @@ namespace Ice
{
val = plugins[clrKey];
plugins.Remove(clrKey);
- }
+ }
loadPlugin(name, val, ref cmdArgs);
}
}
}
-
+
private void loadPlugin(string name, string pluginSpec, ref string[] cmdArgs)
{
Debug.Assert(_communicator != null);
//
- // Separate the entry point from the arguments. First
- // look for the :, then for the next whitespace. This
- // represents the end of the entry point.
+ // Split the entire property value into arguments. An entry point containing spaces
+ // must be enclosed in quotes.
//
- // The remainder of the configuration line represents
- // the arguments.
- //
- string entryPoint = pluginSpec;
- string[] args = new string[0];
- int start = pluginSpec.IndexOf(':');
- if(start != -1)
+ string[] args = null;
+ try
{
- //
- // Skip drive letter, if any.
- //
- if(pluginSpec.Length > 3 &&
- start == 1 &&
- System.Char.IsLetter(pluginSpec[0]) &&
- (pluginSpec[2] == '\\' || pluginSpec[2] == '/'))
- {
- start = pluginSpec.IndexOf(':', 3);
- }
-
- //
- // Find the whitespace.
- //
- int pos = pluginSpec.IndexOf(' ', start);
- if(pos == -1)
- {
- pos = pluginSpec.IndexOf('\t', start);
- }
- if(pos == -1)
- {
- pos = pluginSpec.IndexOf('\n', start);
- }
- if(pos != -1)
- {
- entryPoint = pluginSpec.Substring(0, pos);
- char[] delims = { ' ', '\t', '\n' };
- args = pluginSpec.Substring(pos).Trim().Split(delims);
- }
+ args = IceUtilInternal.Options.split(pluginSpec);
}
-
+ catch(IceUtilInternal.Options.BadQuote ex)
+ {
+ PluginInitializationException e = new PluginInitializationException();
+ e.reason = "invalid arguments for plug-in `" + name + "':\n" + ex.Message;
+ throw e;
+ }
+
+ Debug.Assert(args.Length > 0);
+
+ string entryPoint = args[0];
+
+ //
+ // Shift the arguments.
+ //
+ string[] tmp = new string[args.Length - 1];
+ Array.Copy(args, 1, tmp, 0, args.Length - 1);
+ args = tmp;
+
//
// Convert command-line options into properties. First
// we convert the options from the plug-in
@@ -351,38 +338,41 @@ namespace Ice
Properties properties = _communicator.getProperties();
args = properties.parseCommandLineOptions(name, args);
cmdArgs = properties.parseCommandLineOptions(name, cmdArgs);
-
+
//
- // Retrieve the assembly name and the type.
+ // Extract the assembly name and the class name.
//
- string err = "unable to load plug-in '" + entryPoint + "': ";
+ string err = "unable to load plug-in `" + entryPoint + "': ";
int sepPos = entryPoint.IndexOf(':');
- if(sepPos != -1)
+ if(sepPos != -1 && IceInternal.AssemblyUtil.platform_ == IceInternal.AssemblyUtil.Platform.Windows)
{
+ const string driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if(entryPoint.Length > 3 &&
sepPos == 1 &&
- System.Char.IsLetter(entryPoint[0]) &&
+ driveLetters.IndexOf(entryPoint[0]) != -1 &&
(entryPoint[2] == '\\' || entryPoint[2] == '/'))
{
sepPos = entryPoint.IndexOf(':', 3);
}
}
- if (sepPos == -1)
+ if(sepPos == -1)
{
PluginInitializationException e = new PluginInitializationException();
e.reason = err + "invalid entry point format";
throw e;
}
-
+
System.Reflection.Assembly pluginAssembly = null;
string assemblyName = entryPoint.Substring(0, sepPos);
+ string className = entryPoint.Substring(sepPos + 1);
+
try
{
//
- // First try to load the assemby using Assembly.Load which will succeed
- // if full name is configured or partial name has been qualified in config.
- // If that fails, try Assembly.LoadFrom() which will succeed if a file name
- // is configured or partial name is configured and DEVPATH is used.
+ // First try to load the assembly using Assembly.Load, which will succeed
+ // if a fully-qualified name is provided or if a partial name has been qualified
+ // in configuration. If that fails, try Assembly.LoadFrom(), which will succeed
+ // if a file name is configured or a partial name is configured and DEVPATH is used.
//
try
{
@@ -434,7 +424,7 @@ namespace Ice
#endif
PluginInitializationException e = new PluginInitializationException();
- e.reason = err + "unable to load assembly: '" + assemblyName + "': " + ex.ToString();
+ e.reason = err + "unable to load assembly: `" + assemblyName + "': " + ex.ToString();
throw e;
}
@@ -442,7 +432,6 @@ namespace Ice
// Instantiate the class.
//
PluginFactory pluginFactory = null;
- string className = entryPoint.Substring(sepPos + 1);
System.Type c = null;
try
{
@@ -451,7 +440,7 @@ namespace Ice
catch(System.Exception ex)
{
PluginInitializationException e = new PluginInitializationException(ex);
- e.reason = err + "GetType failed for '" + className + "'";
+ e.reason = err + "GetType failed for `" + className + "'";
throw e;
}
@@ -461,7 +450,7 @@ namespace Ice
if(pluginFactory == null)
{
PluginInitializationException e = new PluginInitializationException();
- e.reason = err + "Can't find constructor for '" + className + "'";
+ e.reason = err + "can't find constructor for `" + className + "'";
throw e;
}
}
@@ -483,7 +472,7 @@ namespace Ice
e.reason = err + "System.Exception: " + ex.ToString();
throw e;
}
-
+
Plugin plugin = null;
try
{
@@ -500,7 +489,7 @@ namespace Ice
e.reason = err + "System.Exception in factory.create: " + ex.ToString();
throw e;
}
-
+
if(plugin == null)
{
PluginInitializationException ex = new PluginInitializationException();
@@ -508,13 +497,32 @@ namespace Ice
throw ex;
}
- _plugins[name] = plugin;
- _initOrder.Add(plugin);
+ PluginInfo info = new PluginInfo();
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.Add(info);
+ }
+
+ private Plugin findPlugin(string name)
+ {
+ foreach(PluginInfo p in _plugins)
+ {
+ if(name.Equals(p.name))
+ {
+ return p.plugin;
+ }
+ }
+ return null;
+ }
+
+ internal class PluginInfo
+ {
+ internal string name;
+ internal Plugin plugin;
}
private Communicator _communicator;
- private Hashtable _plugins;
- private ArrayList _initOrder;
+ private ArrayList _plugins;
private bool _initialized;
private static bool _sslWarnOnce = false;
}
diff --git a/cs/src/IceBox/ServiceManagerI.cs b/cs/src/IceBox/ServiceManagerI.cs
index 30e218abae4..86a5310e138 100644
--- a/cs/src/IceBox/ServiceManagerI.cs
+++ b/cs/src/IceBox/ServiceManagerI.cs
@@ -30,14 +30,12 @@ class ServiceManagerI : ServiceManagerDisp_
_traceServiceObserver = _communicator.getProperties().getPropertyAsInt("IceBox.Trace.ServiceObserver");
}
- public override Dictionary<string, string>
- getSliceChecksums(Ice.Current current)
+ public override Dictionary<string, string> getSliceChecksums(Ice.Current current)
{
return Ice.SliceChecksums.checksums;
}
- public override void
- startService(string name, Ice.Current current)
+ public override void startService(string name, Ice.Current current)
{
ServiceInfo info = new ServiceInfo();
_m.Lock();
@@ -119,8 +117,7 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- public override void
- stopService(string name, Ice.Current current)
+ public override void stopService(string name, Ice.Current current)
{
ServiceInfo info = new ServiceInfo();
_m.Lock();
@@ -201,8 +198,7 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- public override void
- addObserver(ServiceObserverPrx observer, Ice.Current current)
+ public override void addObserver(ServiceObserverPrx observer, Ice.Current current)
{
List<string> activeServices = new List<string>();
@@ -250,14 +246,12 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- public override void
- shutdown(Ice.Current current)
+ public override void shutdown(Ice.Current current)
{
_communicator.shutdown();
}
- public int
- run()
+ public int run()
{
try
{
@@ -466,8 +460,7 @@ class ServiceManagerI : ServiceManagerDisp_
return 0;
}
- private void
- startService(string service, string entryPoint, string[] args)
+ private void startService(string service, string entryPoint, string[] args)
{
_m.Lock();
try
@@ -478,15 +471,16 @@ class ServiceManagerI : ServiceManagerDisp_
info.args = args;
//
- // Retrieve the assembly name and the type.
+ // Extract the assembly name and the class name.
//
string err = "ServiceManager: unable to load service '" + entryPoint + "': ";
int sepPos = entryPoint.IndexOf(':');
- if(sepPos != -1)
+ if(sepPos != -1 && IceInternal.AssemblyUtil.platform_ == IceInternal.AssemblyUtil.Platform.Windows)
{
+ const string driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if(entryPoint.Length > 3 &&
sepPos == 1 &&
- System.Char.IsLetter(entryPoint[0]) &&
+ driveLetters.IndexOf(entryPoint[0]) != -1 &&
(entryPoint[2] == '\\' || entryPoint[2] == '/'))
{
sepPos = entryPoint.IndexOf(':', 3);
@@ -495,19 +489,21 @@ class ServiceManagerI : ServiceManagerDisp_
if(sepPos == -1)
{
FailureException e = new FailureException();
- e.reason = err + "invalid entry point format: " + entryPoint;
+ e.reason = err + "invalid entry point format";
throw e;
}
System.Reflection.Assembly serviceAssembly = null;
string assemblyName = entryPoint.Substring(0, sepPos);
+ string className = entryPoint.Substring(sepPos + 1);
+
try
{
//
- // First try to load the assemby using Assembly.Load which will succeed
- // if full name is configured or partial name has been qualified in config.
- // If that fails, try Assembly.LoadFrom() which will succeed if a file name
- // is configured or partial name is configured and DEVPATH is used.
+ // First try to load the assembly using Assembly.Load, which will succeed
+ // if a fully-qualified name is provided or if a partial name has been qualified
+ // in configuration. If that fails, try Assembly.LoadFrom(), which will succeed
+ // if a file name is configured or a partial name is configured and DEVPATH is used.
//
try
{
@@ -535,7 +531,6 @@ class ServiceManagerI : ServiceManagerDisp_
//
// Instantiate the class.
//
- string className = entryPoint.Substring(sepPos + 1);
System.Type c = null;
try
{
@@ -614,7 +609,7 @@ class ServiceManagerI : ServiceManagerDisp_
else
{
FailureException e = new FailureException(ex.InnerException);
- e.reason = "ServiceManager: exception in service constructor for " + className;
+ e.reason = err + "exception in service constructor for " + className;
throw e;
}
}
@@ -738,8 +733,7 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- private void
- stopAll()
+ private void stopAll()
{
_m.Lock();
try
@@ -837,8 +831,7 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- private void
- servicesStarted(List<String> services, Dictionary<ServiceObserverPrx, bool>.KeyCollection observers)
+ private void servicesStarted(List<String> services, Dictionary<ServiceObserverPrx, bool>.KeyCollection observers)
{
//
// Must be called with 'this' unlocked
@@ -855,8 +848,7 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- private void
- servicesStopped(List<string> services, Dictionary<ServiceObserverPrx, bool>.KeyCollection observers)
+ private void servicesStopped(List<string> services, Dictionary<ServiceObserverPrx, bool>.KeyCollection observers)
{
//
// Must be called with 'this' unlocked
@@ -898,8 +890,7 @@ class ServiceManagerI : ServiceManagerDisp_
}
}
- private void
- observerRemoved(ServiceObserverPrx observer, System.Exception ex)
+ private void observerRemoved(ServiceObserverPrx observer, System.Exception ex)
{
if(_traceServiceObserver >= 1)
{
@@ -942,51 +933,29 @@ class ServiceManagerI : ServiceManagerDisp_
// Separate the entry point from the arguments.
//
name = service;
- entryPoint = value;
- args = new string[0];
- int start = value.IndexOf(':');
- if(start != -1)
+ try
{
- if(value.Length > 3 &&
- start == 1 &&
- System.Char.IsLetter(value[0]) &&
- (value[2] == '\\' || value[2] == '/'))
- {
- start = value.IndexOf(':', 3);
- }
+ args = IceUtilInternal.Options.split(value);
}
-
- if(start != -1)
+ catch(IceUtilInternal.Options.BadQuote ex)
{
- //
- // Find the whitespace.
- //
- int pos = value.IndexOf(' ', start);
- if(pos == -1)
- {
- pos = value.IndexOf('\t', start);
- }
- if(pos == -1)
- {
- pos = value.IndexOf('\n', start);
- }
- if(pos != -1)
- {
- entryPoint = value.Substring(0, pos);
- try
- {
- args = IceUtilInternal.Options.split(value.Substring(pos));
- }
- catch(IceUtilInternal.Options.BadQuote ex)
- {
- FailureException e = new FailureException(ex);
- e.reason = "ServiceManager: invalid arguments for service `" + name + "'";
- throw e;
- }
- }
+ FailureException e = new FailureException();
+ e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.Message;
+ throw e;
}
+ Debug.Assert(args.Length > 0);
+
+ entryPoint = args[0];
+
+ //
+ // Shift the arguments.
+ //
+ string[] tmp = new string[args.Length - 1];
+ Array.Copy(args, 1, tmp, 0, args.Length - 1);
+ args = tmp;
+
if(serverArgs.Length > 0)
{
ArrayList l = new ArrayList();
@@ -1017,14 +986,12 @@ class ServiceManagerI : ServiceManagerDisp_
_properties = properties;
}
- public override string
- getProperty(string name, Ice.Current current)
+ public override string getProperty(string name, Ice.Current current)
{
return _properties.getProperty(name);
}
- public override Dictionary<string, string>
- getPropertiesForPrefix(string name, Ice.Current current)
+ public override Dictionary<string, string> getPropertiesForPrefix(string name, Ice.Current current)
{
return _properties.getPropertiesForPrefix(name);
}
@@ -1032,8 +999,7 @@ class ServiceManagerI : ServiceManagerDisp_
private Ice.Properties _properties;
}
- private Ice.Properties
- createServiceProperties(String service)
+ private Ice.Properties createServiceProperties(String service)
{
Ice.Properties properties;
Ice.Properties communicatorProperties = _communicator.getProperties();
diff --git a/cs/test/Ice/Makefile b/cs/test/Ice/Makefile
index 0fc71beeb86..c1ae0863dba 100644
--- a/cs/test/Ice/Makefile
+++ b/cs/test/Ice/Makefile
@@ -42,7 +42,8 @@ SUBDIRS = application \
udp \
defaultServant \
defaultValue \
- threadPoolPriority
+ threadPoolPriority \
+ plugin
$(EVERYTHING)::
@for subdir in $(SUBDIRS); \
diff --git a/cs/test/Ice/Makefile.mak b/cs/test/Ice/Makefile.mak
index 7d731d91ef2..2aa6588521f 100644
--- a/cs/test/Ice/Makefile.mak
+++ b/cs/test/Ice/Makefile.mak
@@ -42,7 +42,8 @@ SUBDIRS = application \
udp \
defaultServant \
defaultValue \
- threadPoolPriority
+ threadPoolPriority \
+ plugin
$(EVERYTHING)::
@for %i in ( $(SUBDIRS) ) do \
diff --git a/cs/test/Ice/plugin/.depend b/cs/test/Ice/plugin/.depend
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cs/test/Ice/plugin/.depend
diff --git a/cs/test/Ice/plugin/.depend.mak b/cs/test/Ice/plugin/.depend.mak
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cs/test/Ice/plugin/.depend.mak
diff --git a/cs/test/Ice/plugin/BasePlugin.cs b/cs/test/Ice/plugin/BasePlugin.cs
new file mode 100644
index 00000000000..63e3ea9f1af
--- /dev/null
+++ b/cs/test/Ice/plugin/BasePlugin.cs
@@ -0,0 +1,44 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using Ice;
+
+public abstract class BasePlugin : Ice.Plugin
+{
+ public BasePlugin(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ }
+
+ public bool isInitialized()
+ {
+ return _initialized;
+ }
+
+ public bool isDestroyed()
+ {
+ return _destroyed;
+ }
+
+ protected static void test(bool b)
+ {
+ if(!b)
+ {
+ throw new System.Exception();
+ }
+ }
+
+ public abstract void initialize();
+ public abstract void destroy();
+
+ protected Ice.Communicator _communicator;
+ protected bool _initialized = false;
+ protected bool _destroyed = false;
+ protected BasePlugin _other = null;
+}
diff --git a/cs/test/Ice/plugin/BasePluginFail.cs b/cs/test/Ice/plugin/BasePluginFail.cs
new file mode 100644
index 00000000000..1188914f23d
--- /dev/null
+++ b/cs/test/Ice/plugin/BasePluginFail.cs
@@ -0,0 +1,48 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using Ice;
+
+public abstract class BasePluginFail : Ice.Plugin
+{
+ public BasePluginFail(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ _initialized = false;
+ _destroyed = false;
+ }
+
+ public bool isInitialized()
+ {
+ return _initialized;
+ }
+
+ public bool isDestroyed()
+ {
+ return _destroyed;
+ }
+
+ protected static void test(bool b)
+ {
+ if(!b)
+ {
+ throw new System.Exception();
+ }
+ }
+
+ public abstract void initialize();
+ public abstract void destroy();
+
+ protected Ice.Communicator _communicator;
+ protected bool _initialized;
+ protected bool _destroyed;
+ protected BasePluginFail _one;
+ protected BasePluginFail _two;
+ protected BasePluginFail _three;
+}
diff --git a/cs/test/Ice/plugin/Client.cs b/cs/test/Ice/plugin/Client.cs
new file mode 100644
index 00000000000..c4628cb600e
--- /dev/null
+++ b/cs/test/Ice/plugin/Client.cs
@@ -0,0 +1,179 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using Ice;
+
+[assembly: CLSCompliant(true)]
+
+[assembly: AssemblyTitle("IceTest")]
+[assembly: AssemblyDescription("Ice test")]
+[assembly: AssemblyCompany("ZeroC, Inc.")]
+
+public class Client
+{
+ private static void test(bool b)
+ {
+ if(!b)
+ {
+ throw new System.Exception();
+ }
+ }
+
+ public static int Main(string[] args)
+ {
+ Ice.Communicator communicator = null;
+ Console.Write("testing a simple plug-in... ");
+ Console.Out.Flush();
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.Test",
+ "plugins/Plugin.dll:PluginFactory 'C:\\Program Files\\' --DatabasePath " +
+ "'C:\\Program Files\\Application\\db'");
+ communicator = Ice.Util.initialize(ref args, initData);
+ communicator.destroy();
+ }
+ catch(Ice.LocalException ex)
+ {
+ Console.WriteLine(ex.ToString());;
+ test(false);
+ }
+ Console.WriteLine("ok");
+
+ Console.Write("testing a simple plug-in that fails to initialize... ");
+ Console.Out.Flush();
+ communicator = null;
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.Test", "plugins/Plugin.dll:PluginInitializeFailFactory");
+ communicator = Ice.Util.initialize(ref args, initData);
+ test(false);
+ }
+ catch(System.Exception ex)
+ {
+ test(ex.Message.Equals("PluginInitializeFailException"));
+ }
+ test(communicator == null);
+ Console.WriteLine("ok");
+
+ Console.Write("testing plug-in load order... ");
+ Console.Out.Flush();
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.PluginOne", "plugins/Plugin.dll:PluginOneFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginTwo", "plugins/Plugin.dll:PluginTwoFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThree", "plugins/Plugin.dll:PluginThreeFactory");
+ initData.properties.setProperty("Ice.PluginLoadOrder", "PluginOne, PluginTwo"); // Exclude PluginThree
+ communicator = Ice.Util.initialize(ref args, initData);
+ communicator.destroy();
+ }
+ catch(Ice.LocalException ex)
+ {
+ Console.WriteLine(ex.ToString());;
+ test(false);
+ }
+ Console.WriteLine("ok");
+
+ Console.Write("testing plug-in manager... ");
+ Console.Out.Flush();
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.PluginOne", "plugins/Plugin.dll:PluginOneFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginTwo", "plugins/Plugin.dll:PluginTwoFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThree", "plugins/Plugin.dll:PluginThreeFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThree", "plugins/Plugin.dll:PluginThreeFactory");
+ initData.properties.setProperty("Ice.InitPlugins", "0");
+ communicator = Ice.Util.initialize(ref args, initData);
+
+ Ice.PluginManager pm = communicator.getPluginManager();
+ test(pm.getPlugin("PluginOne") != null);
+ test(pm.getPlugin("PluginTwo") != null);
+ test(pm.getPlugin("PluginThree") != null);
+
+ MyPlugin p4 = new MyPlugin();
+ pm.addPlugin("PluginFour", p4);
+ test(pm.getPlugin("PluginFour") != null);
+
+ pm.initializePlugins();
+
+ test(p4.isInitialized());
+
+ communicator.destroy();
+
+ test(p4.isDestroyed());
+ }
+ catch(Ice.LocalException ex)
+ {
+ Console.WriteLine(ex.ToString());;
+ test(false);
+ }
+ Console.WriteLine("ok");
+
+ Console.Write("testing destroy when a plug-in fails to initialize... ");
+ Console.Out.Flush();
+ communicator = null;
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.PluginOneFail",
+ "plugins/Plugin.dll:PluginOneFailFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginTwoFail",
+ "plugins/Plugin.dll:PluginTwoFailFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThreeFail",
+ "plugins/Plugin.dll:PluginThreeFailFactory");
+ initData.properties.setProperty("Ice.PluginLoadOrder", "PluginOneFail, PluginTwoFail, PluginThreeFail");
+ communicator = Ice.Util.initialize(ref args, initData);
+ }
+ catch(System.Exception ex)
+ {
+ test(ex.Message.Equals("PluginInitializeFailException"));
+ }
+ test(communicator == null);
+ Console.WriteLine("ok");
+
+ return 0;
+ }
+
+ internal class MyPlugin : Ice.Plugin
+ {
+ public bool isInitialized()
+ {
+ return _initialized;
+ }
+
+ public bool isDestroyed()
+ {
+ return _destroyed;
+ }
+
+ public void initialize()
+ {
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ }
+
+ private bool _initialized = false;
+ private bool _destroyed = false;
+ }
+}
diff --git a/cs/test/Ice/plugin/Makefile b/cs/test/Ice/plugin/Makefile
new file mode 100644
index 00000000000..3738ee553dc
--- /dev/null
+++ b/cs/test/Ice/plugin/Makefile
@@ -0,0 +1,41 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ../../..
+
+TARGETS = client.exe plugins/Plugin.dll
+
+C_SRCS = Client.cs
+
+P_SRCS = BasePlugin.cs \
+ PluginFactory.cs \
+ PluginInitializeFailException.cs \
+ BasePluginFail.cs \
+ PluginInitializeFailFactory.cs \
+ PluginOneFactory.cs \
+ PluginOneFailFactory.cs \
+ PluginThreeFactory.cs \
+ PluginThreeFailFactory.cs \
+ PluginTwoFactory.cs \
+ PluginTwoFailFactory.cs
+
+SDIR = .
+
+include $(top_srcdir)/config/Make.rules.cs
+
+client.exe: $(C_SRCS)
+ $(MCS) $(MCSFLAGS) -target:exe -out:$@ $(call ref,Ice) $(C_SRCS)
+
+plugins/Plugin.dll: $(P_SRCS)
+ $(MCS) $(MCSFLAGS) -target:library -out:plugins/Plugin.dll $(call ref,Ice) /keyfile:$(KEYFILE) $(P_SRCS)
+
+clean::
+ rm -f plugins/Plugin.dll
+
+include .depend
diff --git a/cs/test/Ice/plugin/Makefile.mak b/cs/test/Ice/plugin/Makefile.mak
new file mode 100644
index 00000000000..f8615231af6
--- /dev/null
+++ b/cs/test/Ice/plugin/Makefile.mak
@@ -0,0 +1,38 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..\..
+
+TARGETS = client.exe plugins\Plugin.dll
+
+C_SRCS = Client.cs
+
+P_SRCS = BasePlugin.cs \
+ PluginFactory.cs \
+ PluginInitializeFailException.cs \
+ BasePluginFail.cs \
+ PluginInitializeFailFactory.cs \
+ PluginOneFactory.cs \
+ PluginOneFailFactory.cs \
+ PluginThreeFactory.cs \
+ PluginThreeFailFactory.cs \
+ PluginTwoFactory.cs \
+ PluginTwoFailFactory.cs
+
+SDIR = .
+
+!include $(top_srcdir)\config\Make.rules.mak.cs
+
+client.exe: $(C_SRCS)
+ $(MCS) $(MCSFLAGS) -target:exe -out:$@ -r:"$(refdir)\Ice.dll" $(C_SRCS)
+
+plugins\Plugin.dll: $(P_SRCS)
+ $(MCS) $(MCSFLAGS) -target:library -out:plugins\Plugin.dll -r:"$(refdir)\Ice.dll" /keyfile:$(KEYFILE) $(P_SRCS)
+
+!include .depend.mak
diff --git a/cs/test/Ice/plugin/PluginFactory.cs b/cs/test/Ice/plugin/PluginFactory.cs
new file mode 100644
index 00000000000..3ac781eeec5
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginFactory.cs
@@ -0,0 +1,64 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+
+public class PluginFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new Plugin(communicator, args);
+ }
+
+ internal class Plugin : Ice.Plugin
+ {
+ public Plugin(Ice.Communicator communicator, string[] args)
+ {
+ _args = args;
+ }
+
+ public void initialize()
+ {
+ _initialized = true;
+ test(_args.Length == 3);
+ test(_args[0] == "C:\\Program Files\\");
+ test(_args[1] == "--DatabasePath");
+ test(_args[2] == "C:\\Program Files\\Application\\db");
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ }
+
+ ~Plugin()
+ {
+ if(!_initialized)
+ {
+ Console.WriteLine("Plugin not initialized");
+ }
+ if(!_destroyed)
+ {
+ Console.WriteLine("Plugin not destroyed");
+ }
+ }
+
+ private static void test(bool b)
+ {
+ if(!b)
+ {
+ throw new System.Exception();
+ }
+ }
+
+ private bool _initialized = false;
+ private bool _destroyed = false;
+ private string[] _args;
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginInitializeFailException.cs b/cs/test/Ice/plugin/PluginInitializeFailException.cs
new file mode 100644
index 00000000000..2fec6a604a1
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginInitializeFailException.cs
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+public class PluginInitializeFailException : System.Exception
+{
+ public PluginInitializeFailException() : base("PluginInitializeFailException")
+ {
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginInitializeFailFactory.cs b/cs/test/Ice/plugin/PluginInitializeFailFactory.cs
new file mode 100644
index 00000000000..fcd47db9244
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginInitializeFailFactory.cs
@@ -0,0 +1,37 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+public class PluginInitializeFailFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginInitializeFail();
+ }
+
+ internal class PluginInitializeFail : Ice.Plugin
+ {
+ public void initialize()
+ {
+ throw new PluginInitializeFailException();
+ }
+
+ public void destroy()
+ {
+ test(false);
+ }
+
+ private static void test(bool b)
+ {
+ if(!b)
+ {
+ throw new System.Exception();
+ }
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginOneFactory.cs b/cs/test/Ice/plugin/PluginOneFactory.cs
new file mode 100644
index 00000000000..f95e60718e3
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginOneFactory.cs
@@ -0,0 +1,36 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+public class PluginOneFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginOne(communicator);
+ }
+
+ internal class PluginOne : BasePlugin
+ {
+ public PluginOne(Ice.Communicator communicator) : base(communicator)
+ {
+ }
+
+ public override void initialize()
+ {
+ _other = (BasePlugin)_communicator.getPluginManager().getPlugin("PluginTwo");
+ test(!_other.isInitialized());
+ _initialized = true;
+ }
+
+ public override void destroy()
+ {
+ _destroyed = true;
+ test(_other.isDestroyed());
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginOneFailFactory.cs b/cs/test/Ice/plugin/PluginOneFailFactory.cs
new file mode 100644
index 00000000000..ef4a2165123
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginOneFailFactory.cs
@@ -0,0 +1,56 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+
+public class PluginOneFailFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginOneFail(communicator);
+ }
+
+ internal class PluginOneFail : BasePluginFail
+ {
+ public PluginOneFail(Ice.Communicator communicator) : base(communicator)
+ {
+ }
+
+ public override void initialize()
+ {
+ _two = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginTwoFail");
+ test(!_two.isInitialized());
+ _three = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginThreeFail");
+ test(!_three.isInitialized());
+ _initialized = true;
+ }
+
+ public override void destroy()
+ {
+ test(_two.isDestroyed());
+ //
+ // Not destroyed because initialize fails.
+ //
+ test(!_three.isDestroyed());
+ _destroyed = true;
+ }
+
+ ~PluginOneFail()
+ {
+ if(!_initialized)
+ {
+ Console.WriteLine("PluginOneFail not initialized");
+ }
+ if(!_destroyed)
+ {
+ Console.WriteLine("PluginOneFail not destroyed");
+ }
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginThreeFactory.cs b/cs/test/Ice/plugin/PluginThreeFactory.cs
new file mode 100644
index 00000000000..a51b627ce0b
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginThreeFactory.cs
@@ -0,0 +1,36 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+public class PluginThreeFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginThree(communicator);
+ }
+
+ internal class PluginThree : BasePlugin
+ {
+ public PluginThree(Ice.Communicator communicator) : base(communicator)
+ {
+ }
+
+ public override void initialize()
+ {
+ _other = (BasePlugin)_communicator.getPluginManager().getPlugin("PluginTwo");
+ test(_other.isInitialized());
+ _initialized = true;
+ }
+
+ public override void destroy()
+ {
+ _destroyed = true;
+ test(!_other.isDestroyed());
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginThreeFailFactory.cs b/cs/test/Ice/plugin/PluginThreeFailFactory.cs
new file mode 100644
index 00000000000..6b708fefd3a
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginThreeFailFactory.cs
@@ -0,0 +1,47 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+
+public class PluginThreeFailFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginThreeFail(communicator);
+ }
+
+ internal class PluginThreeFail : BasePluginFail
+ {
+ public PluginThreeFail(Ice.Communicator communicator) : base(communicator)
+ {
+ }
+
+ public override void initialize()
+ {
+ throw new PluginInitializeFailException();
+ }
+
+ public override void destroy()
+ {
+ test(false);
+ }
+
+ ~PluginThreeFail()
+ {
+ if(_initialized)
+ {
+ Console.WriteLine("PluginThreeFail was initialized");
+ }
+ if(_destroyed)
+ {
+ Console.WriteLine("PluginThreeFail was destroyed");
+ }
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginTwoFactory.cs b/cs/test/Ice/plugin/PluginTwoFactory.cs
new file mode 100644
index 00000000000..5981490e825
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginTwoFactory.cs
@@ -0,0 +1,36 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+public class PluginTwoFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginTwo(communicator);
+ }
+
+ internal class PluginTwo : BasePlugin
+ {
+ public PluginTwo(Ice.Communicator communicator) : base(communicator)
+ {
+ }
+
+ public override void initialize()
+ {
+ _other = (BasePlugin)_communicator.getPluginManager().getPlugin("PluginOne");
+ test(_other.isInitialized());
+ _initialized = true;
+ }
+
+ public override void destroy()
+ {
+ _destroyed = true;
+ test(!_other.isDestroyed());
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/PluginTwoFailFactory.cs b/cs/test/Ice/plugin/PluginTwoFailFactory.cs
new file mode 100644
index 00000000000..1d6e97ec085
--- /dev/null
+++ b/cs/test/Ice/plugin/PluginTwoFailFactory.cs
@@ -0,0 +1,56 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+
+public class PluginTwoFailFactory : Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args)
+ {
+ return new PluginTwoFail(communicator);
+ }
+
+ internal class PluginTwoFail : BasePluginFail
+ {
+ public PluginTwoFail(Ice.Communicator communicator) : base(communicator)
+ {
+ }
+
+ public override void initialize()
+ {
+ _one = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginOneFail");
+ test(_one.isInitialized());
+ _three = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginThreeFail");
+ test(!_three.isInitialized());
+ _initialized = true;
+ }
+
+ public override void destroy()
+ {
+ test(!_one.isDestroyed());
+ //
+ // Not destroyed because initialize fails.
+ //
+ test(!_three.isDestroyed());
+ _destroyed = true;
+ }
+
+ ~PluginTwoFail()
+ {
+ if(!_initialized)
+ {
+ Console.WriteLine("PluginTwoFail not initialized");
+ }
+ if(!_destroyed)
+ {
+ Console.WriteLine("PluginTwoFail not destroyed");
+ }
+ }
+ }
+}
diff --git a/cs/test/Ice/plugin/client.exe.config b/cs/test/Ice/plugin/client.exe.config
new file mode 100755
index 00000000000..cf795ac3756
--- /dev/null
+++ b/cs/test/Ice/plugin/client.exe.config
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <developmentMode developerInstallation="true"/>
+ </runtime>
+</configuration>
diff --git a/cs/test/Ice/plugin/plugins/.gitignore b/cs/test/Ice/plugin/plugins/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/cs/test/Ice/plugin/plugins/.gitignore
diff --git a/cs/test/Ice/plugin/run.py b/cs/test/Ice/plugin/run.py
new file mode 100755
index 00000000000..20e51607f28
--- /dev/null
+++ b/cs/test/Ice/plugin/run.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys, getopt
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise "can't find toplevel directory!"
+sys.path.append(os.path.join(path[0]))
+from scripts import *
+
+client = os.path.join(os.getcwd(), "client")
+
+print "starting client...",
+clientProc = TestUtil.startClient(client, " --Ice.Warn.Dispatch=0 2>&1", startReader = False)
+print "ok"
+clientProc.startReader()
+clientProc.waitTestSuccess()
+
diff --git a/java/allTests.py b/java/allTests.py
index ce7ac3ac3c4..525fd7fc4f3 100755
--- a/java/allTests.py
+++ b/java/allTests.py
@@ -64,6 +64,7 @@ tests = [
("Ice/classLoader", ["core"]),
("Ice/invoke", ["core"]),
("Ice/properties", ["once"]),
+ ("Ice/plugin", ["core"]),
("Ice/hash", ["once"]),
("Ice/optional", ["once"]),
("IceBox/configuration", ["core", "noipv6"]),
diff --git a/java/build.xml b/java/build.xml
index 0c59f90231e..39a2311ca90 100644
--- a/java/build.xml
+++ b/java/build.xml
@@ -640,10 +640,20 @@
<compilerarg value="${javac.lint}"/>
</javac>
</target>
+
+ <target name="test-plugins-jar" depends="test-compile,freeze-jar">
+ <jar jarfile="${lib.dir}/IceTestPlugins.jar" basedir="${lib.dir}">
+ <include name="test/Ice/plugin/plugins/**"/>
+ <manifest>
+ <attribute name="Built-By" value="ZeroC, Inc."/>
+ </manifest>
+ </jar>
+ </target>
<target name="test-jar" depends="test-compile, ice-jar, freeze-jar, glacier2-jar, icebox-jar, icestorm-jar, icegrid-jar">
<jar jarfile="${lib.dir}/IceTest.jar" basedir="${lib.dir}">
<include name="test/**"/>
+ <exclude name="test/Ice/plugin/plugins/**"/>
<manifest>
<attribute name="Built-By" value="ZeroC, Inc."/>
<attribute name="Class-Path" value="Ice.jar"/>
diff --git a/java/src/Ice/PluginManagerI.java b/java/src/Ice/PluginManagerI.java
index e3c569f5f75..8445fb8e55f 100644
--- a/java/src/Ice/PluginManagerI.java
+++ b/java/src/Ice/PluginManagerI.java
@@ -29,10 +29,10 @@ public final class PluginManagerI implements PluginManager
java.util.List<Plugin> initializedPlugins = new java.util.ArrayList<Plugin>();
try
{
- for(Plugin p : _initOrder)
+ for(PluginInfo p : _plugins)
{
- p.initialize();
- initializedPlugins.add(p);
+ p.plugin.initialize();
+ initializedPlugins.add(p.plugin);
}
}
catch(RuntimeException ex)
@@ -64,9 +64,9 @@ public final class PluginManagerI implements PluginManager
getPlugins()
{
java.util.ArrayList<String> names = new java.util.ArrayList<String>();
- for(java.util.Map.Entry<String, Plugin> p : _plugins.entrySet())
+ for(PluginInfo p : _plugins)
{
- names.add(p.getKey());
+ names.add(p.name);
}
return names.toArray(new String[0]);
}
@@ -79,11 +79,12 @@ public final class PluginManagerI implements PluginManager
throw new CommunicatorDestroyedException();
}
- Plugin p = _plugins.get(name);
+ Plugin p = findPlugin(name);
if(p != null)
{
return p;
}
+
NotRegisteredException ex = new NotRegisteredException();
ex.id = name;
ex.kindOfObject = _kindOfObject;
@@ -98,14 +99,18 @@ public final class PluginManagerI implements PluginManager
throw new CommunicatorDestroyedException();
}
- if(_plugins.containsKey(name))
+ if(findPlugin(name) != null)
{
AlreadyRegisteredException ex = new AlreadyRegisteredException();
ex.id = name;
ex.kindOfObject = _kindOfObject;
throw ex;
}
- _plugins.put(name, plugin);
+
+ PluginInfo info = new PluginInfo();
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.add(info);
}
public synchronized void
@@ -115,28 +120,38 @@ public final class PluginManagerI implements PluginManager
{
if(_initialized)
{
- for(java.util.Map.Entry<String, Plugin> p : _plugins.entrySet())
+ java.util.ListIterator<PluginInfo> i = _plugins.listIterator(_plugins.size());
+ while(i.hasPrevious())
{
+ PluginInfo p = i.previous();
try
{
- p.getValue().destroy();
+ p.plugin.destroy();
}
catch(RuntimeException ex)
{
- Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" + p.getKey() +
- "' destruction:\n" + ex.toString());
+ Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" +
+ p.name + "' destruction:\n" + ex.toString());
}
}
}
_communicator = null;
}
+
+ _plugins.clear();
+
+ if(_classLoaders != null)
+ {
+ _classLoaders.clear();
+ }
}
public
- PluginManagerI(Communicator communicator)
+ PluginManagerI(Communicator communicator, IceInternal.Instance instance)
{
_communicator = communicator;
+ _instance = instance;
_initialized = false;
}
@@ -163,7 +178,7 @@ public final class PluginManagerI implements PluginManager
final String[] loadOrder = properties.getPropertyAsList("Ice.PluginLoadOrder");
for(String name : loadOrder)
{
- if(_plugins.containsKey(name))
+ if(findPlugin(name) != null)
{
PluginInitializationException ex = new PluginInitializationException();
ex.reason = "plug-in `" + name + "' already loaded";
@@ -181,7 +196,7 @@ public final class PluginManagerI implements PluginManager
key = "Ice.Plugin." + name;
hasKey = plugins.containsKey(key);
}
-
+
if(hasKey)
{
final String value = plugins.get(key);
@@ -222,10 +237,10 @@ public final class PluginManagerI implements PluginManager
name = name.substring(0, dotPos);
loadPlugin(name, entry.getValue(), cmdArgs);
p.remove();
-
+
//
// Don't want to load this one if it's there!
- //
+ //
plugins.remove("Ice.Plugin." + name);
}
else
@@ -236,7 +251,7 @@ public final class PluginManagerI implements PluginManager
dotPos = -1;
}
}
-
+
if(dotPos == -1)
{
//
@@ -250,7 +265,7 @@ public final class PluginManagerI implements PluginManager
{
value = javaValue;
}
-
+
loadPlugin(name, value, cmdArgs);
}
}
@@ -262,31 +277,88 @@ public final class PluginManagerI implements PluginManager
assert(_communicator != null);
//
- // Separate the entry point from the arguments.
+ // We support the following formats:
//
- String className;
+ // <class-name> [args]
+ // <jar-file>:<class-name> [args]
+ // <class-dir>:<class-name> [args]
+ // "<path with spaces>":<class-name> [args]
+ // "<path with spaces>:<class-name>" [args]
+ //
+
String[] args;
- int pos = pluginSpec.indexOf(' ');
- if(pos == -1)
+ try
{
- pos = pluginSpec.indexOf('\t');
+ args = IceUtilInternal.Options.split(pluginSpec);
}
- if(pos == -1)
+ catch(IceUtilInternal.Options.BadQuote ex)
+ {
+ throw new PluginInitializationException("invalid arguments for plug-in `" + name + "':\n" +
+ ex.getMessage());
+ }
+
+ assert(args.length > 0);
+
+ final String entryPoint = args[0];
+
+ final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
+ boolean absolutePath = false;
+
+ //
+ // Find first ':' that isn't part of the file path.
+ //
+ int pos = entryPoint.indexOf(':');
+ if(isWindows)
+ {
+ final String driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if(pos == 1 && entryPoint.length() > 2 && driveLetters.indexOf(entryPoint.charAt(0)) != -1 &&
+ (entryPoint.charAt(2) == '\\' || entryPoint.charAt(2) == '/'))
+ {
+ absolutePath = true;
+ pos = entryPoint.indexOf(':', pos + 1);
+ }
+ if(!absolutePath)
+ {
+ absolutePath = entryPoint.startsWith("\\\\");
+ }
+ }
+ else
+ {
+ absolutePath = entryPoint.startsWith("/");
+ }
+
+ if((pos == -1 && absolutePath) || (pos != -1 && entryPoint.length() <= pos + 1))
{
- pos = pluginSpec.indexOf('\n');
+ //
+ // Class name is missing.
+ //
+ throw new PluginInitializationException("invalid entry point for plug-in `" + name + "':\n" + entryPoint);
}
+
+ //
+ // Extract the JAR file or subdirectory, if any.
+ //
+ String classDir = null; // Path name of JAR file or subdirectory.
+ String className;
+
if(pos == -1)
{
- className = pluginSpec;
- args = new String[0];
+ className = entryPoint;
}
else
{
- className = pluginSpec.substring(0, pos);
- args = pluginSpec.substring(pos).trim().split("[ \t\n]+", pos);
+ classDir = entryPoint.substring(0, pos).trim();
+ className = entryPoint.substring(pos + 1).trim();
}
//
+ // Shift the arguments.
+ //
+ String[] tmp = new String[args.length - 1];
+ System.arraycopy(args, 1, tmp, 0, args.length - 1);
+ args = tmp;
+
+ //
// 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.
@@ -301,13 +373,85 @@ public final class PluginManagerI implements PluginManager
PluginFactory pluginFactory = null;
try
{
- Class<?> c = IceInternal.Util.getInstance(_communicator).findClass(className);
+ Class<?> c = null;
+
+ //
+ // Use a class loader if the user specified a JAR file or class directory.
+ //
+ if(classDir != null)
+ {
+ try
+ {
+ if(!absolutePath)
+ {
+ classDir = new java.io.File(System.getProperty("user.dir") + java.io.File.separator +
+ classDir).getCanonicalPath();
+ }
+
+ if(!classDir.endsWith(java.io.File.separator) && !classDir.toLowerCase().endsWith(".jar"))
+ {
+ classDir += java.io.File.separator;
+ }
+
+ //
+ // Reuse an existing class loader if we have already loaded a plug-in with
+ // the same value for classDir, otherwise create a new one.
+ //
+ ClassLoader cl = null;
+
+ if(_classLoaders == null)
+ {
+ _classLoaders = new java.util.HashMap<String, ClassLoader>();
+ }
+ else
+ {
+ cl = _classLoaders.get(classDir);
+ }
+
+ if(cl == null)
+ {
+ final java.net.URL[] url = new java.net.URL[] { new java.net.URL("file:///" + classDir) };
+
+ //
+ // Use the custom class loader (if any) as the parent.
+ //
+ if(_instance.initializationData().classLoader != null)
+ {
+ cl = new java.net.URLClassLoader(url, _instance.initializationData().classLoader);
+ }
+ else
+ {
+ cl = new java.net.URLClassLoader(url);
+ }
+
+ _classLoaders.put(classDir, cl);
+ }
+
+ c = cl.loadClass(className);
+ }
+ catch(java.net.MalformedURLException ex)
+ {
+ throw new PluginInitializationException("invalid entry point format `" + pluginSpec + "'", ex);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new PluginInitializationException("invalid path in entry point `" + pluginSpec + "'", ex);
+ }
+ catch(java.lang.ClassNotFoundException ex)
+ {
+ // Ignored
+ }
+ }
+ else
+ {
+ c = IceInternal.Util.getInstance(_communicator).findClass(className);
+ }
+
if(c == null)
{
- PluginInitializationException e = new PluginInitializationException();
- e.reason = "class " + className + " not found";
- throw e;
+ throw new PluginInitializationException("class " + className + " not found");
}
+
java.lang.Object obj = c.newInstance();
try
{
@@ -315,8 +459,8 @@ public final class PluginManagerI implements PluginManager
}
catch(ClassCastException ex)
{
- throw new PluginInitializationException(
- "class " + className + " does not implement Ice.PluginFactory", ex);
+ throw new PluginInitializationException("class " + className + " does not implement Ice.PluginFactory",
+ ex);
}
}
catch(IllegalAccessException ex)
@@ -344,18 +488,40 @@ public final class PluginManagerI implements PluginManager
{
throw new PluginInitializationException("exception in factory " + className, ex);
}
-
+
if(plugin == null)
{
throw new PluginInitializationException("failure in factory " + className);
}
- _plugins.put(name, plugin);
- _initOrder.add(plugin);
+ PluginInfo info = new PluginInfo();
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.add(info);
+ }
+
+ private Plugin
+ findPlugin(String name)
+ {
+ for(PluginInfo p : _plugins)
+ {
+ if(name.equals(p.name))
+ {
+ return p.plugin;
+ }
+ }
+ return null;
+ }
+
+ static class PluginInfo
+ {
+ String name;
+ Plugin plugin;
}
private Communicator _communicator;
- private java.util.Map<String, Plugin> _plugins = new java.util.HashMap<String, Plugin>();
- private java.util.List<Plugin> _initOrder = new java.util.ArrayList<Plugin>();
+ private IceInternal.Instance _instance;
+ private java.util.List<PluginInfo> _plugins = new java.util.ArrayList<PluginInfo>();
private boolean _initialized;
+ private java.util.Map<String, ClassLoader> _classLoaders;
}
diff --git a/java/src/IceBox/ServiceManagerI.java b/java/src/IceBox/ServiceManagerI.java
index 8811bb84932..aa066fb2e7e 100644
--- a/java/src/IceBox/ServiceManagerI.java
+++ b/java/src/IceBox/ServiceManagerI.java
@@ -214,7 +214,6 @@ public class ServiceManagerI extends _ServiceManagerDisp
"Added service observer " + _communicator.proxyToString(observer));
}
-
for(ServiceInfo info: _services)
{
if(info.status == StatusStarted)
@@ -222,7 +221,6 @@ public class ServiceManagerI extends _ServiceManagerDisp
activeServices.add(info.name);
}
}
-
}
}
@@ -355,7 +353,7 @@ public class ServiceManagerI extends _ServiceManagerDisp
for(StartServiceInfo s : servicesInfo)
{
- start(s.name, s.className, s.args);
+ start(s.name, s.className, s.classDir, s.absolutePath, s.args);
}
//
@@ -462,7 +460,7 @@ public class ServiceManagerI extends _ServiceManagerDisp
}
synchronized private void
- start(String service, String className, String[] args)
+ start(String service, String className, String classDir, boolean absolutePath, String[] args)
throws FailureException
{
//
@@ -475,12 +473,74 @@ public class ServiceManagerI extends _ServiceManagerDisp
try
{
- Class<?> c = IceInternal.Util.findClass(className, null);
+ Class<?> c = null;
+
+ //
+ // Use a class loader if the user specified a JAR file or class directory.
+ //
+ if(classDir != null)
+ {
+ try
+ {
+ if(!absolutePath)
+ {
+ classDir = new java.io.File(System.getProperty("user.dir") + java.io.File.separator +
+ classDir).getCanonicalPath();
+ }
+
+ if(!classDir.endsWith(java.io.File.separator) && !classDir.endsWith(".jar"))
+ {
+ classDir += java.io.File.separator;
+ }
+
+ //
+ // Reuse an existing class loader if we have already loaded a plug-in with
+ // the same value for classDir, otherwise create a new one.
+ //
+ ClassLoader cl = null;
+
+ if(_classLoaders == null)
+ {
+ _classLoaders = new java.util.HashMap<String, ClassLoader>();
+ }
+ else
+ {
+ cl = _classLoaders.get(classDir);
+ }
+
+ if(cl == null)
+ {
+ final java.net.URL[] url = new java.net.URL[] { new java.net.URL("file:///" + classDir) };
+
+ cl = new java.net.URLClassLoader(url);
+
+ _classLoaders.put(classDir, cl);
+ }
+
+ c = cl.loadClass(className);
+ }
+ catch(java.net.MalformedURLException ex)
+ {
+ throw new FailureException("ServiceManager: invalid entry point format `" + classDir + "'", ex);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new FailureException("ServiceManager: invalid path in plug-in entry point `" + classDir +
+ "'", ex);
+ }
+ catch(java.lang.ClassNotFoundException ex)
+ {
+ // Ignored
+ }
+ }
+ else
+ {
+ c = IceInternal.Util.findClass(className, null);
+ }
+
if(c == null)
{
- FailureException e = new FailureException();
- e.reason = "ServiceManager: class " + className + " not found";
- throw e;
+ throw new FailureException("ServiceManager: class " + className + " not found");
}
//
@@ -893,28 +953,85 @@ public class ServiceManagerI extends _ServiceManagerDisp
name = service;
//
- // Separate the entry point from the arguments.
+ // We support the following formats:
//
- int pos = IceUtilInternal.StringUtil.findFirstOf(value, " \t\n");
- if(pos == -1)
+ // <class-name> [args]
+ // <jar-file>:<class-name> [args]
+ // <class-dir>:<class-name> [args]
+ // "<path with spaces>":<class-name> [args]
+ // "<path with spaces>:<class-name>" [args]
+ //
+
+ try
{
- className = value;
- args = new String[0];
+ args = IceUtilInternal.Options.split(value);
}
- else
+ catch(IceUtilInternal.Options.BadQuote ex)
{
- className = value.substring(0, pos);
- try
+ throw new FailureException("ServiceManager: invalid arguments for service `" + name + "':\n" +
+ ex.getMessage());
+ }
+
+ assert(args.length > 0);
+
+ final String entryPoint = args[0];
+
+ final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
+ absolutePath = false;
+
+ //
+ // Find first ':' that isn't part of the file path.
+ //
+ int pos = entryPoint.indexOf(':');
+ if(isWindows)
+ {
+ final String driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if(pos == 1 && entryPoint.length() > 2 && driveLetters.indexOf(entryPoint.charAt(0)) != -1 &&
+ (entryPoint.charAt(2) == '\\' || entryPoint.charAt(2) == '/'))
{
- args = IceUtilInternal.Options.split(value.substring(pos));
+ absolutePath = true;
+ pos = entryPoint.indexOf(':', pos + 1);
}
- catch(IceUtilInternal.Options.BadQuote ex)
+ if(!absolutePath)
{
- FailureException e = new FailureException();
- e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.toString();
- throw e;
+ absolutePath = entryPoint.startsWith("\\\\");
}
}
+ else
+ {
+ absolutePath = entryPoint.startsWith("/");
+ }
+
+ if((pos == -1 && absolutePath) || (pos != -1 && entryPoint.length() <= pos + 1))
+ {
+ //
+ // Class name is missing.
+ //
+ throw new FailureException("ServiceManager: invalid entry point for service `" + name + "':\n" +
+ entryPoint);
+ }
+
+ //
+ // Extract the JAR file or subdirectory, if any.
+ //
+ classDir = null; // Path name of JAR file or subdirectory.
+
+ if(pos == -1)
+ {
+ className = entryPoint;
+ }
+ else
+ {
+ classDir = entryPoint.substring(0, pos).trim();
+ className = entryPoint.substring(pos + 1).trim();
+ }
+
+ //
+ // Shift the arguments.
+ //
+ String[] tmp = new String[args.length - 1];
+ System.arraycopy(args, 1, tmp, 0, args.length - 1);
+ args = tmp;
if(serverArgs.length > 0)
{
@@ -933,6 +1050,8 @@ public class ServiceManagerI extends _ServiceManagerDisp
String name;
String[] args;
String className;
+ String classDir;
+ boolean absolutePath;
}
private Ice.Properties
@@ -969,6 +1088,7 @@ public class ServiceManagerI extends _ServiceManagerDisp
private java.util.List<ServiceInfo> _services = new java.util.LinkedList<ServiceInfo>();
private boolean _pendingStatusChanges = false;
private Ice.Callback _observerCompletedCB;
- java.util.HashSet<ServiceObserverPrx> _observers = new java.util.HashSet<ServiceObserverPrx>();
- int _traceServiceObserver = 0;
+ private java.util.HashSet<ServiceObserverPrx> _observers = new java.util.HashSet<ServiceObserverPrx>();
+ private int _traceServiceObserver = 0;
+ private java.util.Map<String, ClassLoader> _classLoaders;
}
diff --git a/java/src/IceInternal/Instance.java b/java/src/IceInternal/Instance.java
index 7ca90d82144..4f1334be0b8 100644
--- a/java/src/IceInternal/Instance.java
+++ b/java/src/IceInternal/Instance.java
@@ -684,7 +684,7 @@ public final class Instance
EndpointFactory udpEndpointFactory = new UdpEndpointFactory(this);
_endpointFactoryManager.add(udpEndpointFactory);
- _pluginManager = new Ice.PluginManagerI(communicator);
+ _pluginManager = new Ice.PluginManagerI(communicator, this);
_outgoingConnectionFactory = new OutgoingConnectionFactory(communicator, this);
diff --git a/java/src/IceInternal/Util.java b/java/src/IceInternal/Util.java
index 6ecc0505a89..f4c383e6388 100644
--- a/java/src/IceInternal/Util.java
+++ b/java/src/IceInternal/Util.java
@@ -151,7 +151,6 @@ public final class Util
private static Class<?>
loadClass(String className, ClassLoader cl)
- throws LinkageError
{
if(cl != null)
{
diff --git a/java/test/Ice/plugin/Client.java b/java/test/Ice/plugin/Client.java
new file mode 100644
index 00000000000..db43197209c
--- /dev/null
+++ b/java/test/Ice/plugin/Client.java
@@ -0,0 +1,197 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin;
+
+import java.io.PrintWriter;
+
+public class Client extends test.Util.Application
+{
+ public int run(String[] args)
+ {
+ Ice.Communicator communicator = communicator();
+ PrintWriter printWriter = getWriter();
+ printWriter.print("testing a simple plug-in... ");
+ printWriter.flush();
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.Test",
+ "../../../lib/IceTestPlugins.jar:test.Ice.plugin.plugins.PluginFactory " +
+ "'C:\\Program Files\\' --DatabasePath 'C:\\Program Files\\Application\\db'");
+ communicator = Ice.Util.initialize(args, initData);
+ communicator.destroy();
+ }
+ catch(Ice.LocalException ex)
+ {
+ ex.printStackTrace();
+ test(false);
+ }
+ printWriter.println("ok");
+
+ printWriter.print("testing a simple plug-in that fails to initialize... ");
+ printWriter.flush();
+ communicator = null;
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.Test",
+ "../../../lib/:test.Ice.plugin.plugins.PluginInitializeFailFactory");
+ communicator = Ice.Util.initialize(args, initData);
+ test(false);
+ }
+ catch(RuntimeException ex)
+ {
+ test(ex.getMessage().equals("PluginInitializeFailException"));
+ }
+ test(communicator == null);
+ printWriter.println("ok");
+
+ printWriter.print("testing plug-in load order... ");
+ printWriter.flush();
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.PluginOne",
+ "../../../lib/:test.Ice.plugin.plugins.PluginOneFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginTwo",
+ "../../../lib/:test.Ice.plugin.plugins.PluginTwoFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThree",
+ "../../../lib/:test.Ice.plugin.plugins.PluginThreeFactory");
+ initData.properties.setProperty("Ice.PluginLoadOrder", "PluginOne, PluginTwo"); // Exclude PluginThree
+ communicator = Ice.Util.initialize(args, initData);
+ communicator.destroy();
+ }
+ catch(Ice.LocalException ex)
+ {
+ ex.printStackTrace();
+ test(false);
+ }
+ printWriter.println("ok");
+
+ printWriter.print("testing plug-in manager... ");
+ printWriter.flush();
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.PluginOne",
+ "../../../lib/:test.Ice.plugin.plugins.PluginOneFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginTwo",
+ "../../../lib/:test.Ice.plugin.plugins.PluginTwoFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThree",
+ "../../../lib/:test.Ice.plugin.plugins.PluginThreeFactory");
+ initData.properties.setProperty("Ice.PluginLoadOrder", "PluginOne, PluginTwo");
+ initData.properties.setProperty("Ice.InitPlugins", "0");
+ communicator = Ice.Util.initialize(args, initData);
+
+ Ice.PluginManager pm = communicator.getPluginManager();
+ test(pm.getPlugin("PluginOne") != null);
+ test(pm.getPlugin("PluginTwo") != null);
+ test(pm.getPlugin("PluginThree") != null);
+
+ MyPlugin p4 = new MyPlugin();
+ pm.addPlugin("PluginFour", p4);
+ test(pm.getPlugin("PluginFour") != null);
+
+ pm.initializePlugins();
+
+ test(p4.isInitialized());
+
+ communicator.destroy();
+
+ test(p4.isDestroyed());
+ }
+ catch(Ice.LocalException ex)
+ {
+ ex.printStackTrace();
+ test(false);
+ }
+ printWriter.println("ok");
+
+ printWriter.print("testing destroy when a plug-in fails to initialize... ");
+ printWriter.flush();
+ communicator = null;
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Plugin.PluginOneFail",
+ "../../../lib/:test.Ice.plugin.plugins.PluginOneFailFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginTwoFail",
+ "../../../lib/:test.Ice.plugin.plugins.PluginTwoFailFactory");
+ initData.properties.setProperty("Ice.Plugin.PluginThreeFail",
+ "../../../lib/:test.Ice.plugin.plugins.PluginThreeFailFactory");
+ initData.properties.setProperty("Ice.PluginLoadOrder", "PluginOneFail, PluginTwoFail, PluginThreeFail");
+ communicator = Ice.Util.initialize(args, initData);
+ }
+ catch(RuntimeException ex)
+ {
+ test(ex.getMessage().equals("PluginInitializeFailException"));
+ }
+ test(communicator == null);
+ printWriter.println("ok");
+
+ System.gc();
+ System.runFinalization();
+ return 0;
+ }
+
+ protected Ice.InitializationData getInitData(Ice.StringSeqHolder argsH)
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties(argsH);
+ return initData;
+ }
+
+ private static void test(boolean b)
+ {
+ if(!b)
+ {
+ throw new RuntimeException();
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ Client app = new Client();
+ int result = app.main("Client", args);
+ System.gc();
+ System.exit(result);
+ }
+
+ static class MyPlugin implements Ice.Plugin
+ {
+ public boolean isInitialized()
+ {
+ return _initialized;
+ }
+
+ public boolean isDestroyed()
+ {
+ return _destroyed;
+ }
+
+ public void initialize()
+ {
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ }
+
+ private boolean _initialized = false;
+ private boolean _destroyed = false;
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/BasePlugin.java b/java/test/Ice/plugin/plugins/BasePlugin.java
new file mode 100644
index 00000000000..da0d7000ca6
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/BasePlugin.java
@@ -0,0 +1,41 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public abstract class BasePlugin implements Ice.Plugin
+{
+ public BasePlugin(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ }
+
+ public boolean isInitialized()
+ {
+ return _initialized;
+ }
+
+ public boolean isDestroyed()
+ {
+ return _destroyed;
+ }
+
+ protected static void test(boolean b)
+ {
+ if(!b)
+ {
+ throw new RuntimeException();
+ }
+ }
+
+ protected Ice.Communicator _communicator;
+ protected boolean _initialized = false;
+ protected boolean _destroyed = false;
+ protected BasePlugin _other = null;
+}
diff --git a/java/test/Ice/plugin/plugins/BasePluginFail.java b/java/test/Ice/plugin/plugins/BasePluginFail.java
new file mode 100644
index 00000000000..bba0cc21760
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/BasePluginFail.java
@@ -0,0 +1,45 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public abstract class BasePluginFail implements Ice.Plugin
+{
+ public BasePluginFail(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ _initialized = false;
+ _destroyed = false;
+ }
+
+ public boolean isInitialized()
+ {
+ return _initialized;
+ }
+
+ public boolean isDestroyed()
+ {
+ return _destroyed;
+ }
+
+ protected static void test(boolean b)
+ {
+ if(!b)
+ {
+ throw new RuntimeException();
+ }
+ }
+
+ protected Ice.Communicator _communicator;
+ protected boolean _initialized;
+ protected boolean _destroyed;
+ protected BasePluginFail _one;
+ protected BasePluginFail _two;
+ protected BasePluginFail _three;
+}
diff --git a/java/test/Ice/plugin/plugins/PluginFactory.java b/java/test/Ice/plugin/plugins/PluginFactory.java
new file mode 100644
index 00000000000..dff16aa61f8
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginFactory.java
@@ -0,0 +1,73 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new Plugin(communicator, args);
+ }
+
+ static class Plugin implements Ice.Plugin
+ {
+ public Plugin(Ice.Communicator communicator, String[] args)
+ {
+ _communicator = communicator;
+ _args = args;
+ }
+
+ public void initialize()
+ {
+ _initialized = true;
+ test(_args.length == 3);
+ test(_args[0].equals("C:\\Program Files\\"));
+ test(_args[1].equals("--DatabasePath"));
+ test(_args[2].equals("C:\\Program Files\\Application\\db"));
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if(!_initialized)
+ {
+ System.out.println("test.Ice.plugin.plugins.Plugin not initialized");
+ }
+ if(!_destroyed)
+ {
+ System.out.println("test.Ice.plugin.plugins.Plugin not destroyed");
+ }
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private static void test(boolean b)
+ {
+ if(!b)
+ {
+ throw new RuntimeException();
+ }
+ }
+
+ private Ice.Communicator _communicator;
+ private String[] _args;
+ private boolean _initialized = false;
+ private boolean _destroyed = false;
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginInitializeFailException.java b/java/test/Ice/plugin/plugins/PluginInitializeFailException.java
new file mode 100644
index 00000000000..ed1700bc4e5
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginInitializeFailException.java
@@ -0,0 +1,18 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginInitializeFailException extends java.lang.RuntimeException
+{
+ public PluginInitializeFailException()
+ {
+ super("PluginInitializeFailException");
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginInitializeFailFactory.java b/java/test/Ice/plugin/plugins/PluginInitializeFailFactory.java
new file mode 100644
index 00000000000..a2e00176ed0
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginInitializeFailFactory.java
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginInitializeFailFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginInitializeFail();
+ }
+
+ static class PluginInitializeFail implements Ice.Plugin
+ {
+ public void initialize()
+ {
+ throw new PluginInitializeFailException();
+ }
+
+ public void destroy()
+ {
+ test(false);
+ }
+
+ private static void test(boolean b)
+ {
+ if(!b)
+ {
+ throw new RuntimeException();
+ }
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginOneFactory.java b/java/test/Ice/plugin/plugins/PluginOneFactory.java
new file mode 100644
index 00000000000..1101ae22f4f
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginOneFactory.java
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginOneFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginOne(communicator);
+ }
+
+ static class PluginOne extends BasePlugin
+ {
+ public PluginOne(Ice.Communicator communicator)
+ {
+ super(communicator);
+ }
+
+ public void initialize()
+ {
+ _other = (BasePlugin)_communicator.getPluginManager().getPlugin("PluginTwo");
+ test(!_other.isInitialized());
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ test(_other.isDestroyed());
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginOneFailFactory.java b/java/test/Ice/plugin/plugins/PluginOneFailFactory.java
new file mode 100644
index 00000000000..84a2db46af2
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginOneFailFactory.java
@@ -0,0 +1,64 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginOneFailFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginOneFail(communicator);
+ }
+
+ static class PluginOneFail extends BasePluginFail
+ {
+ public PluginOneFail(Ice.Communicator communicator)
+ {
+ super(communicator);
+ }
+
+ public void initialize()
+ {
+ _two = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginTwoFail");
+ test(!_two.isInitialized());
+ _three = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginThreeFail");
+ test(!_three.isInitialized());
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ test(_two.isDestroyed());
+ //
+ // Not destroyed because initialize fails.
+ //
+ test(!_three.isDestroyed());
+ _destroyed = true;
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if(!_initialized)
+ {
+ System.out.println(getClass().getName() + " not initialized");
+ }
+ if(!_destroyed)
+ {
+ System.out.println(getClass().getName() + " not destroyed");
+ }
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginThreeFactory.java b/java/test/Ice/plugin/plugins/PluginThreeFactory.java
new file mode 100644
index 00000000000..73eeccabd44
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginThreeFactory.java
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginThreeFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginThree(communicator);
+ }
+
+ static class PluginThree extends BasePlugin
+ {
+ public PluginThree(Ice.Communicator communicator)
+ {
+ super(communicator);
+ }
+
+ public void initialize()
+ {
+ _other = (BasePlugin)_communicator.getPluginManager().getPlugin("PluginTwo");
+ test(_other.isInitialized());
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ test(!_other.isDestroyed());
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginThreeFailFactory.java b/java/test/Ice/plugin/plugins/PluginThreeFailFactory.java
new file mode 100644
index 00000000000..846675fea12
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginThreeFailFactory.java
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginThreeFailFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginThreeFail(communicator);
+ }
+
+ public class PluginThreeFail extends BasePluginFail
+ {
+ public PluginThreeFail(Ice.Communicator communicator)
+ {
+ super(communicator);
+ }
+
+ public void initialize()
+ {
+ throw new PluginInitializeFailException();
+ }
+
+ public void destroy()
+ {
+ test(false);
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if(_initialized)
+ {
+ System.out.println(getClass().getName() + " was initialized");
+ }
+ if(_destroyed)
+ {
+ System.out.println(getClass().getName() + " was destroyed");
+ }
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginTwoFactory.java b/java/test/Ice/plugin/plugins/PluginTwoFactory.java
new file mode 100644
index 00000000000..7b8e970f07c
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginTwoFactory.java
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginTwoFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginTwo(communicator);
+ }
+
+ static class PluginTwo extends BasePlugin
+ {
+ public PluginTwo(Ice.Communicator communicator)
+ {
+ super(communicator);
+ }
+
+ public void initialize()
+ {
+ _other = (BasePlugin)_communicator.getPluginManager().getPlugin("PluginOne");
+ test(_other.isInitialized());
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ _destroyed = true;
+ test(!_other.isDestroyed());
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/plugins/PluginTwoFailFactory.java b/java/test/Ice/plugin/plugins/PluginTwoFailFactory.java
new file mode 100644
index 00000000000..80dd2fdf2f2
--- /dev/null
+++ b/java/test/Ice/plugin/plugins/PluginTwoFailFactory.java
@@ -0,0 +1,64 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package test.Ice.plugin.plugins;
+
+public class PluginTwoFailFactory implements Ice.PluginFactory
+{
+ public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginTwoFail(communicator);
+ }
+
+ static class PluginTwoFail extends BasePluginFail
+ {
+ public PluginTwoFail(Ice.Communicator communicator)
+ {
+ super(communicator);
+ }
+
+ public void initialize()
+ {
+ _one = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginOneFail");
+ test(_one.isInitialized());
+ _three = (BasePluginFail)_communicator.getPluginManager().getPlugin("PluginThreeFail");
+ test(!_three.isInitialized());
+ _initialized = true;
+ }
+
+ public void destroy()
+ {
+ test(!_one.isDestroyed());
+ //
+ // Not destroyed because initialize fails.
+ //
+ test(!_three.isDestroyed());
+ _destroyed = true;
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if(!_initialized)
+ {
+ System.out.println(getClass().getName() + " not initialized");
+ }
+ if(!_destroyed)
+ {
+ System.out.println(getClass().getName() + " not destroyed");
+ }
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+ }
+}
diff --git a/java/test/Ice/plugin/run.py b/java/test/Ice/plugin/run.py
new file mode 100755
index 00000000000..e4b27ab1226
--- /dev/null
+++ b/java/test/Ice/plugin/run.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+import os, sys
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ]
+if len(path) == 0:
+ raise "can't find toplevel directory!"
+sys.path.append(os.path.join(path[0]))
+from scripts import *
+
+print "starting test...",
+clientProc = TestUtil.startClient("test.Ice.plugin.Client",startReader=False)
+print "ok"
+clientProc.startReader()
+
+clientProc.waitTestSuccess()
+