summaryrefslogtreecommitdiff
path: root/php/src/IcePHP/Communicator.cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2006-11-09 18:38:47 +0000
committerMark Spruiell <mes@zeroc.com>2006-11-09 18:38:47 +0000
commit9fc8c2106fdb8e918eefd8614aef6dd77a9c29e3 (patch)
tree3942117e687cbe34477b9d2f48d82fe098cd972b /php/src/IcePHP/Communicator.cpp
parentclean up; align with C++; bug fix (diff)
downloadice-9fc8c2106fdb8e918eefd8614aef6dd77a9c29e3.tar.bz2
ice-9fc8c2106fdb8e918eefd8614aef6dd77a9c29e3.tar.xz
ice-9fc8c2106fdb8e918eefd8614aef6dd77a9c29e3.zip
Reorganizing source code. Changing build process to use Makefiles instead
of configure. Desupporting all platforms except Linux and Windows.
Diffstat (limited to 'php/src/IcePHP/Communicator.cpp')
-rw-r--r--php/src/IcePHP/Communicator.cpp592
1 files changed, 592 insertions, 0 deletions
diff --git a/php/src/IcePHP/Communicator.cpp b/php/src/IcePHP/Communicator.cpp
new file mode 100644
index 00000000000..ba548449ce2
--- /dev/null
+++ b/php/src/IcePHP/Communicator.cpp
@@ -0,0 +1,592 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/DisableWarnings.h>
+#include <Communicator.h>
+#include <Proxy.h>
+#include <Marshal.h>
+#include <Util.h>
+
+using namespace std;
+using namespace IcePHP;
+
+ZEND_EXTERN_MODULE_GLOBALS(ice)
+
+//
+// Class entries represent the PHP class implementations we have registered.
+//
+static zend_class_entry* _communicatorClassEntry;
+
+//
+// Ice::Communicator support.
+//
+static zend_object_handlers _handlers;
+
+extern "C"
+{
+static zend_object_value handleAlloc(zend_class_entry* TSRMLS_DC);
+static zend_object_value handleClone(zval* TSRMLS_DC);
+static void handleFreeStorage(void* TSRMLS_DC);
+
+static union _zend_function* handleGetMethod(zval**, char*, int TSRMLS_DC);
+}
+
+static void initCommunicator(ice_object* TSRMLS_DC);
+
+//
+// Function entries for Ice::Communicator methods.
+//
+static function_entry _methods[] =
+{
+ {"__construct", PHP_FN(Ice_Communicator___construct), NULL},
+ {"getProperty", PHP_FN(Ice_Communicator_getProperty), NULL},
+ {"stringToProxy", PHP_FN(Ice_Communicator_stringToProxy), NULL},
+ {"proxyToString", PHP_FN(Ice_Communicator_proxyToString), NULL},
+ {"stringToIdentity", PHP_FN(Ice_Communicator_stringToIdentity), NULL},
+ {"identityToString", PHP_FN(Ice_Communicator_identityToString), NULL},
+ {"addObjectFactory", PHP_FN(Ice_Communicator_addObjectFactory), NULL},
+ {"findObjectFactory", PHP_FN(Ice_Communicator_findObjectFactory), NULL},
+ {"flushBatchRequests", PHP_FN(Ice_Communicator_flushBatchRequests), NULL},
+ {NULL, NULL, NULL}
+};
+
+bool
+IcePHP::communicatorInit(TSRMLS_D)
+{
+ //
+ // Register the Ice_Communicator class.
+ //
+ zend_class_entry ce;
+ INIT_CLASS_ENTRY(ce, "Ice_Communicator", _methods);
+ ce.create_object = handleAlloc;
+ _communicatorClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
+ memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ _handlers.clone_obj = handleClone;
+ _handlers.get_method = handleGetMethod;
+
+ return true;
+}
+
+bool
+IcePHP::createCommunicator(TSRMLS_D)
+{
+ zval* global;
+ MAKE_STD_ZVAL(global);
+
+ //
+ // Create the global variable for the communicator, but delay creation of the communicator
+ // itself until it is first used (see handleGetMethod).
+ //
+ if(object_init_ex(global, _communicatorClassEntry) != SUCCESS)
+ {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "unable to create object for communicator");
+ return false;
+ }
+
+ //
+ // Register the global variable "ICE" to hold the communicator.
+ //
+ ICE_G(communicator) = global;
+ ZEND_SET_GLOBAL_VAR("ICE", global);
+
+ return true;
+}
+
+Ice::CommunicatorPtr
+IcePHP::getCommunicator(TSRMLS_D)
+{
+ Ice::CommunicatorPtr result;
+
+ zval **zv;
+ if(zend_hash_find(&EG(symbol_table), "ICE", sizeof("ICE"), (void **) &zv) == SUCCESS)
+ {
+ ice_object* obj = getObject(*zv TSRMLS_CC);
+ assert(obj);
+
+ //
+ // Initialize the communicator if necessary.
+ //
+ if(!obj->ptr)
+ {
+ try
+ {
+ initCommunicator(obj TSRMLS_CC);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ ostringstream ostr;
+ ex.ice_print(ostr);
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "unable to initialize communicator:\n%s", ostr.str().c_str());
+ return 0;
+ }
+ }
+
+ Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
+ result = *_this;
+ }
+
+ return result;
+}
+
+zval*
+IcePHP::getCommunicatorZval(TSRMLS_D)
+{
+ zval **zv = NULL;
+ zend_hash_find(&EG(symbol_table), "ICE", sizeof("ICE"), (void **) &zv);
+ assert(zv);
+ return *zv;
+}
+
+ZEND_FUNCTION(Ice_Communicator___construct)
+{
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Ice_Communicator cannot be instantiated, use the global variable $ICE");
+}
+
+ZEND_FUNCTION(Ice_Communicator_getProperty)
+{
+ if(ZEND_NUM_ARGS() < 1 || 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);
+
+ char *name;
+ int nameLen;
+ char *def = NULL;
+ int defLen = 0;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name, &nameLen, &def, &defLen) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ string val = (*_this)->getProperties()->getProperty(name);
+ if(val.empty() && def)
+ {
+ RETURN_STRING(def, 1);
+ }
+ else
+ {
+ RETURN_STRING(const_cast<char*>(val.c_str()), 1);
+ }
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_EMPTY_STRING();
+ }
+}
+
+ZEND_FUNCTION(Ice_Communicator_stringToProxy)
+{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ 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);
+
+ char *str;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::ObjectPrx proxy;
+ try
+ {
+ proxy = (*_this)->stringToProxy(str);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_NULL();
+ }
+
+ if(!createProxy(return_value, proxy TSRMLS_CC))
+ {
+ RETURN_NULL();
+ }
+}
+
+ZEND_FUNCTION(Ice_Communicator_proxyToString)
+{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ 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* zprx;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!", &zprx, proxyClassEntry) == FAILURE)
+ {
+ RETURN_EMPTY_STRING();
+ }
+
+ Ice::ObjectPrx proxy;
+ Slice::ClassDefPtr def;
+ if(!fetchProxy(zprx, proxy, def TSRMLS_CC))
+ {
+ RETURN_EMPTY_STRING();
+ }
+
+ try
+ {
+ string result = (*_this)->proxyToString(proxy);
+ RETURN_STRING(const_cast<char*>(result.c_str()), 1);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ RETURN_EMPTY_STRING();
+ }
+}
+
+ZEND_FUNCTION(Ice_Communicator_identityToString)
+{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ 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);
+
+ zend_class_entry* cls = findClass("Ice_Identity" TSRMLS_CC);
+ assert(cls);
+
+ zval *zid;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zid, cls) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ Ice::Identity id;
+ if(extractIdentity(zid, id TSRMLS_CC))
+ {
+ string s = (*_this)->identityToString(id);
+ RETURN_STRINGL(const_cast<char*>(s.c_str()), s.length(), 1);
+ }
+}
+
+ZEND_FUNCTION(Ice_Communicator_stringToIdentity)
+{
+ if(ZEND_NUM_ARGS() != 1)
+ {
+ 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);
+
+ char* str;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ try
+ {
+ Ice::Identity id = (*_this)->stringToIdentity(str);
+ createIdentity(return_value, id TSRMLS_CC);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ throwException(ex TSRMLS_CC);
+ }
+}
+
+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);
+
+ 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))
+ {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "object does not implement Ice_ObjectFactory");
+ return;
+ }
+
+ ObjectFactoryMap* ofm = static_cast<ObjectFactoryMap*>(ICE_G(objectFactoryMap));
+ ObjectFactoryMap::iterator p = ofm->find(id);
+ if(p != ofm->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 = zfactory->value.obj;
+
+ //
+ // Increment the factory's reference count.
+ //
+ Z_OBJ_HT_P(zv)->add_ref(zv TSRMLS_CC);
+
+ //
+ // Update the factory map.
+ //
+ ofm->insert(ObjectFactoryMap::value_type(id, zv));
+}
+
+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);
+
+ char* id;
+ int len;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &len) == FAILURE)
+ {
+ RETURN_NULL();
+ }
+
+ ObjectFactoryMap* ofm = static_cast<ObjectFactoryMap*>(ICE_G(objectFactoryMap));
+ ObjectFactoryMap::iterator p = ofm->find(id);
+ if(p == ofm->end())
+ {
+ RETURN_NULL();
+ }
+
+ //
+ // Set the zval with the same object handle as the factory.
+ //
+ Z_TYPE_P(return_value) = IS_OBJECT;
+ return_value->value.obj = p->second->value.obj;
+
+ //
+ // Increment the factory's reference count.
+ //
+ Z_OBJ_HT_P(p->second)->add_ref(p->second 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_NULL();
+ }
+ 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
+static zend_object_value
+handleAlloc(zend_class_entry* ce TSRMLS_DC)
+{
+ zend_object_value result;
+
+ ice_object* obj = newObject(ce TSRMLS_CC);
+ assert(obj);
+
+ result.handle = zend_objects_store_put(obj, NULL, (zend_objects_free_object_storage_t)handleFreeStorage,
+ NULL TSRMLS_CC);
+ result.handlers = &_handlers;
+
+ return result;
+}
+
+#ifdef WIN32
+extern "C"
+#endif
+static zend_object_value
+handleClone(zval* zv TSRMLS_DC)
+{
+ zend_object_value result;
+ memset(&result, 0, sizeof(zend_object_value));
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "__clone is not supported for Ice_Communicator");
+ return result;
+}
+
+#ifdef WIN32
+extern "C"
+#endif
+static void
+handleFreeStorage(void* p TSRMLS_DC)
+{
+ ice_object* obj = (ice_object*)p;
+ if(obj->ptr)
+ {
+ Ice::CommunicatorPtr* _this = static_cast<Ice::CommunicatorPtr*>(obj->ptr);
+ try
+ {
+ (*_this)->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ ostringstream ostr;
+ ex.ice_print(ostr);
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "unable to destroy communicator:\n%s", ostr.str().c_str());
+ }
+ delete _this;
+ }
+
+ zend_objects_free_object_storage((zend_object*)p TSRMLS_CC);
+}
+
+#ifdef WIN32
+extern "C"
+#endif
+static union _zend_function*
+handleGetMethod(zval** zv, char* method, int len TSRMLS_DC)
+{
+ //
+ // Delegate to the standard implementation of get_method. We're simply using this hook
+ // as a convenient way of implementing lazy initialization of the communicator.
+ //
+ zend_function* result = zend_get_std_object_handlers()->get_method(zv, method, len TSRMLS_CC);
+ if(result)
+ {
+ ice_object* obj = static_cast<ice_object*>(zend_object_store_get_object(*zv TSRMLS_CC));
+ if(!obj->ptr)
+ {
+ if(ICE_G(profile) == NULL)
+ {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "$ICE used before a profile was loaded");
+ return 0;
+ }
+
+ try
+ {
+ initCommunicator(obj TSRMLS_CC);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ ostringstream ostr;
+ ex.ice_print(ostr);
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "unable to initialize communicator:\n%s", ostr.str().c_str());
+ return 0;
+ }
+ }
+ }
+
+ return result;
+}
+
+//
+// Initialize a communicator instance and store it in the given object. Can raise exceptions.
+//
+static void
+initCommunicator(ice_object* obj TSRMLS_DC)
+{
+ assert(!obj->ptr);
+
+ Ice::PropertiesPtr* properties = static_cast<Ice::PropertiesPtr*>(ICE_G(properties));
+
+ Ice::InitializationData initData;
+ initData.properties = *properties;
+ Ice::CommunicatorPtr communicator = Ice::initialize(initData);
+ obj->ptr = new Ice::CommunicatorPtr(communicator);
+
+ //
+ // Register our default object factory with the communicator.
+ //
+ Ice::ObjectFactoryPtr factory = new PHPObjectFactory(TSRMLS_C);
+ communicator->addObjectFactory(factory, "");
+}