diff options
author | Mark Spruiell <mes@zeroc.com> | 2016-01-19 16:46:11 -0800 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2016-01-19 16:46:11 -0800 |
commit | d5dd7c866e9e1dc59dc7e127eb39f641530bf823 (patch) | |
tree | 61771e4f322a7138b643d5325a6d10acea30fb84 /php/src | |
parent | Deprecate ice_name and add ice_id (diff) | |
download | ice-d5dd7c866e9e1dc59dc7e127eb39f641530bf823.tar.bz2 ice-d5dd7c866e9e1dc59dc7e127eb39f641530bf823.tar.xz ice-d5dd7c866e9e1dc59dc7e127eb39f641530bf823.zip |
ICE-6861 - removing public stream API
Diffstat (limited to 'php/src')
-rw-r--r-- | php/src/IcePHP/Communicator.cpp | 763 | ||||
-rw-r--r-- | php/src/IcePHP/Operation.cpp | 65 | ||||
-rw-r--r-- | php/src/IcePHP/Types.cpp | 183 | ||||
-rw-r--r-- | php/src/IcePHP/Types.h | 158 |
4 files changed, 759 insertions, 410 deletions
diff --git a/php/src/IcePHP/Communicator.cpp b/php/src/IcePHP/Communicator.cpp index 12d46ec1809..494b75f9ad2 100644 --- a/php/src/IcePHP/Communicator.cpp +++ b/php/src/IcePHP/Communicator.cpp @@ -31,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 @@ -52,9 +53,19 @@ public: }; typedef IceUtil::Handle<ActiveCommunicator> ActiveCommunicatorPtr; -typedef std::map<std::string, zval*> ObjectFactoryMap; -typedef std::map<std::string, zval*> ValueFactoryMap; +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: @@ -67,53 +78,110 @@ public: virtual Ice::CommunicatorPtr getCommunicator() const; - bool addObjectFactory(const std::string&, zval* TSRMLS_DC); - bool addValueFactory(const std::string&, zval* TSRMLS_DC); - - bool findObjectFactory(const std::string&, zval* TSRMLS_DC); - bool findValueFactory(const std::string&, zval* TSRMLS_DC); - - void destroyObjectFactories(TSRMLS_D); - void destroyValueFactories(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; - ValueFactoryMap valueFactories; + +private: + + typedef map<string, FactoryWrapperPtr> FactoryMap; + + FactoryMap _factories; + DefaultValueFactoryPtr _defaultFactory; }; typedef IceUtil::Handle<CommunicatorInfoI> CommunicatorInfoIPtr; // +// 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. -// The factory class defined below delegates the create (and destory in the case -// of an object factory) 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: +// (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. // -// There is also an object factory map. Anything added to this map is also added -// to the value factory map, but not vice versa. +// * 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; + + void setCommunicator(const Ice::CommunicatorPtr& c) { _communicator = c; } + Ice::CommunicatorPtr getCommunicator() const { return _communicator; } + + void getZval(zval* TSRMLS_DC); - virtual Ice::ObjectPtr create(const std::string&); - virtual void destroy(); + void destroy(); private: Ice::CommunicatorPtr _communicator; }; +typedef IceUtil::Handle<ValueFactoryManager> ValueFactoryManagerPtr; class ReaperTask : public IceUtil::TimerTask { @@ -132,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. @@ -181,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) @@ -208,8 +285,7 @@ ZEND_METHOD(Ice_Communicator, destroy) // // We need to destroy any object|value factories installed by this request. // - _this->destroyObjectFactories(TSRMLS_C); - _this->destroyValueFactories(TSRMLS_C); + _this->destroyFactories(TSRMLS_C); Ice::CommunicatorPtr c = _this->getCommunicator(); assert(c); @@ -218,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(); @@ -447,25 +527,20 @@ 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(); } } -ZEND_METHOD(Ice_Communicator, addValueFactory) +ZEND_METHOD(Ice_Communicator, findObjectFactory) { CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::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) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!"), &id, &idLen TSRMLS_CC) != SUCCESS) { RETURN_NULL(); } @@ -476,56 +551,45 @@ ZEND_METHOD(Ice_Communicator, addValueFactory) type = string(id, idLen); } - if(!_this->addValueFactory(type, factory TSRMLS_CC)) + FactoryWrapperPtr w = _this->findFactory(type); + if(w && w->isObjectFactory()) { - RETURN_NULL(); + w->getZval(return_value TSRMLS_CC); } -} - -ZEND_METHOD(Ice_Communicator, findObjectFactory) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::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) + else { RETURN_NULL(); } +} - string type; - if(id) - { - type = string(id, idLen); - } - - if(!_this->findObjectFactory(type, return_value TSRMLS_CC)) +ZEND_METHOD(Ice_Communicator, getValueFactoryManager) +{ + if(ZEND_NUM_ARGS() > 0) { - RETURN_NULL(); + WRONG_PARAM_COUNT; } -} -ZEND_METHOD(Ice_Communicator, findValueFactory) -{ CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::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) + try { - RETURN_NULL(); - } + 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(); + } - string type; - if(id) - { - type = string(id, idLen); + Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::extract(return_value TSRMLS_CC); + assert(!obj->ptr); + obj->ptr = new ValueFactoryManagerPtr(vfm); } - - if(!_this->findValueFactory(type, return_value TSRMLS_CC)) + catch(const IceUtil::Exception& ex) { + throwException(ex TSRMLS_CC); RETURN_NULL(); } } @@ -762,6 +826,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 @@ -801,6 +942,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) { @@ -856,10 +1037,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) @@ -871,6 +1051,8 @@ initializeCommunicator(zval* zv, Ice::StringSeq& args, bool hasArgs, const Ice:: catch(...) { } + + vfm->destroy(); } return info; @@ -962,7 +1144,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)) @@ -972,7 +1155,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)) @@ -983,6 +1167,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) @@ -1174,7 +1359,6 @@ ZEND_FUNCTION(Ice_getProperties) } } - // // Necessary to suppress warnings from zend_function_entry in php-5.2 // and INI_STR macro. @@ -1202,8 +1386,7 @@ static zend_function_entry _classMethods[] = 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, addValueFactory, NULL, ZEND_ACC_PUBLIC) - ZEND_ME(Ice_Communicator, findValueFactory, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, getValueFactoryManager, 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) @@ -1215,6 +1398,21 @@ static zend_function_entry _classMethods[] = {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, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_ValueFactoryManager, add, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ValueFactoryManager, find, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + static bool createProfile(const string& name, const string& config, const string& options TSRMLS_DC) { @@ -1425,6 +1623,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 = ""; @@ -1518,8 +1736,7 @@ IcePHP::communicatorRequestShutdown(TSRMLS_D) // // We need to destroy any object|value factories installed during this request. // - info->destroyObjectFactories(TSRMLS_C); - info->destroyValueFactories(TSRMLS_C); + info->destroyFactories(TSRMLS_C); } // @@ -1552,168 +1769,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); -} - -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); -} + // + // Get the TSRM id for the current request. + // + TSRMLS_FETCH(); -Ice::CommunicatorPtr -IcePHP::CommunicatorInfoI::getCommunicator() const -{ - return ac->communicator; -} + // + // 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::UnknownSlicedObject" TSRMLS_CC); + } + else + { + cls = getClassInfoById(id TSRMLS_CC); + } -bool -IcePHP::CommunicatorInfoI::addObjectFactory(const string& id, zval* factory TSRMLS_DC) -{ - ObjectFactoryMap::iterator p = objectFactories.find(id); - if(p != objectFactories.end()) + if(!cls) { - Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); - ex.kindOfObject = "value factory"; - ex.id = id; - throwException(ex TSRMLS_CC); - return false; + return 0; } - objectFactories.insert(ObjectFactoryMap::value_type(id, factory)); - Z_ADDREF_P(factory); - valueFactories.insert(ValueFactoryMap::value_type(id, factory)); - Z_ADDREF_P(factory); + zval* arg; + MAKE_STD_ZVAL(arg); + ZVAL_STRINGL(arg, STRCAST(id.c_str()), static_cast<int>(id.length()), 1); - return true; -} + zval* obj = 0; -bool -IcePHP::CommunicatorInfoI::addValueFactory(const string& id, zval* factory TSRMLS_DC) -{ - ObjectFactoryMap::iterator p = valueFactories.find(id); - if(p != valueFactories.end()) + zend_try { - Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); - ex.kindOfObject = "value 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(); - valueFactories.insert(ValueFactoryMap::value_type(id, factory)); - Z_ADDREF_P(factory); + zval_ptr_dtor(&arg); - return true; -} - -bool -IcePHP::CommunicatorInfoI::findObjectFactory(const string& id, zval* zv TSRMLS_DC) -{ - ObjectFactoryMap::iterator p = objectFactories.find(id); - if(p != objectFactories.end()) + // + // Bail out if an exception has already been thrown. + // + if(!obj || EG(exception)) { - *zv = *p->second; // This is legal - it simply copies the object's handle. - INIT_PZVAL(zv); - zval_copy_ctor(zv); - return true; + throw AbortMarshaling(); } - return false; -} + AutoDestroy destroy(obj); -bool -IcePHP::CommunicatorInfoI::findValueFactory(const string& id, zval* zv TSRMLS_DC) -{ - ValueFactoryMap::iterator p = valueFactories.find(id); - if(p != valueFactories.end()) + 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::CommunicatorInfoI::destroyObjectFactories(TSRMLS_D) +IcePHP::FactoryWrapper::getZval(zval* factory TSRMLS_DC) { - for(ObjectFactoryMap::iterator p = objectFactories.begin(); p != objectFactories.end(); ++p) - { - // - // Invoke the destroy method on each registered PHP factory. - // - invokeMethod(p->second, "destroy" TSRMLS_CC); - zend_clear_exception(TSRMLS_C); - zval_ptr_dtor(&p->second); - } - valueFactories.clear(); + *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::destroyValueFactories(TSRMLS_D) +IcePHP::FactoryWrapper::destroy(TSRMLS_D) { - for(ObjectFactoryMap::iterator p = objectFactories.begin(); p != objectFactories.end(); ++p) + if(_isObjectFactory) { - zval_ptr_dtor(&p->second); + // + // Invoke the destroy method on the PHP factory. + // + invokeMethod(_factory, "destroy" TSRMLS_CC); + zend_clear_exception(TSRMLS_C); } - objectFactories.clear(); + 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. - // - ValueFactoryMap::iterator q = info->valueFactories.find(id); - if(q == info->valueFactories.end()) + if(_delegate) { - q = info->valueFactories.find(""); // Look for a default factory. - } - if(q != info->valueFactories.end()) - { - factory = q->second; + Ice::ValuePtr v = _delegate->create(id); + if(v) + { + return v; + } } // @@ -1738,45 +1918,6 @@ IcePHP::ObjectFactoryI::create(const string& id) return 0; } - if(factory) - { - zval* arg; - MAKE_STD_ZVAL(arg); - ZVAL_STRINGL(arg, STRCAST(id.c_str()), static_cast<int>(id.length()), 1); - - zval* obj = 0; - - 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 - { - obj = 0; - } - zend_end_try(); - - zval_ptr_dtor(&arg); - - // - // Bail out if an exception has already been thrown. - // - if(!obj || EG(exception)) - { - throw AbortMarshaling(); - } - - AutoDestroy destroy(obj); - - if(Z_TYPE_P(obj) == IS_NULL) - { - return 0; - } - - return new ObjectReader(obj, cls, info TSRMLS_CC); - } - // // If the requested type is an abstract class, then we give up. // @@ -1802,11 +1943,155 @@ IcePHP::ObjectFactoryI::create(const string& id) throw AbortMarshaling(); } - return new ObjectReader(obj, cls, info TSRMLS_CC); + return new ObjectReader(obj, cls, _info TSRMLS_CC); +} + +void +IcePHP::DefaultValueFactory::destroy(TSRMLS_D) +{ + if(_delegate) + { + _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)) +{ +} + +void +IcePHP::CommunicatorInfoI::getZval(zval* z TSRMLS_DC) +{ + Z_TYPE_P(z) = IS_OBJECT; + z->value.obj = zv.value.obj; + addRef(TSRMLS_C); +} + +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()) + { + Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); + ex.kindOfObject = "value factory"; + ex.id = id; + throwException(ex TSRMLS_CC); + return false; + } + + _defaultFactory->setDelegate(new FactoryWrapper(factory, isObjectFactory, this)); + } + else + { + FactoryMap::iterator p = _factories.find(id); + if(p != _factories.end()) + { + Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); + ex.kindOfObject = "value factory"; + ex.id = id; + throwException(ex TSRMLS_CC); + return false; + } + + _factories.insert(FactoryMap::value_type(id, new FactoryWrapper(factory, isObjectFactory, this))); + } + + 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 p->second; + } + } + + 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&) +{ + // + // We don't support factories registered in C++. + // + throw Ice::FeatureNotSupportedException(__FILE__, __LINE__, "C++ value factory"); +} + +Ice::ValueFactoryPtr +IcePHP::ValueFactoryManager::find(const string& id) const +{ + // + // 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; + + if(id.empty()) + { + return info->defaultFactory(); + } + else + { + return info->findFactory(id); + } } void -IcePHP::ObjectFactoryI::destroy() +IcePHP::ValueFactoryManager::destroy() { _communicator = 0; } diff --git a/php/src/IcePHP/Operation.cpp b/php/src/IcePHP/Operation.cpp index f9fa024811a..a6bb7e4d7ed 100644 --- a/php/src/IcePHP/Operation.cpp +++ b/php/src/IcePHP/Operation.cpp @@ -129,7 +129,7 @@ protected: OperationIPtr _op; - bool prepareRequest(int, zval**, Ice::OutputStreamPtr&, pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); + bool prepareRequest(int, zval**, Ice::OutputStream*, pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); void unmarshalResults(int, zval**, zval*, const pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); zval* unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); bool validateException(const ExceptionInfoPtr& TSRMLS_DC) const; @@ -148,11 +148,11 @@ public: virtual void invoke(INTERNAL_FUNCTION_PARAMETERS); }; -class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +class UserExceptionFactory : public Ice::UserExceptionFactory { public: - UserExceptionReaderFactoryI(const CommunicatorInfoPtr& communicator TSRMLS_DC) : + UserExceptionFactory(const CommunicatorInfoPtr& communicator TSRMLS_DC) : _communicator(communicator) { #ifdef ZTS @@ -160,7 +160,7 @@ public: #endif } - virtual void createAndThrow(const string& id) const + virtual void createAndThrow(const string& id) { ExceptionInfoPtr info = getExceptionInfo(id TSRMLS_CC); if(info) @@ -460,7 +460,7 @@ IcePHP::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const Commun } bool -IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStreamPtr& os, +IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStream* os, pair<const Ice::Byte*, const Ice::Byte*>& params TSRMLS_DC) { // @@ -488,7 +488,6 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStream // // Marshal the in parameters. // - os = Ice::createOutputStream(_communicator->getCommunicator()); os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format); ObjectMap objectMap; @@ -529,7 +528,7 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStream { ParamInfoPtr info = *p; zval* arg = args[info->pos]; - if(!isUnset(arg TSRMLS_CC) && os->writeOptional(info->tag, info->type->optionalFormat())) + if(!isUnset(arg TSRMLS_CC) && os->writeOpt(info->tag, info->type->optionalFormat())) { info->type->marshal(arg, os, &objectMap, true TSRMLS_CC); } @@ -561,17 +560,17 @@ void IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, const pair<const Ice::Byte*, const Ice::Byte*>& bytes TSRMLS_DC) { - Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator->getCommunicator(), bytes); + Ice::InputStream is(_communicator->getCommunicator(), bytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); - is->startEncapsulation(); + is.startEncapsulation(); ParamInfoList::iterator p; @@ -594,7 +593,7 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, { ResultCallbackPtr cb = new ResultCallback; outParamCallbacks[info->pos] = cb; - info->type->unmarshal(is, cb, _communicator, 0, 0, false TSRMLS_CC); + info->type->unmarshal(&is, cb, _communicator, 0, 0, false TSRMLS_CC); } } @@ -604,7 +603,7 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, if(_op->returnType && !_op->returnType->optional) { retCallback = new ResultCallback; - _op->returnType->type->unmarshal(is, retCallback, _communicator, 0, 0, false TSRMLS_CC); + _op->returnType->type->unmarshal(&is, retCallback, _communicator, 0, 0, false TSRMLS_CC); } // @@ -624,9 +623,9 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, outParamCallbacks[info->pos] = cb; } - if(is->readOptional(info->tag, info->type->optionalFormat())) + if(is.readOpt(info->tag, info->type->optionalFormat())) { - info->type->unmarshal(is, cb, _communicator, 0, 0, true TSRMLS_CC); + info->type->unmarshal(&is, cb, _communicator, 0, 0, true TSRMLS_CC); } else { @@ -636,12 +635,12 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, if(_op->returnsClasses) { - is->readPendingObjects(); + is.readPendingObjects(); } - is->endEncapsulation(); + is.endEncapsulation(); - util.update(TSRMLS_C); + util.updateSlicedData(TSRMLS_C); int i = static_cast<int>(_op->inParams.size()); for(ResultCallbackList::iterator q = outParamCallbacks.begin(); q != outParamCallbacks.end(); ++q, ++i) @@ -668,38 +667,38 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, zval* IcePHP::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& bytes TSRMLS_DC) { - Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator->getCommunicator(), bytes); + Ice::InputStream is(_communicator->getCommunicator(), bytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); - is->startEncapsulation(); + is.startEncapsulation(); try { - Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(_communicator TSRMLS_CC); - is->throwException(factory); + Ice::UserExceptionFactoryPtr factory = new UserExceptionFactory(_communicator TSRMLS_CC); + is.throwException(factory); } catch(const ExceptionReader& r) { - is->endEncapsulation(); + is.endEncapsulation(); zval* ex = r.getException(); ExceptionInfoPtr info = r.getInfo(); if(validateException(info TSRMLS_CC)) { - util.update(TSRMLS_C); + util.updateSlicedData(TSRMLS_C); Ice::SlicedDataPtr slicedData = r.getSlicedData(); if(slicedData) { - SlicedDataUtil::setMember(ex, slicedData TSRMLS_CC); + StreamUtil::setSlicedDataMember(ex, slicedData TSRMLS_CC); } return ex; @@ -771,9 +770,9 @@ IcePHP::SyncTypedInvocation::invoke(INTERNAL_FUNCTION_PARAMETERS) return; } - Ice::OutputStreamPtr os; + Ice::OutputStream os(_prx->ice_getCommunicator()); pair<const Ice::Byte*, const Ice::Byte*> params; - if(!prepareRequest(ZEND_NUM_ARGS(), *args, os, params TSRMLS_CC)) + if(!prepareRequest(ZEND_NUM_ARGS(), *args, &os, params TSRMLS_CC)) { return; } diff --git a/php/src/IcePHP/Types.cpp b/php/src/IcePHP/Types.cpp index afc8150e188..2c1c52417cf 100644 --- a/php/src/IcePHP/Types.cpp +++ b/php/src/IcePHP/Types.cpp @@ -227,38 +227,13 @@ IcePHP::getExceptionInfo(const string& id TSRMLS_DC) return 0; } -namespace IcePHP -{ - -class ReadObjectCallback : public Ice::ReadObjectCallback -{ -public: - - ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, zval*, void* TSRMLS_DC); - ~ReadObjectCallback(); - - virtual void invoke(const ::Ice::ObjectPtr&); - -private: - - ClassInfoPtr _info; - UnmarshalCallbackPtr _cb; - zval* _target; - void* _closure; -#if ZTS - TSRMLS_D; -#endif -}; - -} - // -// SlicedDataUtil implementation +// StreamUtil implementation // -zend_class_entry* IcePHP::SlicedDataUtil::_slicedDataType = 0; -zend_class_entry* IcePHP::SlicedDataUtil::_sliceInfoType = 0; +zend_class_entry* IcePHP::StreamUtil::_slicedDataType = 0; +zend_class_entry* IcePHP::StreamUtil::_sliceInfoType = 0; -IcePHP::SlicedDataUtil::~SlicedDataUtil() +IcePHP::StreamUtil::~StreamUtil() { // // Make sure we break any cycles among the ObjectReaders in preserved slices. @@ -281,23 +256,29 @@ IcePHP::SlicedDataUtil::~SlicedDataUtil() } void -IcePHP::SlicedDataUtil::add(const ObjectReaderPtr& reader) +IcePHP::StreamUtil::add(const ReadObjectCallbackPtr& callback) +{ + _callbacks.push_back(callback); +} + +void +IcePHP::StreamUtil::add(const ObjectReaderPtr& reader) { assert(reader->getSlicedData()); _readers.insert(reader); } void -IcePHP::SlicedDataUtil::update(TSRMLS_D) +IcePHP::StreamUtil::updateSlicedData(TSRMLS_D) { for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) { - setMember((*p)->getObject(), (*p)->getSlicedData() TSRMLS_CC); + setSlicedDataMember((*p)->getObject(), (*p)->getSlicedData() TSRMLS_CC); } } void -IcePHP::SlicedDataUtil::setMember(zval* obj, const Ice::SlicedDataPtr& slicedData TSRMLS_DC) +IcePHP::StreamUtil::setSlicedDataMember(zval* obj, const Ice::SlicedDataPtr& slicedData TSRMLS_DC) { // // Create a PHP equivalent of the SlicedData object. @@ -454,7 +435,7 @@ IcePHP::SlicedDataUtil::setMember(zval* obj, const Ice::SlicedDataPtr& slicedDat // named _ice_slicedData which is an instance of the PHP class Ice_SlicedData. // Ice::SlicedDataPtr -IcePHP::SlicedDataUtil::getMember(zval* obj, ObjectMap* objectMap TSRMLS_DC) +IcePHP::StreamUtil::getSlicedDataMember(zval* obj, ObjectMap* objectMap TSRMLS_DC) { Ice::SlicedDataPtr slicedData; @@ -846,7 +827,7 @@ IcePHP::PrimitiveInfo::optionalFormat() const } void -IcePHP::PrimitiveInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool TSRMLS_DC) +IcePHP::PrimitiveInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap*, bool TSRMLS_DC) { switch(kind) { @@ -954,7 +935,7 @@ IcePHP::PrimitiveInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectM } void -IcePHP::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +IcePHP::PrimitiveInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr&, zval* target, void* closure, bool TSRMLS_DC) { zval* zv; @@ -1124,7 +1105,7 @@ IcePHP::EnumInfo::optionalFormat() const } void -IcePHP::EnumInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool TSRMLS_DC) +IcePHP::EnumInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap*, bool TSRMLS_DC) { assert(Z_TYPE_P(zv) == IS_LONG); // validate() should have caught this. const Ice::Int val = static_cast<Ice::Int>(Z_LVAL_P(zv)); @@ -1134,7 +1115,7 @@ IcePHP::EnumInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, } void -IcePHP::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +IcePHP::EnumInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr&, zval* target, void* closure, bool TSRMLS_DC) { zval* zv; @@ -1363,7 +1344,7 @@ IcePHP::StructInfo::usesClasses() const } void -IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC) +IcePHP::StructInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap* objectMap, bool optional TSRMLS_DC) { assert(Z_TYPE_P(zv) == IS_NULL || (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == zce)); @@ -1427,7 +1408,7 @@ IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* } void -IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +IcePHP::StructInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) { zval* zv; @@ -1559,7 +1540,7 @@ IcePHP::SequenceInfo::usesClasses() const } void -IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC) +IcePHP::SequenceInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap* objectMap, bool optional TSRMLS_DC) { Ice::Int sz = 0; HashTable* arr = 0; @@ -1623,7 +1604,7 @@ IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMa } void -IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +IcePHP::SequenceInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) { if(optional) @@ -1719,8 +1700,7 @@ IcePHP::SequenceInfo::destroy() } void -IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zv, const Ice::OutputStreamPtr& os - TSRMLS_DC) +IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zv, Ice::OutputStream* os TSRMLS_DC) { HashTable* arr = Z_ARRVAL_P(zv); @@ -1933,14 +1913,14 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* seq[i++] = s; zend_hash_move_forward_ex(arr, &pos); } - os->write(seq, true); + os->write(seq); break; } } } void -IcePHP::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, const Ice::InputStreamPtr& is, +IcePHP::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, Ice::InputStream* is, const UnmarshalCallbackPtr& cb, zval* target, void* closure TSRMLS_DC) { zval* zv; @@ -2119,7 +2099,7 @@ IcePHP::DictionaryInfo::usesClasses() const } void -IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC) +IcePHP::DictionaryInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap* objectMap, bool optional TSRMLS_DC) { Ice::Int sz = 0; HashTable* arr = 0; @@ -2266,7 +2246,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object } void -IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +IcePHP::DictionaryInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) { if(optional) @@ -2548,7 +2528,7 @@ IcePHP::ClassInfo::usesClasses() const } void -IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool TSRMLS_DC) +IcePHP::ClassInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap* objectMap, bool TSRMLS_DC) { if(!defined) { @@ -2558,7 +2538,8 @@ IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* if(Z_TYPE_P(zv) == IS_NULL) { - os->writeObject(0); + Ice::ObjectPtr nil; + os->write(nil); return; } @@ -2587,11 +2568,24 @@ IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* // // Give the writer to the stream. The stream will eventually call write() on it. // - os->writeObject(writer); + os->write(writer); } +namespace +{ + void -IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +patchObject(void* addr, const Ice::ObjectPtr& v) +{ + ReadObjectCallback* cb = static_cast<ReadObjectCallback*>(addr); + assert(cb); + cb->invoke(v); +} + +} + +void +IcePHP::ClassInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr& comm, zval* target, void* closure, bool TSRMLS_DC) { if(!defined) @@ -2600,7 +2594,16 @@ IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb throw AbortMarshaling(); } - is->readObject(new ReadObjectCallback(this, cb, target, closure TSRMLS_CC)); + // + // This callback is notified when the Slice value is actually read. The StreamUtil object + // attached to the stream keeps a reference to the callback object to ensure it lives + // long enough. + // + ReadObjectCallbackPtr rocb = new ReadObjectCallback(this, cb, target, closure TSRMLS_CC); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); + assert(util); + util->add(rocb); + is->read(patchObject, rocb.get()); } void @@ -2812,7 +2815,7 @@ IcePHP::ProxyInfo::optionalFormat() const } void -IcePHP::ProxyInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional TSRMLS_DC) +IcePHP::ProxyInfo::marshal(zval* zv, Ice::OutputStream* os, ObjectMap*, bool optional TSRMLS_DC) { Ice::OutputStream::size_type sizePos = 0; if(optional) @@ -2848,7 +2851,7 @@ IcePHP::ProxyInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, } void -IcePHP::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, +IcePHP::ProxyInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) { zval* zv; @@ -2956,7 +2959,7 @@ IcePHP::ObjectWriter::ice_preMarshal() } void -IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const +IcePHP::ObjectWriter::__write(Ice::OutputStream* os) const { Ice::SlicedDataPtr slicedData; @@ -2965,7 +2968,7 @@ IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const // // Retrieve the SlicedData object that we stored as a hidden member of the PHP object. // - slicedData = SlicedDataUtil::getMember(_object, const_cast<ObjectMap*>(_map) TSRMLS_CC); + slicedData = StreamUtil::getSlicedDataMember(_object, const_cast<ObjectMap*>(_map) TSRMLS_CC); } os->startObject(slicedData); @@ -2992,7 +2995,13 @@ IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const } void -IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemberList& members) const +IcePHP::ObjectWriter::__read(Ice::InputStream*) +{ + assert(false); +} + +void +IcePHP::ObjectWriter::writeMembers(Ice::OutputStream* os, const DataMemberList& members) const { for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { @@ -3009,7 +3018,7 @@ IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMem zval** val = reinterpret_cast<zval**>(data); if(member->optional && (isUnset(*val TSRMLS_CC) || - !os->writeOptional(member->tag, member->type->optionalFormat()))) + !os->writeOpt(member->tag, member->type->optionalFormat()))) { continue; } @@ -3057,7 +3066,13 @@ IcePHP::ObjectReader::ice_postUnmarshal() } void -IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is) +IcePHP::ObjectReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IcePHP::ObjectReader::__read(Ice::InputStream* is) { is->startObject(); @@ -3087,7 +3102,7 @@ IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is) for(p = info->optionalMembers.begin(); p != info->optionalMembers.end(); ++p) { DataMemberPtr member = *p; - if(is->readOptional(member->tag, member->type->optionalFormat())) + if(is->readOpt(member->tag, member->type->optionalFormat())) { member->type->unmarshal(is, member, _communicator, _object, 0, true TSRMLS_CC); } @@ -3111,7 +3126,7 @@ IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is) if(_slicedData) { - SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure()); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); assert(util); util->add(this); @@ -3216,7 +3231,7 @@ IcePHP::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) // ExceptionInfo implementation. // zval* -IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const CommunicatorInfoPtr& comm TSRMLS_DC) +IcePHP::ExceptionInfo::unmarshal(Ice::InputStream* is, const CommunicatorInfoPtr& comm TSRMLS_DC) { zval* zv; MAKE_STD_ZVAL(zv); @@ -3250,7 +3265,7 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat for(q = info->optionalMembers.begin(); q != info->optionalMembers.end(); ++q) { DataMemberPtr member = *q; - if(is->readOptional(member->tag, member->type->optionalFormat())) + if(is->readOpt(member->tag, member->type->optionalFormat())) { member->type->unmarshal(is, member, comm, zv, 0, true TSRMLS_CC); } @@ -3376,7 +3391,7 @@ IcePHP::ExceptionInfo::isA(const string& typeId) const // IcePHP::ExceptionReader::ExceptionReader(const CommunicatorInfoPtr& communicatorInfo, const ExceptionInfoPtr& info TSRMLS_DC) : - Ice::UserExceptionReader(communicatorInfo->getCommunicator()), _communicatorInfo(communicatorInfo), _info(info) + _communicatorInfo(communicatorInfo), _info(info) { #ifdef ZTS this->TSRMLS_C = TSRMLS_C; @@ -3388,22 +3403,6 @@ IcePHP::ExceptionReader::~ExceptionReader() { } -void -IcePHP::ExceptionReader::read(const Ice::InputStreamPtr& is) const -{ - is->startException(); - - const_cast<zval*&>(_ex) = _info->unmarshal(is, _communicatorInfo TSRMLS_CC); - - const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); -} - -bool -IcePHP::ExceptionReader::usesClasses() const -{ - return _info->usesClasses; -} - string IcePHP::ExceptionReader::ice_id() const { @@ -3431,6 +3430,28 @@ IcePHP::ExceptionReader::ice_throw() const throw *this; } +void +IcePHP::ExceptionReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IcePHP::ExceptionReader::__read(Ice::InputStream* is) +{ + is->startException(); + + const_cast<zval*&>(_ex) = _info->unmarshal(is, _communicatorInfo TSRMLS_CC); + + const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); +} + +bool +IcePHP::ExceptionReader::__usesClasses() const +{ + return _info->usesClasses; +} + ExceptionInfoPtr IcePHP::ExceptionReader::getInfo() const { diff --git a/php/src/IcePHP/Types.h b/php/src/IcePHP/Types.h index 5644ed88c5e..af0f6c01ab1 100644 --- a/php/src/IcePHP/Types.h +++ b/php/src/IcePHP/Types.h @@ -13,7 +13,6 @@ #include <Config.h> #include <Communicator.h> #include <Operation.h> -#include <Ice/Stream.h> #include <IceUtil/OutputUtil.h> // @@ -44,35 +43,15 @@ class AbortMarshaling { }; +class ClassInfo; +typedef IceUtil::Handle<ClassInfo> ClassInfoPtr; +typedef std::vector<ClassInfoPtr> ClassInfoList; + typedef std::map<unsigned int, Ice::ObjectPtr> ObjectMap; class ObjectReader; typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; -// -// This class keeps track of PHP objects (instances of Slice classes -// and exceptions) that have preserved slices. -// -class SlicedDataUtil -{ -public: - - ~SlicedDataUtil(); - - void add(const ObjectReaderPtr&); - - void update(TSRMLS_D); - - static void setMember(zval*, const Ice::SlicedDataPtr& TSRMLS_DC); - static Ice::SlicedDataPtr getMember(zval*, ObjectMap* TSRMLS_DC); - -private: - - std::set<ObjectReaderPtr> _readers; - static zend_class_entry* _slicedDataType; - static zend_class_entry* _sliceInfoType; -}; - struct PrintObjectHistory { int index; @@ -103,6 +82,64 @@ public: typedef IceUtil::Handle<UnmarshalCallback> UnmarshalCallbackPtr; // +// ReadObjectCallback retains all of the information necessary to store an unmarshaled +// Slice value as a PHP object. +// +class ReadObjectCallback : public IceUtil::Shared +{ +public: + + ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, zval*, void* TSRMLS_DC); + ~ReadObjectCallback(); + + virtual void invoke(const ::Ice::ObjectPtr&); + +private: + + ClassInfoPtr _info; + UnmarshalCallbackPtr _cb; + zval* _target; + void* _closure; +#if ZTS + TSRMLS_D; +#endif +}; +typedef IceUtil::Handle<ReadObjectCallback> ReadObjectCallbackPtr; + +// +// This class keeps track of PHP objects (instances of Slice classes +// and exceptions) that have preserved slices. +// +class StreamUtil +{ +public: + + ~StreamUtil(); + + // + // Keep a reference to a ReadObjectCallback for patching purposes. + // + void add(const ReadObjectCallbackPtr&); + + // + // Keep track of object instances that have preserved slices. + // + void add(const ObjectReaderPtr&); + + void updateSlicedData(TSRMLS_D); + + static void setSlicedDataMember(zval*, const Ice::SlicedDataPtr& TSRMLS_DC); + static Ice::SlicedDataPtr getSlicedDataMember(zval*, ObjectMap* TSRMLS_DC); + +private: + + std::vector<ReadObjectCallbackPtr> _callbacks; + std::set<ObjectReaderPtr> _readers; + static zend_class_entry* _slicedDataType; + static zend_class_entry* _sliceInfoType; +}; + +// // Base class for type information. // class TypeInfo : public UnmarshalCallback @@ -133,8 +170,8 @@ public: // The marshal and unmarshal functions can raise Ice exceptions, and may raise // AbortMarshaling if an error occurs. // - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC) = 0; - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC) = 0; + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC) = 0; virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC) = 0; @@ -156,8 +193,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -195,8 +232,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -243,8 +280,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -283,8 +320,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -298,8 +335,8 @@ public: private: - void marshalPrimitiveSequence(const PrimitiveInfoPtr&, zval*, const Ice::OutputStreamPtr& TSRMLS_DC); - void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, + void marshalPrimitiveSequence(const PrimitiveInfoPtr&, zval*, Ice::OutputStream* TSRMLS_DC); + void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, Ice::InputStream*, const UnmarshalCallbackPtr&, zval*, void* TSRMLS_DC); }; typedef IceUtil::Handle<SequenceInfo> SequenceInfoPtr; @@ -323,8 +360,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -372,10 +409,6 @@ class ExceptionInfo; typedef IceUtil::Handle<ExceptionInfo> ExceptionInfoPtr; typedef std::vector<ExceptionInfoPtr> ExceptionInfoList; -class ClassInfo; -typedef IceUtil::Handle<ClassInfo> ClassInfoPtr; -typedef std::vector<ClassInfoPtr> ClassInfoList; - typedef std::vector<TypeInfoPtr> TypeInfoList; class ClassInfo : public TypeInfo @@ -396,8 +429,8 @@ public: virtual bool usesClasses() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -446,8 +479,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -467,7 +500,7 @@ class ExceptionInfo : public IceUtil::Shared { public: - zval* unmarshal(const Ice::InputStreamPtr&, const CommunicatorInfoPtr& TSRMLS_DC); + zval* unmarshal(Ice::InputStream*, const CommunicatorInfoPtr& TSRMLS_DC); void print(zval*, IceUtilInternal::Output& TSRMLS_DC); void printMembers(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); @@ -498,7 +531,7 @@ bool typesRequestShutdown(TSRMLS_D); // // ObjectWriter wraps a PHP object for marshaling. // -class ObjectWriter : public Ice::ObjectWriter +class ObjectWriter : public Ice::Object { public: @@ -507,11 +540,12 @@ public: virtual void ice_preMarshal(); - virtual void write(const Ice::OutputStreamPtr&) const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); private: - void writeMembers(const Ice::OutputStreamPtr&, const DataMemberList&) const; + void writeMembers(Ice::OutputStream*, const DataMemberList&) const; zval* _object; ObjectMap* _map; @@ -524,7 +558,7 @@ private: // // ObjectReader unmarshals the state of an Ice object. // -class ObjectReader : public Ice::ObjectReader +class ObjectReader : public Ice::Object { public: @@ -533,7 +567,8 @@ public: virtual void ice_postUnmarshal(); - virtual void read(const Ice::InputStreamPtr&); + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); virtual ClassInfoPtr getInfo() const; @@ -555,16 +590,13 @@ private: // // ExceptionReader creates a PHP user exception and unmarshals it. // -class ExceptionReader : public Ice::UserExceptionReader +class ExceptionReader : public Ice::UserException { public: ExceptionReader(const CommunicatorInfoPtr&, const ExceptionInfoPtr& TSRMLS_DC); ~ExceptionReader() throw(); - virtual void read(const Ice::InputStreamPtr&) const; - virtual bool usesClasses() const; - virtual std::string ice_id() const; #ifndef ICE_CPP11_MAPPING ICE_DEPRECATED_API("ice_name() is deprecated, use ice_id() instead.") @@ -573,12 +605,24 @@ public: virtual ExceptionReader* ice_clone() const; virtual void ice_throw() const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + virtual bool __usesClasses() const; + ExceptionInfoPtr getInfo() const; zval* getException() const; Ice::SlicedDataPtr getSlicedData() const; + using Ice::UserException::__read; + using Ice::UserException::__write; + +protected: + + virtual void __writeImpl(Ice::OutputStream*) const {} + virtual void __readImpl(Ice::InputStream*) {} + private: CommunicatorInfoPtr _communicatorInfo; |