summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/ReferenceFactory.cpp
diff options
context:
space:
mode:
authorJoe George <joe@zeroc.com>2015-03-03 17:30:50 -0500
committerJoe George <joe@zeroc.com>2015-05-12 11:41:55 -0400
commitd35bb9f5c19e34aee31f83d445695a8186ef675e (patch)
treed5324eaf44f5f9776495537c51653f50a66a7237 /cpp/src/Ice/ReferenceFactory.cpp
downloadice-d35bb9f5c19e34aee31f83d445695a8186ef675e.tar.bz2
ice-d35bb9f5c19e34aee31f83d445695a8186ef675e.tar.xz
ice-d35bb9f5c19e34aee31f83d445695a8186ef675e.zip
Ice 3.4.2 Source Distributionv3.4.2
Diffstat (limited to 'cpp/src/Ice/ReferenceFactory.cpp')
-rw-r--r--cpp/src/Ice/ReferenceFactory.cpp817
1 files changed, 817 insertions, 0 deletions
diff --git a/cpp/src/Ice/ReferenceFactory.cpp b/cpp/src/Ice/ReferenceFactory.cpp
new file mode 100644
index 00000000000..bf877e86f51
--- /dev/null
+++ b/cpp/src/Ice/ReferenceFactory.cpp
@@ -0,0 +1,817 @@
+// **********************************************************************
+//
+// 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/Communicator.h>
+#include <Ice/ReferenceFactory.h>
+#include <Ice/ProxyFactory.h>
+#include <Ice/LocalException.h>
+#include <Ice/Instance.h>
+#include <Ice/EndpointI.h>
+#include <Ice/ConnectionI.h>
+#include <Ice/EndpointFactoryManager.h>
+#include <Ice/RouterInfo.h>
+#include <Ice/Router.h>
+#include <Ice/LocatorInfo.h>
+#include <Ice/Locator.h>
+#include <Ice/LoggerUtil.h>
+#include <Ice/BasicStream.h>
+#include <Ice/Properties.h>
+#include <Ice/DefaultsAndOverrides.h>
+#include <Ice/PropertyNames.h>
+#include <IceUtil/StringUtil.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IceInternal;
+
+IceUtil::Shared* IceInternal::upCast(::IceInternal::ReferenceFactory* p) { return p; }
+
+ReferencePtr
+IceInternal::ReferenceFactory::copy(const Reference* r) const
+{
+ const Ice::Identity& ident = r->getIdentity();
+ if(ident.name.empty() && ident.category.empty())
+ {
+ return 0;
+ }
+
+ return r->clone();
+}
+
+ReferencePtr
+IceInternal::ReferenceFactory::create(const Identity& ident,
+ const string& facet,
+ const ReferencePtr& tmpl,
+ const vector<EndpointIPtr>& endpoints)
+{
+ if(ident.name.empty() && ident.category.empty())
+ {
+ return 0;
+ }
+
+ return create(ident, facet, tmpl->getMode(), tmpl->getSecure(), endpoints, "", "");
+}
+
+ReferencePtr
+IceInternal::ReferenceFactory::create(const Identity& ident,
+ const string& facet,
+ const ReferencePtr& tmpl,
+ const string& adapterId)
+{
+ if(ident.name.empty() && ident.category.empty())
+ {
+ return 0;
+ }
+
+ return create(ident, facet, tmpl->getMode(), tmpl->getSecure(), vector<EndpointIPtr>(), adapterId, "");
+}
+
+ReferencePtr
+IceInternal::ReferenceFactory::create(const Identity& ident, const Ice::ConnectionIPtr& connection)
+{
+ if(ident.name.empty() && ident.category.empty())
+ {
+ return 0;
+ }
+
+ //
+ // Create new reference
+ //
+ return new FixedReference(_instance,
+ _communicator,
+ ident,
+ "", // Facet
+ connection->endpoint()->datagram() ? Reference::ModeDatagram : Reference::ModeTwoway,
+ connection->endpoint()->secure(),
+ connection);
+}
+
+ReferencePtr
+IceInternal::ReferenceFactory::create(const string& str, const string& propertyPrefix)
+{
+ if(str.empty())
+ {
+ return 0;
+ }
+
+ const string delim = " \t\r\n";
+
+ string s(str);
+ string::size_type beg;
+ string::size_type end = 0;
+
+ beg = s.find_first_not_of(delim, end);
+ if(beg == string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "no non-whitespace characters found in `" + s + "'";
+ throw ex;
+ }
+
+ //
+ // Extract the identity, which may be enclosed in single
+ // or double quotation marks.
+ //
+ string idstr;
+ end = IceUtilInternal::checkQuote(s, beg);
+ if(end == string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "mismatched quotes around identity in `" + s + "'";
+ throw ex;
+ }
+ else if(end == 0)
+ {
+ end = s.find_first_of(delim + ":@", beg);
+ if(end == string::npos)
+ {
+ end = s.size();
+ }
+ idstr = s.substr(beg, end - beg);
+ }
+ else
+ {
+ beg++; // Skip leading quote
+ idstr = s.substr(beg, end - beg);
+ end++; // Skip trailing quote
+ }
+
+ if(beg == end)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "no identity in `" + s + "'";
+ throw ex;
+ }
+
+ //
+ // Parsing the identity may raise IdentityParseException.
+ //
+ Identity ident = _instance->stringToIdentity(idstr);
+ if(ident.name.empty())
+ {
+ //
+ // An identity with an empty name and a non-empty
+ // category is illegal.
+ //
+ if(!ident.category.empty())
+ {
+ IllegalIdentityException e(__FILE__, __LINE__);
+ e.id = ident;
+ throw e;
+ }
+ //
+ // Treat a stringified proxy containing two double
+ // quotes ("") the same as an empty string, i.e.,
+ // a null proxy, but only if nothing follows the
+ // quotes.
+ //
+ else if(s.find_first_not_of(delim, end) != string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "invalid characters after identity in `" + s + "'";
+ throw ex;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ string facet;
+ Reference::Mode mode = Reference::ModeTwoway;
+ bool secure = false;
+ string adapter;
+
+ while(true)
+ {
+ beg = s.find_first_not_of(delim, end);
+ if(beg == string::npos)
+ {
+ break;
+ }
+
+ if(s[beg] == ':' || s[beg] == '@')
+ {
+ break;
+ }
+
+ end = s.find_first_of(delim + ":@", beg);
+ if(end == string::npos)
+ {
+ end = s.length();
+ }
+
+ if(beg == end)
+ {
+ break;
+ }
+
+ string option = s.substr(beg, end - beg);
+ if(option.length() != 2 || option[0] != '-')
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "expected a proxy option but found `" + option + "' in `" + s + "'";
+ throw ex;
+ }
+
+ //
+ // Check for the presence of an option argument. The
+ // argument may be enclosed in single or double
+ // quotation marks.
+ //
+ string argument;
+ string::size_type argumentBeg = s.find_first_not_of(delim, end);
+ if(argumentBeg != string::npos)
+ {
+ if(s[argumentBeg] != '@' && s[argumentBeg] != ':' && s[argumentBeg] != '-')
+ {
+ beg = argumentBeg;
+ end = IceUtilInternal::checkQuote(s, beg);
+ if(end == string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "mismatched quotes around value for " + option + " option in `" + s + "'";
+ throw ex;
+ }
+ else if(end == 0)
+ {
+ end = s.find_first_of(delim + ":@", beg);
+ if(end == string::npos)
+ {
+ end = s.size();
+ }
+ argument = s.substr(beg, end - beg);
+ }
+ else
+ {
+ beg++; // Skip leading quote
+ argument = s.substr(beg, end - beg);
+ end++; // Skip trailing quote
+ }
+ }
+ }
+
+ //
+ // If any new options are added here,
+ // IceInternal::Reference::toString() and its derived classes must be updated as well.
+ //
+ switch(option[1])
+ {
+ case 'f':
+ {
+ if(argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "no argument provided for -f option in `" + s + "'";
+ throw ex;
+ }
+
+ try
+ {
+ facet = IceUtilInternal::unescapeString(argument, 0, argument.size());
+ }
+ catch(const IceUtil::IllegalArgumentException& e)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "invalid facet in `" + s + "': " + e.reason();
+ throw ex;
+ }
+
+ facet = Ice::UTF8ToNative(_instance->initializationData().stringConverter, facet);
+ break;
+ }
+
+ case 't':
+ {
+ if(!argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unexpected argument `" + argument + "' provided for -t option in `" + s + "'";
+ throw ex;
+ }
+ mode = Reference::ModeTwoway;
+ break;
+ }
+
+ case 'o':
+ {
+ if(!argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unexpected argument `" + argument + "' provided for -o option in `" + s + "'";
+ throw ex;
+ }
+ mode = Reference::ModeOneway;
+ break;
+ }
+
+ case 'O':
+ {
+ if(!argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unexpected argument `" + argument + "' provided for -O option in `" + s + "'";
+ throw ex;
+ }
+ mode = Reference::ModeBatchOneway;
+ break;
+ }
+
+ case 'd':
+ {
+ if(!argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unexpected argument `" + argument + "' provided for -d option in `" + s + "'";
+ throw ex;
+ }
+ mode = Reference::ModeDatagram;
+ break;
+ }
+
+ case 'D':
+ {
+ if(!argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unexpected argument `" + argument + "' provided for -D option in `" + s + "'";
+ throw ex;
+ }
+ mode = Reference::ModeBatchDatagram;
+ break;
+ }
+
+ case 's':
+ {
+ if(!argument.empty())
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unexpected argument `" + argument + "' provided for -s option in `" + s + "'";
+ throw ex;
+ }
+ secure = true;
+ break;
+ }
+
+ default:
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "unknown option `" + option + "' in `" + s + "'";
+ throw ex;
+ }
+ }
+ }
+
+
+ if(beg == string::npos)
+ {
+ return create(ident, facet, mode, secure, vector<EndpointIPtr>(), "", propertyPrefix);
+ }
+
+ vector<EndpointIPtr> endpoints;
+
+ switch(s[beg])
+ {
+ case ':':
+ {
+ vector<string> unknownEndpoints;
+ end = beg;
+
+ while(end < s.length() && s[end] == ':')
+ {
+ beg = end + 1;
+
+ end = beg;
+ while(true)
+ {
+ end = s.find(':', end);
+ if(end == string::npos)
+ {
+ end = s.length();
+ break;
+ }
+ else
+ {
+ bool quoted = false;
+ string::size_type quote = beg;
+ while(true)
+ {
+ quote = s.find('\"', quote);
+ if(quote == string::npos || end < quote)
+ {
+ break;
+ }
+ else
+ {
+ quote = s.find('\"', ++quote);
+ if(quote == string::npos)
+ {
+ break;
+ }
+ else if(end < quote)
+ {
+ quoted = true;
+ break;
+ }
+ ++quote;
+ }
+ }
+ if(!quoted)
+ {
+ break;
+ }
+ ++end;
+ }
+ }
+
+ string es = s.substr(beg, end - beg);
+ EndpointIPtr endp = _instance->endpointFactoryManager()->create(es, false);
+ if(endp != 0)
+ {
+ endpoints.push_back(endp);
+ }
+ else
+ {
+ unknownEndpoints.push_back(es);
+ }
+ }
+ if(endpoints.size() == 0)
+ {
+ assert(!unknownEndpoints.empty());
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "invalid endpoint `" + unknownEndpoints.front() + "' in `" + s + "'";
+ throw ex;
+ }
+ else if(unknownEndpoints.size() != 0 &&
+ _instance->initializationData().properties->
+ getPropertyAsIntWithDefault("Ice.Warn.Endpoints", 1) > 0)
+ {
+ Warning out(_instance->initializationData().logger);
+ out << "Proxy contains unknown endpoints:";
+ for(unsigned int idx = 0; idx < unknownEndpoints.size(); ++idx)
+ {
+ out << " `" << unknownEndpoints[idx] << "'";
+ }
+ }
+
+ return create(ident, facet, mode, secure, endpoints, "", propertyPrefix);
+ break;
+ }
+ case '@':
+ {
+ beg = s.find_first_not_of(delim, beg + 1);
+ if(beg == string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "missing adapter id in `" + s + "'";
+ throw ex;
+ }
+
+ string adapterstr;
+ end = IceUtilInternal::checkQuote(s, beg);
+ if(end == string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "mismatched quotes around adapter id in `" + s + "'";
+ throw ex;
+ }
+ else if(end == 0)
+ {
+ end = s.find_first_of(delim, beg);
+ if(end == string::npos)
+ {
+ end = s.size();
+ }
+ adapterstr = s.substr(beg, end - beg);
+ }
+ else
+ {
+ beg++; // Skip leading quote
+ adapterstr = s.substr(beg, end - beg);
+ end++; // Skip trailing quote.
+ }
+
+ // Check for trailing whitespace.
+ if(end != string::npos && s.find_first_not_of(delim, end) != string::npos)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "invalid trailing characters after `" + s.substr(0, end + 1) + "' in `" + s + "'";
+ throw ex;
+ }
+
+ try
+ {
+ adapter = IceUtilInternal::unescapeString(adapterstr, 0, adapterstr.size());
+ }
+ catch(const IceUtil::IllegalArgumentException& e)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "invalid adapter id in `" + s + "': " + e.reason();
+ throw ex;
+ }
+ if(adapter.size() == 0)
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "empty adapter id in `" + s + "'";
+ throw ex;
+ }
+
+ adapter = Ice::UTF8ToNative(_instance->initializationData().stringConverter, adapter);
+
+ return create(ident, facet, mode, secure, vector<EndpointIPtr>(), adapter, propertyPrefix);
+ break;
+ }
+ default:
+ {
+ ProxyParseException ex(__FILE__, __LINE__);
+ ex.str = "malformed proxy `" + s + "'";
+ throw ex;
+ }
+ }
+
+ return 0; // Unreachable, prevents compiler warning.
+}
+
+ReferencePtr
+IceInternal::ReferenceFactory::create(const Identity& ident, BasicStream* s)
+{
+ //
+ // Don't read the identity here. Operations calling this
+ // constructor read the identity, and pass it as a parameter.
+ //
+
+ if(ident.name.empty() && ident.category.empty())
+ {
+ return 0;
+ }
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ vector<string> facetPath;
+ s->read(facetPath);
+ string facet;
+ if(!facetPath.empty())
+ {
+ if(facetPath.size() > 1)
+ {
+ throw ProxyUnmarshalException(__FILE__, __LINE__);
+ }
+ facet.swap(facetPath[0]);
+ }
+
+ Byte modeAsByte;
+ s->read(modeAsByte);
+ Reference::Mode mode = static_cast<Reference::Mode>(modeAsByte);
+ if(mode < 0 || mode > Reference::ModeLast)
+ {
+ throw ProxyUnmarshalException(__FILE__, __LINE__);
+ }
+
+ bool secure;
+ s->read(secure);
+
+ vector<EndpointIPtr> endpoints;
+ string adapterId;
+
+ Ice::Int sz;
+ s->readSize(sz);
+
+ if(sz > 0)
+ {
+ endpoints.reserve(sz);
+ while(sz--)
+ {
+ EndpointIPtr endpoint = _instance->endpointFactoryManager()->read(s);
+ endpoints.push_back(endpoint);
+ }
+ }
+ else
+ {
+ s->read(adapterId);
+ }
+
+ return create(ident, facet, mode, secure, endpoints, adapterId, "");
+}
+
+ReferenceFactoryPtr
+IceInternal::ReferenceFactory::setDefaultRouter(const RouterPrx& defaultRouter)
+{
+ if(defaultRouter == _defaultRouter)
+ {
+ return this;
+ }
+
+ ReferenceFactoryPtr factory = new ReferenceFactory(_instance, _communicator);
+ factory->_defaultLocator = _defaultLocator;
+ factory->_defaultRouter = defaultRouter;
+ return factory;
+}
+
+RouterPrx
+IceInternal::ReferenceFactory::getDefaultRouter() const
+{
+ return _defaultRouter;
+}
+
+ReferenceFactoryPtr
+IceInternal::ReferenceFactory::setDefaultLocator(const LocatorPrx& defaultLocator)
+{
+ if(defaultLocator == _defaultLocator)
+ {
+ return this;
+ }
+
+ ReferenceFactoryPtr factory = new ReferenceFactory(_instance, _communicator);
+ factory->_defaultRouter = _defaultRouter;
+ factory->_defaultLocator = defaultLocator;
+ return factory;
+}
+
+LocatorPrx
+IceInternal::ReferenceFactory::getDefaultLocator() const
+{
+ return _defaultLocator;
+}
+
+IceInternal::ReferenceFactory::ReferenceFactory(const InstancePtr& instance, const CommunicatorPtr& communicator) :
+ _instance(instance),
+ _communicator(communicator)
+{
+}
+
+void
+IceInternal::ReferenceFactory::checkForUnknownProperties(const string& prefix)
+{
+ static const string suffixes[] =
+ {
+ "EndpointSelection",
+ "ConnectionCached",
+ "PreferSecure",
+ "LocatorCacheTimeout",
+ "Locator",
+ "Router",
+ "CollocationOptimized"
+ };
+
+ //
+ // Do not warn about unknown properties list if Ice prefix, ie Ice, Glacier2, etc
+ //
+ for(const char** i = IceInternal::PropertyNames::clPropNames; *i != 0; ++i)
+ {
+ if(prefix.find(*i) == 0)
+ {
+ return;
+ }
+ }
+
+ StringSeq unknownProps;
+ PropertyDict props = _instance->initializationData().properties->getPropertiesForPrefix(prefix + ".");
+ PropertyDict::const_iterator p;
+ for(p = props.begin(); p != props.end(); ++p)
+ {
+ bool valid = false;
+ for(unsigned int i = 0; i < sizeof(suffixes)/sizeof(*suffixes); ++i)
+ {
+ string prop = prefix + "." + suffixes[i];
+ if(p->first == prop)
+ {
+ valid = true;
+ break;
+ }
+ }
+
+ if(!valid)
+ {
+ unknownProps.push_back(p->first);
+ }
+ }
+
+ if(unknownProps.size())
+ {
+ Warning out(_instance->initializationData().logger);
+ out << "found unknown properties for proxy '" << prefix << "':";
+ for(unsigned int i = 0; i < unknownProps.size(); ++i)
+ {
+ out << "\n " << unknownProps[i];
+ }
+ }
+}
+
+RoutableReferencePtr
+IceInternal::ReferenceFactory::create(const Identity& ident,
+ const string& facet,
+ Reference::Mode mode,
+ bool secure,
+ const vector<EndpointIPtr>& endpoints,
+ const string& adapterId,
+ const string& propertyPrefix)
+{
+ DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
+
+ //
+ // Default local proxy options.
+ //
+ LocatorInfoPtr locatorInfo = _instance->locatorManager()->get(_defaultLocator);
+ RouterInfoPtr routerInfo = _instance->routerManager()->get(_defaultRouter);
+ bool collocationOptimized = defaultsAndOverrides->defaultCollocationOptimization;
+ bool cacheConnection = true;
+ bool preferSecure = defaultsAndOverrides->defaultPreferSecure;
+ Ice::EndpointSelectionType endpointSelection = defaultsAndOverrides->defaultEndpointSelection;
+ int locatorCacheTimeout = defaultsAndOverrides->defaultLocatorCacheTimeout;
+
+ //
+ // Override the defaults with the proxy properties if a property prefix is defined.
+ //
+ if(!propertyPrefix.empty())
+ {
+ PropertiesPtr properties = _instance->initializationData().properties;
+ if(properties->getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
+ {
+ checkForUnknownProperties(propertyPrefix);
+ }
+
+ string property;
+
+ property = propertyPrefix + ".Locator";
+ LocatorPrx locator = LocatorPrx::uncheckedCast(_communicator->propertyToProxy(property));
+ if(locator)
+ {
+ locatorInfo = _instance->locatorManager()->get(locator);
+ }
+
+ property = propertyPrefix + ".Router";
+ RouterPrx router = RouterPrx::uncheckedCast(_communicator->propertyToProxy(property));
+ if(router)
+ {
+ if(propertyPrefix.size() > 7 && propertyPrefix.substr(propertyPrefix.size() - 7, 7) == ".Router")
+ {
+ Warning out(_instance->initializationData().logger);
+ out << "`" << property << "=" << properties->getProperty(property)
+ << "': cannot set a router on a router; setting ignored";
+ }
+ else
+ {
+ routerInfo = _instance->routerManager()->get(router);
+ }
+ }
+
+ property = propertyPrefix + ".CollocationOptimized";
+ collocationOptimized = properties->getPropertyAsIntWithDefault(property, collocationOptimized) > 0;
+
+ property = propertyPrefix + ".ConnectionCached";
+ cacheConnection = properties->getPropertyAsIntWithDefault(property, cacheConnection) > 0;
+
+ property = propertyPrefix + ".PreferSecure";
+ preferSecure = properties->getPropertyAsIntWithDefault(property, preferSecure) > 0;
+
+ property = propertyPrefix + ".EndpointSelection";
+ if(!properties->getProperty(property).empty())
+ {
+ string type = properties->getProperty(property);
+ if(type == "Random")
+ {
+ endpointSelection = Random;
+ }
+ else if(type == "Ordered")
+ {
+ endpointSelection = Ordered;
+ }
+ else
+ {
+ EndpointSelectionTypeParseException ex(__FILE__, __LINE__);
+ ex.str = "illegal value `" + type + "'; expected `Random' or `Ordered'";
+ throw ex;
+ }
+ }
+
+ property = propertyPrefix + ".LocatorCacheTimeout";
+ locatorCacheTimeout = properties->getPropertyAsIntWithDefault(property, locatorCacheTimeout);
+ }
+
+ //
+ // Create new reference
+ //
+ return new RoutableReference(_instance,
+ _communicator,
+ ident,
+ facet,
+ mode,
+ secure,
+ endpoints,
+ adapterId,
+ locatorInfo,
+ routerInfo,
+ collocationOptimized,
+ cacheConnection,
+ preferSecure,
+ endpointSelection,
+ locatorCacheTimeout);
+}
+