summaryrefslogtreecommitdiff
path: root/php/src/php5/Communicator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'php/src/php5/Communicator.cpp')
-rw-r--r--php/src/php5/Communicator.cpp771
1 files changed, 587 insertions, 184 deletions
diff --git a/php/src/php5/Communicator.cpp b/php/src/php5/Communicator.cpp
index c1002bd046b..a541b426ebe 100644
--- a/php/src/php5/Communicator.cpp
+++ b/php/src/php5/Communicator.cpp
@@ -13,6 +13,7 @@
#include <Proxy.h>
#include <Types.h>
#include <Util.h>
+#include <IceUtil/DisableWarnings.h>
#include <IceUtil/Options.h>
#include <IceUtil/MutexPtrLock.h>
#include <IceUtil/StringUtil.h>
@@ -30,6 +31,7 @@ namespace IcePHP
{
zend_class_entry* communicatorClassEntry = 0;
+zend_class_entry* valueFactoryManagerClassEntry = 0;
//
// An active communicator is in use by at least one request and may have
@@ -51,8 +53,19 @@ public:
};
typedef IceUtil::Handle<ActiveCommunicator> ActiveCommunicatorPtr;
-typedef std::map<std::string, zval*> ObjectFactoryMap;
+class FactoryWrapper;
+typedef IceUtil::Handle<FactoryWrapper> FactoryWrapperPtr;
+class DefaultValueFactory;
+typedef IceUtil::Handle<DefaultValueFactory> DefaultValueFactoryPtr;
+
+//
+// CommunicatorInfoI encapsulates communicator-related information that
+// is specific to a PHP "request". In other words, multiple PHP requests
+// might share the same communicator instance but still need separate
+// workspaces. For example, we don't want the value factories installed
+// by one request to influence the behavior of another request.
+//
class CommunicatorInfoI : public CommunicatorInfo
{
public:
@@ -65,44 +78,110 @@ public:
virtual Ice::CommunicatorPtr getCommunicator() const;
- bool addObjectFactory(const std::string&, zval* TSRMLS_DC);
- bool findObjectFactory(const std::string&, zval* TSRMLS_DC);
- void destroyObjectFactories(TSRMLS_D);
+ bool addFactory(zval*, const string&, bool TSRMLS_DC);
+ FactoryWrapperPtr findFactory(const string&) const;
+ Ice::ValueFactoryPtr defaultFactory() const { return _defaultFactory; }
+ void destroyFactories(TSRMLS_D);
const ActiveCommunicatorPtr ac;
const zval zv;
- ObjectFactoryMap objectFactories;
+
+private:
+
+ typedef map<string, FactoryWrapperPtr> FactoryMap;
+
+ FactoryMap _factories;
+ DefaultValueFactoryPtr _defaultFactory;
};
typedef IceUtil::Handle<CommunicatorInfoI> CommunicatorInfoIPtr;
//
-// Each PHP request has its own set of object factories. More precisely, there is
-// an object factory map for each communicator that is created by a PHP request.
-// The factory class defined below delegates the create/destroy methods to PHP
-// objects supplied by the application. An instance of this class is installed
-// as the communicator's default object factory, and the class holds a reference
-// to its communicator. When create is invoked, the class resolves the appropriate
-// PHP object as follows:
+// Wraps a PHP object/value factory.
+//
+class FactoryWrapper : public Ice::ValueFactory
+{
+public:
+
+ FactoryWrapper(zval*, bool, const CommunicatorInfoIPtr&);
+
+ virtual Ice::ValuePtr create(const string&);
+
+ void getZval(zval* TSRMLS_DC);
+
+ bool isObjectFactory() const;
+
+ void destroy(TSRMLS_D);
+
+protected:
+
+ zval* _factory;
+ bool _isObjectFactory;
+ CommunicatorInfoIPtr _info;
+};
+
+//
+// Implements the default value factory behavior.
+//
+class DefaultValueFactory : public Ice::ValueFactory
+{
+public:
+
+ DefaultValueFactory(const CommunicatorInfoIPtr&);
+
+ virtual Ice::ValuePtr create(const string&);
+
+ void setDelegate(const FactoryWrapperPtr& d) { _delegate = d; }
+ FactoryWrapperPtr getDelegate() const { return _delegate; }
+
+ void destroy(TSRMLS_D);
+
+private:
+
+ FactoryWrapperPtr _delegate;
+ CommunicatorInfoIPtr _info;
+};
+
+//
+// Each PHP request has its own set of value factories. More precisely, there is
+// a value factory map for each communicator that is created by a PHP request.
+// (see CommunicatorInfoI).
+//
+// We define a custom value factory manager implementation that delegates to
+// to PHP objects supplied by the application.
+//
+// An instance of this class is installed as the communicator's value factory
+// manager, and the class holds a reference to its communicator. When find() is
+// invoked, the class resolves the appropriate factory as follows:
//
// * Using its communicator reference as the key, look up the corresponding
// CommunicatorInfoI object in the request-specific communicator map.
//
-// * In the object factory map held by the CommunicatorInfoI object, look for a
-// PHP factory object using the same algorithm as the Ice core.
+// * If the type-id is empty, return the default factory. This factory will
+// either delegate to an application-supplied default factory (if present) or
+// default-construct an instance of a concrete Slice class type.
+//
+// * For non-empty type-ids, return a wrapper around the application-supplied
+// factory, if any.
//
-class ObjectFactoryI : public Ice::ObjectFactory
+class ValueFactoryManager : public Ice::ValueFactoryManager
{
public:
- ObjectFactoryI(const Ice::CommunicatorPtr&);
+ virtual void add(const Ice::ValueFactoryPtr&, const string&);
+ virtual Ice::ValueFactoryPtr find(const string&) const;
- virtual Ice::ObjectPtr create(const std::string&);
- virtual void destroy();
+ void setCommunicator(const Ice::CommunicatorPtr& c) { _communicator = c; }
+ Ice::CommunicatorPtr getCommunicator() const { return _communicator; }
+
+ void getZval(zval* TSRMLS_DC);
+
+ void destroy();
private:
Ice::CommunicatorPtr _communicator;
};
+typedef IceUtil::Handle<ValueFactoryManager> ValueFactoryManagerPtr;
class ReaperTask : public IceUtil::TimerTask
{
@@ -121,6 +200,11 @@ namespace
zend_object_handlers _handlers;
//
+// ValueFactoryManager support.
+//
+zend_object_handlers _vfmHandlers;
+
+//
// The profile map holds Properties objects corresponding to the "default" profile
// (defined via the ice.config & ice.options settings in php.ini) as well as named
// profiles defined in an external file.
@@ -154,7 +238,7 @@ public:
{
_registeredCommunicatorsMutex = new IceUtil::Mutex();
}
-
+
~Init()
{
delete _registeredCommunicatorsMutex;
@@ -170,6 +254,10 @@ extern "C"
static zend_object_value handleAlloc(zend_class_entry* TSRMLS_DC);
static void handleFreeStorage(void* TSRMLS_DC);
static zend_object_value handleClone(zval* TSRMLS_DC);
+
+static zend_object_value handleVfmAlloc(zend_class_entry* TSRMLS_DC);
+static void handleVfmFreeStorage(void* TSRMLS_DC);
+static zend_object_value handleVfmClone(zval* TSRMLS_DC);
}
ZEND_METHOD(Ice_Communicator, __construct)
@@ -195,9 +283,9 @@ ZEND_METHOD(Ice_Communicator, destroy)
}
//
- // We need to destroy any object factories installed by this request.
+ // We need to destroy any object|value factories installed by this request.
//
- _this->destroyObjectFactories(TSRMLS_C);
+ _this->destroyFactories(TSRMLS_C);
Ice::CommunicatorPtr c = _this->getCommunicator();
assert(c);
@@ -206,6 +294,10 @@ ZEND_METHOD(Ice_Communicator, destroy)
assert(m->find(c) != m->end());
m->erase(c);
+ ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(c->getValueFactoryManager());
+ assert(vfm);
+ vfm->destroy();
+
try
{
c->destroy();
@@ -262,7 +354,7 @@ ZEND_METHOD(Ice_Communicator, proxyToString)
if(zv)
{
Ice::ObjectPrx prx;
- ClassInfoPtr info;
+ ProxyInfoPtr info;
if(!fetchProxy(zv, prx, info TSRMLS_CC))
{
RETURN_NULL();
@@ -328,13 +420,13 @@ ZEND_METHOD(Ice_Communicator, proxyToProperty)
if(zv)
{
Ice::ObjectPrx prx;
- ClassInfoPtr info;
+ ProxyInfoPtr info;
if(!fetchProxy(zv, prx, info TSRMLS_CC))
{
RETURN_NULL();
}
assert(prx);
-
+
Ice::PropertyDict val = _this->getCommunicator()->proxyToProperty(prx, prefix);
if(!createStringMap(return_value, val TSRMLS_CC))
{
@@ -435,7 +527,7 @@ ZEND_METHOD(Ice_Communicator, addObjectFactory)
type = string(id, idLen);
}
- if(!_this->addObjectFactory(type, factory TSRMLS_CC))
+ if(!_this->addFactory(factory, type, true TSRMLS_CC))
{
RETURN_NULL();
}
@@ -459,8 +551,45 @@ ZEND_METHOD(Ice_Communicator, findObjectFactory)
type = string(id, idLen);
}
- if(!_this->findObjectFactory(type, return_value TSRMLS_CC))
+ FactoryWrapperPtr w = _this->findFactory(type);
+ if(w && w->isObjectFactory())
+ {
+ w->getZval(return_value TSRMLS_CC);
+ }
+ else
+ {
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_Communicator, getValueFactoryManager)
+{
+ if(ZEND_NUM_ARGS() > 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ try
+ {
+ ValueFactoryManagerPtr vfm =
+ ValueFactoryManagerPtr::dynamicCast(_this->getCommunicator()->getValueFactoryManager());
+ assert(vfm);
+ if(object_init_ex(return_value, valueFactoryManagerClassEntry) != SUCCESS)
+ {
+ runtimeError("unable to initialize properties object" TSRMLS_CC);
+ RETURN_NULL();
+ }
+
+ Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::extract(return_value TSRMLS_CC);
+ assert(!obj->ptr);
+ obj->ptr = new ValueFactoryManagerPtr(vfm);
+ }
+ catch(const IceUtil::Exception& ex)
{
+ throwException(ex TSRMLS_CC);
RETURN_NULL();
}
}
@@ -501,7 +630,7 @@ ZEND_METHOD(Ice_Communicator, getLogger)
{
WRONG_PARAM_COUNT;
}
-
+
CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC);
assert(_this);
@@ -535,7 +664,7 @@ ZEND_METHOD(Ice_Communicator, getDefaultRouter)
Ice::RouterPrx router = _this->getCommunicator()->getDefaultRouter();
if(router)
{
- ClassInfoPtr info = getClassInfoById("::Ice::Router" TSRMLS_CC);
+ ProxyInfoPtr info = getProxyInfo("::Ice::Router" TSRMLS_CC);
if(!info)
{
runtimeError("no definition for Ice::Router" TSRMLS_CC);
@@ -571,7 +700,7 @@ ZEND_METHOD(Ice_Communicator, setDefaultRouter)
}
Ice::ObjectPrx proxy;
- ClassInfoPtr info;
+ ProxyInfoPtr info;
if(zv && !fetchProxy(zv, proxy, info TSRMLS_CC))
{
RETURN_NULL();
@@ -613,7 +742,7 @@ ZEND_METHOD(Ice_Communicator, getDefaultLocator)
Ice::LocatorPrx locator = _this->getCommunicator()->getDefaultLocator();
if(locator)
{
- ClassInfoPtr info = getClassInfoById("::Ice::Locator" TSRMLS_CC);
+ ProxyInfoPtr info = getProxyInfo("::Ice::Locator" TSRMLS_CC);
if(!info)
{
runtimeError("no definition for Ice::Locator" TSRMLS_CC);
@@ -649,7 +778,7 @@ ZEND_METHOD(Ice_Communicator, setDefaultLocator)
}
Ice::ObjectPrx proxy;
- ClassInfoPtr info;
+ ProxyInfoPtr info;
if(zv && !fetchProxy(zv, proxy, info TSRMLS_CC))
{
RETURN_NULL();
@@ -678,17 +807,25 @@ ZEND_METHOD(Ice_Communicator, setDefaultLocator)
ZEND_METHOD(Ice_Communicator, flushBatchRequests)
{
- CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC);
- assert(_this);
+ zval* compress;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("z"), &compress TSRMLS_CC) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
- if(ZEND_NUM_ARGS() != 8)
+ if(Z_TYPE_P(compress) != IS_LONG)
{
- WRONG_PARAM_COUNT;
+ invalidArgument("value for 'compress' argument must be an enumerator of CompressBatch" TSRMLS_CC);
+ RETURN_NULL();
}
+ Ice::CompressBatch cb = static_cast<Ice::CompressBatch>(Z_LVAL_P(compress));
+
+ CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
try
{
- _this->getCommunicator()->flushBatchRequests();
+ _this->getCommunicator()->flushBatchRequests(cb);
}
catch(const IceUtil::Exception& ex)
{
@@ -697,6 +834,83 @@ ZEND_METHOD(Ice_Communicator, flushBatchRequests)
}
}
+ZEND_METHOD(Ice_ValueFactoryManager, __construct)
+{
+ runtimeError("value factory managers cannot be instantiated directly" TSRMLS_CC);
+}
+
+ZEND_METHOD(Ice_ValueFactoryManager, add)
+{
+ ValueFactoryManagerPtr _this = Wrapper<ValueFactoryManagerPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ zend_class_entry* factoryClass = idToClass("Ice::ValueFactory" TSRMLS_CC);
+ assert(factoryClass);
+
+ zval* factory;
+ char* id;
+ int idLen;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("Os!"), &factory, factoryClass, &id,
+ &idLen TSRMLS_CC) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ string type;
+ if(id)
+ {
+ type = string(id, idLen);
+ }
+
+ CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap));
+ assert(m);
+ CommunicatorMap::iterator p = m->find(_this->getCommunicator());
+ assert(p != m->end());
+
+ CommunicatorInfoIPtr info = p->second;
+
+ if(!info->addFactory(factory, type, false TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+}
+
+ZEND_METHOD(Ice_ValueFactoryManager, find)
+{
+ ValueFactoryManagerPtr _this = Wrapper<ValueFactoryManagerPtr>::value(getThis() TSRMLS_CC);
+ assert(_this);
+
+ char* id;
+ int idLen;
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!"), &id, &idLen TSRMLS_CC) != SUCCESS)
+ {
+ RETURN_NULL();
+ }
+
+ string type;
+ if(id)
+ {
+ type = string(id, idLen);
+ }
+
+ CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap));
+ assert(m);
+ CommunicatorMap::iterator p = m->find(_this->getCommunicator());
+ assert(p != m->end());
+
+ CommunicatorInfoIPtr info = p->second;
+
+ FactoryWrapperPtr w = info->findFactory(type);
+ if(w)
+ {
+ w->getZval(return_value TSRMLS_CC);
+ }
+ else
+ {
+ RETURN_NULL();
+ }
+}
+
#ifdef _WIN32
extern "C"
#endif
@@ -736,6 +950,46 @@ handleClone(zval* zv TSRMLS_DC)
return zend_object_value();
}
+#ifdef _WIN32
+extern "C"
+#endif
+static zend_object_value
+handleVfmAlloc(zend_class_entry* ce TSRMLS_DC)
+{
+ zend_object_value result;
+
+ Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::create(ce TSRMLS_CC);
+ assert(obj);
+
+ result.handle =
+ zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleVfmFreeStorage, 0 TSRMLS_CC);
+ result.handlers = &_vfmHandlers;
+
+ return result;
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static void
+handleVfmFreeStorage(void* p TSRMLS_DC)
+{
+ Wrapper<ValueFactoryManagerPtr>* obj = static_cast<Wrapper<ValueFactoryManagerPtr>*>(p);
+ delete obj->ptr;
+ zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC);
+ efree(p);
+}
+
+#ifdef _WIN32
+extern "C"
+#endif
+static zend_object_value
+handleVfmClone(zval* zv TSRMLS_DC)
+{
+ php_error_docref(0 TSRMLS_CC, E_ERROR, "value factory managers cannot be cloned");
+ return zend_object_value();
+}
+
static CommunicatorInfoIPtr
createCommunicator(zval* zv, const ActiveCommunicatorPtr& ac TSRMLS_DC)
{
@@ -791,10 +1045,9 @@ initializeCommunicator(zval* zv, Ice::StringSeq& args, bool hasArgs, const Ice::
ActiveCommunicatorPtr ac = new ActiveCommunicator(c);
- //
- // Install a default object factory that delegates to PHP factories.
- //
- c->addObjectFactory(new ObjectFactoryI(c), "");
+ ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(c->getValueFactoryManager());
+ assert(vfm);
+ vfm->setCommunicator(c);
CommunicatorInfoIPtr info = createCommunicator(zv, ac TSRMLS_CC);
if(!info)
@@ -806,6 +1059,8 @@ initializeCommunicator(zval* zv, Ice::StringSeq& args, bool hasArgs, const Ice::
catch(...)
{
}
+
+ vfm->destroy();
}
return info;
@@ -897,7 +1152,8 @@ ZEND_FUNCTION(Ice_initialize)
string member;
member = "properties";
- if(zend_hash_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), static_cast<uint>(member.size() + 1), &data) == SUCCESS)
+ if(zend_hash_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), static_cast<uint>(member.size() + 1), &data)
+ == SUCCESS)
{
zval** val = reinterpret_cast<zval**>(data);
if(!fetchProperties(*val, initData.properties TSRMLS_CC))
@@ -907,7 +1163,8 @@ ZEND_FUNCTION(Ice_initialize)
}
member = "logger";
- if(zend_hash_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), static_cast<uint>(member.size() + 1), &data) == SUCCESS)
+ if(zend_hash_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), static_cast<uint>(member.size() + 1), &data)
+ == SUCCESS)
{
zval** val = reinterpret_cast<zval**>(data);
if(!fetchLogger(*val, initData.logger TSRMLS_CC))
@@ -918,6 +1175,7 @@ ZEND_FUNCTION(Ice_initialize)
}
initData.compactIdResolver = new IdResolver(TSRMLS_C);
+ initData.valueFactoryManager = new ValueFactoryManager;
CommunicatorInfoIPtr info = initializeCommunicator(return_value, seq, hasArgs, initData TSRMLS_CC);
if(!info)
@@ -1115,7 +1373,9 @@ ZEND_FUNCTION(Ice_identityToString)
assert(identityClass);
zval* zv;
- if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, identityClass) != SUCCESS)
+ long mode = 0;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O|l"), &zv, identityClass, &mode TSRMLS_CC) != SUCCESS)
{
RETURN_NULL();
}
@@ -1127,7 +1387,7 @@ ZEND_FUNCTION(Ice_identityToString)
try
{
- string str = Ice::identityToString(id);
+ string str = identityToString(id, static_cast<Ice::ToStringMode>(mode));
RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1);
}
catch(const IceUtil::Exception& ex)
@@ -1179,24 +1439,40 @@ static zend_function_entry _interfaceMethods[] =
};
static zend_function_entry _classMethods[] =
{
- ZEND_ME(Ice_Communicator, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
- ZEND_ME(Ice_Communicator, destroy, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, stringToProxy, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, proxyToString, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, propertyToProxy, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, proxyToProperty, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, stringToIdentity, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, identityToString, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, addObjectFactory, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, findObjectFactory, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, getImplicitContext, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, getProperties, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, getLogger, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, getDefaultRouter, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, setDefaultRouter, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, getDefaultLocator, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, setDefaultLocator, NULL, ZEND_ACC_PUBLIC)
- ZEND_ME(Ice_Communicator, flushBatchRequests, NULL, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
+ ZEND_ME(Ice_Communicator, destroy, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, stringToProxy, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, proxyToString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, propertyToProxy, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, proxyToProperty, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, stringToIdentity, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, identityToString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, addObjectFactory, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, findObjectFactory, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, getValueFactoryManager, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, getImplicitContext, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, getProperties, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, getLogger, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, getDefaultRouter, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, setDefaultRouter, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, getDefaultLocator, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, setDefaultLocator, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_Communicator, flushBatchRequests, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ {0, 0, 0}
+};
+
+//
+// Predefined methods for ValueFactoryManager.
+//
+static zend_function_entry _vfmInterfaceMethods[] =
+{
+ {0, 0, 0}
+};
+static zend_function_entry _vfmClassMethods[] =
+{
+ ZEND_ME(Ice_ValueFactoryManager, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
+ ZEND_ME(Ice_ValueFactoryManager, add, ICE_NULLPTR, ZEND_ACC_PUBLIC)
+ ZEND_ME(Ice_ValueFactoryManager, find, ICE_NULLPTR, ZEND_ACC_PUBLIC)
{0, 0, 0}
};
@@ -1410,6 +1686,26 @@ IcePHP::communicatorInit(TSRMLS_D)
zend_class_implements(communicatorClassEntry TSRMLS_CC, 1, interface);
//
+ // Register the ValueFactoryManager interface.
+ //
+#ifdef ICEPHP_USE_NAMESPACES
+ INIT_NS_CLASS_ENTRY(ce, "Ice", "ValueFactoryManager", _vfmInterfaceMethods);
+#else
+ INIT_CLASS_ENTRY(ce, "Ice_ValueFactoryManager", _vfmInterfaceMethods);
+#endif
+ zend_class_entry* vfmInterface = zend_register_internal_interface(&ce TSRMLS_CC);
+
+ //
+ // Register the ValueFactoryManager class.
+ //
+ INIT_CLASS_ENTRY(ce, "IcePHP_ValueFactoryManager", _vfmClassMethods);
+ ce.create_object = handleVfmAlloc;
+ valueFactoryManagerClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
+ memcpy(&_vfmHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ _vfmHandlers.clone_obj = handleVfmClone;
+ zend_class_implements(valueFactoryManagerClassEntry TSRMLS_CC, 1, vfmInterface);
+
+ //
// Create the profiles from configuration settings.
//
const char* empty = "";
@@ -1501,9 +1797,9 @@ IcePHP::communicatorRequestShutdown(TSRMLS_D)
CommunicatorInfoIPtr info = p->second;
//
- // We need to destroy any object factories installed during this request.
+ // We need to destroy any object|value factories installed during this request.
//
- info->destroyObjectFactories(TSRMLS_C);
+ info->destroyFactories(TSRMLS_C);
}
//
@@ -1536,121 +1832,131 @@ IcePHP::ActiveCommunicator::~ActiveCommunicator()
}
}
-IcePHP::CommunicatorInfoI::CommunicatorInfoI(const ActiveCommunicatorPtr& c, zval* z) :
- ac(c),
- zv(*z) // This is legal - it simply copies the object's handle.
+IcePHP::FactoryWrapper::FactoryWrapper(zval* factory, bool isObjectFactory, const CommunicatorInfoIPtr& info) :
+ _factory(factory),
+ _isObjectFactory(isObjectFactory),
+ _info(info)
{
+ Z_ADDREF_P(_factory);
}
-void
-IcePHP::CommunicatorInfoI::getZval(zval* z TSRMLS_DC)
+Ice::ValuePtr
+IcePHP::FactoryWrapper::create(const string& id)
{
- Z_TYPE_P(z) = IS_OBJECT;
- z->value.obj = zv.value.obj;
- addRef(TSRMLS_C);
-}
+ //
+ // Get the TSRM id for the current request.
+ //
+ TSRMLS_FETCH();
-void
-IcePHP::CommunicatorInfoI::addRef(TSRMLS_D)
-{
- zval* p = const_cast<zval*>(&zv);
- Z_OBJ_HT_P(p)->add_ref(p TSRMLS_CC);
-}
+ //
+ // Get the type information.
+ //
+ ClassInfoPtr cls;
+ if(id == Ice::Object::ice_staticId())
+ {
+ //
+ // When the ID is that of Ice::Object, it indicates that the stream has not
+ // found a factory and is providing us an opportunity to preserve the object.
+ //
+ cls = getClassInfoById("::Ice::UnknownSlicedValue" TSRMLS_CC);
+ }
+ else
+ {
+ cls = getClassInfoById(id TSRMLS_CC);
+ }
-void
-IcePHP::CommunicatorInfoI::decRef(TSRMLS_D)
-{
- zval* p = const_cast<zval*>(&zv);
- Z_OBJ_HT(zv)->del_ref(p TSRMLS_CC);
-}
+ if(!cls)
+ {
+ return 0;
+ }
-Ice::CommunicatorPtr
-IcePHP::CommunicatorInfoI::getCommunicator() const
-{
- return ac->communicator;
-}
+ zval* arg;
+ MAKE_STD_ZVAL(arg);
+ ZVAL_STRINGL(arg, STRCAST(id.c_str()), static_cast<int>(id.length()), 1);
-bool
-IcePHP::CommunicatorInfoI::addObjectFactory(const string& id, zval* factory TSRMLS_DC)
-{
- ObjectFactoryMap::iterator p = objectFactories.find(id);
- if(p != objectFactories.end())
+ zval* obj = 0;
+
+ zend_try
{
- Ice::AlreadyRegisteredException ex(__FILE__, __LINE__);
- ex.kindOfObject = "object factory";
- ex.id = id;
- throwException(ex TSRMLS_CC);
- return false;
+ const char* func = "create";
+ zend_call_method(&_factory, 0, 0, const_cast<char*>(func), static_cast<int>(strlen(func)), &obj, 1, arg,
+ 0 TSRMLS_CC);
}
+ zend_catch
+ {
+ obj = 0;
+ }
+ zend_end_try();
- objectFactories.insert(ObjectFactoryMap::value_type(id, factory));
- Z_ADDREF_P(factory);
+ zval_ptr_dtor(&arg);
- return true;
-}
+ //
+ // Bail out if an exception has already been thrown.
+ //
+ if(!obj || EG(exception))
+ {
+ throw AbortMarshaling();
+ }
-bool
-IcePHP::CommunicatorInfoI::findObjectFactory(const string& id, zval* zv TSRMLS_DC)
-{
- ObjectFactoryMap::iterator p = objectFactories.find(id);
- if(p != objectFactories.end())
+ AutoDestroy destroy(obj);
+
+ if(Z_TYPE_P(obj) == IS_NULL)
{
- *zv = *p->second; // This is legal - it simply copies the object's handle.
- INIT_PZVAL(zv);
- zval_copy_ctor(zv);
- return true;
+ return 0;
}
- return false;
+ return new ObjectReader(obj, cls, _info TSRMLS_CC);
+}
+
+void
+IcePHP::FactoryWrapper::getZval(zval* factory TSRMLS_DC)
+{
+ *factory = *_factory; // This is legal - it simply copies the object's handle.
+ INIT_PZVAL(factory);
+ zval_copy_ctor(factory);
+}
+
+bool
+IcePHP::FactoryWrapper::isObjectFactory() const
+{
+ return _isObjectFactory;
}
void
-IcePHP::CommunicatorInfoI::destroyObjectFactories(TSRMLS_D)
+IcePHP::FactoryWrapper::destroy(TSRMLS_D)
{
- for(ObjectFactoryMap::iterator p = objectFactories.begin(); p != objectFactories.end(); ++p)
+ if(_isObjectFactory)
{
//
- // Invoke the destroy method on each registered PHP factory.
+ // Invoke the destroy method on the PHP factory.
//
- invokeMethod(p->second, "destroy" TSRMLS_CC);
+ invokeMethod(_factory, "destroy" TSRMLS_CC);
zend_clear_exception(TSRMLS_C);
- zval_ptr_dtor(&p->second);
}
+ zval_ptr_dtor(&_factory);
+ _info = 0;
}
-IcePHP::ObjectFactoryI::ObjectFactoryI(const Ice::CommunicatorPtr& communicator) :
- _communicator(communicator)
+IcePHP::DefaultValueFactory::DefaultValueFactory(const CommunicatorInfoIPtr& info) :
+ _info(info)
{
}
-Ice::ObjectPtr
-IcePHP::ObjectFactoryI::create(const string& id)
+Ice::ValuePtr
+IcePHP::DefaultValueFactory::create(const string& id)
{
//
// Get the TSRM id for the current request.
//
TSRMLS_FETCH();
- CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap));
- assert(m);
- CommunicatorMap::iterator p = m->find(_communicator);
- assert(p != m->end());
-
- CommunicatorInfoIPtr info = p->second;
-
- zval* factory = 0;
-
- //
- // Check if the application has registered a factory for this id.
- //
- ObjectFactoryMap::iterator q = info->objectFactories.find(id);
- if(q == info->objectFactories.end())
+ if(_delegate)
{
- q = info->objectFactories.find(""); // Look for a default factory.
- }
- if(q != info->objectFactories.end())
- {
- factory = q->second;
+ Ice::ValuePtr v = _delegate->create(id);
+ if(v)
+ {
+ return v;
+ }
}
//
@@ -1663,7 +1969,7 @@ IcePHP::ObjectFactoryI::create(const string& id)
// When the ID is that of Ice::Object, it indicates that the stream has not
// found a factory and is providing us an opportunity to preserve the object.
//
- cls = getClassInfoById("::Ice::UnknownSlicedObject" TSRMLS_CC);
+ cls = getClassInfoById("::Ice::UnknownSlicedValue" TSRMLS_CC);
}
else
{
@@ -1675,75 +1981,172 @@ IcePHP::ObjectFactoryI::create(const string& id)
return 0;
}
- if(factory)
+ //
+ // Instantiate the object.
+ //
+ zval* obj;
+ MAKE_STD_ZVAL(obj);
+ AutoDestroy destroy(obj);
+
+ if(object_init_ex(obj, const_cast<zend_class_entry*>(cls->zce)) != SUCCESS)
+ {
+ throw AbortMarshaling();
+ }
+
+ if(!invokeMethod(obj, ZEND_CONSTRUCTOR_FUNC_NAME TSRMLS_CC))
+ {
+ throw AbortMarshaling();
+ }
+
+ return new ObjectReader(obj, cls, _info TSRMLS_CC);
+}
+
+void
+IcePHP::DefaultValueFactory::destroy(TSRMLS_D)
+{
+ if(_delegate)
{
- zval* arg;
- MAKE_STD_ZVAL(arg);
- ZVAL_STRINGL(arg, STRCAST(id.c_str()), static_cast<int>(id.length()), 1);
+ _delegate->destroy();
+ _delegate = 0;
+ }
+ _info = 0;
+}
+
+IcePHP::CommunicatorInfoI::CommunicatorInfoI(const ActiveCommunicatorPtr& c, zval* z) :
+ ac(c),
+ zv(*z), // This is legal - it simply copies the object's handle.
+ _defaultFactory(new DefaultValueFactory(this))
+{
+}
- zval* obj = 0;
+void
+IcePHP::CommunicatorInfoI::getZval(zval* z TSRMLS_DC)
+{
+ Z_TYPE_P(z) = IS_OBJECT;
+ z->value.obj = zv.value.obj;
+ addRef(TSRMLS_C);
+}
- zend_try
- {
- const char* func = "create";
- zend_call_method(&factory, 0, 0, const_cast<char*>(func), static_cast<int>(strlen(func)), &obj, 1, arg, 0 TSRMLS_CC);
- }
- zend_catch
+void
+IcePHP::CommunicatorInfoI::addRef(TSRMLS_D)
+{
+ zval* p = const_cast<zval*>(&zv);
+ Z_OBJ_HT_P(p)->add_ref(p TSRMLS_CC);
+}
+
+void
+IcePHP::CommunicatorInfoI::decRef(TSRMLS_D)
+{
+ zval* p = const_cast<zval*>(&zv);
+ Z_OBJ_HT(zv)->del_ref(p TSRMLS_CC);
+}
+
+Ice::CommunicatorPtr
+IcePHP::CommunicatorInfoI::getCommunicator() const
+{
+ return ac->communicator;
+}
+
+bool
+IcePHP::CommunicatorInfoI::addFactory(zval* factory, const string& id, bool isObjectFactory TSRMLS_DC)
+{
+ if(id.empty())
+ {
+ if(_defaultFactory->getDelegate())
{
- obj = 0;
+ Ice::AlreadyRegisteredException ex(__FILE__, __LINE__);
+ ex.kindOfObject = "value factory";
+ ex.id = id;
+ throwException(ex TSRMLS_CC);
+ return false;
}
- zend_end_try();
- zval_ptr_dtor(&arg);
-
- //
- // Bail out if an exception has already been thrown.
- //
- if(!obj || EG(exception))
+ _defaultFactory->setDelegate(new FactoryWrapper(factory, isObjectFactory, this));
+ }
+ else
+ {
+ FactoryMap::iterator p = _factories.find(id);
+ if(p != _factories.end())
{
- throw AbortMarshaling();
+ Ice::AlreadyRegisteredException ex(__FILE__, __LINE__);
+ ex.kindOfObject = "value factory";
+ ex.id = id;
+ throwException(ex TSRMLS_CC);
+ return false;
}
- AutoDestroy destroy(obj);
+ _factories.insert(FactoryMap::value_type(id, new FactoryWrapper(factory, isObjectFactory, this)));
+ }
- if(Z_TYPE_P(obj) == IS_NULL)
+ return true;
+}
+
+FactoryWrapperPtr
+IcePHP::CommunicatorInfoI::findFactory(const string& id) const
+{
+ if(id.empty())
+ {
+ return _defaultFactory->getDelegate();
+ }
+ else
+ {
+ FactoryMap::const_iterator p = _factories.find(id);
+ if(p != _factories.end())
{
- return 0;
+ return p->second;
}
+ }
- return new ObjectReader(obj, cls, info TSRMLS_CC);
+ return 0;
+}
+
+void
+IcePHP::CommunicatorInfoI::destroyFactories(TSRMLS_D)
+{
+ for(FactoryMap::iterator p = _factories.begin(); p != _factories.end(); ++p)
+ {
+ p->second->destroy(TSRMLS_C);
}
+ _factories.clear();
+ _defaultFactory->destroy(TSRMLS_C);
+}
+void
+IcePHP::ValueFactoryManager::add(const Ice::ValueFactoryPtr&, const string&)
+{
//
- // If the requested type is an abstract class, then we give up.
+ // We don't support factories registered in C++.
//
- if(cls->isAbstract)
- {
- return 0;
- }
+ throw Ice::FeatureNotSupportedException(__FILE__, __LINE__, "C++ value factory");
+}
+Ice::ValueFactoryPtr
+IcePHP::ValueFactoryManager::find(const string& id) const
+{
//
- // Instantiate the object.
+ // Get the TSRM id for the current request.
//
- zval* obj;
- MAKE_STD_ZVAL(obj);
- AutoDestroy destroy(obj);
+ TSRMLS_FETCH();
- if(object_init_ex(obj, const_cast<zend_class_entry*>(cls->zce)) != SUCCESS)
+ CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap));
+ assert(m);
+ CommunicatorMap::iterator p = m->find(_communicator);
+ assert(p != m->end());
+
+ CommunicatorInfoIPtr info = p->second;
+
+ if(id.empty())
{
- throw AbortMarshaling();
+ return info->defaultFactory();
}
-
- if(!invokeMethod(obj, ZEND_CONSTRUCTOR_FUNC_NAME TSRMLS_CC))
+ else
{
- throw AbortMarshaling();
+ return info->findFactory(id);
}
-
- return new ObjectReader(obj, cls, info TSRMLS_CC);
}
void
-IcePHP::ObjectFactoryI::destroy()
+IcePHP::ValueFactoryManager::destroy()
{
_communicator = 0;
}