diff options
author | Joe George <joe@zeroc.com> | 2020-12-03 12:20:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-03 12:20:37 -0500 |
commit | 606e7d6db1b07988ca149741e5b4c41779c12b65 (patch) | |
tree | d164a4f838f8183333b0e6e3090451d7b94ee15c /php/src/php7/Communicator.cpp | |
parent | Workaround JS frameworks that don't support Symbol.species with Promise types... (diff) | |
download | ice-606e7d6db1b07988ca149741e5b4c41779c12b65.tar.bz2 ice-606e7d6db1b07988ca149741e5b4c41779c12b65.tar.xz ice-606e7d6db1b07988ca149741e5b4c41779c12b65.zip |
Add support for PHP 8 (Fixes #1172) (#1177)
Diffstat (limited to 'php/src/php7/Communicator.cpp')
-rw-r--r-- | php/src/php7/Communicator.cpp | 2249 |
1 files changed, 0 insertions, 2249 deletions
diff --git a/php/src/php7/Communicator.cpp b/php/src/php7/Communicator.cpp deleted file mode 100644 index 4143ec65a4c..00000000000 --- a/php/src/php7/Communicator.cpp +++ /dev/null @@ -1,2249 +0,0 @@ -// -// Copyright (c) ZeroC, Inc. All rights reserved. -// - -#include <Communicator.h> -#include <Logger.h> -#include <Properties.h> -#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> -#include <IceUtil/Timer.h> -#include <fstream> - -#ifdef getcwd -# undef getcwd -#endif -#include <IceUtil/FileUtil.h> - -using namespace std; -using namespace IcePHP; - -ZEND_EXTERN_MODULE_GLOBALS(ice) - -// -// Class entries represent the PHP class implementations we have registered. -// -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 -// registered so that it remains active after a request completes. The -// communicator is destroyed when there are no more references to this -// object. -// -class ActiveCommunicator : public IceUtil::Shared -{ -public: - - ActiveCommunicator(const Ice::CommunicatorPtr& c); - ~ActiveCommunicator(); - - const Ice::CommunicatorPtr communicator; - vector<string> ids; - int expires; - IceUtil::Time lastAccess; -}; -typedef IceUtil::Handle<ActiveCommunicator> ActiveCommunicatorPtr; - -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: - - CommunicatorInfoI(const ActiveCommunicatorPtr&, zval*); - - virtual void getZval(zval*); - virtual void addRef(void); - virtual void decRef(void); - - virtual Ice::CommunicatorPtr getCommunicator() const; - - bool addFactory(zval*, const string&, bool); - FactoryWrapperPtr findFactory(const string&) const; - Ice::ValueFactoryPtr defaultFactory() const { return _defaultFactory; } - void destroyFactories(void); - - const ActiveCommunicatorPtr ac; - zval zv; - -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*); - - bool isObjectFactory() const; - - void destroy(void); - -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(void); - -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. -// -// * 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 ValueFactoryManager : public Ice::ValueFactoryManager -{ -public: - - virtual void add(const Ice::ValueFactoryPtr&, const string&); - virtual Ice::ValueFactoryPtr find(const string&) const ICE_NOEXCEPT; - - void setCommunicator(const Ice::CommunicatorPtr& c) { _communicator = c; } - Ice::CommunicatorPtr getCommunicator() const { return _communicator; } - - void getZval(zval*); - - void destroy(); - -private: - - Ice::CommunicatorPtr _communicator; -}; -typedef IceUtil::Handle<ValueFactoryManager> ValueFactoryManagerPtr; - -class ReaperTask : public IceUtil::TimerTask -{ -public: - - virtual void runTimerTask(); -}; - -} - -namespace -{ -// -// Communicator support. -// -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. -// -typedef map<string, Ice::PropertiesPtr> ProfileMap; -ProfileMap _profiles; -const string _defaultProfileName = ""; - -// -// This map represents communicators that have been registered so that they can be used -// by multiple PHP requests. -// -typedef map<string, ActiveCommunicatorPtr> RegisteredCommunicatorMap; -RegisteredCommunicatorMap _registeredCommunicators; -IceUtil::Mutex* _registeredCommunicatorsMutex = 0; - -IceUtil::TimerPtr _timer; - -// -// This map is stored in the "global" variables for each PHP request and holds -// the communicators that have been created (or registered communicators that have -// been used) by the request. -// -typedef map<Ice::CommunicatorPtr, CommunicatorInfoIPtr> CommunicatorMap; - -class Init -{ -public: - - Init() - { - _registeredCommunicatorsMutex = new IceUtil::Mutex(); - } - - ~Init() - { - delete _registeredCommunicatorsMutex; - _registeredCommunicatorsMutex = 0; - } -}; - -Init init; -} - -extern "C" -{ -static zend_object* handleAlloc(zend_class_entry*); -static void handleFreeStorage(zend_object*); -static zend_object* handleClone(zval*); - -static zend_object* handleVfmAlloc(zend_class_entry*); -static void handleVfmFreeStorage(zend_object*); -static zend_object* handleVfmClone(zval*); -} - -ZEND_METHOD(Ice_Communicator, __construct) -{ - runtimeError("communicators cannot be instantiated directly"); -} - -ZEND_METHOD(Ice_Communicator, shutdown) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); - assert(_this); - - try - { - _this->getCommunicator()->shutdown(); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex TSRMLS_CC); - } -} - -ZEND_METHOD(Ice_Communicator, isShutdown) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); - assert(_this); - - try - { - RETURN_BOOL(_this->getCommunicator()->isShutdown() ? 1 : 0); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex TSRMLS_CC); - RETURN_FALSE; - } -} - -ZEND_METHOD(Ice_Communicator, waitForShutdown) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); - assert(_this); - - try - { - _this->getCommunicator()->waitForShutdown(); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex TSRMLS_CC); - } -} - -ZEND_METHOD(Ice_Communicator, destroy) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - Ice::CommunicatorPtr c = _this->getCommunicator(); - assert(c); - CommunicatorMap* m = reinterpret_cast<CommunicatorMap*>(ICE_G(communicatorMap)); - assert(m); - if(m->find(c) != m->end()) - { - m->erase(c); - - // - // Remove all registrations. - // - { - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); - for(vector<string>::iterator p = _this->ac->ids.begin(); p != _this->ac->ids.end(); ++p) - { - _registeredCommunicators.erase(*p); - } - _this->ac->ids.clear(); - } - - // - // We need to destroy any object|value factories installed by this request. - // - _this->destroyFactories(); - - ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(c->getValueFactoryManager()); - assert(vfm); - vfm->destroy(); - - c->destroy(); - } -} - -ZEND_METHOD(Ice_Communicator, stringToProxy) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - char* str; - size_t strLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) - { - RETURN_NULL(); - } - string s(str, strLen); - - try - { - Ice::ObjectPrx prx = _this->getCommunicator()->stringToProxy(s); - if(!createProxy(return_value, prx, _this)) - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, proxyToString) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - zval* zv; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zv, proxyClassEntry) != SUCCESS) - { - RETURN_NULL(); - } - - try - { - string str; - if(zv) - { - Ice::ObjectPrx prx; - ProxyInfoPtr info; - if(!fetchProxy(zv, prx, info)) - { - RETURN_NULL(); - } - assert(prx); - str = prx->ice_toString(); - } - RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, propertyToProxy) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - char* str; - size_t strLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) - { - RETURN_NULL(); - } - string s(str, strLen); - - try - { - Ice::ObjectPrx prx = _this->getCommunicator()->propertyToProxy(s); - if(!createProxy(return_value, prx, _this)) - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, proxyToProperty) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - zval* zv; - char* str; - size_t strLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!s"), &zv, proxyClassEntry, &str, &strLen) - != SUCCESS) - { - RETURN_NULL(); - } - - string prefix(str, strLen); - - try - { - if(zv) - { - Ice::ObjectPrx prx; - ProxyInfoPtr info; - if(!fetchProxy(zv, prx, info)) - { - RETURN_NULL(); - } - assert(prx); - - Ice::PropertyDict val = _this->getCommunicator()->proxyToProperty(prx, prefix); - if(!createStringMap(return_value, val)) - { - RETURN_NULL(); - } - } - else - { - array_init(return_value); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, stringToIdentity) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - char* str; - size_t strLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) - { - RETURN_NULL(); - } - string s(str, strLen); - - try - { - Ice::Identity id = _this->getCommunicator()->stringToIdentity(s); - if(!createIdentity(return_value, id)) - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, identityToString) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - zend_class_entry* identityClass = idToClass("::Ice::Identity"); - assert(identityClass); - - zval* zv; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, identityClass) != SUCCESS) - { - RETURN_NULL(); - } - Ice::Identity id; - if(!extractIdentity(zv, id)) - { - RETURN_NULL(); - } - - try - { - string str = _this->getCommunicator()->identityToString(id); - RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, addObjectFactory) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - zend_class_entry* factoryClass = idToClass("Ice::ObjectFactory"); - assert(factoryClass); - - zval* factory; - char* id; - size_t idLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("Os!"), &factory, factoryClass, &id, - &idLen) != SUCCESS) - { - RETURN_NULL(); - } - - string type; - if(id) - { - type = string(id, idLen); - } - - if(!_this->addFactory(factory, type, true)) - { - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, findObjectFactory) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - char* id; - size_t idLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s!"), &id, &idLen) != SUCCESS) - { - RETURN_NULL(); - } - - string type; - if(id) - { - type = string(id, idLen); - } - - FactoryWrapperPtr w = _this->findFactory(type); - if(w && w->isObjectFactory()) - { - w->getZval(return_value); - } - else - { - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, getValueFactoryManager) -{ - if(ZEND_NUM_ARGS() > 0) - { - WRONG_PARAM_COUNT; - } - - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - 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"); - RETURN_NULL(); - } - - Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::extract(return_value); - assert(!obj->ptr); - obj->ptr = new ValueFactoryManagerPtr(vfm); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, getImplicitContext) -{ - runtimeError("not implemented"); -} - -ZEND_METHOD(Ice_Communicator, getProperties) -{ - if(ZEND_NUM_ARGS() > 0) - { - WRONG_PARAM_COUNT; - } - - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - try - { - Ice::PropertiesPtr props = _this->getCommunicator()->getProperties(); - if(!createProperties(return_value, props)) - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, getLogger) -{ - if(ZEND_NUM_ARGS() > 0) - { - WRONG_PARAM_COUNT; - } - - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - try - { - Ice::LoggerPtr logger = _this->getCommunicator()->getLogger(); - if(!createLogger(return_value, logger)) - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, getDefaultRouter) -{ - if(ZEND_NUM_ARGS() > 0) - { - WRONG_PARAM_COUNT; - } - - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - try - { - Ice::RouterPrx router = _this->getCommunicator()->getDefaultRouter(); - if(router) - { - ProxyInfoPtr info = getProxyInfo("::Ice::Router"); - if(!info) - { - runtimeError("no definition for Ice::Router"); - RETURN_NULL(); - } - if(!createProxy(return_value, router, info, _this)) - { - RETURN_NULL(); - } - } - else - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, setDefaultRouter) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - zval* zv; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zv, proxyClassEntry) != - SUCCESS) - { - RETURN_NULL(); - } - - Ice::ObjectPrx proxy; - ProxyInfoPtr info; - if(zv && !fetchProxy(zv, proxy, info)) - { - RETURN_NULL(); - } - - try - { - Ice::RouterPrx router; - if(proxy) - { - if(!info || !info->isA("::Ice::Router")) - { - invalidArgument("setDefaultRouter requires a proxy narrowed to Ice::Router"); - RETURN_NULL(); - } - router = Ice::RouterPrx::uncheckedCast(proxy); - } - _this->getCommunicator()->setDefaultRouter(router); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, getDefaultLocator) -{ - if(ZEND_NUM_ARGS() > 0) - { - WRONG_PARAM_COUNT; - } - - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - try - { - Ice::LocatorPrx locator = _this->getCommunicator()->getDefaultLocator(); - if(locator) - { - ProxyInfoPtr info = getProxyInfo("::Ice::Locator"); - if(!info) - { - runtimeError("no definition for Ice::Locator"); - RETURN_NULL(); - } - if(!createProxy(return_value, locator, info, _this)) - { - RETURN_NULL(); - } - } - else - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, setDefaultLocator) -{ - CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); - assert(_this); - - zval* zv; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zv, proxyClassEntry) != - SUCCESS) - { - RETURN_NULL(); - } - - Ice::ObjectPrx proxy; - ProxyInfoPtr info; - if(zv && !fetchProxy(zv, proxy, info)) - { - RETURN_NULL(); - } - - try - { - Ice::LocatorPrx locator; - if(proxy) - { - if(!info || !info->isA("::Ice::Locator")) - { - invalidArgument("setDefaultLocator requires a proxy narrowed to Ice::Locator"); - RETURN_NULL(); - } - locator = Ice::LocatorPrx::uncheckedCast(proxy); - } - _this->getCommunicator()->setDefaultLocator(locator); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_Communicator, flushBatchRequests) -{ - zval* compress; - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("z"), &compress TSRMLS_CC) != SUCCESS) - { - RETURN_NULL(); - } - - if(Z_TYPE_P(compress) != IS_LONG) - { - 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(cb); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex TSRMLS_CC); - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_ValueFactoryManager, __construct) -{ - runtimeError("value factory managers cannot be instantiated directly"); -} - -ZEND_METHOD(Ice_ValueFactoryManager, add) -{ - ValueFactoryManagerPtr _this = Wrapper<ValueFactoryManagerPtr>::value(getThis()); - assert(_this); - - zend_class_entry* factoryClass = idToClass("Ice::ValueFactory"); - assert(factoryClass); - - zval* factory; - char* id; - size_t idLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("Os!"), &factory, factoryClass, &id, - &idLen) != 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)) - { - RETURN_NULL(); - } -} - -ZEND_METHOD(Ice_ValueFactoryManager, find) -{ - ValueFactoryManagerPtr _this = Wrapper<ValueFactoryManagerPtr>::value(getThis()); - assert(_this); - - char* id; - size_t idLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s!"), &id, &idLen) != 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); - } - else - { - RETURN_NULL(); - } -} - -#ifdef _WIN32 -extern "C" -#endif -static zend_object* -handleAlloc(zend_class_entry* ce) -{ - Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::create(ce); - assert(obj); - - obj->zobj.handlers = &_handlers; - - return &obj->zobj; -} - -#ifdef _WIN32 -extern "C" -#endif -static void -handleFreeStorage(zend_object* object) -{ - Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::fetch(object); - assert(obj); - - delete obj->ptr; - zend_object_std_dtor(object); -} - -#ifdef _WIN32 -extern "C" -#endif -static zend_object* -handleClone(zval* zv) -{ - php_error_docref(0, E_ERROR, "communicators cannot be cloned"); - return 0; -} - -#ifdef _WIN32 -extern "C" -#endif -static zend_object* -handleVfmAlloc(zend_class_entry* ce) -{ - Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::create(ce); - assert(obj); - - obj->zobj.handlers = &_vfmHandlers; - - return &obj->zobj; -} - -#ifdef _WIN32 -extern "C" -#endif -static void -handleVfmFreeStorage(zend_object* object) -{ - Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::fetch(object); - assert(obj); - - delete obj->ptr; - zend_object_std_dtor(object); -} - -#ifdef _WIN32 -extern "C" -#endif -static zend_object* -handleVfmClone(zval* zv) -{ - php_error_docref(0, E_ERROR, "value factory managers cannot be cloned"); - return 0; -} - -static CommunicatorInfoIPtr -createCommunicator(zval* zv, const ActiveCommunicatorPtr& ac) -{ - try - { - if(object_init_ex(zv, communicatorClassEntry) != SUCCESS) - { - runtimeError("unable to initialize communicator object"); - return 0; - } - - Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::extract(zv); - assert(!obj->ptr); - - CommunicatorInfoIPtr info = new CommunicatorInfoI(ac, zv); - obj->ptr = new CommunicatorInfoIPtr(info); - - CommunicatorMap* m; - if(ICE_G(communicatorMap)) - { - m = reinterpret_cast<CommunicatorMap*>(ICE_G(communicatorMap)); - } - else - { - m = new CommunicatorMap; - ICE_G(communicatorMap) = m; - } - m->insert(CommunicatorMap::value_type(ac->communicator, info)); - - return info; - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - return 0; - } -} - -static CommunicatorInfoIPtr -initializeCommunicator(zval* zv, Ice::StringSeq& args, bool hasArgs, const Ice::InitializationData& initData) -{ - try - { - Ice::CommunicatorPtr c; - if(hasArgs) - { - c = Ice::initialize(args, initData); - } - else - { - c = Ice::initialize(initData); - } - ActiveCommunicatorPtr ac = new ActiveCommunicator(c); - - ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(c->getValueFactoryManager()); - assert(vfm); - vfm->setCommunicator(c); - - CommunicatorInfoIPtr info = createCommunicator(zv, ac); - if(!info) - { - try - { - c->destroy(); - } - catch(...) - { - } - - vfm->destroy(); - } - - return info; - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - return 0; - } -} - -ZEND_FUNCTION(Ice_initialize) -{ - if(ZEND_NUM_ARGS() > 2) - { - runtimeError("too many arguments"); - RETURN_NULL(); - } - - zend_class_entry* initClass = idToClass("::Ice::InitializationData"); - assert(initClass); - - // - // Retrieve the arguments. - // - - zval* args = static_cast<zval*>(emalloc(ZEND_NUM_ARGS() * sizeof(zval))); - AutoEfree autoArgs(args); // Call efree on return - if(zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) - { - runtimeError("unable to get arguments"); - RETURN_NULL(); - } - - Ice::StringSeq seq; - Ice::InitializationData initData; - zval* zvargs = 0; - zval* zvinit = 0; - - // - // The argument options are: - // - // initialize() - // initialize(args) - // initialize(initData) - // initialize(args, initData) - // initialize(initData, args) - // - - if(ZEND_NUM_ARGS() > 2) - { - runtimeError("too many arguments to initialize"); - RETURN_NULL(); - } - - if(ZEND_NUM_ARGS() > 0) - { - zval* arg = &args[0]; - while(Z_TYPE_P(arg) == IS_REFERENCE) - { - arg = Z_REFVAL_P(arg); - } - - if(Z_TYPE_P(arg) == IS_ARRAY) - { - zvargs = arg; - } - else if(Z_TYPE_P(arg) == IS_OBJECT && Z_OBJCE_P(arg) == initClass) - { - zvinit = arg; - } - else - { - invalidArgument("initialize expects an argument list, an InitializationData object, or both"); - RETURN_NULL(); - } - } - - if(ZEND_NUM_ARGS() > 1) - { - zval* arg = &args[1]; - while(Z_TYPE_P(arg) == IS_REFERENCE) - { - arg = Z_REFVAL_P(arg); - } - - if(Z_TYPE_P(arg) == IS_ARRAY) - { - if(zvargs) - { - invalidArgument("unexpected array argument to initialize"); - RETURN_NULL(); - } - zvargs = arg; - } - else if(Z_TYPE_P(arg) == IS_OBJECT && Z_OBJCE_P(arg) == initClass) - { - if(zvinit) - { - invalidArgument("unexpected InitializationData argument to initialize"); - RETURN_NULL(); - } - zvinit = arg; - } - else - { - invalidArgument("initialize expects an argument list, an InitializationData object, or both"); - RETURN_NULL(); - } - } - - if(zvargs && !extractStringArray(zvargs, seq)) - { - RETURN_NULL(); - } - - if(zvinit) - { - zval* data; - string member; - - member = "properties"; - { - if((data = zend_hash_str_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), member.size())) != 0) - { - assert(Z_TYPE_P(data) == IS_INDIRECT); - if(!fetchProperties(Z_INDIRECT_P(data), initData.properties)) - { - RETURN_NULL(); - } - } - } - - member = "logger"; - { - if((data = zend_hash_str_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), member.size())) != 0) - { - assert(Z_TYPE_P(data) == IS_INDIRECT); - if(!fetchLogger(Z_INDIRECT_P(data), initData.logger)) - { - RETURN_NULL(); - } - } - } - } - - initData.compactIdResolver = new IdResolver(); - initData.valueFactoryManager = new ValueFactoryManager; - - if(!initData.properties) - { - initData.properties = Ice::createProperties(); - } - - // Always accept cycles in PHP - initData.properties->setProperty("Ice.AcceptClassCycles", "1"); - - CommunicatorInfoIPtr info = initializeCommunicator(return_value, seq, zvargs != 0, initData); - if(!info) - { - RETURN_NULL(); - } - - // - // Replace the existing argument array with the filtered set. - // - if(zvargs) - { - zval_dtor(zvargs); - if(!createStringArray(zvargs, seq)) - { - RETURN_NULL(); - } - } -} - -ZEND_FUNCTION(Ice_register) -{ - zval* comm; - char* s; - size_t sLen; - zend_long expires = 0; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("Os|l"), &comm, communicatorClassEntry, &s, - &sLen, &expires) != SUCCESS) - { - RETURN_NULL(); - } - - string id(s, sLen); - if(id.empty()) - { - invalidArgument("communicator id cannot be empty"); - RETURN_NULL(); - } - - CommunicatorInfoIPtr info = Wrapper<CommunicatorInfoIPtr>::value(comm); - assert(info); - - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); - - RegisteredCommunicatorMap::iterator p = _registeredCommunicators.find(id); - if(p != _registeredCommunicators.end()) - { - if(p->second->communicator != info->getCommunicator()) - { - // - // A different communicator is already registered with that ID. - // - RETURN_FALSE; - } - } - else - { - info->ac->ids.push_back(id); - _registeredCommunicators[id] = info->ac; - } - - if(expires > 0) - { - // - // Update the expiration time. If a communicator is registered with multiple IDs, we - // always use the most recent expiration setting. - // - info->ac->expires = static_cast<int>(expires); - info->ac->lastAccess = IceUtil::Time::now(); - - // - // Start the timer if necessary. Reap expired communicators every five minutes. - // - if(!_timer) - { - _timer = new IceUtil::Timer; - _timer->scheduleRepeated(new ReaperTask, IceUtil::Time::seconds(5 * 60)); - } - } - - RETURN_TRUE; -} - -ZEND_FUNCTION(Ice_unregister) -{ - char* s; - size_t sLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &s, &sLen) != SUCCESS) - { - RETURN_NULL(); - } - - string id(s, sLen); - - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); - - RegisteredCommunicatorMap::iterator p = _registeredCommunicators.find(id); - if(p == _registeredCommunicators.end()) - { - // - // No communicator registered with that ID. - // - RETURN_FALSE; - } - - // - // Remove the ID from the ActiveCommunicator's list of registered IDs. - // - ActiveCommunicatorPtr ac = p->second; - vector<string>::iterator q = find(ac->ids.begin(), ac->ids.end(), id); - assert(q != ac->ids.end()); - ac->ids.erase(q); - - _registeredCommunicators.erase(p); - - RETURN_TRUE; -} - -ZEND_FUNCTION(Ice_find) -{ - char* s; - size_t sLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &s, &sLen) != SUCCESS) - { - RETURN_NULL(); - } - - string id(s, sLen); - - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); - - RegisteredCommunicatorMap::iterator p = _registeredCommunicators.find(id); - if(p == _registeredCommunicators.end()) - { - // - // No communicator registered with that ID. - // - RETURN_NULL(); - } - - if(p->second->expires > 0) - { - p->second->lastAccess = IceUtil::Time::now(); - } - - // - // Check if this communicator has already been obtained by the current request. - // If so, we can return the existing PHP object that corresponds to the communicator. - // - CommunicatorMap* m = reinterpret_cast<CommunicatorMap*>(ICE_G(communicatorMap)); - if(m) - { - CommunicatorMap::iterator q = m->find(p->second->communicator); - if(q != m->end()) - { - q->second->getZval(return_value); - return; - } - } - - if(!createCommunicator(return_value, p->second)) - { - RETURN_NULL(); - } -} - -ZEND_FUNCTION(Ice_getProperties) -{ - char* s = 0; - size_t sLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("|s"), &s, &sLen) != SUCCESS) - { - RETURN_NULL(); - } - - string name; - if(s) - { - name = string(s, sLen); - } - - ProfileMap::iterator p = _profiles.find(name); - if(p == _profiles.end()) - { - RETURN_NULL(); - } - - Ice::PropertiesPtr clone = p->second->clone(); - if(!createProperties(return_value, clone)) - { - RETURN_NULL(); - } -} - -ZEND_FUNCTION(Ice_identityToString) -{ - zend_class_entry* identityClass = idToClass("::Ice::Identity"); - assert(identityClass); - - zval* zv; - zend_long mode = 0; - - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O|l"), &zv, identityClass, &mode) != SUCCESS) - { - RETURN_NULL(); - } - Ice::Identity id; - if(!extractIdentity(zv, id)) - { - RETURN_NULL(); - } - - try - { - string str = Ice::identityToString(id, static_cast<Ice::ToStringMode>(mode)); - RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -ZEND_FUNCTION(Ice_stringToIdentity) -{ - char* str; - size_t strLen; - if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) - { - RETURN_NULL(); - } - string s(str, strLen); - - try - { - Ice::Identity id = Ice::stringToIdentity(s); - if(!createIdentity(return_value, id)) - { - RETURN_NULL(); - } - } - catch(const IceUtil::Exception& ex) - { - throwException(ex); - RETURN_NULL(); - } -} - -// -// Necessary to suppress warnings from zend_function_entry in php-5.2 -// and INI_STR macro. -// -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wwrite-strings" -#endif - -// -// Predefined methods for Communicator. -// -static zend_function_entry _interfaceMethods[] = -{ - {0, 0, 0} -}; -static zend_function_entry _classMethods[] = -{ - ZEND_ME(Ice_Communicator, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) - ZEND_ME(Ice_Communicator, shutdown, ICE_NULLPTR, ZEND_ACC_PUBLIC) - ZEND_ME(Ice_Communicator, isShutdown, ICE_NULLPTR, ZEND_ACC_PUBLIC) - ZEND_ME(Ice_Communicator, waitForShutdown, ICE_NULLPTR, ZEND_ACC_PUBLIC) - 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} -}; - -static bool -createProfile(const string& name, const string& config, const string& options) -{ - ProfileMap::iterator p = _profiles.find(name); - if(p != _profiles.end()) - { - php_error_docref(0, E_WARNING, "duplicate Ice profile `%s'", name.c_str()); - return false; - } - - Ice::PropertiesPtr properties = Ice::createProperties(); - - if(!config.empty()) - { - try - { - properties->load(config); - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - php_error_docref(0, E_WARNING, "unable to load Ice configuration file %s:\n%s", config.c_str(), - ostr.str().c_str()); - return false; - } - } - - if(!options.empty()) - { - vector<string> args; - try - { - args = IceUtilInternal::Options::split(options); - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - string msg = ostr.str(); - php_error_docref(0, E_WARNING, "error occurred while parsing the options `%s':\n%s", - options.c_str(), msg.c_str()); - return false; - } - - properties->parseCommandLineOptions("", args); - } - - _profiles[name] = properties; - return true; -} - -static bool -parseProfiles(const string& file) -{ - // - // The Zend engine doesn't export a function for loading an INI file, so we - // have to do it ourselves. The format is: - // - // [profile-name] - // ice.config = config-file - // ice.options = args - // - ifstream in(IceUtilInternal::streamFilename(file).c_str()); - if(!in) - { - php_error_docref(0, E_WARNING, "unable to open Ice profiles in %s", file.c_str()); - return false; - } - - string name, config, options; - char line[1024]; - while(in.getline(line, 1024)) - { - const string delim = " \t\r\n"; - string s = line; - - string::size_type idx = s.find(';'); - if(idx != string::npos) - { - s.erase(idx); - } - - idx = s.find_last_not_of(delim); - if(idx != string::npos && idx + 1 < s.length()) - { - s.erase(idx + 1); - } - - string::size_type beg = s.find_first_not_of(delim); - if(beg == string::npos) - { - continue; - } - - if(s[beg] == '[') - { - beg++; - string::size_type end = s.find_first_of(" \t]", beg); - if(end == string::npos || s[s.length() - 1] != ']') - { - php_error_docref(0, E_WARNING, "invalid profile section in file %s:\n%s\n", file.c_str(), - line); - return false; - } - - if(!name.empty()) - { - createProfile(name, config, options); - config.clear(); - options.clear(); - } - - name = s.substr(beg, end - beg); - } - else - { - string::size_type end = s.find_first_of(delim + "=", beg); - assert(end != string::npos); - - string key = s.substr(beg, end - beg); - - end = s.find('=', end); - if(end == string::npos) - { - php_error_docref(0, E_WARNING, "invalid profile entry in file %s:\n%s\n", file.c_str(), line); - return false; - } - ++end; - - string value; - beg = s.find_first_not_of(delim, end); - if(beg != string::npos) - { - end = s.length(); - value = s.substr(beg, end - beg); - - // - // Check for quotes and remove them if present - // - string::size_type qpos = IceUtilInternal::checkQuote(value); - if(qpos != string::npos) - { - value = value.substr(1, qpos - 1); - } - } - - if(key == "config" || key == "ice.config") - { - config = value; - } - else if(key == "options" || key == "ice.options") - { - options = value; - } - else - { - php_error_docref(0, E_WARNING, "unknown profile entry in file %s:\n%s\n", file.c_str(), line); - } - - if(name.empty()) - { - php_error_docref(0, E_WARNING, "no section for profile entry in file %s:\n%s\n", file.c_str(), - line); - return false; - } - } - } - - if(!name.empty()) - { - if(!createProfile(name, config, options)) - { - return false; - } - } - - return true; -} - -bool -IcePHP::communicatorInit(void) -{ - // - // We register an interface and a class that implements the interface. This allows - // applications to safely include the Slice-generated code for the type. - // - - // - // Register the Communicator interface. - // - zend_class_entry ce; -#ifdef ICEPHP_USE_NAMESPACES - INIT_NS_CLASS_ENTRY(ce, "Ice", "Communicator", _interfaceMethods); -#else - INIT_CLASS_ENTRY(ce, "Ice_Communicator", _interfaceMethods); -#endif - zend_class_entry* interface = zend_register_internal_interface(&ce); - - // - // Register the Communicator class. - // - INIT_CLASS_ENTRY(ce, "IcePHP_Communicator", _classMethods); - ce.create_object = handleAlloc; - communicatorClassEntry = zend_register_internal_class(&ce); - memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - _handlers.clone_obj = handleClone; - _handlers.free_obj = handleFreeStorage; - _handlers.offset = XtOffsetOf(Wrapper<CommunicatorInfoIPtr>, zobj); - zend_class_implements(communicatorClassEntry, 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); - - // - // Register the ValueFactoryManager class. - // - INIT_CLASS_ENTRY(ce, "IcePHP_ValueFactoryManager", _vfmClassMethods); - ce.create_object = handleVfmAlloc; - valueFactoryManagerClassEntry = zend_register_internal_class(&ce); - memcpy(&_vfmHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - _vfmHandlers.clone_obj = handleVfmClone; - _vfmHandlers.free_obj = handleVfmFreeStorage; - _vfmHandlers.offset = XtOffsetOf(Wrapper<ValueFactoryManagerPtr>, zobj); - zend_class_implements(valueFactoryManagerClassEntry, 1, vfmInterface); - - // - // Create the profiles from configuration settings. - // - const char* empty = ""; - const char* config = INI_STR("ice.config"); // Needs to be a string literal! - if(!config) - { - config = empty; - } - const char* options = INI_STR("ice.options"); // Needs to be a string literal! - if(!options) - { - options = empty; - } - if(!createProfile(_defaultProfileName, config, options)) - { - return false; - } - - const char* profiles = INI_STR("ice.profiles"); // Needs to be a string literal! - if(!profiles) - { - profiles = empty; - } - if(strlen(profiles) > 0) - { - if(!parseProfiles(profiles)) - { - return false; - } - - if(INI_BOOL(const_cast<char*>("ice.hide_profiles"))) - { - memset(const_cast<char*>(profiles), '*', strlen(profiles)); - // - // For some reason the code below does not work as expected. It causes a call - // to ini_get_all() to segfault. - // - /* - if(zend_alter_ini_entry("ice.profiles", sizeof("ice.profiles"), "<hidden>", sizeof("<hidden>") - 1, - PHP_INI_ALL, PHP_INI_STAGE_STARTUP) == FAILURE) - { - return false; - } - */ - } - } - - return true; -} - -bool -IcePHP::communicatorShutdown(void) -{ - _profiles.clear(); - - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); - - if(_timer) - { - _timer->destroy(); - _timer = 0; - } - - // - // Clearing the map releases the last remaining reference counts of the ActiveCommunicator - // objects. The ActiveCommunicator destructor destroys its communicator. - // - _registeredCommunicators.clear(); - - return true; -} - -bool -IcePHP::communicatorRequestInit(void) -{ - ICE_G(communicatorMap) = 0; - - return true; -} - -bool -IcePHP::communicatorRequestShutdown(void) -{ - if(ICE_G(communicatorMap)) - { - CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap)); - for(CommunicatorMap::iterator p = m->begin(); p != m->end(); ++p) - { - CommunicatorInfoIPtr info = p->second; - - // - // We need to destroy any object|value factories installed during this request. - // - info->destroyFactories(); - } - - // - // Deleting the map decrements the reference count of its ActiveCommunicator - // values. If there are no other references to an ActiveCommunicator, its - // destructor destroys the communicator. - // - delete m; - } - - return true; -} - -IcePHP::ActiveCommunicator::ActiveCommunicator(const Ice::CommunicatorPtr& c) : - communicator(c), expires(0) -{ -} - -IcePHP::ActiveCommunicator::~ActiveCommunicator() -{ - // - // There are no more references to this communicator, so we can safely destroy it now. - // - try - { - communicator->destroy(); - } - catch(...) - { - } -} - -IcePHP::FactoryWrapper::FactoryWrapper(zval* factory, bool isObjectFactory, const CommunicatorInfoIPtr& info) : - _isObjectFactory(isObjectFactory), - _info(info) -{ - ZVAL_COPY(&_factory, factory); -} - -Ice::ValuePtr -IcePHP::FactoryWrapper::create(const string& id) -{ - // - // Get the TSRM id for the current request. - // - - // - // 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"); - } - else - { - cls = getClassInfoById(id); - } - - if(!cls) - { - return 0; - } - - zval arg; - ZVAL_STRINGL(&arg, STRCAST(id.c_str()), static_cast<int>(id.length())); - - zval obj; - ZVAL_UNDEF(&obj); - - zend_try - { - assert(Z_TYPE(_factory) == IS_OBJECT); - zend_call_method(&_factory, 0, 0, const_cast<char*>("create"), sizeof("create") - 1, &obj, 1, &arg, 0); - } - zend_catch - { - // obj; - } - zend_end_try(); - - // - // Bail out if an exception has already been thrown. - // - if(Z_ISUNDEF(obj) || EG(exception)) - { - throw AbortMarshaling(); - } - - AutoDestroy destroy(&obj); - - if(Z_TYPE(obj) == IS_NULL) - { - return 0; - } - - return new ObjectReader(&obj, cls, _info); -} - -void -IcePHP::FactoryWrapper::getZval(zval* factory) -{ - ZVAL_DUP(factory, &_factory); -} - -bool -IcePHP::FactoryWrapper::isObjectFactory() const -{ - return _isObjectFactory; -} - -void -IcePHP::FactoryWrapper::destroy(void) -{ - if(_isObjectFactory) - { - // - // Invoke the destroy method on the PHP factory. - // - invokeMethod(&_factory, "destroy"); - zend_clear_exception(); - } - zval_ptr_dtor(&_factory); - _info = 0; -} - -IcePHP::DefaultValueFactory::DefaultValueFactory(const CommunicatorInfoIPtr& info) : - _info(info) -{ -} - -Ice::ValuePtr -IcePHP::DefaultValueFactory::create(const string& id) -{ - // - // Get the TSRM id for the current request. - // - if(_delegate) - { - Ice::ValuePtr v = _delegate->create(id); - if(v) - { - return v; - } - } - - // - // 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"); - } - else - { - cls = getClassInfoById(id); - } - - if(!cls) - { - return 0; - } - - // - // Instantiate the object. - // - zval obj; - - if(object_init_ex(&obj, const_cast<zend_class_entry*>(cls->zce)) != SUCCESS) - { - throw AbortMarshaling(); - } - - if(!invokeMethod(&obj, ZEND_CONSTRUCTOR_FUNC_NAME)) - { - throw AbortMarshaling(); - } - - return new ObjectReader(&obj, cls, _info); -} - -void -IcePHP::DefaultValueFactory::destroy(void) -{ - if(_delegate) - { - _delegate->destroy(); - _delegate = 0; - } - _info = 0; -} - -IcePHP::CommunicatorInfoI::CommunicatorInfoI(const ActiveCommunicatorPtr& c, zval* z) : - ac(c), - _defaultFactory(new DefaultValueFactory(this)) -{ - ZVAL_COPY_VALUE(&zv, z); -} - -void -IcePHP::CommunicatorInfoI::getZval(zval* z) -{ - ZVAL_COPY_VALUE(z, &zv); - addRef(); -} - -void -IcePHP::CommunicatorInfoI::addRef(void) -{ - Z_ADDREF_P(&zv); -} - -void -IcePHP::CommunicatorInfoI::decRef(void) -{ - Z_DELREF_P(&zv); -} - -Ice::CommunicatorPtr -IcePHP::CommunicatorInfoI::getCommunicator() const -{ - return ac->communicator; -} - -bool -IcePHP::CommunicatorInfoI::addFactory(zval* factory, const string& id, bool isObjectFactory) -{ - if(id.empty()) - { - if(_defaultFactory->getDelegate()) - { - Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); - ex.kindOfObject = "value factory"; - ex.id = id; - throwException(ex); - 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); - 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()) - { - assert(p->second); - return p->second; - } - } - return 0; -} - -void -IcePHP::CommunicatorInfoI::destroyFactories(void) -{ - for(FactoryMap::iterator p = _factories.begin(); p != _factories.end(); ++p) - { - p->second->destroy(); - } - _factories.clear(); - _defaultFactory->destroy(); -} - -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 ICE_NOEXCEPT -{ - // - // Get the TSRM id for the current request. - // - - 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::ValueFactoryManager::destroy() -{ - _communicator = 0; -} - -void -IcePHP::ReaperTask::runTimerTask() -{ - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); - - IceUtil::Time now = IceUtil::Time::now(); - RegisteredCommunicatorMap::iterator p = _registeredCommunicators.begin(); - while(p != _registeredCommunicators.end()) - { - if(p->second->lastAccess + IceUtil::Time::seconds(p->second->expires * 60) <= now) - { - try - { - p->second->communicator->destroy(); - } - catch(...) - { - } - _registeredCommunicators.erase(p++); - } - else - { - ++p; - } - } -} |