diff options
author | David Eriksson <eriksson@php.net> | 2000-09-01 22:10:15 +0000 |
---|---|---|
committer | David Eriksson <eriksson@php.net> | 2000-09-01 22:10:15 +0000 |
commit | 2ad0310fd36de9eeabc65138eae28d39d0dbf55b (patch) | |
tree | c1fc8f0ce35fc6f58fc2f99e6868a0e10881b2f0 /ext/satellite/object.c | |
parent | cd8af6aa446ae69e28415bd68e4928cafe07f8a0 (diff) | |
download | php-git-2ad0310fd36de9eeabc65138eae28d39d0dbf55b.tar.gz |
- Initial submission of CORBA extension for PHP: Satellite
Diffstat (limited to 'ext/satellite/object.c')
-rw-r--r-- | ext/satellite/object.c | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/ext/satellite/object.c b/ext/satellite/object.c new file mode 100644 index 0000000000..d01272dcb2 --- /dev/null +++ b/ext/satellite/object.c @@ -0,0 +1,851 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: David Eriksson <eriksson@php.net> | + +----------------------------------------------------------------------+ + */ + +/* + * $Id$ + * vim: syntax=c tabstop=2 shiftwidth=2 + */ + +/* ----------------------------------------------------------------------- + * + * OrbitObject class + * + * There are three ways to create an object + * + * (1) OrbitObject_Constructor, for new OrbitObject(...) in PHP + * (2) OrbitObject_Create, used when a CORBA method returns an object + * (3) OrbitObject_Wakeup, used on "unserialization" + * + * ----------------------------------------------------------------------- + */ +#include "class.h" +#include "corba.h" +#include "common.h" +#include "object.h" +#include "typemanager.h" +#include "namedvalue_to_zval.h" +#include "zval_to_namedvalue.h" +#include "typecode.h" /* for satellite_release_typecode */ + +#define PROFILE 0 + +#if PROFILE +#include <sys/time.h> +#include <unistd.h> +#endif + +struct _OrbitObject +{ + CORBA_Object mCorbaObject; + InterfaceType * mpInterface; +}; + +static void OrbitObject_Wakeup(INTERNAL_FUNCTION_PARAMETERS); +static void OrbitObject_Sleep(INTERNAL_FUNCTION_PARAMETERS); + +static zend_function_entry OrbitObject_functions[] = +{ + {"__sleep", OrbitObject_Sleep}, + {"__wakeup", OrbitObject_Wakeup}, + {NULL, NULL} +}; + +#define MY_IMPLEMENT_CLASS(name, flags)\ +IMPLEMENT_DECLARATIONS(name, flags) \ +IMPLEMENT_FUNCTION_CALL(name, flags) \ +IMPLEMENT_PUT_PROPERTY(name, flags) \ +IMPLEMENT_GET_PROPERTY(name, flags) \ +IMPLEMENT_INIT_EX(name, flags, ##name##_functions, _##name##_FunctionCall, _##name##_GetProperty, _##name##_PutProperty)\ +IMPLEMENT_DATA_HELPERS(name, flags) + +MY_IMPLEMENT_CLASS(OrbitObject, ~0); + +CORBA_Object OrbitObject_GetCorbaObject(OrbitObject * pObject) +{ + if (pObject == NULL) + return FALSE; + else + return pObject->mCorbaObject; +} +#define IOR_PROPERTY_KEY "IOR" + +/* + * prepare for serialization + * + * this means creating a property containing the object IOR and returning an + * array containing the names of properties we want serialized + * + * TODO: save environment as property?! + * + */ +static void OrbitObject_Sleep(INTERNAL_FUNCTION_PARAMETERS) +{ + CORBA_char * p_ior = NULL; + /* get object data */ + OrbitObject * p_object = OrbitObject_RetrieveData(this_ptr); + + /* validate data */ + if (p_object == NULL) + { + goto error; + } + + /* get IOR from object */ + p_ior = CORBA_ORB_object_to_string( + orbit_get_orb(), p_object->mCorbaObject, orbit_get_environment()); + if (p_ior == NULL || orbit_caught_exception()) + goto error; + + /* add property to zval */ + add_property_string(this_ptr, IOR_PROPERTY_KEY, p_ior, TRUE); + + /* create array */ + array_init(return_value); + + /* add name of property IOR to array */ + add_next_index_string(return_value, IOR_PROPERTY_KEY, TRUE); + + return; + +error: + RETURN_NULL(); +} + +/* + * initialize OrbitObject structure + */ +static zend_bool OrbitObject_InitializeData(OrbitObject * pObject, const char * pIor) +{ + /* get object */ + pObject->mCorbaObject = CORBA_ORB_string_to_object( + orbit_get_orb(), + pIor, + orbit_get_environment()); + + if (pObject->mCorbaObject == NULL || orbit_caught_exception()) + { + zend_error(E_ERROR, "(Satellite) Unable to resolve IOR"); + goto error; + } + + /* find type info */ + pObject->mpInterface = + TypeManager_FindInterface(pObject->mCorbaObject->type_id); + + if (pObject->mpInterface == NULL) + { + zend_error(E_ERROR, "(Satellite) unknown interface '%s'", + pObject->mCorbaObject->type_id); + /* TODO: set exception */ + goto error; + } + + return TRUE; + +error: + return FALSE; +} + +/* + * recover from serialization + * + * this means reading the property IOR and reconstructing the object! + * + */ +static void OrbitObject_Wakeup(INTERNAL_FUNCTION_PARAMETERS) +{ + zval ** pp_ior = NULL; + + /* create data object */ + OrbitObject * p_object = orbit_new(OrbitObject); + + /* find IOR property */ + if (zend_hash_find( + this_ptr->value.obj.properties, + IOR_PROPERTY_KEY, + sizeof(IOR_PROPERTY_KEY), + (void**)&pp_ior) != SUCCESS) + { + /* TODO: set exception */ + goto error; + } + + if ((*pp_ior)->type != IS_STRING) + { + /* TODO: set exception */ + goto error; + } + + /* initialize data */ + if (!OrbitObject_InitializeData( + p_object, + (*pp_ior)->value.str.val)) + { + goto error; + } + + /* save data to zval */ + OrbitObject_SaveData(this_ptr, p_object); + + return; + +error: + zend_error(E_ERROR, "(Satellite) Invalid serialized object"); + OrbitObject_Destructor(p_object); +} + + +/* instansiate a class */ +zend_bool OrbitObject_Create(CORBA_Object source, zval * pDestination) +{ + OrbitObject * p_object = NULL; + + /* source might be NULL */ + if (source == NULL) + { + ZVAL_NULL(pDestination); + return TRUE; + } + + /* allocate object */ + p_object = orbit_new(OrbitObject); + + /* save corba object */ + p_object->mCorbaObject = source; + + /* find type info */ + p_object->mpInterface = + TypeManager_FindInterface(p_object->mCorbaObject->type_id); + + if (p_object->mpInterface == NULL) + { + zend_error(E_ERROR, "(Satellite) unknown interface '%s'", + p_object->mCorbaObject->type_id); + goto error; + } + + /* set zval members */ + pDestination->type = IS_OBJECT; + pDestination->is_ref = 1; + pDestination->refcount = 1; + + pDestination->value.obj.ce = &OrbitObject_class_entry; + pDestination->value.obj.properties = orbit_new(HashTable); + + zend_hash_init( + pDestination->value.obj.properties, /* hash table */ + 0, /* size */ + NULL, /* hash function */ + ZVAL_PTR_DTOR, /* destructor */ + 0); /* persistent */ + + /* save orbit data */ + OrbitObject_SaveData(pDestination, p_object); + + return TRUE; + +error: + OrbitObject_Destructor(p_object); + return FALSE; +} + + + +/* + * constructor + * + * parameters: IOR, OrbitEnvironment + */ +zend_bool OrbitObject_Constructor(OrbitObject ** ppObject, + int parameterCount, const zval ** ppParameters) +{ + OrbitObject * p_object = NULL; + + /* allocate object */ + p_object = orbit_new(OrbitObject); + + /* check parameter count */ + if (parameterCount != 1) + { + wrong_param_count(); + goto error; + } + + /* validate parameter types */ + if (ppParameters[0]->type != IS_STRING) + { + zend_error(E_ERROR, "(Satellite) IOR is not a string"); + goto error; + } + + /* initialize data object */ + if ( !OrbitObject_InitializeData( + p_object, + ppParameters[0]->value.str.val) ) + { + goto error; + } + + *ppObject = p_object; + return TRUE; + +error: + OrbitObject_Destructor(p_object); + *ppObject = NULL; + + /* TODO: all errors above should set exceptions! */ + + return FALSE; +} + +/* + * destructor + */ +zend_bool OrbitObject_Destructor(OrbitObject * pObject) +{ + InterfaceType_release(pObject->mpInterface); + + if (pObject->mCorbaObject != NULL) + CORBA_Object_release((CORBA_Object)pObject->mCorbaObject, NULL); + + orbit_delete(pObject); + + return TRUE; +} + +/* + * prepare a function call result + */ +static CORBA_NamedValue * OrbitObject_PrepareResult(OrbitObject * pObject, + OperationType * pOperation) +{ + CORBA_NamedValue * p_result = orbit_new(CORBA_NamedValue); + + p_result->argument._type = OperationType_GetReturnType(pOperation); + + if (p_result->argument._type == NULL) + { + orbit_delete(p_result); + p_result = NULL; + } + else + { + orbit_zval_to_namedvalue(NULL, p_result); + } + + return p_result; +} + +/* + * add an argument to a function call + */ +static zend_bool OrbitObject_AddSingleArgument(OrbitObject * pObject, + CORBA_Request request, ParameterType * pParameter, const zval * pSource, CORBA_NamedValue * pDestination) +{ + pDestination->argument._type = ParameterType_GetType(pParameter); + pDestination->arg_modes = ParameterType_GetPassingMode(pParameter); + + /* if the argument is output only, don't care about input value */ + if (pDestination->arg_modes == CORBA_ARG_OUT) + pSource = NULL; + + if (!orbit_zval_to_namedvalue(pSource, pDestination)) + return FALSE; + + /* add parameter to request */ + CORBA_Request_add_arg( + request, /* request */ + NULL, /* arg_name */ + pDestination->argument._type, /* type */ + pDestination->argument._value, /* value */ + pDestination->len, /* length */ + pDestination->arg_modes, /* flags */ + orbit_get_environment() + ); + + if (orbit_caught_exception()) + return FALSE; + + return TRUE; +} + +/* + * add the function call arguments + */ +static zend_bool OrbitObject_AddArguments(OrbitObject * pObject, + CORBA_Request request, OperationType * pOperation, int argumentCount, + const zval ** ppArguments, CORBA_NamedValue ** ppNamedValue) +{ + ParameterType * p_parameter = OperationType_GetFirstParameter(pOperation); + int i = 0; + zend_bool success; + + if (argumentCount < 1) + return TRUE; /* nothing to do */ + + do + { + ppNamedValue[i] = satellite_new(CORBA_NamedValue); + success = OrbitObject_AddSingleArgument( pObject, + request, p_parameter, ppArguments[i], ppNamedValue[i]); + + if (!success) + return FALSE; + + i++; + } while (i < argumentCount && ParameterType_GetNext(p_parameter)); + + /* i should equal argument count and there should be no more parameters */ + if (i != argumentCount || ParameterType_GetNext(p_parameter)) + { +/* printf("%i, %i, %i\n", i, argumentCount, ParameterType_IsValid(p_parameter));*/ + + /* bad number of arguments */ + wrong_param_count(); + return FALSE; + } + + return TRUE; +} + +/* + * release a namedvalue that we have allocated + * + * (move to another file?) + */ +static void satellite_release_namedvalue(CORBA_NamedValue * pNamedValue) +{ + if (pNamedValue == NULL) + return; + + /* clear value */ + if (pNamedValue->argument._value != NULL) + { + /* allocated with ORBit_alloc_tcval */ + CORBA_free(pNamedValue->argument._value); + } + + /* clear typecode */ + satellite_release_typecode(pNamedValue->argument._type); + + /* allocated with satellite_new */ + satellite_delete(pNamedValue); +} + +static void satellite_release_namedvalue_list( + CORBA_NamedValue ** ppNamedValue, int length) +{ + int i; + + if (ppNamedValue == NULL) + return; + + for (i = 0; i < length; i++) + { + /* release named values */ + satellite_release_namedvalue(ppNamedValue[i]); + ppNamedValue[i] = NULL; + } + + satellite_delete(ppNamedValue); +} + +/* + * post-process arguments (take care of output parameters, release memory) + */ +static zend_bool OrbitObject_ReleaseArguments(OrbitObject * pObject, + CORBA_Request request, OperationType * pOperation, int argumentCount, + const zval ** ppArguments, CORBA_NamedValue ** ppNamedValue) +{ + /* TODO: handle output parameters */ + + return TRUE; +} + + + +/* + * call a function + */ +zend_bool OrbitObject_CallFunction(OrbitObject * pObject, + const char * pFunctionName, int parameterCount, const zval ** ppParameters, zval * pReturnValue) +{ + zend_bool success; + CORBA_Request request = NULL; + OperationType * p_operation = NULL; + CORBA_NamedValue ** pp_arguments = NULL; + CORBA_NamedValue * p_result = NULL; + CORBA_TypeCode * p_exception_list = NULL; + +#if PROFILE + int i; + struct timeval tv[4]; + gettimeofday(&tv[0], NULL); +#endif + + /* clear exception */ + CORBA_exception_free(orbit_get_environment()); + + p_operation = InterfaceType_FindOperation(pObject->mpInterface, pFunctionName); + + if (p_operation == NULL) + { + /* no such operation */ + zend_error(E_ERROR, "(Satellite) unknown operation name '%s' in interface '%s'", + pFunctionName, pObject->mCorbaObject->type_id); + goto error; + } + + p_exception_list = OperationType_GetExceptionList(p_operation); + + /* XXX: it's ok if this returns NULL, because the operation may be void! */ + p_result = OrbitObject_PrepareResult(pObject, p_operation); + + /* create the request */ + CORBA_Object_create_request2( + pObject->mCorbaObject, /* object */ + NULL, /* context */ + OperationType_GetName(p_operation), /* name */ + NULL, /* arg_list */ + p_result, /* result */ + p_exception_list, /* user exception list */ + &request, /* request */ + CORBA_OUT_LIST_MEMORY, /* flags */ + orbit_get_environment() /* environment */ + ); + + /* check for exception */ + if (orbit_caught_exception()) + goto error; + + /* add parameters */ + pp_arguments = satellite_new_n(CORBA_NamedValue*, parameterCount); + success = OrbitObject_AddArguments(pObject, + request, p_operation, parameterCount, ppParameters, pp_arguments); + + if (!success) + { + /* bad arguments */ + goto error; + } + +#if PROFILE + gettimeofday(&tv[1], NULL); +#endif + + /* send request and get response */ + CORBA_Request_invoke(request, 0, orbit_get_environment()); + +#if PROFILE + gettimeofday(&tv[2], NULL); +#endif + + if (orbit_caught_exception()) + goto error; + + /* release arguments */ + success = OrbitObject_ReleaseArguments(pObject, + request, p_operation, parameterCount, ppParameters, pp_arguments); + if (!success) + goto error; + + /* take care of return value */ + if (p_result != NULL) + { + orbit_namedvalue_to_zval(p_result, pReturnValue); + } + +#if PROFILE + gettimeofday(&tv[3], NULL); + printf("%s\n", OperationType_GetName(p_operation)); + for(i = 0; i < 4; i++) + printf("%i:%i\n", tv[i].tv_sec, tv[i].tv_usec); +#endif + + success = TRUE; + goto exit; + +error: + /* TODO: all errors above should set exceptions! */ + success = FALSE; + +exit: + CORBA_Object_release((CORBA_Object)request, orbit_get_environment()); + satellite_release_namedvalue(p_result); + satellite_release_namedvalue_list(pp_arguments, parameterCount); + orbit_delete(p_operation); + TypeCodeList_release(p_exception_list); + + return success; +} + +#define GET_PREFIX "_get_" +#define SET_PREFIX "_set_" +#define GET_PREFIX_LENGTH (sizeof(GET_PREFIX)-1) +#define SET_PREFIX_LENGTH (sizeof(SET_PREFIX)-1) + + +/* + * add an argument to a function call + */ +static zend_bool OrbitObject_AddAttributeArgument(OrbitObject * pObject, + CORBA_Request request, AttributeType * pAttribute, const zval * pSource) +{ + CORBA_NamedValue destination; + memset(&destination, 0, sizeof(CORBA_NamedValue)); + + destination.argument._type = AttributeType_GetType(pAttribute); + destination.arg_modes = CORBA_ARG_IN; + + if (!orbit_zval_to_namedvalue(pSource, &destination)) + return FALSE; + + /* add parameter to request */ + CORBA_Request_add_arg( + request, /* request */ + NULL, /* arg_name */ + destination.argument._type, /* type */ + destination.argument._value, /* value */ + destination.len, /* length */ + destination.arg_modes, /* flags */ + orbit_get_environment() + ); + + if (orbit_caught_exception()) + return FALSE; + + return TRUE; +} + + + +/* + * set a php property, or rather a corba attribute + */ +zend_bool OrbitObject_PutProperty(OrbitObject * pObject, + const char * pPropertyName, const zval * pValue) +{ + zend_bool success; + char * p_name = NULL; + CORBA_Request request = NULL; + AttributeType * p_attribute = NULL; + + /* clear exception */ + CORBA_exception_free(orbit_get_environment()); + + /* find attribute type */ + p_attribute = InterfaceType_FindAttribute(pObject->mpInterface, pPropertyName); + + if (p_attribute == NULL) + { + /*printf("InterfaceType_FindAttribute failed for property %s\n", pPropertyName);*/ + /* no such atttribute */ + zend_error(E_ERROR, "(Satellite) unknown attribute name '%s' in interface '%s'", + pPropertyName, pObject->mCorbaObject->type_id); + goto OrbitObject_PutProperty_error; + } + + if (AttributeType_IsReadonly(p_attribute)) + { + /* can't set a readonly attribute! */ + goto OrbitObject_PutProperty_error; + } + + /* create operation name */ + p_name = orbit_new_n(char, strlen(pPropertyName) + SET_PREFIX_LENGTH + 1); + strcpy(p_name, SET_PREFIX); + strcat(p_name, AttributeType_GetName(p_attribute)); + + /* create the request */ + CORBA_Object_create_request( + pObject->mCorbaObject, /* object */ + NULL, /* context */ + p_name, /* name */ + NULL, /* arg_list */ + NULL, /* result */ + &request, /* request */ + CORBA_OUT_LIST_MEMORY, /* flags */ + orbit_get_environment() /* environment */ + ); + + /* check for exception */ + if (orbit_caught_exception()) + goto OrbitObject_PutProperty_error; + + if (request == NULL) + goto OrbitObject_PutProperty_error; + + success = OrbitObject_AddAttributeArgument( + pObject, request, p_attribute, pValue); + + if (!success) + goto OrbitObject_PutProperty_error; + + /* send request and get response */ + CORBA_Request_invoke(request, 0, orbit_get_environment()); + + if (orbit_caught_exception()) + goto OrbitObject_PutProperty_error; + + success = TRUE; + goto OrbitObject_PutProperty_exit; + +OrbitObject_PutProperty_error: + /* TODO: all errors above should set exceptions! */ + success = FALSE; + +OrbitObject_PutProperty_exit: + CORBA_Object_release((CORBA_Object)request, orbit_get_environment()); + orbit_delete(p_attribute); + orbit_delete(p_name); + + return success; +} + +/* + * prepare a function call result + */ +static CORBA_NamedValue * OrbitObject_PrepareAttributeResult(OrbitObject * pObject, + AttributeType * pAttribute) +{ + CORBA_NamedValue * p_result = orbit_new(CORBA_NamedValue); + + p_result->argument._type = AttributeType_GetType(pAttribute); + + if (p_result->argument._type == NULL) + { +/* printf("AttributeType_GetType failed for attribute %s\n", + AttributeType_GetName(pAttribute));*/ + orbit_delete(p_result); + p_result = NULL; + } + else + { + orbit_zval_to_namedvalue(NULL, p_result); + } + + return p_result; +} + + +/* + * get a php property, equal to a corba attribute + */ +zend_bool OrbitObject_GetProperty(OrbitObject * pObject, + const char * pPropertyName, zval * pReturnValue) +{ + zend_bool success; + char * p_name = NULL; + CORBA_Request request = NULL; + AttributeType * p_attribute = NULL; + CORBA_NamedValue * p_result = NULL; + +#if PROFILE + int i; + struct timeval tv[4]; + gettimeofday(&tv[0], NULL); +#endif + + /* clear exception */ + CORBA_exception_free(orbit_get_environment()); + + /* find attribute type */ + p_attribute = InterfaceType_FindAttribute(pObject->mpInterface, pPropertyName); + + if (p_attribute == NULL) + { + /*printf("InterfaceType_FindAttribute failed for property %s\n", pPropertyName);*/ + /* no such atttribute */ + zend_error(E_ERROR, "(Satellite) unknown attribute name '%s' in interface '%s'", + pPropertyName, pObject->mCorbaObject->type_id); + goto OrbitObject_GetProperty_error; + } + + /* prepare result */ + p_result = OrbitObject_PrepareAttributeResult(pObject, p_attribute); + + if (p_result == NULL) + { + /* probably bad return type */ + goto OrbitObject_GetProperty_error; + } + + /* create operation name */ + p_name = orbit_new_n(char, strlen(pPropertyName) + GET_PREFIX_LENGTH + 1); + strcpy(p_name, GET_PREFIX); + strcat(p_name, AttributeType_GetName(p_attribute)); + + /* create the request */ + CORBA_Object_create_request( + pObject->mCorbaObject, /* object */ + NULL, /* context */ + p_name, /* name */ + NULL, /* arg_list */ + p_result, /* result */ + &request, /* request */ + CORBA_OUT_LIST_MEMORY, /* flags */ + orbit_get_environment() /* environment */ + ); + + /* check for exception */ + if (orbit_caught_exception()) + goto OrbitObject_GetProperty_error; + + if (request == NULL) + goto OrbitObject_GetProperty_error; + +#if PROFILE + gettimeofday(&tv[1], NULL); +#endif + + /* send request and get response */ + CORBA_Request_invoke(request, 0, orbit_get_environment()); + +#if PROFILE + gettimeofday(&tv[2], NULL); +#endif + + if (orbit_caught_exception()) + goto OrbitObject_GetProperty_error; + + /* take care of return value */ + orbit_namedvalue_to_zval(p_result, pReturnValue); + +#if 0 /* PROFILE */ + gettimeofday(&tv[3], NULL); + printf("%s\n", p_name); + for(i = 0; i < 4; i++) + printf("%i:%i\n", tv[i].tv_sec, tv[i].tv_usec); +#endif + + success = TRUE; + goto OrbitObject_GetProperty_exit; + +OrbitObject_GetProperty_error: + /* TODO: all errors above should set exceptions! */ + success = FALSE; + +OrbitObject_GetProperty_exit: + CORBA_Object_release((CORBA_Object)request, orbit_get_environment()); + orbit_delete(p_attribute); + orbit_delete(p_name); + satellite_release_namedvalue(p_result); + + return success; +} + |