summaryrefslogtreecommitdiff
path: root/php/src
diff options
context:
space:
mode:
Diffstat (limited to 'php/src')
-rw-r--r--php/src/ice/communicator.cpp170
-rw-r--r--php/src/ice/ice_communicator.h14
-rw-r--r--php/src/ice/ice_marshal.h9
-rw-r--r--php/src/ice/ice_util.h18
-rw-r--r--php/src/ice/marshal.cpp247
-rw-r--r--php/src/ice/profile.cpp19
-rw-r--r--php/src/ice/util.cpp106
7 files changed, 516 insertions, 67 deletions
diff --git a/php/src/ice/communicator.cpp b/php/src/ice/communicator.cpp
index d306ee93c1b..0788425bba4 100644
--- a/php/src/ice/communicator.cpp
+++ b/php/src/ice/communicator.cpp
@@ -51,9 +51,13 @@ static void initCommunicator(ice_object* TSRMLS_DC);
//
static function_entry _methods[] =
{
- {"__construct", PHP_FN(Ice_Communicator___construct), NULL},
- {"stringToProxy", PHP_FN(Ice_Communicator_stringToProxy), NULL},
- {"proxyToString", PHP_FN(Ice_Communicator_proxyToString), NULL},
+ {"__construct", PHP_FN(Ice_Communicator___construct), NULL},
+ {"stringToProxy", PHP_FN(Ice_Communicator_stringToProxy), NULL},
+ {"proxyToString", PHP_FN(Ice_Communicator_proxyToString), NULL},
+ {"addObjectFactory", PHP_FN(Ice_Communicator_addObjectFactory), NULL},
+ {"removeObjectFactory", PHP_FN(Ice_Communicator_removeObjectFactory), NULL},
+ {"findObjectFactory", PHP_FN(Ice_Communicator_findObjectFactory), NULL},
+ {"flushBatchRequests", PHP_FN(Ice_Communicator_flushBatchRequests), NULL},
{NULL, NULL, NULL}
};
@@ -151,6 +155,11 @@ ZEND_FUNCTION(Ice_Communicator___construct)
ZEND_FUNCTION(Ice_Communicator_stringToProxy)
{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
ice_object* obj = getObject(getThis() TSRMLS_CC);
if(!obj)
{
@@ -159,11 +168,6 @@ ZEND_FUNCTION(Ice_Communicator_stringToProxy)
assert(obj->ptr);
Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
- if(ZEND_NUM_ARGS() != 1)
- {
- WRONG_PARAM_COUNT;
- }
-
char *str;
int len;
@@ -191,6 +195,11 @@ ZEND_FUNCTION(Ice_Communicator_stringToProxy)
ZEND_FUNCTION(Ice_Communicator_proxyToString)
{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
ice_object* obj = getObject(getThis() TSRMLS_CC);
if(!obj)
{
@@ -199,11 +208,6 @@ ZEND_FUNCTION(Ice_Communicator_proxyToString)
assert(obj->ptr);
Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
- if(ZEND_NUM_ARGS() != 1)
- {
- WRONG_PARAM_COUNT;
- }
-
zval* zprx;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!", &zprx, proxyClassEntry) == FAILURE)
@@ -230,6 +234,146 @@ ZEND_FUNCTION(Ice_Communicator_proxyToString)
}
}
+ZEND_FUNCTION(Ice_Communicator_addObjectFactory)
+{
+ if(ZEND_NUM_ARGS() != 2)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ice_object* obj = getObject(getThis() TSRMLS_CC);
+ if(!obj)
+ {
+ return;
+ }
+ assert(obj->ptr);
+ Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
+
+ zval* zfactory;
+ char* id;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os", &zfactory, &id, &len) == FAILURE)
+ {
+ return;
+ }
+
+ //
+ // Verify that the object implements Ice_ObjectFactory.
+ //
+ // TODO: When zend_check_class is changed to also check interfaces, we can remove this code and
+ // pass the class entry for Ice_ObjectFactory to zend_parse_parameters instead.
+ //
+ zend_class_entry* ce = Z_OBJCE_P(zfactory);
+ zend_class_entry* base = findClass("Ice_ObjectFactory" TSRMLS_CC);
+ assert(base);
+ if(!checkClass(ce, base))
+ {
+ zend_error(E_ERROR, "%s(): object does not implement Ice_ObjectFactory", get_active_function_name(TSRMLS_C));
+ return;
+ }
+
+ //
+ // Retrieve the PHPObjectFactory.
+ //
+ Ice::ObjectFactoryPtr factory = (*_this)->findObjectFactory("");
+ PHPObjectFactoryPtr phpFactory = PHPObjectFactoryPtr::dynamicCast(factory);
+ assert(phpFactory);
+
+ phpFactory->addObjectFactory(zfactory, id TSRMLS_CC);
+}
+
+ZEND_FUNCTION(Ice_Communicator_removeObjectFactory)
+{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ice_object* obj = getObject(getThis() TSRMLS_CC);
+ if(!obj)
+ {
+ RETURN_NULL();
+ }
+ assert(obj->ptr);
+ Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
+
+ char* id;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ //
+ // Retrieve the PHPObjectFactory.
+ //
+ Ice::ObjectFactoryPtr factory = (*_this)->findObjectFactory("");
+ PHPObjectFactoryPtr phpFactory = PHPObjectFactoryPtr::dynamicCast(factory);
+ assert(phpFactory);
+
+ phpFactory->removeObjectFactory(id TSRMLS_CC);
+}
+
+ZEND_FUNCTION(Ice_Communicator_findObjectFactory)
+{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ice_object* obj = getObject(getThis() TSRMLS_CC);
+ if(!obj)
+ {
+ RETURN_NULL();
+ }
+ assert(obj->ptr);
+ Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
+
+ char* id;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ //
+ // Retrieve the PHPObjectFactory.
+ //
+ Ice::ObjectFactoryPtr factory = (*_this)->findObjectFactory("");
+ PHPObjectFactoryPtr phpFactory = PHPObjectFactoryPtr::dynamicCast(factory);
+ assert(phpFactory);
+
+ phpFactory->findObjectFactory(id, return_value TSRMLS_CC);
+}
+
+ZEND_FUNCTION(Ice_Communicator_flushBatchRequests)
+{
+ if(ZEND_NUM_ARGS() != 0)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ice_object* obj = getObject(getThis() TSRMLS_CC);
+ if(!obj)
+ {
+ return;
+ }
+ assert(obj->ptr);
+ Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
+
+ try
+ {
+ (*_this)->flushBatchRequests();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ }
+}
+
#ifdef WIN32
extern "C"
#endif
diff --git a/php/src/ice/ice_communicator.h b/php/src/ice/ice_communicator.h
index b5d43f3f44a..131d2839ece 100644
--- a/php/src/ice/ice_communicator.h
+++ b/php/src/ice/ice_communicator.h
@@ -25,12 +25,20 @@ extern "C"
ZEND_FUNCTION(Ice_Communicator___construct);
ZEND_FUNCTION(Ice_Communicator_stringToProxy);
ZEND_FUNCTION(Ice_Communicator_proxyToString);
+ZEND_FUNCTION(Ice_Communicator_addObjectFactory);
+ZEND_FUNCTION(Ice_Communicator_removeObjectFactory);
+ZEND_FUNCTION(Ice_Communicator_findObjectFactory);
+ZEND_FUNCTION(Ice_Communicator_flushBatchRequests);
}
#define ICE_PHP_COMMUNICATOR_FUNCTIONS \
- ZEND_FE(Ice_Communicator___construct, NULL) \
- ZEND_FE(Ice_Communicator_stringToProxy, NULL) \
- ZEND_FE(Ice_Communicator_proxyToString, NULL)
+ ZEND_FE(Ice_Communicator___construct, NULL) \
+ ZEND_FE(Ice_Communicator_stringToProxy, NULL) \
+ ZEND_FE(Ice_Communicator_proxyToString, NULL) \
+ ZEND_FE(Ice_Communicator_addObjectFactory, NULL) \
+ ZEND_FE(Ice_Communicator_removeObjectFactory, NULL) \
+ ZEND_FE(Ice_Communicator_findObjectFactory, NULL) \
+ ZEND_FE(Ice_Communicator_flushBatchRequests, NULL)
namespace IcePHP
{
diff --git a/php/src/ice/ice_marshal.h b/php/src/ice/ice_marshal.h
index 19239343658..d8ad51c02df 100644
--- a/php/src/ice/ice_marshal.h
+++ b/php/src/ice/ice_marshal.h
@@ -84,7 +84,8 @@ class AbortMarshaling
//
// PHPObjectFactory is an implementation of Ice::ObjectFactory that creates PHP objects.
-// A single instance can be used for all types.
+// It is also the registry for user-defined PHP factory implementations. A single instance
+// can be used for all types.
//
class PHPObjectFactory : public Ice::ObjectFactory
{
@@ -94,11 +95,17 @@ public:
virtual Ice::ObjectPtr create(const std::string&);
virtual void destroy();
+ void addObjectFactory(zval*, const std::string& TSRMLS_DC);
+ void removeObjectFactory(const std::string& TSRMLS_DC);
+ void findObjectFactory(const std::string&, zval* TSRMLS_DC);
+
private:
#ifdef ZTS
TSRMLS_D;
#endif
+ std::map<std::string, zval*> _factories;
};
+typedef IceUtil::Handle<PHPObjectFactory> PHPObjectFactoryPtr;
} // End of namespace IcePHP
diff --git a/php/src/ice/ice_util.h b/php/src/ice/ice_util.h
index df642753610..28173d97185 100644
--- a/php/src/ice/ice_util.h
+++ b/php/src/ice/ice_util.h
@@ -111,6 +111,11 @@ bool isNativeKey(const Slice::TypePtr&);
bool getContext(zval*, Ice::Context& TSRMLS_DC);
//
+// Determines whether a class (or interface) inherits from a base class (or interface).
+//
+bool checkClass(zend_class_entry*, zend_class_entry*);
+
+//
// Exception-safe efree.
//
class AutoEfree
@@ -123,6 +128,19 @@ private:
void* _p;
};
+//
+// Exception-safe zval destroy.
+//
+class AutoDestroy
+{
+public:
+ AutoDestroy(zval* zv) : _zv(zv) {}
+ ~AutoDestroy() { if(_zv) zval_ptr_dtor(&_zv); }
+
+private:
+ zval* _zv;
+};
+
} // End of namespace IcePHP
#endif
diff --git a/php/src/ice/marshal.cpp b/php/src/ice/marshal.cpp
index 1d44b128495..6524294b4ce 100644
--- a/php/src/ice/marshal.cpp
+++ b/php/src/ice/marshal.cpp
@@ -250,7 +250,7 @@ private:
class ObjectReader : public Ice::Object
{
public:
- ObjectReader(zend_class_entry*, const Slice::ClassDefPtr& TSRMLS_DC);
+ ObjectReader(zval*, const Slice::ClassDefPtr& TSRMLS_DC);
~ObjectReader();
virtual void __write(::IceInternal::BasicStream*) const;
@@ -259,12 +259,12 @@ public:
void setValue(zend_class_entry*, zval*);
private:
- zend_class_entry* _class;
+ zval* _value;
Slice::ClassDefPtr _type; // nil if type is ::Ice::Object
#ifdef ZTS
TSRMLS_D;
#endif
- zval* _value;
+ zend_class_entry* _class;
};
typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr;
@@ -1521,28 +1521,21 @@ IcePHP::ObjectWriter::__read(IceInternal::BasicStream* is, bool rid)
//
// ObjectReader implementation.
//
-IcePHP::ObjectReader::ObjectReader(zend_class_entry* cls, const Slice::ClassDefPtr& type TSRMLS_DC) :
- _class(cls), _type(type)
+IcePHP::ObjectReader::ObjectReader(zval* val, const Slice::ClassDefPtr& type TSRMLS_DC) :
+ _value(val), _type(type)
{
#ifdef ZTS
this->TSRMLS_C = TSRMLS_C;
#endif
- //
- // Create a zval to hold the new object.
- //
- MAKE_STD_ZVAL(_value);
+ ZVAL_ADDREF(_value);
- //
- // Instantiate the new object.
- //
- object_init_ex(_value, _class);
+ _class = Z_OBJCE_P(_value);
}
IcePHP::ObjectReader::~ObjectReader()
{
- Z_OBJ_HT_P(_value)->del_ref(_value TSRMLS_CC);
- efree(_value);
+ zval_ptr_dtor(&_value);
}
void
@@ -1638,23 +1631,11 @@ IcePHP::ObjectReader::setValue(zend_class_entry* ce, zval* zv)
//
// Compare the class entries. The argument "ce" represents the formal type.
//
- if(_class != ce)
+ if(!checkClass(_class, ce))
{
- //
- // Check for inheritance.
- //
- zend_class_entry* c = _class->parent;
- while(c && c != ce)
- {
- c = c->parent;
- }
-
- if(c == NULL)
- {
- zend_error(E_ERROR, "%s(): expected object value of type %s but received %s",
- get_active_function_name(TSRMLS_C), ce->name, _class->name);
- return;
- }
+ Ice::NoObjectFactoryException ex(__FILE__, __LINE__);
+ ex.type = ce->name;
+ throw ex;
}
//
@@ -1833,6 +1814,96 @@ IcePHP::PHPObjectFactory::create(const string& scoped)
{
Ice::ObjectPtr result;
+ Profile* profile = static_cast<Profile*>(ICE_G(profile));
+ assert(profile);
+
+ //
+ // First check our map for a factory registered for this type.
+ //
+ map<string, zval*>::iterator p;
+ p = _factories.find(scoped);
+ if(p == _factories.end())
+ {
+ //
+ // Next, check for a default factory.
+ //
+ p = _factories.find("");
+ }
+
+ //
+ // If we found a factory, invoke create() on the object.
+ //
+ if(p != _factories.end())
+ {
+ zval** args[1];
+ zval* id;
+ MAKE_STD_ZVAL(id);
+ ZVAL_STRINGL(id, const_cast<char*>(scoped.c_str()), scoped.length(), 1);
+
+ zval* create;
+ MAKE_STD_ZVAL(create);
+ ZVAL_STRINGL(create, "create", sizeof("create") - 1, 1);
+
+ args[0] = &id;
+ zval* zresult = NULL;
+ int status = call_user_function_ex(NULL, &p->second, create, &zresult, 1, args, 0, NULL TSRMLS_CC);
+
+ zval_ptr_dtor(&create);
+ zval_ptr_dtor(&id);
+
+ AutoDestroy destroyResult(zresult);
+
+ //
+ // Bail out if an exception has been thrown.
+ //
+ if(EG(exception))
+ {
+ throw AbortMarshaling();
+ }
+
+ if(zresult)
+ {
+ //
+ // If the factory returned a non-null value, verify that it is an object, and that it
+ // inherits from Ice_ObjectImpl.
+ //
+ if(!ZVAL_IS_NULL(zresult))
+ {
+ if(Z_TYPE_P(zresult) != IS_OBJECT)
+ {
+ zend_error(E_ERROR, "object factory did not return an object");
+ throw AbortMarshaling();
+ }
+
+ zend_class_entry* ce = Z_OBJCE_P(zresult);
+ zend_class_entry* base = findClass("Ice_ObjectImpl" TSRMLS_CC);
+ if(!checkClass(ce, base))
+ {
+ zend_error(E_ERROR, "object returned by factory does not implement Ice_ObjectImpl");
+ throw AbortMarshaling();
+ }
+
+ //
+ // Attempt to find a class definition for the object.
+ //
+ Profile::ClassMap::iterator p;
+ while(ce != NULL && (p = profile->classes.find(ce->name)) == profile->classes.end())
+ {
+ ce = ce->parent;
+ }
+
+ Slice::ClassDefPtr def;
+ if(ce != NULL)
+ {
+ assert(p != profile->classes.end());
+ def = p->second;
+ }
+
+ return new ObjectReader(zresult, def TSRMLS_CC);
+ }
+ }
+ }
+
//
// Attempt to find a class entry for the given type id. If no class entry is
// found, or the class is abstract, then we return nil and the stream will skip
@@ -1850,14 +1921,16 @@ IcePHP::PHPObjectFactory::create(const string& scoped)
}
if(cls && (cls->ce_flags & ZEND_CE_ABSTRACT) == 0)
{
- Profile* profile = static_cast<Profile*>(ICE_G(profile));
- assert(profile);
Profile::ClassMap::iterator p = profile->classes.find(cls->name);
if(p != profile->classes.end())
{
def = p->second;
}
- result = new ObjectReader(cls, def TSRMLS_CC);
+ zval* obj;
+ MAKE_STD_ZVAL(obj);
+ object_init_ex(obj, cls);
+ result = new ObjectReader(obj, def TSRMLS_CC);
+ zval_ptr_dtor(&obj);
}
return result;
@@ -1866,6 +1939,112 @@ IcePHP::PHPObjectFactory::create(const string& scoped)
void
IcePHP::PHPObjectFactory::destroy()
{
+ //
+ // Invoke destroy() on each registered factory.
+ //
+ for(map<string, zval*>::iterator p = _factories.begin(); p != _factories.end(); ++p)
+ {
+ zval* funcName;
+ MAKE_STD_ZVAL(funcName);
+ ZVAL_STRINGL(funcName, "destroy", sizeof("destroy") - 1, 1);
+
+ zval* result = NULL;
+ int status = call_user_function_ex(NULL, &p->second, funcName, &result, 0, NULL, 0, NULL TSRMLS_CC);
+
+ zval_ptr_dtor(&funcName);
+ if(result)
+ {
+ zval_ptr_dtor(&result);
+ }
+
+ Z_OBJ_HT_P(p->second)->del_ref(p->second TSRMLS_CC);
+ zval_ptr_dtor(&p->second);
+ }
+
+ _factories.clear();
+}
+
+void
+IcePHP::PHPObjectFactory::addObjectFactory(zval* factory, const string& id TSRMLS_DC)
+{
+ map<string, zval*>::iterator p = _factories.find(id);
+ if(p != _factories.end())
+ {
+ Ice::AlreadyRegisteredException ex(__FILE__, __LINE__);
+ ex.kindOfObject = "object factory";
+ ex.id = id;
+ throwException(ex TSRMLS_CC);
+ return;
+ }
+
+ //
+ // Create a new zval with the same object handle as the factory.
+ //
+ zval* zv;
+ MAKE_STD_ZVAL(zv);
+ Z_TYPE_P(zv) = IS_OBJECT;
+ zv->value.obj = factory->value.obj;
+
+ //
+ // Increment the factory's reference count.
+ //
+ Z_OBJ_HT_P(factory)->add_ref(factory TSRMLS_CC);
+
+ //
+ // Update the factory map.
+ //
+ _factories[id] = zv;
+}
+
+void
+IcePHP::PHPObjectFactory::removeObjectFactory(const string& id TSRMLS_DC)
+{
+ map<string, zval*>::iterator p = _factories.find(id);
+ if(p == _factories.end())
+ {
+ Ice::NotRegisteredException ex(__FILE__, __LINE__);
+ ex.kindOfObject = "object factory";
+ ex.id = id;
+ throwException(ex TSRMLS_CC);
+ return;
+ }
+
+ //
+ // Decrement the factory's reference count.
+ //
+ Z_OBJ_HT_P(p->second)->del_ref(p->second TSRMLS_CC);
+
+ //
+ // Destroy the zval.
+ //
+ zval_ptr_dtor(&p->second);
+
+ //
+ // Update the factory map.
+ //
+ _factories.erase(p);
+}
+
+void
+IcePHP::PHPObjectFactory::findObjectFactory(const string& id, zval* factory TSRMLS_DC)
+{
+ map<string, zval*>::iterator p = _factories.find(id);
+ if(p == _factories.end())
+ {
+ ZVAL_NULL(factory);
+ return;
+ }
+
+ //
+ // Set the zval with the same object handle as the factory.
+ //
+ Z_TYPE_P(factory) = IS_OBJECT;
+ factory->value.obj = p->second->value.obj;
+
+ //
+ // Increment the factory's reference count.
+ //
+ Z_OBJ_HT_P(p->second)->add_ref(p->second TSRMLS_CC);
}
//
diff --git a/php/src/ice/profile.cpp b/php/src/ice/profile.cpp
index e556cb3d269..695125f850e 100644
--- a/php/src/ice/profile.cpp
+++ b/php/src/ice/profile.cpp
@@ -119,6 +119,19 @@ static const char* _coreTypes =
"{\n"
"}\n"
"\n"
+ "class Ice_ProtocolException extends Ice_LocalException\n"
+ "{\n"
+ "}\n"
+ "\n"
+ "class Ice_MarshalException extends Ice_ProtocolException\n"
+ "{\n"
+ "}\n"
+ "\n"
+ "class Ice_NoObjectFactoryException extends Ice_MarshalException\n"
+ "{\n"
+ " var $type;\n"
+ "}\n"
+ "\n"
"abstract class Ice_UserException\n"
"{\n"
"}\n"
@@ -139,6 +152,12 @@ static const char* _coreTypes =
"{\n"
" var $ice_facets = array();\n"
"}\n"
+ "\n"
+ "interface Ice_ObjectFactory implements Ice_LocalObject\n"
+ "{\n"
+ " function create($id);\n"
+ " function destroy();\n"
+ "}\n"
;
//
diff --git a/php/src/ice/util.cpp b/php/src/ice/util.cpp
index b24ac10626f..83002e49fde 100644
--- a/php/src/ice/util.cpp
+++ b/php/src/ice/util.cpp
@@ -376,15 +376,13 @@ IcePHP::throwException(const IceUtil::Exception& ex TSRMLS_DC)
//
EG(exception) = zex;
}
- catch(const Ice::LocalException& e)
+ catch(const Ice::NoObjectFactoryException& e)
{
- //
- // All other local exceptions are raised as UnknownLocalException.
- //
- zend_class_entry* cls = findClass("Ice_UnknownLocalException" TSRMLS_CC);
+ string name = e.ice_name();
+ zend_class_entry* cls = findClassScoped(name TSRMLS_CC);
if(!cls)
{
- zend_error(E_ERROR, "unable to find class Ice_UnknownLocalException");
+ zend_error(E_ERROR, "unable to find class %s", name.c_str());
return;
}
@@ -397,20 +395,72 @@ IcePHP::throwException(const IceUtil::Exception& ex TSRMLS_DC)
}
//
- // Set the unknown member.
+ // Set the type member.
//
- zval* unknown;
- MAKE_STD_ZVAL(unknown);
- ostringstream ostr;
- e.ice_print(ostr);
- string str = ostr.str();
- ZVAL_STRINGL(unknown, const_cast<char*>(str.c_str()), str.length(), 1);
- if(add_property_zval(zex, "unknown", unknown) == FAILURE)
+ zval* type;
+ MAKE_STD_ZVAL(type);
+ ZVAL_STRINGL(type, const_cast<char*>(e.type.c_str()), e.type.length(), 1);
+ if(add_property_zval(zex, "type", type) == FAILURE)
{
- zend_error(E_ERROR, "unable to set unknown member of %s", cls->name);
+ zend_error(E_ERROR, "unable to set type member of %s", cls->name);
return;
}
- zval_ptr_dtor(&unknown); // add_property_zval increments the refcount
+ zval_ptr_dtor(&type); // add_property_zval increments the refcount
+
+ //
+ // Throw the exception.
+ //
+ EG(exception) = zex;
+ }
+ catch(const Ice::LocalException& e)
+ {
+ zval* zex;
+ MAKE_STD_ZVAL(zex);
+
+ //
+ // See if we have a PHP class for the exception, otherwise raise UnknownLocalException.
+ //
+ string name = e.ice_name();
+ zend_class_entry* cls = findClassScoped(name TSRMLS_CC);
+ if(cls)
+ {
+ if(object_init_ex(zex, cls) != SUCCESS)
+ {
+ zend_error(E_ERROR, "unable to create exception %s", cls->name);
+ return;
+ }
+ }
+ else
+ {
+ cls = findClass("Ice_UnknownLocalException" TSRMLS_CC);
+ if(!cls)
+ {
+ zend_error(E_ERROR, "unable to find class Ice_UnknownLocalException");
+ return;
+ }
+
+ if(object_init_ex(zex, cls) != SUCCESS)
+ {
+ zend_error(E_ERROR, "unable to create exception %s", cls->name);
+ return;
+ }
+
+ //
+ // Set the unknown member.
+ //
+ zval* unknown;
+ MAKE_STD_ZVAL(unknown);
+ ostringstream ostr;
+ e.ice_print(ostr);
+ string str = ostr.str();
+ ZVAL_STRINGL(unknown, const_cast<char*>(str.c_str()), str.length(), 1);
+ if(add_property_zval(zex, "unknown", unknown) == FAILURE)
+ {
+ zend_error(E_ERROR, "unable to set unknown member of %s", cls->name);
+ return;
+ }
+ zval_ptr_dtor(&unknown); // add_property_zval increments the refcount
+ }
//
// Throw the exception.
@@ -658,3 +708,27 @@ IcePHP::getContext(zval* zv, Ice::Context& ctx TSRMLS_DC)
return true;
}
+
+bool
+IcePHP::checkClass(zend_class_entry* ce, zend_class_entry* base)
+{
+ while(ce != NULL)
+ {
+ if(ce == base)
+ {
+ return true;
+ }
+
+ for(zend_uint i = 0; i < ce->num_interfaces; ++i)
+ {
+ if(checkClass(ce->interfaces[i], base))
+ {
+ return true;
+ }
+ }
+
+ ce = ce->parent;
+ }
+
+ return false;
+}