diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-05-23 15:02:14 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-05-23 15:02:14 -0700 |
commit | 0ce3ea49125e83ba758c66ab6c88142315d047d3 (patch) | |
tree | 1d8c549acf22d5abeaa30fae67a292970f294a34 | |
parent | Added implementation of optional data members encoding (not tested yet) (diff) | |
download | ice-0ce3ea49125e83ba758c66ab6c88142315d047d3.tar.bz2 ice-0ce3ea49125e83ba758c66ab6c88142315d047d3.tar.xz ice-0ce3ea49125e83ba758c66ab6c88142315d047d3.zip |
PHP port; misc. fixes
42 files changed, 1804 insertions, 413 deletions
diff --git a/cpp/src/Slice/RubyUtil.cpp b/cpp/src/Slice/RubyUtil.cpp index c9a3bae5820..d5f8f771a13 100755 --- a/cpp/src/Slice/RubyUtil.cpp +++ b/cpp/src/Slice/RubyUtil.cpp @@ -912,7 +912,9 @@ Slice::Ruby::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) // // Emit the type information. // - _out << sp << nl << "T_" << name << " = ::Ice::__defineException('" << scoped << "', " << name << ", "; + const bool preserved = p->hasMetaData("preserve-slice") || p->inheritsMetaData("preserve-slice"); + _out << sp << nl << "T_" << name << " = ::Ice::__defineException('" << scoped << "', " << name << ", " + << (preserved ? "true" : "false") << ", "; if(!base) { _out << "nil"; diff --git a/cpp/src/slice2php/Main.cpp b/cpp/src/slice2php/Main.cpp index 7a3209ad287..a30a16eca2d 100644 --- a/cpp/src/slice2php/Main.cpp +++ b/cpp/src/slice2php/Main.cpp @@ -388,8 +388,9 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // Emit the type information. // + const bool preserved = p->hasMetaData("preserve-slice") || p->inheritsMetaData("preserve-slice"); _out << sp << nl << type << " = IcePHP_defineClass('" << scoped << "', '" << escapeName(abs) << "', " - << (isAbstract ? "true" : "false") << ", "; + << (isAbstract ? "true" : "false") << ", " << (preserved ? "true" : "false") << ", "; if(!base) { _out << "$Ice__t_Object"; @@ -459,7 +460,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // Define each operation. The arguments to IcePHP_defineOperation are: // - // $ClassType, 'opName', Mode, SendMode, (InParams), (OutParams), ReturnType, (Exceptions) + // $ClassType, 'opName', Mode, SendMode, FormatType, (InParams), (OutParams), ReturnType, (Exceptions) // // where InParams and OutParams are arrays of type descriptions, and Exceptions // is an array of exception type ids. @@ -475,7 +476,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) _out << nl << "IcePHP_defineOperation(" << type << ", '" << (*oli)->name() << "', " << getOperationMode((*oli)->mode(), _ns) << ", " << getOperationMode((*oli)->sendMode(), _ns) - << ", "; + << ", " << static_cast<int>((*oli)->format()) << ", "; for(t = params.begin(), count = 0; t != params.end(); ++t) { if(!(*t)->isOutParam()) @@ -671,7 +672,9 @@ CodeVisitor::visitExceptionStart(const ExceptionPtr& p) // // Emit the type information. // - _out << sp << nl << type << " = IcePHP_defineException('" << scoped << "', '" << escapeName(abs) << "', "; + const bool preserved = p->hasMetaData("preserve-slice") || p->inheritsMetaData("preserve-slice"); + _out << sp << nl << type << " = IcePHP_defineException('" << scoped << "', '" << escapeName(abs) << "', " + << (preserved ? "true" : "false") << ", "; if(!base) { _out << "null"; diff --git a/php/lib/Ice.php b/php/lib/Ice.php index 4171c91f6f9..c146f96a503 100644 --- a/php/lib/Ice.php +++ b/php/lib/Ice.php @@ -87,9 +87,9 @@ abstract class Ice_ObjectImpl implements Ice_Object } } -$Ice__t_Object = IcePHP_defineClass('::Ice::Object', "Ice_Object", true, null, null, null); +$Ice__t_Object = IcePHP_defineClass('::Ice::Object', "Ice_Object", true, false, null, null, null); $Ice__t_ObjectSeq = IcePHP_defineSequence('::Ice::ObjectSeq', $Ice__t_Object); -$Ice__t_LocalObject = IcePHP_defineClass('::Ice::LocalObject', "Ice_LocalObject", true, null, null, null); +$Ice__t_LocalObject = IcePHP_defineClass('::Ice::LocalObject', "Ice_LocalObject", true, false, null, null, null); $Ice__t_ObjectPrx = IcePHP_defineProxy($Ice__t_Object); $Ice__t_ObjectProxySeq = IcePHP_defineSequence('::Ice::ObjectProxySeq', $Ice__t_ObjectPrx); @@ -111,6 +111,25 @@ class Ice_InitializationData public $logger; } +class Ice_SlicedData +{ + public $slices; +} + +class Ice_SliceInfo +{ + public $typeId; + public $bytes; + public $objects; +} + +class Ice_FormatType +{ + const DefaultFormat = 0; + const CompactFormat = 1; + const SlicedFormat = 2; +} + $Ice_sliceChecksums = array(); // @@ -124,11 +143,16 @@ require_once 'Ice/Locator.php'; require_once 'Ice/ObjectFactory.php'; require_once 'Ice/Process.php'; require_once 'Ice/Router.php'; +require_once 'Ice/Version.php'; + +$Ice_Protocol_1_0 = new Ice_ProtocolVersion(1, 0); +$Ice_Encoding_1_0 = new Ice_EncodingVersion(1, 0); +$Ice_Encoding_1_1 = new Ice_EncodingVersion(1, 1); -IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, array($IcePHP__t_string), null, $IcePHP__t_bool, null); -IcePHP_defineOperation($Ice__t_Object, 'ice_ping', 2, 1, null, null, null, null); -IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, null, null, $IcePHP__t_string, null); -IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, null, null, $Ice__t_StringSeq, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, 0, array($IcePHP__t_string), null, $IcePHP__t_bool, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_ping', 2, 1, 0, null, null, null, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, 0, null, null, $IcePHP__t_string, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, 0, null, null, $Ice__t_StringSeq, null); // // Proxy comparison functions. diff --git a/php/lib/Ice_ns.php b/php/lib/Ice_ns.php index b3bfd9f2384..f1229986f9d 100644 --- a/php/lib/Ice_ns.php +++ b/php/lib/Ice_ns.php @@ -92,9 +92,9 @@ namespace Ice } } - $Ice__t_Object = IcePHP_defineClass('::Ice::Object', "\\Ice\\Object", true, null, null, null); + $Ice__t_Object = IcePHP_defineClass('::Ice::Object', "\\Ice\\Object", true, false, null, null, null); $Ice__t_ObjectSeq = IcePHP_defineSequence('::Ice::ObjectSeq', $Ice__t_Object); - $Ice__t_LocalObject = IcePHP_defineClass('::Ice::LocalObject', "\\Ice\\LocalObject", true, null, null, null); + $Ice__t_LocalObject = IcePHP_defineClass('::Ice::LocalObject', "\\Ice\\LocalObject", true, false, null, null, null); $Ice__t_ObjectPrx = IcePHP_defineProxy($Ice__t_Object); $Ice__t_ObjectProxySeq = IcePHP_defineSequence('::Ice::ObjectProxySeq', $Ice__t_ObjectPrx); @@ -116,6 +116,25 @@ namespace Ice public $logger; } + class SlicedData + { + public $slices; + } + + class SliceInfo + { + public $typeId; + public $bytes; + public $objects; + } + + class FormatType + { + const DefaultFormat = 0; + const CompactFormat = 1; + const SlicedFormat = 2; + } + $Ice_sliceChecksums = array(); } @@ -132,15 +151,24 @@ require_once 'Ice/Locator.php'; require_once 'Ice/ObjectFactory.php'; require_once 'Ice/Process.php'; require_once 'Ice/Router.php'; +require_once 'Ice/Version.php'; -IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, array($IcePHP__t_string), array(), $IcePHP__t_bool, null); -IcePHP_defineOperation($Ice__t_Object, 'ice_ping', 2, 1, null, null, null, null); -IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, null, null, $IcePHP__t_string, null); -IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, null, null, $Ice__t_StringSeq, null); +$Ice_Protocol_1_0 = new Ice\ProtocolVersion(1, 0); +$Ice_Encoding_1_0 = new Ice\EncodingVersion(1, 0); +$Ice_Encoding_1_1 = new Ice\EncodingVersion(1, 1); + +IcePHP_defineOperation($Ice__t_Object, 'ice_isA', 2, 1, 0, array($IcePHP__t_string), array(), $IcePHP__t_bool, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_ping', 2, 1, 0, null, null, null, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_id', 2, 1, 0, null, null, $IcePHP__t_string, null); +IcePHP_defineOperation($Ice__t_Object, 'ice_ids', 2, 1, 0, null, null, $Ice__t_StringSeq, null); } namespace Ice { + $Protocol_1_0 = new ProtocolVersion(1, 0); + $Encoding_1_0 = new EncodingVersion(1, 0); + $Encoding_1_1 = new EncodingVersion(1, 1); + // // Proxy comparison functions. // diff --git a/php/lib/Makefile b/php/lib/Makefile index 076c6e98589..ac86bb0f68e 100644 --- a/php/lib/Makefile +++ b/php/lib/Makefile @@ -45,7 +45,8 @@ ICE_SRCS = Ice/LocalException.php \ Ice/SliceChecksumDict.php \ Ice/Endpoint.php \ Ice/EndpointF.php \ - Ice/EndpointTypes.php + Ice/EndpointTypes.php \ + Ice/Version.php # # IMPORTANT: If you add or remove Slice files, you also need to check Glacier2.php! diff --git a/php/lib/Makefile.mak b/php/lib/Makefile.mak index c5a81e40d6f..2b5e267e684 100644 --- a/php/lib/Makefile.mak +++ b/php/lib/Makefile.mak @@ -45,7 +45,8 @@ ICE_SRCS = Ice\LocalException.php \ Ice\SliceChecksumDict.php \
Ice\Endpoint.php \
Ice\EndpointF.php \
- Ice\EndpointTypes.php
+ Ice\EndpointTypes.php \
+ Ice\Version.php
#
# IMPORTANT: If you add or remove Slice files, you also need to check Glacier2.php!
diff --git a/php/src/IcePHP/Endpoint.cpp b/php/src/IcePHP/Endpoint.cpp index 85449b00ec6..a0f3829c010 100644 --- a/php/src/IcePHP/Endpoint.cpp +++ b/php/src/IcePHP/Endpoint.cpp @@ -286,6 +286,10 @@ IcePHP::endpointInit(TSRMLS_D) ce.create_object = handleEndpointInfoAlloc; endpointInfoClassEntry = zend_register_internal_class(&ce TSRMLS_CC); memcpy(&_endpointInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_declare_property_null(endpointInfoClassEntry, STRCAST("protocol"), sizeof("protocol") - 1, + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(endpointInfoClassEntry, STRCAST("encoding"), sizeof("encoding") - 1, + ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_long(endpointInfoClassEntry, STRCAST("timeout"), sizeof("timeout") - 1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_bool(endpointInfoClassEntry, STRCAST("compress"), sizeof("compress") - 1, 0, @@ -327,14 +331,6 @@ IcePHP::endpointInit(TSRMLS_D) #endif ce.create_object = handleEndpointInfoAlloc; udpEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, ipEndpointInfoClassEntry, NULL TSRMLS_CC); - zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("protocolMajor"), sizeof("protocolMajor") - 1, 0, - ZEND_ACC_PUBLIC TSRMLS_CC); - zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("protocolMinor"), sizeof("protocolMinor") - 1, 0, - ZEND_ACC_PUBLIC TSRMLS_CC); - zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("encodingMajor"), sizeof("encodingMajor") - 1, 0, - ZEND_ACC_PUBLIC TSRMLS_CC); - zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("encodingMinor"), sizeof("encodingMinor") - 1, 0, - ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_string(udpEndpointInfoClassEntry, STRCAST("mcastInterface"), sizeof("mcastInterface") - 1, STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("mcastTtl"), sizeof("mcastTtl") - 1, 0, @@ -350,6 +346,8 @@ IcePHP::endpointInit(TSRMLS_D) #endif ce.create_object = handleEndpointInfoAlloc; opaqueEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, endpointInfoClassEntry, NULL TSRMLS_CC); + zend_declare_property_null(opaqueEndpointInfoClassEntry, STRCAST("rawEncoding"), sizeof("rawEncoding") - 1, + ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(opaqueEndpointInfoClassEntry, STRCAST("rawBytes"), sizeof("rawBytes") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); @@ -410,10 +408,6 @@ IcePHP::createEndpointInfo(zval* zv, const Ice::EndpointInfoPtr& p TSRMLS_DC) Ice::UDPEndpointInfoPtr info = Ice::UDPEndpointInfoPtr::dynamicCast(p); if((status = object_init_ex(zv, udpEndpointInfoClassEntry)) == SUCCESS) { - add_property_long(zv, STRCAST("protocolMajor"), static_cast<long>(info->protocolMajor)); - add_property_long(zv, STRCAST("protocolMinor"), static_cast<long>(info->protocolMinor)); - add_property_long(zv, STRCAST("encodingMajor"), static_cast<long>(info->encodingMajor)); - add_property_long(zv, STRCAST("encodingMinor"), static_cast<long>(info->encodingMinor)); add_property_string(zv, STRCAST("mcastInterface"), const_cast<char*>(info->mcastInterface.c_str()), 1); add_property_long(zv, STRCAST("mcastTtl"), static_cast<long>(info->mcastTtl)); } @@ -423,6 +417,12 @@ IcePHP::createEndpointInfo(zval* zv, const Ice::EndpointInfoPtr& p TSRMLS_DC) Ice::OpaqueEndpointInfoPtr info = Ice::OpaqueEndpointInfoPtr::dynamicCast(p); if((status = object_init_ex(zv, opaqueEndpointInfoClassEntry)) == SUCCESS) { + zval* rawEncoding; + MAKE_STD_ZVAL(rawEncoding); + createEncodingVersion(rawEncoding, info->rawEncoding TSRMLS_CC); + add_property_zval(zv, STRCAST("rawEncoding"), rawEncoding); + zval_ptr_dtor(&rawEncoding); // add_property_zval increased the refcount of rawEncoding + zval* rawBytes; MAKE_STD_ZVAL(rawBytes); array_init(rawBytes); @@ -456,6 +456,18 @@ IcePHP::createEndpointInfo(zval* zv, const Ice::EndpointInfoPtr& p TSRMLS_DC) add_property_long(zv, STRCAST("port"), static_cast<long>(info->port)); } + zval* protocol; + MAKE_STD_ZVAL(protocol); + createProtocolVersion(protocol, p->protocol TSRMLS_CC); + add_property_zval(zv, STRCAST("protocol"), protocol); + zval_ptr_dtor(&protocol); // add_property_zval increased the refcount of protocol + + zval* encoding; + MAKE_STD_ZVAL(encoding); + createEncodingVersion(encoding, p->encoding TSRMLS_CC); + add_property_zval(zv, STRCAST("encoding"), encoding); + zval_ptr_dtor(&encoding); // add_property_zval increased the refcount of encoding + add_property_long(zv, STRCAST("timeout"), static_cast<long>(p->timeout)); add_property_bool(zv, STRCAST("compress"), static_cast<long>(p->compress)); diff --git a/php/src/IcePHP/Init.cpp b/php/src/IcePHP/Init.cpp index 9da2f13db9a..5f2f3f7d3a0 100644 --- a/php/src/IcePHP/Init.cpp +++ b/php/src/IcePHP/Init.cpp @@ -74,13 +74,27 @@ ZEND_END_ARG_INFO() #define ICEPHP_UTIL_FUNCTIONS \ ZEND_FE(Ice_stringVersion, NULL) \ ZEND_FE(Ice_intVersion, NULL) \ - ZEND_FE(Ice_generateUUID, NULL) + ZEND_FE(Ice_generateUUID, NULL) \ + ZEND_FE(Ice_currentProtocol, NULL) \ + ZEND_FE(Ice_currentProtocolEncoding, NULL) \ + ZEND_FE(Ice_currentEncoding, NULL) \ + ZEND_FE(Ice_protocolVersionToString, NULL) \ + ZEND_FE(Ice_stringToProtocolVersion, NULL) \ + ZEND_FE(Ice_encodingVersionToString, NULL) \ + ZEND_FE(Ice_stringToEncodingVersion, NULL) #ifdef ICEPHP_USE_NAMESPACES # define ICEPHP_UTIL_NS_FUNCTIONS \ ZEND_NS_FALIAS("Ice", stringVersion, Ice_stringVersion, NULL) \ ZEND_NS_FALIAS("Ice", intVersion, Ice_intVersion, NULL) \ - ZEND_NS_FALIAS("Ice", generateUUID, Ice_generateUUID, NULL) + ZEND_NS_FALIAS("Ice", generateUUID, Ice_generateUUID, NULL) \ + ZEND_NS_FALIAS("Ice", currentProtocol, Ice_currentProtocol, NULL) \ + ZEND_NS_FALIAS("Ice", currentProtocolEncoding, Ice_currentProtocolEncoding, NULL) \ + ZEND_NS_FALIAS("Ice", currentEncoding, Ice_currentEncoding, NULL) \ + ZEND_NS_FALIAS("Ice", protocolVersionToString, Ice_protocolVersionToString, NULL) \ + ZEND_NS_FALIAS("Ice", stringToProtocolVersion, Ice_stringToProtocolVersion, NULL) \ + ZEND_NS_FALIAS("Ice", encodingVersionToString, Ice_encodingVersionToString, NULL) \ + ZEND_NS_FALIAS("Ice", stringToEncodingVersion, Ice_stringToEncodingVersion, NULL) #else # define ICEPHP_UTIL_NS_FUNCTIONS #endif diff --git a/php/src/IcePHP/Operation.cpp b/php/src/IcePHP/Operation.cpp index 5bdf6ddc20b..ff1ad8b7805 100644 --- a/php/src/IcePHP/Operation.cpp +++ b/php/src/IcePHP/Operation.cpp @@ -50,7 +50,8 @@ class OperationI : public Operation { public: - OperationI(const char*, Ice::OperationMode, Ice::OperationMode, zval*, zval*, zval*, zval* TSRMLS_DC); + OperationI(const char*, Ice::OperationMode, Ice::OperationMode, Ice::FormatType, zval*, zval*, zval*, zval* + TSRMLS_DC); ~OperationI(); virtual zend_function* function(); @@ -58,6 +59,7 @@ public: string name; // On-the-wire name. Ice::OperationMode mode; Ice::OperationMode sendMode; + Ice::FormatType format; TypeInfoList inParams; TypeInfoList outParams; TypeInfoPtr returnType; @@ -129,6 +131,35 @@ public: virtual void invoke(INTERNAL_FUNCTION_PARAMETERS); }; +class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +{ +public: + + UserExceptionReaderFactoryI(const CommunicatorInfoPtr& communicator TSRMLS_DC) : + _communicator(communicator) + { +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + } + + virtual void createAndThrow(const string& id) const + { + ExceptionInfoPtr info = getExceptionInfo(id TSRMLS_CC); + if(info) + { + throw ExceptionReader(_communicator, info TSRMLS_CC); + } + } + +private: + + const CommunicatorInfoPtr _communicator; +#if ZTS + TSRMLS_D; +#endif +}; + } // @@ -160,9 +191,9 @@ IcePHP::ResultCallback::unmarshaled(zval* val, zval*, void* TSRMLS_DC) // // OperationI implementation. // -IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::OperationMode sm, zval* in, zval* out, - zval* ret, zval* ex TSRMLS_DC) : - name(n), mode(m), sendMode(sm), sendsClasses(false), returnsClasses(false), _zendFunction(0) +IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::OperationMode sm, Ice::FormatType f, zval* in, + zval* out, zval* ret, zval* ex TSRMLS_DC) : + name(n), mode(m), sendMode(sm), format(f), sendsClasses(false), returnsClasses(false), _zendFunction(0) { // // inParams @@ -361,6 +392,12 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::ByteSeq& byt // Marshal the in parameters. // Ice::OutputStreamPtr os = Ice::createOutputStream(_communicator->getCommunicator()); + os->startEncapsulation(_prx->ice_getEncodingVersion()); + + if(_op->sendsClasses && _op->format != Ice::DefaultFormat) + { + os->format(_op->format); + } ObjectMap objectMap; int i = 0; @@ -380,6 +417,7 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::ByteSeq& byt os->writePendingObjects(); } + os->endEncapsulation(); os->finished(bytes); } catch(const AbortMarshaling&) @@ -403,6 +441,16 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, Ice::InputStreamPtr is = Ice::createInputStream(_communicator->getCommunicator(), bytes); // + // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + SlicedDataUtil util; + assert(!is->closure()); + is->closure(&util); + + is->startEncapsulation(); + + // // These callbacks collect references to the unmarshaled values. We copy them into // the argument list *after* any pending objects have been unmarshaled. // @@ -433,6 +481,10 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, is->readPendingObjects(); } + util.update(TSRMLS_C); + + is->endEncapsulation(); + int i = static_cast<int>(_op->inParams.size()); for(ResultCallbackList::iterator q = outParamCallbacks.begin(); q != outParamCallbacks.end(); ++q, ++i) { @@ -458,71 +510,48 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, zval* IcePHP::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& bytes TSRMLS_DC) { - int traceSlicing = -1; - Ice::InputStreamPtr is = Ice::createInputStream(_communicator->getCommunicator(), bytes); - bool usesClasses; - is->read(usesClasses); + // + // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + SlicedDataUtil util; + assert(!is->closure()); + is->closure(&util); - string id; - is->read(id); - const string origId = id; + is->startEncapsulation(); - while(!id.empty()) + try { - ExceptionInfoPtr info = getExceptionInfo(id TSRMLS_CC); - if(info) - { - zval* ex = info->unmarshal(is, _communicator TSRMLS_CC); - if(ex) - { - if(info->usesClasses) - { - is->readPendingObjects(); - } + Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(_communicator TSRMLS_CC); + is->throwException(factory); + } + catch(const ExceptionReader& r) + { + is->endEncapsulation(); - if(validateException(info TSRMLS_CC)) - { - return ex; - } - else - { - zval_ptr_dtor(&ex); - Ice::UnknownUserException uue(__FILE__, __LINE__, - "operation raised undeclared exception `" + id + "'"); - return convertException(uue TSRMLS_CC); - } - } - } - else + zval* ex = r.getException(); + ExceptionInfoPtr info = r.getInfo(); + + if(validateException(info TSRMLS_CC)) { - if(traceSlicing == -1) - { - traceSlicing = - _communicator->getCommunicator()->getProperties()->getPropertyAsInt("Ice.Trace.Slicing") > 0; - } + util.update(TSRMLS_C); - if(traceSlicing > 0) + Ice::SlicedDataPtr slicedData = r.getSlicedData(); + if(slicedData) { - _communicator->getCommunicator()->getLogger()->trace("Slicing", "unknown exception type `" + id + "'"); + SlicedDataUtil::setMember(ex, slicedData TSRMLS_CC); } - is->skipSlice(); // Slice off what we don't understand. - - try - { - is->read(id); // Read type id for next slice. - } - catch(Ice::UnmarshalOutOfBoundsException& ex) - { - // - // When readString raises this exception it means we've seen the last slice, - // so we set the reason member to a more helpful message. - // - ex.reason = "unknown exception type `" + origId + "'"; - return convertException(ex TSRMLS_CC); - } + return ex; + } + else + { + zval_ptr_dtor(&ex); + Ice::UnknownUserException uue(__FILE__, __LINE__, + "operation raised undeclared exception `" + info->id + "'"); + return convertException(uue TSRMLS_CC); } } @@ -532,7 +561,7 @@ IcePHP::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const I // have a factory for. This means that sender and receiver disagree // about the Slice definitions they use. // - Ice::UnknownUserException uue(__FILE__, __LINE__, "unknown exception type `" + origId + "'"); + Ice::UnknownUserException uue(__FILE__, __LINE__, "unknown exception"); return convertException(uue TSRMLS_CC); } @@ -675,13 +704,14 @@ ZEND_FUNCTION(IcePHP_defineOperation) int nameLen; long mode; long sendMode; + long format; zval* inParams; zval* outParams; zval* returnType; zval* exceptions; - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("oslla!a!o!a!"), &cls, &name, &nameLen, &mode, - &sendMode, &inParams, &outParams, &returnType, &exceptions) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("osllla!a!o!a!"), &cls, &name, &nameLen, + &mode, &sendMode, &format, &inParams, &outParams, &returnType, &exceptions) == FAILURE) { return; } @@ -691,8 +721,8 @@ ZEND_FUNCTION(IcePHP_defineOperation) assert(c); OperationIPtr op = new OperationI(name, static_cast<Ice::OperationMode>(mode), - static_cast<Ice::OperationMode>(sendMode), inParams, outParams, returnType, - exceptions TSRMLS_CC); + static_cast<Ice::OperationMode>(sendMode), static_cast<Ice::FormatType>(format), + inParams, outParams, returnType, exceptions TSRMLS_CC); c->addOperation(name, op); } diff --git a/php/src/IcePHP/Proxy.cpp b/php/src/IcePHP/Proxy.cpp index a8dfcd18c07..f8dcfc88ec2 100644 --- a/php/src/IcePHP/Proxy.cpp +++ b/php/src/IcePHP/Proxy.cpp @@ -645,6 +645,62 @@ ZEND_METHOD(Ice_ObjectPrx, ice_secure) } } +ZEND_METHOD(Ice_ObjectPrx, ice_getEncodingVersion) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!createEncodingVersion(return_value, _this->proxy->ice_getEncodingVersion() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_encodingVersion) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_class_entry* cls = idToClass("::Ice::EncodingVersion" TSRMLS_CC); + assert(cls); + + zval *zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, cls) == FAILURE) + { + RETURN_NULL(); + } + + Ice::EncodingVersion v; + if(extractEncodingVersion(zv, v TSRMLS_CC)) + { + try + { + if(!_this->clone(return_value, _this->proxy->ice_encodingVersion(v) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } + } +} + ZEND_METHOD(Ice_ObjectPrx, ice_isPreferSecure) { if(ZEND_NUM_ARGS() != 0) @@ -1213,6 +1269,27 @@ ZEND_METHOD(Ice_ObjectPrx, ice_getCachedConnection) } } +ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + _this->proxy->ice_flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + static ClassInfoPtr lookupClass(const string& id TSRMLS_DC) { @@ -1570,6 +1647,8 @@ static zend_function_entry _proxyMethods[] = ZEND_ME(Ice_ObjectPrx, ice_endpointSelection, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_isSecure, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_secure, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getEncodingVersion, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_encodingVersion, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_isPreferSecure, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_preferSecure, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_getRouter, NULL, ZEND_ACC_PUBLIC) @@ -1591,6 +1670,7 @@ static zend_function_entry _proxyMethods[] = ZEND_ME(Ice_ObjectPrx, ice_connectionId, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_getConnection, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_getCachedConnection, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_flushBatchRequests, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_uncheckedCast, NULL, ZEND_ACC_PUBLIC) ZEND_ME(Ice_ObjectPrx, ice_checkedCast, NULL, ZEND_ACC_PUBLIC) {0, 0, 0} diff --git a/php/src/IcePHP/Types.cpp b/php/src/IcePHP/Types.cpp index 21f6030009f..b1d392fa3a0 100644 --- a/php/src/IcePHP/Types.cpp +++ b/php/src/IcePHP/Types.cpp @@ -14,6 +14,7 @@ #include <IceUtil/OutputUtil.h> #include <IceUtil/ScopedArray.h> #include <Slice/PHPUtil.h> +#include <Ice/SlicedData.h> using namespace std; using namespace IcePHP; @@ -139,6 +140,39 @@ getMostDerived(zend_class_entry* formal, zend_class_entry* cls, const ClassInfoP return curr; } +static ClassInfoPtr +getClassInfoByClass(zend_class_entry* cls, zend_class_entry* formal TSRMLS_DC) +{ + // + // See if there's a match in our class name => ClassInfo map. + // + ClassInfoPtr info = getClassInfoByName(cls->name TSRMLS_CC); + + // + // Check the base class, assuming it's compatible with our formal type (if any). + // + if(!info && cls->parent && (!formal || checkClass(cls->parent, formal))) + { + info = getClassInfoByClass(cls->parent, formal TSRMLS_CC); + } + + // + // Check interfaces. + // + if(!info) + { + for(zend_uint i = 0; i < cls->num_interfaces && !info; ++i) + { + if(!formal || checkClass(cls->interfaces[i], formal)) + { + info = getClassInfoByClass(cls->interfaces[i], formal TSRMLS_CC); + } + } + } + + return info; +} + // // getClassInfoById() // @@ -233,6 +267,263 @@ zend_object_handle _h; } // +// SlicedDataUtil implementation +// +zend_class_entry* IcePHP::SlicedDataUtil::_slicedDataType = 0; +zend_class_entry* IcePHP::SlicedDataUtil::_sliceInfoType = 0; + +IcePHP::SlicedDataUtil::~SlicedDataUtil() +{ + // + // Make sure we break any cycles among the objects in preserved slices. + // + for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) + { + (*p)->getSlicedData()->clearObjects(); + } +} + +void +IcePHP::SlicedDataUtil::add(const ObjectReaderPtr& reader) +{ + assert(reader->getSlicedData()); + _readers.insert(reader); +} + +void +IcePHP::SlicedDataUtil::update(TSRMLS_D) +{ + for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) + { + setMember((*p)->getObject(), (*p)->getSlicedData() TSRMLS_CC); + } +} + +void +IcePHP::SlicedDataUtil::setMember(zval* obj, const Ice::SlicedDataPtr& slicedData TSRMLS_DC) +{ + // + // Create a PHP equivalent of the SlicedData object. + // + + assert(slicedData); + + if(!_slicedDataType) + { + _slicedDataType = idToClass("::Ice::SlicedData" TSRMLS_CC); + assert(_slicedDataType); + } + if(!_sliceInfoType) + { + _sliceInfoType = idToClass("::Ice::SliceInfo" TSRMLS_CC); + assert(_sliceInfoType); + } + + zval* sd; + MAKE_STD_ZVAL(sd); + AutoDestroy sdDestroyer(sd); + + if(object_init_ex(sd, _slicedDataType) != SUCCESS) + { + throw AbortMarshaling(); + } + + zval* slices; + MAKE_STD_ZVAL(slices); + array_init(slices); + AutoDestroy slicesDestroyer(slices); + + if(add_property_zval(sd, STRCAST("slices"), slices) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // Translate each SliceInfo object into its PHP equivalent. + // + for(vector<Ice::SliceInfoPtr>::const_iterator p = slicedData->slices.begin(); p != slicedData->slices.end(); ++p) + { + zval* slice; + MAKE_STD_ZVAL(slice); + AutoDestroy sliceDestroyer(slice); + + if(object_init_ex(slice, _sliceInfoType) != SUCCESS) + { + throw AbortMarshaling(); + } + + add_next_index_zval(slices, slice); // Steals a reference. + Z_ADDREF_P(slice); + + // + // typeId + // + zval* typeId; + MAKE_STD_ZVAL(typeId); + AutoDestroy typeIdDestroyer(typeId); + ZVAL_STRINGL(typeId, STRCAST((*p)->typeId.c_str()), (*p)->typeId.size(), 1); + if(add_property_zval(slice, STRCAST("typeId"), typeId) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // bytes + // + zval* bytes; + MAKE_STD_ZVAL(bytes); + array_init(bytes); + AutoDestroy bytesDestroyer(bytes); + for(vector<Ice::Byte>::const_iterator q = (*p)->bytes.begin(); q != (*p)->bytes.end(); ++q) + { + add_next_index_long(bytes, *q & 0xff); + } + if(add_property_zval(slice, STRCAST("bytes"), bytes) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // objects + // + zval* objects; + MAKE_STD_ZVAL(objects); + array_init(objects); + AutoDestroy objectsDestroyer(objects); + if(add_property_zval(slice, STRCAST("objects"), objects) != SUCCESS) + { + throw AbortMarshaling(); + } + + for(vector<Ice::ObjectPtr>::const_iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q) + { + // + // Each element in the objects list is an instance of ObjectReader that wraps a PHP object. + // + assert(*q); + ObjectReaderPtr r = ObjectReaderPtr::dynamicCast(*q); + assert(r); + zval* o = r->getObject(); + assert(Z_TYPE_P(o) == IS_OBJECT); // Should be non-nil. + add_next_index_zval(objects, o); // Steals a reference. + Z_ADDREF_P(o); + } + } + + if(add_property_zval(obj, STRCAST("_ice_slicedData"), sd) != SUCCESS) + { + throw AbortMarshaling(); + } +} + +// +// Instances of preserved class and exception types may have a data member +// named _ice_slicedData which is an instance of the PHP class Ice_SlicedData. +// +Ice::SlicedDataPtr +IcePHP::SlicedDataUtil::getMember(zval* obj, ObjectMap* objectMap TSRMLS_DC) +{ + Ice::SlicedDataPtr slicedData; + + string name = "_ice_slicedData"; + void* data; + if(zend_hash_find(Z_OBJPROP_P(obj), STRCAST(name.c_str()), name.size() + 1, &data) == SUCCESS) + { + zval* sd = *(reinterpret_cast<zval**>(data)); + + if(Z_TYPE_P(sd) != IS_NULL) + { + int status; + + // + // The "slices" member is an array of Ice_SliceInfo objects. + // + status = zend_hash_find(Z_OBJPROP_P(sd), STRCAST("slices"), sizeof("slices"), &data); + assert(status == SUCCESS); + zval* sl = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(sl) == IS_ARRAY); + + Ice::SliceInfoSeq slices; + + HashTable* arr = Z_ARRVAL_P(sl); + assert(arr); + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval* s = *(reinterpret_cast<zval**>(data)); + assert(Z_OBJCE_P(s) == _sliceInfoType); + + Ice::SliceInfoPtr info = new Ice::SliceInfo; + + status = zend_hash_find(Z_OBJPROP_P(s), STRCAST("typeId"), sizeof("typeId"), &data); + assert(status == SUCCESS); + zval* typeId = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(typeId) == IS_STRING); + info->typeId = string(Z_STRVAL_P(typeId), Z_STRLEN_P(typeId)); + + status = zend_hash_find(Z_OBJPROP_P(s), STRCAST("bytes"), sizeof("bytes"), &data); + assert(status == SUCCESS); + zval* bytes = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(bytes) == IS_ARRAY); + HashTable* barr = Z_ARRVAL_P(bytes); + HashPosition bpos; + zend_hash_internal_pointer_reset_ex(barr, &bpos); + info->bytes.resize(zend_hash_num_elements(barr)); + + vector<Ice::Byte>::size_type i = 0; + while(zend_hash_get_current_data_ex(barr, &data, &bpos) != FAILURE) + { + zval* e = *(reinterpret_cast<zval**>(data)); + long l = Z_LVAL_P(e); + assert(l >= 0 && l <= 255); + info->bytes[i++] = static_cast<Ice::Byte>(l); + zend_hash_move_forward_ex(barr, &bpos); + } + + status = zend_hash_find(Z_OBJPROP_P(s), STRCAST("objects"), sizeof("objects"), &data); + assert(status == SUCCESS); + zval* objects = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(objects) == IS_ARRAY); + HashTable* oarr = Z_ARRVAL_P(objects); + HashPosition opos; + zend_hash_internal_pointer_reset_ex(oarr, &opos); + + while(zend_hash_get_current_data_ex(oarr, &data, &opos) != FAILURE) + { + zval* o = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(o) == IS_OBJECT); + + Ice::ObjectPtr writer; + + ObjectMap::iterator i = objectMap->find(Z_OBJ_HANDLE_P(o)); + if(i == objectMap->end()) + { + writer = new ObjectWriter(o, objectMap, 0 TSRMLS_CC); + objectMap->insert(ObjectMap::value_type(Z_OBJ_HANDLE_P(o), writer)); + } + else + { + writer = i->second; + } + + info->objects.push_back(writer); + zend_hash_move_forward_ex(oarr, &opos); + } + + slices.push_back(info); + zend_hash_move_forward_ex(arr, &pos); + } + + slicedData = new Ice::SlicedData(slices); + } + } + + return slicedData; +} + +// // UnmarshalCallback implementation. // IcePHP::UnmarshalCallback::~UnmarshalCallback() @@ -1770,13 +2061,7 @@ IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* ObjectMap::iterator q = objectMap->find(Z_OBJ_HANDLE_P(zv)); if(q == objectMap->end()) { - // - // Determine the most-derived Slice type implemented by this object by scanning its - // inheritance hierarchy until we find a class or interface that we recognize. - // - ClassInfoPtr info = getMostDerived(zce, Z_OBJCE_P(zv), 0 TSRMLS_CC); - assert(info); - writer = new ObjectWriter(info, zv, objectMap TSRMLS_CC); + writer = new ObjectWriter(zv, objectMap, this TSRMLS_CC); objectMap->insert(ObjectMap::value_type(Z_OBJ_HANDLE_P(zv), writer)); } else @@ -2045,19 +2330,29 @@ IcePHP::ProxyInfo::destroy() // // ObjectWriter implementation. // -IcePHP::ObjectWriter::ObjectWriter(const ClassInfoPtr& info, zval* object, ObjectMap* objectMap TSRMLS_DC) : - _info(info), _object(object), _map(objectMap) +IcePHP::ObjectWriter::ObjectWriter(zval* object, ObjectMap* objectMap, const ClassInfoPtr& formal TSRMLS_DC) : + _object(object), _map(objectMap) { #ifdef ZTS this->TSRMLS_C = TSRMLS_C; #endif - Z_OBJ_HT_P(_object)->add_ref(_object TSRMLS_CC); + Z_ADDREF_P(_object); + + // + // We need to determine the most-derived Slice type supported by this object. + // This is typically a Slice class, but it can also be an interface. + // + // The caller may have provided a ClassInfo representing the formal type, in + // which case we ensure that the actual type is compatible with the formal type. + // + _info = getClassInfoByClass(Z_OBJCE_P(object), formal ? formal->zce : 0 TSRMLS_CC); + assert(_info); } IcePHP::ObjectWriter::~ObjectWriter() { - Z_OBJ_HT_P(_object)->del_ref(_object TSRMLS_CC); + zval_ptr_dtor(&_object); } void @@ -2076,12 +2371,24 @@ IcePHP::ObjectWriter::ice_preMarshal() void IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const { + Ice::SlicedDataPtr slicedData; + + if(_info->preserve) + { + // + // Retrieve the SlicedData object that we stored as a hidden member of the PHP object. + // + slicedData = SlicedDataUtil::getMember(_object, const_cast<ObjectMap*>(_map) TSRMLS_CC); + } + + os->startObject(slicedData); + ClassInfoPtr info = _info; while(info && info->id != Ice::Object::ice_staticId()) { - os->writeTypeId(info->id); - - os->startSlice(); + assert(info->base); // All classes have the Ice::Object base type. + const bool lastSlice = info->base->id == Ice::Object::ice_staticId(); + os->startSlice(info->id, lastSlice); for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q) { DataMemberPtr member = *q; @@ -2107,13 +2414,7 @@ IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const info = info->base; } - // - // Marshal the Ice::Object slice. - // - os->writeTypeId(Ice::Object::ice_staticId()); - os->startSlice(); - os->writeSize(0); // For compatibility with the old AFM. - os->endSlice(); + os->endObject(); } // @@ -2148,19 +2449,16 @@ IcePHP::ObjectReader::ice_postUnmarshal() } void -IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is, bool rid) +IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is) { + is->startObject(); + // // Unmarshal the slices of a user-defined class. // ClassInfoPtr info = _info; while(info && info->id != Ice::Object::ice_staticId()) { - if(rid) - { - is->readTypeId(); - } - is->startSlice(); for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p) { @@ -2169,27 +2467,17 @@ IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is, bool rid) } is->endSlice(); - rid = true; - info = info->base; } - // - // Unmarshal the Ice::Object slice. - // - if(rid) - { - is->readTypeId(); - } + _slicedData = is->endObject(_info->preserve); - is->startSlice(); - // For compatibility with the old AFM. - Ice::Int sz = is->readSize(); - if(sz != 0) + if(_slicedData) { - throw Ice::MarshalException(__FILE__, __LINE__); + SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure()); + assert(util); + util->add(this); } - is->endSlice(); } ClassInfoPtr @@ -2204,6 +2492,12 @@ IcePHP::ObjectReader::getObject() const return _object; } +Ice::SlicedDataPtr +IcePHP::ObjectReader::getSlicedData() const +{ + return _slicedData; +} + // // ReadObjectCallback implementation. // @@ -2297,11 +2591,6 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat is->endSlice(); info = info->base; - if(info) - { - string id; - is->read(id); // Read the ID of the next slice. - } } return destroy.release(); @@ -2378,6 +2667,81 @@ IcePHP::ExceptionInfo::isA(const string& typeId) const return false; } +// +// ExceptionReader implementation. +// +IcePHP::ExceptionReader::ExceptionReader(const CommunicatorInfoPtr& communicatorInfo, const ExceptionInfoPtr& info + TSRMLS_DC) : + Ice::UserExceptionReader(communicatorInfo->getCommunicator()), _communicatorInfo(communicatorInfo), _info(info) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif +} + +IcePHP::ExceptionReader::~ExceptionReader() + throw() +{ +} + +void +IcePHP::ExceptionReader::read(const Ice::InputStreamPtr& is) const +{ + is->startException(); + + const_cast<zval*&>(_ex) = _info->unmarshal(is, _communicatorInfo TSRMLS_CC); + + const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); +} + +bool +IcePHP::ExceptionReader::usesClasses() const +{ + return _info->usesClasses; +} + +void +IcePHP::ExceptionReader::usesClasses(bool) +{ +} + +string +IcePHP::ExceptionReader::ice_name() const +{ + return _info->id; +} + +Ice::Exception* +IcePHP::ExceptionReader::ice_clone() const +{ + assert(false); + return 0; +} + +void +IcePHP::ExceptionReader::ice_throw() const +{ + throw *this; +} + +ExceptionInfoPtr +IcePHP::ExceptionReader::getInfo() const +{ + return _info; +} + +zval* +IcePHP::ExceptionReader::getException() const +{ + return _ex; +} + +Ice::SlicedDataPtr +IcePHP::ExceptionReader::getSlicedData() const +{ + return _slicedData; +} + #ifdef _WIN32 extern "C" #endif @@ -2631,12 +2995,13 @@ ZEND_FUNCTION(IcePHP_defineClass) char* name; int nameLen; zend_bool isAbstract; + zend_bool preserve; zval* base; zval* interfaces; zval* members; - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ssbo!a!a!"), &id, &idLen, &name, &nameLen, - &isAbstract, &base, &interfaces, &members) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ssbbo!a!a!"), &id, &idLen, &name, &nameLen, + &isAbstract, &preserve, &base, &interfaces, &members) == FAILURE) { return; } @@ -2653,6 +3018,7 @@ ZEND_FUNCTION(IcePHP_defineClass) addClassInfoByName(type TSRMLS_CC); type->isAbstract = isAbstract ? true : false; + type->preserve = preserve ? true : false; if(base) { TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(base TSRMLS_CC); @@ -2746,11 +3112,12 @@ ZEND_FUNCTION(IcePHP_defineException) int idLen; char* name; int nameLen; + zend_bool preserve; zval* base; zval* members; - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sso!a!"), &id, &idLen, &name, &nameLen, - &base, &members) == FAILURE) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ssbo!a!"), &id, &idLen, &name, &nameLen, + &preserve, &base, &members) == FAILURE) { return; } @@ -2758,6 +3125,7 @@ ZEND_FUNCTION(IcePHP_defineException) ExceptionInfoPtr ex = new ExceptionInfo(); ex->id = id; ex->name = name; + ex->preserve = preserve ? true : false; if(base) { ex->base = Wrapper<ExceptionInfoPtr>::value(base TSRMLS_CC); diff --git a/php/src/IcePHP/Types.h b/php/src/IcePHP/Types.h index 14ce1d0ec6d..917ad19c89b 100644 --- a/php/src/IcePHP/Types.h +++ b/php/src/IcePHP/Types.h @@ -45,6 +45,33 @@ class AbortMarshaling typedef std::map<unsigned int, Ice::ObjectPtr> ObjectMap; +class ObjectReader; +typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; + +// +// This class keeps track of PHP objects (instances of Slice classes +// and exceptions) that have preserved slices. +// +class SlicedDataUtil +{ +public: + + ~SlicedDataUtil(); + + void add(const ObjectReaderPtr&); + + void update(TSRMLS_D); + + static void setMember(zval*, const Ice::SlicedDataPtr& TSRMLS_DC); + static Ice::SlicedDataPtr getMember(zval*, ObjectMap* TSRMLS_DC); + +private: + + std::set<ObjectReaderPtr> _readers; + static zend_class_entry* _slicedDataType; + static zend_class_entry* _sliceInfoType; +}; + struct PrintObjectHistory { int index; @@ -329,6 +356,7 @@ public: std::string id; std::string name; // PHP class name bool isAbstract; + bool preserve; ClassInfoPtr base; ClassInfoList interfaces; DataMemberList members; @@ -379,6 +407,7 @@ public: std::string id; std::string name; // PHP class name + bool preserve; ExceptionInfoPtr base; DataMemberList members; bool usesClasses; @@ -400,7 +429,7 @@ class ObjectWriter : public Ice::ObjectWriter { public: - ObjectWriter(const ClassInfoPtr&, zval*, ObjectMap* TSRMLS_DC); + ObjectWriter(zval*, ObjectMap*, const ClassInfoPtr& TSRMLS_DC); ~ObjectWriter(); virtual void ice_preMarshal(); @@ -409,9 +438,9 @@ public: private: - ClassInfoPtr _info; zval* _object; ObjectMap* _map; + ClassInfoPtr _info; #if ZTS TSRMLS_D; #endif @@ -429,22 +458,59 @@ public: virtual void ice_postUnmarshal(); - virtual void read(const Ice::InputStreamPtr&, bool); + virtual void read(const Ice::InputStreamPtr&); virtual ClassInfoPtr getInfo() const; zval* getObject() const; + Ice::SlicedDataPtr getSlicedData() const; + private: zval* _object; ClassInfoPtr _info; CommunicatorInfoPtr _communicator; + Ice::SlicedDataPtr _slicedData; +#if ZTS + TSRMLS_D; +#endif +}; + +// +// ExceptionReader creates a PHP user exception and unmarshals it. +// +class ExceptionReader : public Ice::UserExceptionReader +{ +public: + + ExceptionReader(const CommunicatorInfoPtr&, const ExceptionInfoPtr& TSRMLS_DC); + ~ExceptionReader() throw(); + + virtual void read(const Ice::InputStreamPtr&) const; + virtual bool usesClasses() const; + virtual void usesClasses(bool); + + virtual std::string ice_name() const; + virtual Ice::Exception* ice_clone() const; + virtual void ice_throw() const; + + ExceptionInfoPtr getInfo() const; + + zval* getException() const; + + Ice::SlicedDataPtr getSlicedData() const; + +private: + + CommunicatorInfoPtr _communicatorInfo; + ExceptionInfoPtr _info; + zval* _ex; + Ice::SlicedDataPtr _slicedData; #if ZTS TSRMLS_D; #endif }; -typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; } // End of namespace IcePHP diff --git a/php/src/IcePHP/Util.cpp b/php/src/IcePHP/Util.cpp index 60b52ac15a0..2bd1875bce5 100644 --- a/php/src/IcePHP/Util.cpp +++ b/php/src/IcePHP/Util.cpp @@ -17,6 +17,169 @@ using namespace std; using namespace IcePHP; using namespace Slice::PHP; +namespace +{ + +bool +getMember(zval* zv, const string& name, zval** member, int type, bool required TSRMLS_DC) +{ + *member = 0; + + void* data = 0; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(name.c_str()), name.size() + 1, &data) == FAILURE) + { + if(required) + { + invalidArgument("object does not contain member `%s'" TSRMLS_CC, name.c_str()); + return false; + } + } + + if(data) + { + zval** val = reinterpret_cast<zval**>(data); + + if(Z_TYPE_PP(val) != type) + { + string expected = zendTypeToString(type); + string actual = zendTypeToString(Z_TYPE_PP(val)); + invalidArgument("expected value of type %s for member `%s' but received %s" TSRMLS_CC, expected.c_str(), + name.c_str(), actual.c_str()); + return false; + } + + *member = *val; + } + + return true; +} + +void +setStringMember(zval* obj, const string& name, const string& val TSRMLS_DC) +{ + zend_class_entry* cls = Z_OBJCE_P(obj); + assert(cls); + zend_update_property_stringl(cls, obj, const_cast<char*>(name.c_str()), static_cast<int>(name.size()), + const_cast<char*>(val.c_str()), static_cast<int>(val.size()) TSRMLS_CC); +} + +template<typename T, const char* PT> +bool +getVersion(zval* zv, T& v TSRMLS_DC) +{ + if(Z_TYPE_P(zv) != IS_OBJECT) + { + invalidArgument("value does not contain an object" TSRMLS_CC); + return false; + } + + zend_class_entry* cls = idToClass(PT TSRMLS_CC); + assert(cls); + + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != cls) + { + invalidArgument("expected an instance of %s" TSRMLS_CC, ce->name); + return false; + } + + zval* majorVal; + if(!getMember(zv, "major", &majorVal, IS_LONG, true TSRMLS_CC)) + { + return false; + } + + zval* minorVal; + if(!getMember(zv, "minor", &minorVal, IS_LONG, true TSRMLS_CC)) + { + return false; + } + + long m; + m = Z_LVAL_P(majorVal); + if(m < 0 || m > 255) + { + invalidArgument("version major must be a value between 0 and 255" TSRMLS_CC); + return false; + } + v.major = m; + + m = Z_LVAL_P(minorVal); + if(m < 0 || m > 255) + { + invalidArgument("version minor must be a value between 0 and 255" TSRMLS_CC); + return false; + } + v.minor = m; + + return true; +} + +template<typename T, const char* PT> +bool +createVersion(zval* zv, const T& version TSRMLS_DC) +{ + zend_class_entry* cls = idToClass(PT TSRMLS_CC); + assert(cls); + + if(object_init_ex(zv, cls) != SUCCESS) + { + runtimeError("unable to initialize %s" TSRMLS_CC, cls->name); + return false; + } + + zend_update_property_long(cls, zv, const_cast<char*>("major"), sizeof("major") - 1, version.major TSRMLS_CC); + zend_update_property_long(cls, zv, const_cast<char*>("minor"), sizeof("minor") - 1, version.minor TSRMLS_CC); + + return true; +} + +template<typename T, const char* PT> +bool +versionToString(zval* zv, zval* s TSRMLS_DC) +{ + T v; + if(!getVersion<T, PT>(zv, v TSRMLS_CC)) + { + return false; + } + + try + { + string str = IceInternal::versionToString<T>(v); + ZVAL_STRINGL(s, STRCAST(str.c_str()), str.length(), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + return false; + } + + return true; +} + +template<typename T, const char* PT> +bool +stringToVersion(const string& s, zval* zv TSRMLS_DC) +{ + try + { + T v = IceInternal::stringToVersion<T>(s); + return createVersion<T, PT>(zv, v TSRMLS_CC); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + } + + return false; +} + +char Ice_ProtocolVersion[] = "::Ice::ProtocolVersion"; +char Ice_EncodingVersion[] = "::Ice::EncodingVersion"; + +} + #if PHP_VERSION_ID < 50400 #ifdef _WIN32 extern "C" @@ -103,10 +266,8 @@ IcePHP::createIdentity(zval* zv, const Ice::Identity& id TSRMLS_DC) return false; } - zend_update_property_string(cls, zv, const_cast<char*>("name"), sizeof("name") - 1, STRCAST(id.name.c_str()) - TSRMLS_CC); - zend_update_property_string(cls, zv, const_cast<char*>("category"), sizeof("category") - 1, - STRCAST(id.category.c_str()) TSRMLS_CC); + setStringMember(zv, "name", id.name TSRMLS_CC); + setStringMember(zv, "category", id.category TSRMLS_CC); return true; } @@ -133,35 +294,19 @@ IcePHP::extractIdentity(zval* zv, Ice::Identity& id TSRMLS_DC) // // Category is optional, but name is required. // - void* categoryData = 0; - void* nameData; - if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST("name"), sizeof("name"), &nameData) == FAILURE) - { - invalidArgument("identity value does not contain member `name'" TSRMLS_CC); - return false; - } - zend_hash_find(Z_OBJPROP_P(zv), STRCAST("category"), sizeof("category"), &categoryData); - zval** categoryVal = reinterpret_cast<zval**>(categoryData); - zval** nameVal = reinterpret_cast<zval**>(nameData); + zval* categoryVal; + zval* nameVal; - if(Z_TYPE_PP(nameVal) != IS_STRING) + if(!getMember(zv, "category", &categoryVal, IS_STRING, false TSRMLS_CC) || + !getMember(zv, "name", &nameVal, IS_STRING, true TSRMLS_CC)) { - string s = zendTypeToString(Z_TYPE_PP(nameVal)); - invalidArgument("expected a string value for identity member `name' but received %s" TSRMLS_CC, s.c_str()); return false; } - if(categoryVal && Z_TYPE_PP(categoryVal) != IS_STRING && Z_TYPE_PP(categoryVal) != IS_NULL) + id.name = Z_STRVAL_P(nameVal); + if(categoryVal) { - string s = zendTypeToString(Z_TYPE_PP(categoryVal)); - invalidArgument("expected a string value for identity member `category' but received %s" TSRMLS_CC, s.c_str()); - return false; - } - - id.name = Z_STRVAL_PP(nameVal); - if(categoryVal && Z_TYPE_PP(categoryVal) == IS_STRING) - { - id.category = Z_STRVAL_PP(categoryVal); + id.category = Z_STRVAL_P(categoryVal); } else { @@ -286,13 +431,22 @@ IcePHP::extractStringArray(zval* zv, Ice::StringSeq& seq TSRMLS_DC) return true; } -static void -setStringMember(zval* obj, const string& name, const string& val TSRMLS_DC) +bool +IcePHP::createProtocolVersion(zval* zv, const Ice::ProtocolVersion& v TSRMLS_DC) { - zend_class_entry* cls = Z_OBJCE_P(obj); - assert(cls); - zend_update_property_stringl(cls, obj, const_cast<char*>(name.c_str()), static_cast<int>(name.size()), - const_cast<char*>(val.c_str()), static_cast<int>(val.size()) TSRMLS_CC); + return createVersion<Ice::ProtocolVersion, Ice_ProtocolVersion>(zv, v TSRMLS_CC); +} + +bool +IcePHP::createEncodingVersion(zval* zv, const Ice::EncodingVersion& v TSRMLS_DC) +{ + return createVersion<Ice::EncodingVersion, Ice_EncodingVersion>(zv, v TSRMLS_CC); +} + +bool +IcePHP::extractEncodingVersion(zval* zv, Ice::EncodingVersion& v TSRMLS_DC) +{ + return getVersion<Ice::EncodingVersion, Ice_EncodingVersion>(zv, v TSRMLS_CC); } static bool @@ -368,6 +522,7 @@ convertLocalException(const Ice::LocalException& ex, zval* zex TSRMLS_DC) return false; } zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, id TSRMLS_CC); + zval_ptr_dtor(&id); } catch(const Ice::RequestFailedException& e) { @@ -379,6 +534,7 @@ convertLocalException(const Ice::LocalException& ex, zval* zex TSRMLS_DC) return false; } zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, id TSRMLS_CC); + zval_ptr_dtor(&id); setStringMember(zex, "facet", e.facet TSRMLS_CC); setStringMember(zex, "operation", e.operation TSRMLS_CC); } @@ -398,21 +554,45 @@ convertLocalException(const Ice::LocalException& ex, zval* zex TSRMLS_DC) } catch(const Ice::UnsupportedProtocolException& e) { - zend_update_property_long(cls, zex, const_cast<char*>("badMajor"), sizeof("badMajor") - 1, e.badMajor - TSRMLS_CC); - zend_update_property_long(cls, zex, const_cast<char*>("badMinor"), sizeof("badMinor") - 1, e.badMinor - TSRMLS_CC); - zend_update_property_long(cls, zex, const_cast<char*>("major"), sizeof("major") - 1, e.major TSRMLS_CC); - zend_update_property_long(cls, zex, const_cast<char*>("minor"), sizeof("minor") - 1, e.minor TSRMLS_CC); + zval* v; + MAKE_STD_ZVAL(v); + if(!createProtocolVersion(v, e.bad TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); + + MAKE_STD_ZVAL(v); + if(!createProtocolVersion(v, e.supported TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); } catch(const Ice::UnsupportedEncodingException& e) { - zend_update_property_long(cls, zex, const_cast<char*>("badMajor"), sizeof("badMajor") - 1, e.badMajor - TSRMLS_CC); - zend_update_property_long(cls, zex, const_cast<char*>("badMinor"), sizeof("badMinor") - 1, e.badMinor - TSRMLS_CC); - zend_update_property_long(cls, zex, const_cast<char*>("major"), sizeof("major") - 1, e.major TSRMLS_CC); - zend_update_property_long(cls, zex, const_cast<char*>("minor"), sizeof("minor") - 1, e.minor TSRMLS_CC); + zval* v; + MAKE_STD_ZVAL(v); + if(!createEncodingVersion(v, e.bad TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); + + MAKE_STD_ZVAL(v); + if(!createEncodingVersion(v, e.supported TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); } catch(const Ice::NoObjectFactoryException& e) { @@ -746,3 +926,108 @@ ZEND_FUNCTION(Ice_generateUUID) string uuid = IceUtil::generateUUID(); RETURN_STRINGL(STRCAST(uuid.c_str()), uuid.size(), 1); } + +ZEND_FUNCTION(Ice_currentProtocol) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createProtocolVersion(return_value, Ice::currentProtocol TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_currentProtocolEncoding) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createEncodingVersion(return_value, Ice::currentProtocolEncoding TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_currentEncoding) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createEncodingVersion(return_value, Ice::currentEncoding TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_protocolVersionToString) +{ + zend_class_entry* versionClass = idToClass(Ice_ProtocolVersion TSRMLS_CC); + assert(versionClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, versionClass) != SUCCESS) + { + RETURN_NULL(); + } + + if(!versionToString<Ice::ProtocolVersion, Ice_ProtocolVersion>(zv, return_value TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToProtocolVersion) +{ + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + if(!stringToVersion<Ice::ProtocolVersion, Ice_ProtocolVersion>(s, return_value TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_encodingVersionToString) +{ + zend_class_entry* versionClass = idToClass(Ice_EncodingVersion TSRMLS_CC); + assert(versionClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, versionClass) != SUCCESS) + { + RETURN_NULL(); + } + + if(!versionToString<Ice::EncodingVersion, Ice_EncodingVersion>(zv, return_value TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToEncodingVersion) +{ + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + if(!stringToVersion<Ice::EncodingVersion, Ice_EncodingVersion>(s, return_value TSRMLS_CC)) + { + RETURN_NULL(); + } +} diff --git a/php/src/IcePHP/Util.h b/php/src/IcePHP/Util.h index 8dde23d9969..e73bcfaf296 100644 --- a/php/src/IcePHP/Util.h +++ b/php/src/IcePHP/Util.h @@ -20,6 +20,13 @@ extern "C" ZEND_FUNCTION(Ice_stringVersion); ZEND_FUNCTION(Ice_intVersion); ZEND_FUNCTION(Ice_generateUUID); +ZEND_FUNCTION(Ice_currentProtocol); +ZEND_FUNCTION(Ice_currentProtocolEncoding); +ZEND_FUNCTION(Ice_currentEncoding); +ZEND_FUNCTION(Ice_protocolVersionToString); +ZEND_FUNCTION(Ice_stringToProtocolVersion); +ZEND_FUNCTION(Ice_encodingVersionToString); +ZEND_FUNCTION(Ice_stringToEncodingVersion); } namespace IcePHP @@ -73,6 +80,21 @@ bool createStringArray(zval*, const Ice::StringSeq& TSRMLS_DC); bool extractStringArray(zval*, Ice::StringSeq& TSRMLS_DC); // +// Create a PHP instance of Ice_ProtocolVersion. +// +bool createProtocolVersion(zval*, const Ice::ProtocolVersion& TSRMLS_DC); + +// +// Create a PHP instance of Ice_EncodingVersion. +// +bool createEncodingVersion(zval*, const Ice::EncodingVersion& TSRMLS_DC); + +// +// Extracts the members of an encoding version. +// +bool extractEncodingVersion(zval*, Ice::EncodingVersion& TSRMLS_DC); + +// // Convert the given exception into its PHP equivalent. // zval* convertException(const Ice::Exception& TSRMLS_DC); diff --git a/php/test/Ice/exceptions/junk.php b/php/test/Ice/exceptions/junk.php deleted file mode 100644 index d6a44f5c74d..00000000000 --- a/php/test/Ice/exceptions/junk.php +++ /dev/null @@ -1,12 +0,0 @@ -<!-- ********************************************************************** --> -<!-- --> -<!-- Copyright (c) 2003-2012 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. --> -<!-- --> -<!-- ********************************************************************** --> - -<? -echo "value = ",PHP_CONFIG_FILE_PATH,"\n"; -?> diff --git a/php/test/Ice/exceptions/run.py b/php/test/Ice/exceptions/run.py index 0248812b4bb..7732c33648e 100755 --- a/php/test/Ice/exceptions/run.py +++ b/php/test/Ice/exceptions/run.py @@ -20,7 +20,15 @@ if len(path) == 0: sys.path.append(os.path.join(path[0], "scripts")) import TestUtil -print("tests with regular server.") +print("Running test with compact (default) format.") TestUtil.clientServerTest() -print("tests with AMD server.") +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") +print("Running test with compact (default) format and AMD server.") TestUtil.clientServerTest(server="serveramd") +print("Running test with sliced format and AMD server.") +TestUtil.clientServerTest(server="serveramd", additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with 1.0 encoding and AMD server.") +TestUtil.clientServerTest(server="serveramd", additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/php/test/Ice/info/Client.php b/php/test/Ice/info/Client.php index b936100f942..4bded0b35b6 100644 --- a/php/test/Ice/info/Client.php +++ b/php/test/Ice/info/Client.php @@ -39,18 +39,22 @@ function allTests($communicator) $udpEndpointType = $NS ? constant("Ice\\UDPEndpointType") : constant("Ice_UDPEndpointType"); $udpEndpointInfoClass = $NS ? "Ice\\UDPEndpointInfo" : "Ice_UDPEndpointInfo"; $sslEndpointType = 2; + $protocolVersionClass = $NS ? "Ice\\ProtocolVersion" : "Ice_ProtocolVersion"; + $encodingVersionClass = $NS ? "Ice\\EncodingVersion" : "Ice_EncodingVersion"; echo "testing proxy endpoint information... "; flush(); { - $p1 = $communicator->stringToProxy("test -t:default -h tcphost -p 10000 -t 1200 -z:" . + $p1 = $communicator->stringToProxy("test -t:default -v 1.4 -e 1.3 -h tcphost -p 10000 -t 1200 -z:" . "udp -h udphost -p 10001 --interface eth0 --ttl 5:" . - "opaque -t 100 -v ABCD"); + "opaque -e 1.8 -t 100 -v ABCD"); $endps = $p1->ice_getEndpoints(); $ipEndpoint = $endps[0]->getInfo(); test($ipEndpoint instanceof $ipEndpointInfoClass); + test($ipEndpoint->protocol == eval("return new " . $protocolVersionClass . "(1, 4);")); + test($ipEndpoint->encoding == eval("return new " . $encodingVersionClass . "(1, 3);")); test($ipEndpoint->host == "tcphost"); test($ipEndpoint->port == 10000); test($ipEndpoint->timeout == 1200); @@ -63,6 +67,8 @@ function allTests($communicator) $udpEndpoint = $endps[1]->getInfo(); test($udpEndpoint instanceof $udpEndpointInfoClass); + test($udpEndpoint->protocol == Ice_currentProtocol()); + test($udpEndpoint->encoding == Ice_currentEncoding()); test($udpEndpoint->host == "udphost"); test($udpEndpoint->port == 10001); test($udpEndpoint->mcastInterface == "eth0"); diff --git a/php/test/Ice/ini/Client.php b/php/test/Ice/ini/Client.php index fa09f2ead78..70c80181e24 100644 --- a/php/test/Ice/ini/Client.php +++ b/php/test/Ice/ini/Client.php @@ -32,9 +32,9 @@ $communicator = null; if($NS) { - $initData = eval("new Ice\\InitializationData;"); - $initData->properties = eval("Ice\\getProperties();"); - $communicator = eval("Ice\\initialize($initData);"); + $initData = eval("return new Ice\\InitializationData;"); + $initData->properties = eval("return Ice\\getProperties();"); + $communicator = eval("return Ice\\initialize(\$initData);"); } else { diff --git a/php/test/Ice/ini/ClientWithProfile.php b/php/test/Ice/ini/ClientWithProfile.php index b60fd3ed04a..7d8da674b7c 100644 --- a/php/test/Ice/ini/ClientWithProfile.php +++ b/php/test/Ice/ini/ClientWithProfile.php @@ -37,9 +37,9 @@ $communicator = null; if($NS) { - $initData = eval("new Ice\\InitializationData;"); - $initData->properties = eval("Ice\\getProperties();"); - $communicator = eval("Ice\\initialize($initData);"); + $initData = eval("return new Ice\\InitializationData;"); + $initData->properties = eval("return Ice\\getProperties();"); + $communicator = eval("return Ice\\initialize(\$initData);"); } else { @@ -53,7 +53,7 @@ test($communicator != null); $properties = null; if($NS) { - $properties = eval("Ice\\getProperties(\"Test\");"); + $properties = eval("return Ice\\getProperties(\"Test\");"); } else { diff --git a/php/test/Ice/objects/run.py b/php/test/Ice/objects/run.py index 751a8e1d456..3d61174d3d1 100755 --- a/php/test/Ice/objects/run.py +++ b/php/test/Ice/objects/run.py @@ -20,4 +20,9 @@ if len(path) == 0: sys.path.append(os.path.join(path[0], "scripts")) import TestUtil +print("Running test with compact (default) format.") TestUtil.clientServerTest() +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/php/test/Ice/proxy/Client.php b/php/test/Ice/proxy/Client.php index 4747643ff0a..9991bdb6813 100644 --- a/php/test/Ice/proxy/Client.php +++ b/php/test/Ice/proxy/Client.php @@ -32,9 +32,12 @@ function test($b) function allTests($communicator) { global $NS; + global $Ice_Encoding_1_0; + global $Ice_Encoding_1_1; $random = $NS ? constant("Ice\\EndpointSelectionType::Random") : constant("Ice_EndpointSelectionType::Random"); $ordered = $NS ? constant("Ice\\EndpointSelectionType::Ordered") : constant("Ice_EndpointSelectionType::Ordered"); + $encodingVersion = $NS ? "Ice\\EncodingVersion" : "Ice_EncodingVersion"; echo "testing stringToProxy... "; flush(); @@ -368,6 +371,42 @@ function allTests($communicator) //test(!$b1->ice_isCollocationOptimized()); //$communicator->getProperties()->setProperty($property, ""); + $property = $propertyPrefix . ".EncodingVersion"; + test($b1->ice_getEncodingVersion() == Ice_currentEncoding()); + $communicator->getProperties()->setProperty($property, "1.0"); + $b1 = $communicator->propertyToProxy($propertyPrefix); + test($b1->ice_getEncodingVersion()->major == 1 && $b1->ice_getEncodingVersion()->minor == 0); + $communicator->getProperties()->setProperty($property, "6.5"); + try + { + $communicator->propertyToProxy($propertyPrefix); + test(false); + } + catch(Exception $ex) + { + $cls = $NS ? "Ice\\UnsupportedEncodingException" : "Ice_UnsupportedEncodingException"; + if(!($ex instanceof $cls)) + { + throw $ex; + } + } + + $communicator->getProperties()->setProperty($property, "1.2"); + try + { + $communicator->propertyToProxy($propertyPrefix); + test(false); + } + catch(Exception $ex) + { + $cls = $NS ? "Ice\\UnsupportedEncodingException" : "Ice_UnsupportedEncodingException"; + if(!($ex instanceof $cls)) + { + throw $ex; + } + } + $communicator->getProperties()->setProperty($property, ""); + echo "ok\n"; echo "testing proxyToProperty... "; @@ -379,6 +418,7 @@ function allTests($communicator) $b1 = $b1->ice_preferSecure(false); $b1 = $b1->ice_endpointSelection($ordered); $b1 = $b1->ice_locatorCacheTimeout(100); + $b1 = $b1->ice_encodingVersion(eval("return new " . $encodingVersion . "(1, 0);")); $router = $communicator->stringToProxy("router"); //$router = $router->ice_collocationOptimized(false); @@ -398,10 +438,11 @@ function allTests($communicator) $b1 = $b1->ice_locator($locator->ice_uncheckedCast("::Ice::Locator")); $proxyProps = $communicator->proxyToProperty($b1, "Test"); - test(count($proxyProps) == 18); + test(count($proxyProps) == 21); test($proxyProps["Test"] == "test -t"); //test($proxyProps["Test.CollocationOptimized"] == "1"); + test($proxyProps["Test.EncodingVersion"] == "1.0"); test($proxyProps["Test.ConnectionCached"] == "1"); test($proxyProps["Test.PreferSecure"] == "0"); test($proxyProps["Test.EndpointSelection"] == "Ordered"); @@ -409,6 +450,7 @@ function allTests($communicator) test($proxyProps["Test.Locator"] == "locator -t"); //test($proxyProps["Test.Locator.CollocationOptimized"] == "1"); + test($proxyProps["Test.Locator.EncodingVersion"] == Ice_encodingVersionToString(Ice_currentEncoding())); test($proxyProps["Test.Locator.ConnectionCached"] == "0"); test($proxyProps["Test.Locator.PreferSecure"] == "1"); test($proxyProps["Test.Locator.EndpointSelection"] == "Random"); @@ -416,11 +458,31 @@ function allTests($communicator) test($proxyProps["Test.Locator.Router"] == "router -t"); //test($proxyProps["Test.Locator.Router.CollocationOptimized"] == "0"); + test($proxyProps["Test.Locator.Router.EncodingVersion"] == Ice_encodingVersionToString(Ice_currentEncoding())); test($proxyProps["Test.Locator.Router.ConnectionCached"] == "1"); test($proxyProps["Test.Locator.Router.PreferSecure"] == "1"); test($proxyProps["Test.Locator.Router.EndpointSelection"] == "Random"); test($proxyProps["Test.Locator.Router.LocatorCacheTimeout"] == "200"); + try + { + $b1->ice_encodingVersion(eval("return new " . $encodingVersion . "(3, 4);")); + test(false); + } + catch(Exception $ex) + { + $cls = $NS ? "Ice\\UnsupportedEncodingException" : "Ice_UnsupportedEncodingException"; + if(!($ex instanceof $cls)) + { + throw $ex; + } + } + + echo "ok\n"; + + echo "testing ice_getCommunicator... "; + flush(); + test($base->ice_getCommunicator() === $communicator); echo "ok\n"; echo "testing proxy methods... "; @@ -435,16 +497,16 @@ function allTests($communicator) test($base->ice_batchDatagram()->ice_isBatchDatagram()); test($base->ice_secure(true)->ice_isSecure()); test(!$base->ice_secure(false)->ice_isSecure()); + test($base->ice_preferSecure(true)->ice_isPreferSecure()); + test(!$base->ice_preferSecure(false)->ice_isPreferSecure()); test($base->ice_connectionId("id1")->ice_getConnectionId() == "id1"); test($base->ice_connectionId("id2")->ice_getConnectionId() == "id2"); + test($base->ice_encodingVersion($Ice_Encoding_1_0)->ice_getEncodingVersion() == $Ice_Encoding_1_0); + test($base->ice_encodingVersion($Ice_Encoding_1_1)->ice_getEncodingVersion() == $Ice_Encoding_1_1); + test($base->ice_encodingVersion($Ice_Encoding_1_0)->ice_getEncodingVersion() != $Ice_Encoding_1_1); echo "ok\n"; - echo "testing ice_getCommunicator... "; - flush(); - test($base->ice_getCommunicator() === $communicator); - echo "ok\n"; - echo "testing checked cast... "; flush(); $cl = $base->ice_checkedCast("::Test::MyClass"); @@ -637,11 +699,19 @@ function allTests($communicator) } } - // Legal TCP endpoint expressed as opaque endpoint - $p1 = $communicator->stringToProxy("test:opaque -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAA=="); + // Legal TCP endpoint expressed as opaque endpoint. + $p1 = $communicator->stringToProxy("test:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMeouAAAQJwAAAA=="); $pstr = $communicator->proxyToString($p1); test($pstr == "test -t:tcp -h 127.0.0.1 -p 12010 -t 10000"); + // 1.1 TCP endpoint encoded with 1.1 encoding. + $p2 = $communicator->stringToProxy("test:opaque -e 1.1 -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAAEAAQE="); + test($communicator->proxyToString($p2) == "test -t:tcp -e 1.1 -h 127.0.0.1 -p 12010 -t 10000"); + + // 1.0 TCP endpoint encoded with 1.1 encoding. + $p2 = $communicator->stringToProxy("test: opaque -t 1 -e 1.1 -v CTEyNy4wLjAuMeouAAAQJwAAAAEAAQA="); + test($communicator->proxyToString($p2) == "test -t:tcp -h 127.0.0.1 -p 12010 -t 10000"); + // Working? if($communicator->getProperties()->getProperty("Ice.IPv6") == "" || $communicator->getProperties()->getProperty("Ice.IPv6") == "0") @@ -649,11 +719,11 @@ function allTests($communicator) $ssl = $communicator->getProperties()->getProperty("Ice.Default.Protocol") == "ssl"; if(!$ssl) { - $p1->ice_ping(); + $p1->ice_encodingVersion($Ice_Encoding_1_0)->ice_ping(); } // Two legal TCP endpoints expressed as opaque endpoints - $p1 = $communicator->stringToProxy("test:opaque -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAA==:opaque -t 1 -v CTEyNy4wLjAuMusuAAAQJwAAAA=="); + $p1 = $communicator->stringToProxy("test:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMeouAAAQJwAAAA==:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMusuAAAQJwAAAA=="); $pstr = $communicator->proxyToString($p1); test($pstr == "test -t:tcp -h 127.0.0.1 -p 12010 -t 10000:tcp -h 127.0.0.2 -p 12011 -t 10000"); @@ -661,11 +731,11 @@ function allTests($communicator) // Test that an SSL endpoint and a nonsense endpoint get written // back out as an opaque endpoint. // - $p1 = $communicator->stringToProxy("test:opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -v abch"); + $p1 = $communicator->stringToProxy("test:opaque -t 2 -e 1.0 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -e 1.0 -v abch"); $pstr = $communicator->proxyToString($p1); if(!$ssl) { - test($pstr == "test -t:opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -v abch"); + test($pstr == "test -t:opaque -t 2 -e 1.0 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -e 1.0 -v abch"); } else { @@ -679,7 +749,7 @@ function allTests($communicator) // try { - $p1->ice_ping(); + $p1->ice_encodingVersion($Ice_Encoding_1_0)->ice_ping(); test(false); } catch(Exception $ex) @@ -710,11 +780,11 @@ function allTests($communicator) $pstr = $communicator->proxyToString($p2); if(!$ssl) { - test($pstr == "test -t:opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -v abch"); + test($pstr == "test -t:opaque -t 2 -e 1.0 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -e 1.0 -v abch"); } else { - test($pstr == "test -t:ssl -h 127.0.0.1 -p 10001:opaque -t 99 -v abch"); + test($pstr == "test -t:ssl -h 127.0.0.1 -p 10001:opaque -t 99 -e 1.0 -v abch"); } } echo "ok\n"; diff --git a/php/test/Ice/slicing/exceptions/Client.php b/php/test/Ice/slicing/exceptions/Client.php index ff114ac5b20..5646e7b4c78 100644 --- a/php/test/Ice/slicing/exceptions/Client.php +++ b/php/test/Ice/slicing/exceptions/Client.php @@ -23,11 +23,12 @@ function test($b) function allTests($communicator) { global $NS; + global $Ice_Encoding_1_0; $obj = $communicator->stringToProxy("Test:default -p 12010"); $test = $obj->ice_checkedCast("::Test::TestIntf"); - echo "testing throwing a base exception... "; + echo "base... "; flush(); { try @@ -40,7 +41,7 @@ function allTests($communicator) $excls = $NS ? "Test\\Base" : "Test_Base"; if(!($b instanceof $excls)) { - throw $ex; + throw $b; } test($b->b == "Base.b"); test(get_class($b) == ($NS ? "Test\\Base" : "Test_Base")); @@ -48,7 +49,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of unknown derived exception... "; + echo "unknown derived... "; flush(); { try @@ -61,7 +62,7 @@ function allTests($communicator) $excls = $NS ? "Test\\Base" : "Test_Base"; if(!($b instanceof $excls)) { - throw $ex; + throw $b; } test($b->b == "UnknownDerived.b"); test(get_class($b) == ($NS ? "Test\\Base" : "Test_Base")); @@ -69,7 +70,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing non-slicing of known derived exception thrown as base exception... "; + echo "non-slicing of known derived as base... "; flush(); { try @@ -82,7 +83,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownDerived" : "Test_KnownDerived"; if(!($k instanceof $excls)) { - throw $ex; + throw $k; } test($k->b == "KnownDerived.b"); test($k->kd == "KnownDerived.kd"); @@ -91,7 +92,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing non-slicing of known derived exception thrown as derived exception... "; + echo "non-slicing of known derived as derived... "; flush(); { try @@ -104,7 +105,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownDerived" : "Test_KnownDerived"; if(!($k instanceof $excls)) { - throw $ex; + throw $k; } test($k->b == "KnownDerived.b"); test($k->kd == "KnownDerived.kd"); @@ -113,7 +114,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of unknown intermediate exception thrown as base exception... "; + echo "slicing of unknown intermediate as base... "; flush(); { try @@ -126,7 +127,7 @@ function allTests($communicator) $excls = $NS ? "Test\\Base" : "Test_Base"; if(!($b instanceof $excls)) { - throw $ex; + throw $b; } test($b->b == "UnknownIntermediate.b"); test(get_class($b) == ($NS ? "Test\\Base" : "Test_Base")); @@ -134,7 +135,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of known intermediate exception thrown as base exception... "; + echo "slicing of known intermediate as base... "; flush(); { try @@ -147,7 +148,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownIntermediate" : "Test_KnownIntermediate"; if(!($ki instanceof $excls)) { - throw $ex; + throw $ki; } test($ki->b == "KnownIntermediate.b"); test($ki->ki == "KnownIntermediate.ki"); @@ -156,7 +157,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of known most derived exception thrown as base exception... "; + echo "slicing of known most derived as base... "; flush(); { try @@ -169,7 +170,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownMostDerived" : "Test_KnownMostDerived"; if(!($kmd instanceof $excls)) { - throw $ex; + throw $kmd; } test($kmd->b == "KnownMostDerived.b"); test($kmd->ki == "KnownMostDerived.ki"); @@ -179,7 +180,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing non-slicing of known intermediate exception thrown as intermediate exception... "; + echo "non-slicing of known intermediate as intermediate... "; flush(); { try @@ -192,7 +193,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownIntermediate" : "Test_KnownIntermediate"; if(!($ki instanceof $excls)) { - throw $ex; + throw $ki; } test($ki->b == "KnownIntermediate.b"); test($ki->ki == "KnownIntermediate.ki"); @@ -201,7 +202,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing non-slicing of known most derived thrown as intermediate exception... "; + echo "non-slicing of known most derived as intermediate... "; flush(); { try @@ -214,7 +215,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownMostDerived" : "Test_KnownMostDerived"; if(!($kmd instanceof $excls)) { - throw $ex; + throw $kmd; } test($kmd->b == "KnownMostDerived.b"); test($kmd->ki == "KnownMostDerived.ki"); @@ -224,7 +225,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing non-slicing of known most derived thrown as most derived exception... "; + echo "non-slicing of known most derived as most derived... "; flush(); { try @@ -237,7 +238,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownMostDerived" : "Test_KnownMostDerived"; if(!($kmd instanceof $excls)) { - throw $ex; + throw $kmd; } test($kmd->b == "KnownMostDerived.b"); test($kmd->ki == "KnownMostDerived.ki"); @@ -247,7 +248,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of unknown most derived with known intermediate thrown as base exception... "; + echo "slicing of unknown most derived, known intermediate as base... "; flush(); { try @@ -260,7 +261,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownIntermediate" : "Test_KnownIntermediate"; if(!($ki instanceof $excls)) { - throw $ex; + throw $ki; } test($ki->b == "UnknownMostDerived1.b"); test($ki->ki == "UnknownMostDerived1.ki"); @@ -269,7 +270,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of unknown most derived with known intermediate thrown as intermediate exception... "; + echo "slicing of unknown most derived, known intermediate as intermediate... "; flush(); { try @@ -282,7 +283,7 @@ function allTests($communicator) $excls = $NS ? "Test\\KnownIntermediate" : "Test_KnownIntermediate"; if(!($ki instanceof $excls)) { - throw $ex; + throw $ki; } test($ki->b == "UnknownMostDerived1.b"); test($ki->ki == "UnknownMostDerived1.ki"); @@ -291,7 +292,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing slicing of unknown most derived with unknown intermediate thrown as base exception... "; + echo "slicing of unknown most derived, unknown intermediate as base... "; flush(); { try @@ -304,7 +305,7 @@ function allTests($communicator) $excls = $NS ? "Test\\Base" : "Test_Base"; if(!($b instanceof $excls)) { - throw $ex; + throw $b; } test($b->b == "UnknownMostDerived2.b"); test(get_class($b) == ($NS ? "Test\\Base" : "Test_Base")); @@ -312,6 +313,114 @@ function allTests($communicator) } echo "ok\n"; + echo "unknown most derived in compact format... "; + flush(); + { + try + { + $test->unknownMostDerived2AsBaseCompact(); + test(false); + } + catch(Exception $b) + { + $excls = $NS ? "Test\\Base" : "Test_Base"; + if(($b instanceof $excls)) + if(get_class($b) == ($NS ? "Test\\Base" : "Test_Base")) + { + // + // For the 1.0 encoding, the unknown exception is sliced to Base. + // + test($test->ice_getEncodingVersion() == $Ice_Encoding_1_0); + } + else if(get_class($b) == ($NS ? "Ice\\MarshalException" : "Ice_MarshalException")) + { + // + // A MarshalException is raised for the compact format because the + // most-derived type is unknown and the exception cannot be sliced. + // + test($test->ice_getEncodingVersion() != $Ice_Encoding_1_0); + } + else + { + throw $b; + } + } + } + echo "ok\n"; + + echo "preserved exceptions... "; + flush(); + { + try + { + $test->knownPreservedAsBase(); + test(false); + } + catch(Exception $b) + { + $excls = $NS ? "Test\\KnownPreservedDerived" : "Test_KnownPreservedDerived"; + if(!($b instanceof $excls)) + { + throw $b; + } + test($b->b == "base"); + test($b->kp == "preserved"); + test($b->kpd == "derived"); + } + + try + { + $test->knownPreservedAsKnownPreserved(); + test(false); + } + catch(Exception $b) + { + $excls = $NS ? "Test\\KnownPreservedDerived" : "Test_KnownPreservedDerived"; + if(!($b instanceof $excls)) + { + throw $b; + } + test($b->b == "base"); + test($b->kp == "preserved"); + test($b->kpd == "derived"); + } + + try + { + $test->unknownPreservedAsBase(); + test(false); + } + catch(Exception $b) + { + $excls = $NS ? "Test\\KnownPreservedDerived" : "Test_KnownPreservedDerived"; + if(!($b instanceof $excls)) + { + throw $b; + } + test($b->b == "base"); + test($b->kp == "preserved"); + test($b->kpd == "derived"); + } + + try + { + $test->unknownPreservedAsKnownPreserved(); + test(false); + } + catch(Exception $b) + { + $excls = $NS ? "Test\\KnownPreservedDerived" : "Test_KnownPreservedDerived"; + if(!($b instanceof $excls)) + { + throw $b; + } + test($b->b == "base"); + test($b->kp == "preserved"); + test($b->kpd == "derived"); + } + } + echo "ok\n"; + return $test; } diff --git a/php/test/Ice/slicing/exceptions/Test.ice b/php/test/Ice/slicing/exceptions/Test.ice index 1c92fe0fbcf..e558935d440 100644 --- a/php/test/Ice/slicing/exceptions/Test.ice +++ b/php/test/Ice/slicing/exceptions/Test.ice @@ -32,7 +32,35 @@ exception KnownMostDerived extends KnownIntermediate string kmd; }; -["ami"] interface TestIntf +["preserve-slice"] +exception KnownPreserved extends Base +{ + string kp; +}; + +exception KnownPreservedDerived extends KnownPreserved +{ + string kpd; +}; + +["preserve-slice"] +class BaseClass +{ + string bc; +}; + +["format:sliced"] +interface Relay +{ + void knownPreservedAsBase() throws Base; + void knownPreservedAsKnownPreserved() throws KnownPreserved; + + void unknownPreservedAsBase() throws Base; + void unknownPreservedAsKnownPreserved() throws KnownPreserved; +}; + +["format:sliced"] +interface TestIntf { void baseAsBase() throws Base; void unknownDerivedAsBase() throws Base; @@ -50,6 +78,20 @@ exception KnownMostDerived extends KnownIntermediate void unknownMostDerived1AsKnownIntermediate() throws KnownIntermediate; void unknownMostDerived2AsBase() throws Base; + ["format:compact"] void unknownMostDerived2AsBaseCompact() throws Base; + + void knownPreservedAsBase() throws Base; + void knownPreservedAsKnownPreserved() throws KnownPreserved; + + void relayKnownPreservedAsBase(Relay* r) throws Base; + void relayKnownPreservedAsKnownPreserved(Relay* r) throws KnownPreserved; + + void unknownPreservedAsBase() throws Base; + void unknownPreservedAsKnownPreserved() throws KnownPreserved; + + void relayUnknownPreservedAsBase(Relay* r) throws Base; + void relayUnknownPreservedAsKnownPreserved(Relay* r) throws KnownPreserved; + void shutdown(); }; diff --git a/php/test/Ice/slicing/exceptions/run.py b/php/test/Ice/slicing/exceptions/run.py index 286dd895700..9fde25714bd 100755 --- a/php/test/Ice/slicing/exceptions/run.py +++ b/php/test/Ice/slicing/exceptions/run.py @@ -20,4 +20,7 @@ if len(path) == 0: sys.path.append(os.path.join(path[0], "scripts")) import TestUtil +print("Running test with sliced format.") TestUtil.clientServerTest() +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/php/test/Ice/slicing/objects/Client.php b/php/test/Ice/slicing/objects/Client.php index 55d5ac1ad6e..e57f3b44269 100644 --- a/php/test/Ice/slicing/objects/Client.php +++ b/php/test/Ice/slicing/objects/Client.php @@ -24,6 +24,7 @@ function test($b) function allTests($communicator) { global $NS; + global $Ice_Encoding_1_0; $d1cls = $NS ? "Test\\D1" : "Test_D1"; $d3cls = $NS ? "Test\\D3" : "Test_D3"; @@ -31,7 +32,7 @@ function allTests($communicator) $obj = $communicator->stringToProxy("Test:default -p 12010"); $test = $obj->ice_checkedCast("::Test::TestIntf"); - echo "testing base as Object... "; + echo "base as Object... "; flush(); { $o = $test->SBaseAsObject(); @@ -41,7 +42,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing base as base... "; + echo "base as base... "; flush(); { $o = $test->SBaseAsSBase(); @@ -49,7 +50,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing base with known derived as base... "; + echo "base with known derived as base... "; flush(); { $sb = $test->SBSKnownDerivedAsSBase(); @@ -59,7 +60,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing base with known derived as known derived... "; + echo "base with known derived as known derived... "; flush(); { $sbksd = $test->SBSKnownDerivedAsSBSKnownDerived(); @@ -67,15 +68,46 @@ function allTests($communicator) } echo "ok\n"; - echo "testing base with unknown derived as base... "; + echo "base with unknown derived as base... "; flush(); { $sb = $test->SBSUnknownDerivedAsSBase(); test($sb->sb == "SBSUnknownDerived.sb"); } + if($test->ice_getEncodingVersion() == $Ice_Encoding_1_0) + { + try + { + // + // This test succeeds for the 1.0 encoding. + // + $sb = $test->SBSUnknownDerivedAsSBaseCompact(); + test($sb->sb == "SBSUnknownDerived.sb"); + } + catch(Exception $ex) + { + test(false); + } + } + else + { + try + { + // + // This test fails when using the compact format because the instance cannot + // be sliced to a known type. + // + $sb = $test->SBSUnknownDerivedAsSBaseCompact(); + test(false); + } + catch(Exception $ex) + { + test(get_class($ex) == ($NS ? "Ice\\MarshalException" : "Ice_MarshalException")); + } + } echo "ok\n"; - echo "testing unknown with Object as Object... "; + echo "unknown with Object as Object... "; flush(); { try @@ -94,7 +126,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing one-element cycle... "; + echo "one-element cycle... "; flush(); { $b = $test->oneElementCycle(); @@ -110,7 +142,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing two-element cycle... "; + echo "two-element cycle... "; flush(); { $b1 = $test->twoElementCycle(); @@ -131,7 +163,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing known derived pointer slicing as base... "; + echo "known derived pointer slicing as base... "; flush(); { $b1 = $test->D1AsB(); @@ -159,7 +191,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing known derived pointer slicing as derived... "; + echo "known derived pointer slicing as derived... "; flush(); { $d1 = $test->D1AsD1(); @@ -182,7 +214,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing unknown derived pointer slicing as base... "; + echo "unknown derived pointer slicing as base... "; flush(); { $b2 = $test->D2AsB(); @@ -210,7 +242,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing parameter pointer slicing with known first... "; + echo "parameter pointer slicing with known first... "; flush(); { $test->paramTest1($b1, $b2); @@ -236,7 +268,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing parameter pointer slicing with unknown first... "; + echo "parameter pointer slicing with unknown first... "; flush(); { $test->paramTest2($b2, $b1); @@ -262,7 +294,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing return value identity with known first... "; + echo "return value identity with known first... "; flush(); { $r = $test->returnTest1($p1, $p2); @@ -275,7 +307,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing return value identity with unknown first... "; + echo "return value identity with unknown first... "; flush(); { $r = $test->returnTest2($p1, $p2); @@ -288,7 +320,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing return value identity for input params known first... "; + echo "return value identity for input params known first... "; flush(); { $d1 = $NS ? eval("return new Test\\D1;") : eval("return new Test_D1;"); @@ -334,7 +366,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing return value identity for input params unknown first... "; + echo "return value identity for input params unknown first... "; flush(); { $d1 = $NS ? eval("return new Test\\D1;") : eval("return new Test_D1;"); @@ -380,7 +412,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing return value identity for input params unknown first... "; + echo "return value identity for input params unknown first... "; flush(); { $d1 = $NS ? eval("return new Test\\D1;") : eval("return new Test_D1;"); @@ -428,7 +460,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing remainder unmarshaling (3 instances)... "; + echo "remainder unmarshaling (3 instances)... "; flush(); { $ret = $test->paramTest3($p1, $p2); @@ -450,7 +482,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing remainder unmarshaling (4 instances)... "; + echo "remainder unmarshaling (4 instances)... "; flush(); { $ret = $test->paramTest4($b); @@ -467,7 +499,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing parameter pointer slicing with first instance marshaled in unknown derived as base... "; + echo "parameter pointer slicing with first instance marshaled in unknown derived as base... "; flush(); { $b1 = $NS ? eval("return new Test\\B;") : eval("return new Test_B;"); @@ -501,7 +533,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing parameter pointer slicing with first instance marshaled in unknown derived as derived... "; + echo "parameter pointer slicing with first instance marshaled in unknown derived as derived... "; flush(); { $d11 = $NS ? eval("return new Test\\D1;") : eval("return new Test_D1;"); @@ -540,7 +572,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing sequence slicing... "; + echo "sequence slicing... "; flush(); { $ss = null; @@ -632,7 +664,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing dictionary slicing... "; + echo "dictionary slicing... "; flush(); { $bin = array(); @@ -695,7 +727,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing base exception thrown as base exception... "; + echo "base exception thrown as base exception... "; flush(); { try @@ -724,7 +756,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing derived exception thrown as base exception... "; + echo "derived exception thrown as base exception... "; flush(); { try @@ -761,7 +793,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing derived exception thrown as derived exception... "; + echo "derived exception thrown as derived exception... "; flush(); { try @@ -798,7 +830,7 @@ function allTests($communicator) } echo "ok\n"; - echo "testing unknown derived exception thrown as base exception... "; + echo "unknown derived exception thrown as base exception... "; flush(); { try @@ -827,6 +859,173 @@ function allTests($communicator) } echo "ok\n"; + echo "forward-declared class... "; + flush(); + { + try + { + $f = null; + $test->useForward($f); + test($f != null); + } + catch(Exception $e) + { + test(false); + } + } + echo "ok\n"; + + echo "preserved classes... "; + flush(); + { + // + // Server knows the most-derived class PDerived. + // + $pd = $NS ? eval("return new Test\\PDerived;") : eval("return new Test_PDerived;"); + $pd->pi = 3; + $pd->ps = "preserved"; + $pd->pb = $pd; + + $r = $test->exchangePBase($pd); + test(get_class($r) == ($NS ? "Test\\PDerived" : "Test_PDerived")); + test($r->pi == 3); + test($r->ps == "preserved"); + test($r->pb === $r); // Object identity comparison + + // + // Server only knows the base (non-preserved) type, so the object is sliced. + // + $pu = $NS ? eval("return new Test\\PCUnknown;") : eval("return new Test_PCUnknown;"); + $pu->pi = 3; + $pu->pu = "preserved"; + + $r = $test->exchangePBase($pu); + test(get_class($r) != ($NS ? "Test\\PCUnknown" : "Test_PCUnknown")); + test($r->pi == 3); + + // + // Server only knows the intermediate type Preserved. The object will be sliced to + // Preserved for the 1.0 encoding; otherwise it should be returned intact. + // + $pcd = $NS ? eval("return new Test\\PCDerived;") : eval("return new Test_PCDerived;"); + $pcd->pi = 3; + $pcd->pbs = array($pcd); + + $r = $test->exchangePBase($pcd); + if($test->ice_getEncodingVersion() == $Ice_Encoding_1_0) + { + test(get_class($r) != ($NS ? "Test\\PCDerived" : "Test_PCDerived")); + test($r->pi == 3); + } + else + { + test(get_class($r) == ($NS ? "Test\\PCDerived" : "Test_PCDerived")); + test($r->pi == 3); + test($r->pbs[0] === $r); // Object identity comparison + } + + // + // Send an object that will have multiple preserved slices in the server. + // The object will be sliced to Preserved for the 1.0 encoding. + // + $pcd = $NS ? eval("return new Test\\PCDerived3;") : eval("return new Test_PCDerived3;"); + $pcd->pi = 3; + // + // Sending more than 254 objects exercises the encoding for object ids. + // + $pcd->pbs = array(); + for($i = 0; $i < 300; ++$i) + { + $p2 = $NS ? eval("return new Test\\PCDerived2;") : eval("return new Test_PCDerived2;"); + $p2->pi = $i; + $p2->pbs = array(null); // Nil reference. This slice should not have an indirection table. + $p2->pcd2 = $i; + array_push($pcd->pbs, $p2); + } + $pcd->pcd2 = $pcd->pi; + $pcd->pcd3 = $pcd->pbs[10]; + + $r = $test->exchangePBase($pcd); + if($test->ice_getEncodingVersion() == $Ice_Encoding_1_0) + { + test(get_class($r) != ($NS ? "Test\\PCDerived3" : "Test_PCDerived3")); + test(get_class($r) == ($NS ? "Test\\PDerived" : "Test_PDerived")); + test($r->pi == 3); + } + else + { + test(get_class($r) == ($NS ? "Test\\PCDerived3" : "Test_PCDerived3")); + test($r->pi == 3); + for($i = 0; $i < 300; ++$i) + { + $p2 = $r->pbs[$i]; + test(get_class($p2) == ($NS ? "Test\\PCDerived2" : "Test_PCDerived2")); + test($p2->pi == $i); + test(count($p2->pbs) == 1); + test($p2->pbs[0] == null); + test($p2->pcd2 == $i); + } + test($r->pcd2 == $r->pi); + test($r->pcd3 === $r->pbs[10]); // Object identity comparison + } + + // + // Obtain an object with preserved slices and send it back to the server. + // The preserved slices should be excluded for the 1.0 encoding, otherwise + // they should be included. + // + $p = $test->PBSUnknownAsPreserved(); + $test->checkPBSUnknown($p); + if($test->ice_getEncodingVersion() != $Ice_Encoding_1_0) + { + $test->ice_encodingVersion($Ice_Encoding_1_0)->checkPBSUnknown($p); + } + + // + // Relay a graph through the server. This test uses a preserved class + // with a class member. + // + $c = $NS ? eval("return new Test\\PNode;") : eval("return new Test_PNode;"); + $c->next = $NS ? eval("return new Test\\PNode;") : eval("return new Test_PNode;"); + $c->next->next = $NS ? eval("return new Test\\PNode;") : eval("return new Test_PNode;"); + $c->next->next->next = $c; // Create a cyclic graph. + + $n = $test->exchangePNode($c); + test($n->next != null); + test($n->next !== $n->next->next); // Object identity comparison + test($n->next->next !== $n->next->next->next); // Object identity comparison + test($n->next->next->next === $n); // Object identity comparison + $n = null; // Release reference. + + // + // Obtain a preserved object from the server where the most-derived + // type is unknown. The preserved slice refers to a graph of PNode + // objects. + // + $p = $test->PBSUnknownAsPreservedWithGraph(); + test($p != null); + $test->checkPBSUnknownWithGraph($p); + $p = null; // Release reference. + + // + // Obtain a preserved object from the server where the most-derived + // type is unknown. A data member in the preserved slice refers to the + // outer object, so the chain of references looks like this: + // + // outer->slicedData->outer + // + $p = $test->PBSUnknown2AsPreservedWithGraph(); + test($p != null); + if($test->ice_getEncodingVersion() != $Ice_Encoding_1_0) + { + test($p->_ice_slicedData != null); + } + $test->checkPBSUnknown2WithGraph($p); + $p->_ice_slicedData = null; // Break the cycle. + $p = null; // Release reference. + } + echo "ok\n"; + return $test; } diff --git a/php/test/Ice/slicing/objects/ClientPrivate.ice b/php/test/Ice/slicing/objects/ClientPrivate.ice index b4e22a0d495..f8708d424c3 100644 --- a/php/test/Ice/slicing/objects/ClientPrivate.ice +++ b/php/test/Ice/slicing/objects/ClientPrivate.ice @@ -20,4 +20,25 @@ class D3 extends B B pd3; }; +["preserve-slice"] +class PCUnknown extends PBase +{ + string pu; +}; + +class PCDerived extends PDerived +{ + PBaseSeq pbs; +}; + +class PCDerived2 extends PCDerived +{ + int pcd2; +}; + +class PCDerived3 extends PCDerived2 +{ + Object pcd3; +}; + }; diff --git a/php/test/Ice/slicing/objects/Test.ice b/php/test/Ice/slicing/objects/Test.ice index 509a6544f25..8e20db55def 100644 --- a/php/test/Ice/slicing/objects/Test.ice +++ b/php/test/Ice/slicing/objects/Test.ice @@ -46,7 +46,7 @@ class SS2 BSeq s; }; -struct SS +struct SS3 { SS1 c1; SS2 c2; @@ -66,9 +66,39 @@ exception DerivedException extends BaseException D1 pd1; }; -class Forward; // Forward-declared class defined in another compilation unit +class Forward; /* Forward-declared class defined in another compilation unit */ -["ami"] interface TestIntf +class PBase +{ + int pi; +}; + +sequence<PBase> PBaseSeq; + +["preserve-slice"] +class Preserved extends PBase +{ + string ps; +}; + +class PDerived extends Preserved +{ + PBase pb; +}; + +["preserve-slice"] +class PNode +{ + PNode next; +}; + +["preserve-slice"] +exception PreservedException +{ +}; + +["format:sliced"] +interface TestIntf { Object SBaseAsObject(); SBase SBaseAsSBase(); @@ -77,6 +107,8 @@ class Forward; // Forward-declared class defined in another compilation SBase SBSUnknownDerivedAsSBase(); + ["format:compact"] SBase SBSUnknownDerivedAsSBaseCompact(); + Object SUnknownAsObject(); B oneElementCycle(); @@ -94,14 +126,28 @@ class Forward; // Forward-declared class defined in another compilation B returnTest2(out B p2, out B p1); B returnTest3(B p1, B p2); - SS sequenceTest(SS1 p1, SS2 p2); + SS3 sequenceTest(SS1 p1, SS2 p2); BDict dictionaryTest(BDict bin, out BDict bout); + PBase exchangePBase(PBase pb); + + Preserved PBSUnknownAsPreserved(); + void checkPBSUnknown(Preserved p); + + ["amd"] Preserved PBSUnknownAsPreservedWithGraph(); + void checkPBSUnknownWithGraph(Preserved p); + + ["amd"] Preserved PBSUnknown2AsPreservedWithGraph(); + void checkPBSUnknown2WithGraph(Preserved p); + + PNode exchangePNode(PNode pn); + void throwBaseAsBase() throws BaseException; void throwDerivedAsBase() throws BaseException; void throwDerivedAsDerived() throws DerivedException; void throwUnknownDerivedAsBase() throws BaseException; + ["amd"] void throwPreservedException() throws PreservedException; void useForward(out Forward f); /* Use of forward-declared class to verify that code is generated correctly. */ diff --git a/php/test/Ice/slicing/objects/run.py b/php/test/Ice/slicing/objects/run.py index 286dd895700..9fde25714bd 100755 --- a/php/test/Ice/slicing/objects/run.py +++ b/php/test/Ice/slicing/objects/run.py @@ -20,4 +20,7 @@ if len(path) == 0: sys.path.append(os.path.join(path[0], "scripts")) import TestUtil +print("Running test with sliced format.") TestUtil.clientServerTest() +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/php/test/Slice/structure/Client.php b/php/test/Slice/structure/Client.php index 51c72baa3e3..d0c37f10e0a 100644 --- a/php/test/Slice/structure/Client.php +++ b/php/test/Slice/structure/Client.php @@ -40,9 +40,9 @@ function allTests($communicator) // Define some default values. // $def_s2 = $NS ? - eval("new Test\\S2(true, 98, 99, 100, 101, 1.0, 2.0, \"string\", array(\"one\", \"two\", \"three\"), - array(\"abc\" => \"def\"), new Test\\S1(\"name\"), new Test\\C(5), - $communicator->stringToProxy(\"test\"));") : + eval("return new Test\\S2(true, 98, 99, 100, 101, 1.0, 2.0, \"string\", array(\"one\", \"two\", \"three\"), + array(\"abc\" => \"def\"), new Test\\S1(\"name\"), new Test\\C(5), + \$communicator->stringToProxy(\"test\"));") : new Test_S2(true, 98, 99, 100, 101, 1.0, 2.0, "string", array("one", "two", "three"), array("abc" => "def"), new Test_S1("name"), new Test_C(5), $communicator->stringToProxy("test")); @@ -50,7 +50,7 @@ function allTests($communicator) // // Compare default-constructed structures. // - test($NS ? eval("new Test\\S2 == new Test\\S2;") : new Test_S2 == new Test_S2); + test($NS ? eval("return new Test\\S2 == new Test\\S2;") : new Test_S2 == new Test_S2); // // Change one primitive member at a time. @@ -167,11 +167,11 @@ function allTests($communicator) test($v1 == $def_s2); $v1 = clone $def_s2; - $v1->s = $NS ? eval("new Test\\S1(\"name\");") : new Test_S1("name"); + $v1->s = $NS ? eval("return new Test\\S1(\"name\");") : new Test_S1("name"); test($v1 == $def_s2); $v1 = clone $def_s2; - $v1->s = $NS ? eval("new Test\\S1(\"noname\");") : new Test_S1("noname"); + $v1->s = $NS ? eval("return new Test\\S1(\"noname\");") : new Test_S1("noname"); test($v1 != $def_s2); $v1 = clone $def_s2; diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp index 401109e84b9..2c5931ba9ab 100644 --- a/py/modules/IcePy/Operation.cpp +++ b/py/modules/IcePy/Operation.cpp @@ -1563,6 +1563,8 @@ IcePy::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ic } catch(const ExceptionReader& r) { + is->endEncapsulation(); + PyObject* ex = r.getException(); if(validateException(ex)) diff --git a/py/modules/IcePy/Types.cpp b/py/modules/IcePy/Types.cpp index 97dbf7f989f..526ca3aa63e 100644 --- a/py/modules/IcePy/Types.cpp +++ b/py/modules/IcePy/Types.cpp @@ -370,8 +370,13 @@ IcePy::SlicedDataUtil::setMember(PyObject* obj, const Ice::SlicedDataPtr& sliced // // bytes // +#if PY_VERSION_HEX >= 0x03000000 + PyObjectHandle bytes = + PyBytes_FromStringAndSize(reinterpret_cast<const char*>(&(*p)->bytes[0]), (*p)->bytes.size()); +#else PyObjectHandle bytes = PyString_FromStringAndSize(reinterpret_cast<const char*>(&(*p)->bytes[0]), (*p)->bytes.size()); +#endif if(!bytes.get() || PyObject_SetAttrString(slice.get(), STRCAST("bytes"), bytes.get()) < 0) { assert(PyErr_Occurred()); @@ -446,14 +451,19 @@ IcePy::SlicedDataUtil::getMember(PyObject* obj, ObjectMap* objectMap) PyObjectHandle typeId = PyObject_GetAttrString(s.get(), STRCAST("typeId")); assert(typeId.get()); - assert(PyString_Check(typeId.get())); info->typeId = getString(typeId.get()); PyObjectHandle bytes = PyObject_GetAttrString(s.get(), STRCAST("bytes")); assert(bytes.get()); + char* str; + Py_ssize_t strsz; +#if PY_VERSION_HEX >= 0x03000000 + assert(PyBytes_Check(bytes.get())); + PyBytes_AsStringAndSize(bytes.get(), &str, &strsz); +#else assert(PyString_Check(bytes.get())); - const char* str = PyString_AS_STRING(bytes.get()); - Py_ssize_t strsz = PyString_GET_SIZE(bytes.get()); + PyString_AsStringAndSize(bytes.get(), &str, &strsz); +#endif vector<Ice::Byte> vtmp(str, str + strsz); info->bytes.swap(vtmp); diff --git a/py/modules/IcePy/Util.cpp b/py/modules/IcePy/Util.cpp index 1aae7f471a6..e49bd332334 100644 --- a/py/modules/IcePy/Util.cpp +++ b/py/modules/IcePy/Util.cpp @@ -36,8 +36,8 @@ setVersion(PyObject* p, const T& version) { assert(checkIsInstance(p, PT)); - PyObjectHandle major = PyInt_FromLong(version.major); - PyObjectHandle minor = PyInt_FromLong(version.minor); + PyObjectHandle major = PyLong_FromLong(version.major); + PyObjectHandle minor = PyLong_FromLong(version.minor); if(!major.get() || !minor.get()) { return false; @@ -58,12 +58,12 @@ getVersion(PyObject* p, T& v) PyObjectHandle minor = PyObject_GetAttrString(p, STRCAST("minor")); if(major.get()) { - if(!PyInt_Check(major.get())) + if(!PyLong_Check(major.get())) { PyErr_Format(PyExc_ValueError, STRCAST("version major must be a numeric value")); return false; } - int m = PyInt_AsLong(major.get()); + long m = PyLong_AsLong(major.get()); if(m < 0 || m > 255) { PyErr_Format(PyExc_ValueError, STRCAST("version major must be a value between 0 and 255")); @@ -73,12 +73,12 @@ getVersion(PyObject* p, T& v) } if(minor.get()) { - if(!PyInt_Check(minor.get())) + if(!PyLong_Check(minor.get())) { PyErr_Format(PyExc_ValueError, STRCAST("version minor must be a numeric value")); return false; } - int m = PyInt_AsLong(minor.get()); + long m = PyLong_AsLong(minor.get()); if(m < 0 || m > 255) { PyErr_Format(PyExc_ValueError, STRCAST("version minor must be a value between 0 and 255")); @@ -134,7 +134,7 @@ versionToString(PyObject* args) IcePy::setPythonException(ex); return NULL; } - return PyString_FromString(const_cast<char*>(s.c_str())); + return createString(s); } template<typename T, const char* PT> PyObject* diff --git a/rb/src/IceRuby/Operation.cpp b/rb/src/IceRuby/Operation.cpp index a8743a3145e..182f971626a 100644 --- a/rb/src/IceRuby/Operation.cpp +++ b/rb/src/IceRuby/Operation.cpp @@ -64,7 +64,7 @@ private: bool _returnsClasses; string _deprecateMessage; - void prepareRequest(const Ice::ObjectPrx&, VALUE, bool, vector<Ice::Byte>&); + void prepareRequest(const Ice::ObjectPrx&, VALUE, vector<Ice::Byte>&); VALUE unmarshalResults(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); VALUE unmarshalException(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); bool validateException(VALUE) const; @@ -275,7 +275,7 @@ IceRuby::OperationI::invoke(const Ice::ObjectPrx& proxy, VALUE args, VALUE hctx) // Marshal the input parameters to a byte sequence. // Ice::ByteSeq params; - prepareRequest(proxy, args, false, params); + prepareRequest(proxy, args, params); if(!_deprecateMessage.empty()) { @@ -355,7 +355,7 @@ IceRuby::OperationI::deprecate(const string& msg) } void -IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, bool async, vector<Ice::Byte>& bytes) +IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, vector<Ice::Byte>& bytes) { // // Validate the number of arguments. @@ -388,17 +388,9 @@ IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, boo volatile VALUE arg = RARRAY_PTR(args)[i]; if(!(*p)->type->validate(arg)) { - string opName; - if(async) - { - opName = fixIdent(_name, IdentNormal) + "_async"; - } - else - { - opName = fixIdent(_name, IdentNormal); - } - throw RubyException(rb_eTypeError, "invalid value for argument %ld in operation `%s'", - async ? i + 2 : i + 1, opName.c_str()); + string opName = fixIdent(_name, IdentNormal); + throw RubyException(rb_eTypeError, "invalid value for argument %ld in operation `%s'", i + 1, + opName.c_str()); } (*p)->type->marshal(arg, os, &objectMap); } @@ -483,12 +475,20 @@ IceRuby::OperationI::unmarshalException(const vector<Ice::Byte>& bytes, const Ic } catch(const ExceptionReader& r) { + is->endEncapsulation(); + volatile VALUE ex = r.getException(); if(validateException(ex)) { util.update(); + Ice::SlicedDataPtr slicedData = r.getSlicedData(); + if(slicedData) + { + SlicedDataUtil::setMember(ex, slicedData); + } + return ex; } else diff --git a/rb/src/IceRuby/Types.cpp b/rb/src/IceRuby/Types.cpp index 5c29dd817b1..bc028a3177a 100644 --- a/rb/src/IceRuby/Types.cpp +++ b/rb/src/IceRuby/Types.cpp @@ -271,7 +271,7 @@ IceRuby::SlicedDataUtil::setMember(VALUE obj, const Ice::SlicedDataPtr& slicedDa for(vector<Ice::ObjectPtr>::iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q) { // - // Each element in the objects list is an instance of ObjectReader that wraps a Python object. + // Each element in the objects list is an instance of ObjectReader that wraps a Ruby object. // assert(*q); ObjectReaderPtr r = ObjectReaderPtr::dynamicCast(*q); @@ -1869,7 +1869,7 @@ IceRuby::ObjectWriter::write(const Ice::OutputStreamPtr& os) const if(_info->preserve) { // - // Retrieve the SlicedData object that we stored as a hidden member of the Python object. + // Retrieve the SlicedData object that we stored as a hidden member of the Ruby object. // slicedData = SlicedDataUtil::getMember(_object, const_cast<ObjectMap*>(_map)); } @@ -2116,7 +2116,7 @@ IceRuby::ExceptionReader::read(const Ice::InputStreamPtr& is) const const_cast<VALUE&>(_ex) = _info->unmarshal(is); - is->endException(false); + const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); } bool @@ -2158,7 +2158,7 @@ IceRuby::ExceptionReader::getException() const Ice::SlicedDataPtr IceRuby::ExceptionReader::getSlicedData() const { - return 0; + return _slicedData; } extern "C" @@ -2331,13 +2331,15 @@ IceRuby_declareLocalClass(VALUE /*self*/, VALUE id) extern "C" VALUE -IceRuby_defineException(VALUE /*self*/, VALUE id, VALUE type, VALUE base, VALUE members) +IceRuby_defineException(VALUE /*self*/, VALUE id, VALUE type, VALUE preserve, VALUE base, VALUE members) { ICE_RUBY_TRY { ExceptionInfoPtr info = new ExceptionInfo; info->id = getString(id); + info->preserve = preserve == Qtrue; + if(!NIL_P(base)) { info->base = ExceptionInfoPtr::dynamicCast(getException(base)); @@ -2540,7 +2542,7 @@ IceRuby::initTypes(VALUE iceModule) rb_define_module_function(iceModule, "__declareProxy", CAST_METHOD(IceRuby_declareProxy), 1); rb_define_module_function(iceModule, "__declareClass", CAST_METHOD(IceRuby_declareClass), 1); rb_define_module_function(iceModule, "__declareLocalClass", CAST_METHOD(IceRuby_declareLocalClass), 1); - rb_define_module_function(iceModule, "__defineException", CAST_METHOD(IceRuby_defineException), 4); + rb_define_module_function(iceModule, "__defineException", CAST_METHOD(IceRuby_defineException), 5); rb_define_method(_typeInfoClass, "defineClass", CAST_METHOD(IceRuby_TypeInfo_defineClass), 6); rb_define_method(_typeInfoClass, "defineProxy", CAST_METHOD(IceRuby_TypeInfo_defineProxy), 2); diff --git a/rb/src/IceRuby/Types.h b/rb/src/IceRuby/Types.h index 954272f8f02..96d3756616a 100644 --- a/rb/src/IceRuby/Types.h +++ b/rb/src/IceRuby/Types.h @@ -373,6 +373,7 @@ public: void printMembers(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); std::string id; + bool preserve; ExceptionInfoPtr base; DataMemberList members; bool usesClasses; @@ -424,7 +425,6 @@ private: ClassInfoPtr _info; Ice::SlicedDataPtr _slicedData; }; -typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; // // ExceptionReader creates a Ruby user exception and unmarshals it. diff --git a/rb/src/IceRuby/Util.cpp b/rb/src/IceRuby/Util.cpp index b5333cbcbd1..6e62ee391d5 100644 --- a/rb/src/IceRuby/Util.cpp +++ b/rb/src/IceRuby/Util.cpp @@ -99,7 +99,7 @@ versionToString(VALUE p) T v; if(!getVersion<T, PT>(p, v)) { - return NULL; + return Qnil; } ICE_RUBY_TRY @@ -558,43 +558,6 @@ IceRuby::getEncodingVersion(VALUE p, Ice::EncodingVersion& v) return true; } -#if 0 -VALUE -IceRuby::currentProtocol(VALUE) -{ -} - -VALUE -IceRuby::currentProtocolEncoding(VALUE) -{ -} - -VALUE -IceRuby::currentEncoding(VALUE) -{ -} - -VALUE -IceRuby::protocolVersionToString(VALUE, VALUE) -{ -} - -VALUE -IceRuby::stringToProtocolVersion(VALUE, VALUE) -{ -} - -VALUE -IceRuby::encodingVersionToString(VALUE, VALUE) -{ -} - -VALUE -IceRuby::stringToEncodingVersion(VALUE, VALUE) -{ -} -#endif - VALUE IceRuby::callProtected(RubyFunction func, VALUE arg) { diff --git a/rb/test/Ice/exceptions/run.py b/rb/test/Ice/exceptions/run.py index 152a9fbcccb..7732c33648e 100755 --- a/rb/test/Ice/exceptions/run.py +++ b/rb/test/Ice/exceptions/run.py @@ -20,9 +20,15 @@ if len(path) == 0: sys.path.append(os.path.join(path[0], "scripts")) import TestUtil -print("tests with regular server.") +print("Running test with compact (default) format.") TestUtil.clientServerTest() -print("tests with AMD server.") +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") +print("Running test with compact (default) format and AMD server.") TestUtil.clientServerTest(server="serveramd") - -sys.exit(0) +print("Running test with sliced format and AMD server.") +TestUtil.clientServerTest(server="serveramd", additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with 1.0 encoding and AMD server.") +TestUtil.clientServerTest(server="serveramd", additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/rb/test/Ice/objects/run.py b/rb/test/Ice/objects/run.py index 61d1af84e72..3d61174d3d1 100755 --- a/rb/test/Ice/objects/run.py +++ b/rb/test/Ice/objects/run.py @@ -20,5 +20,9 @@ if len(path) == 0: sys.path.append(os.path.join(path[0], "scripts")) import TestUtil +print("Running test with compact (default) format.") TestUtil.clientServerTest() - +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/rb/test/Ice/proxy/AllTests.rb b/rb/test/Ice/proxy/AllTests.rb index 23b28227b11..89f892186aa 100644 --- a/rb/test/Ice/proxy/AllTests.rb +++ b/rb/test/Ice/proxy/AllTests.rb @@ -451,7 +451,7 @@ def allTests(communicator) #test(!(compObj.ice_locator(loc1) < compObj.ice_locator(nil))) #test(compObj.ice_locator(loc1) < compObj.ice_locator(loc2)) #test(!(compObj.ice_locator(loc2) < compObj.ice_locator(loc1))) - + rtr1 = Ice::RouterPrx::uncheckedCast(communicator.stringToProxy("rtr1:default -p 10000")) rtr2 = Ice::RouterPrx::uncheckedCast(communicator.stringToProxy("rtr2:default -p 10000")) test(compObj.ice_router(nil) == compObj.ice_router(nil)) @@ -475,12 +475,12 @@ def allTests(communicator) test(compObj.ice_context(ctx1) != compObj.ice_context(ctx2)) #test(compObj.ice_context(ctx1) < compObj.ice_context(ctx2)) #test(!(compObj.ice_context(ctx2) < compObj.ice_context(ctx1))) - + test(compObj.ice_preferSecure(true) == compObj.ice_preferSecure(true)) test(compObj.ice_preferSecure(true) != compObj.ice_preferSecure(false)) #test(compObj.ice_preferSecure(false) < compObj.ice_preferSecure(true)) #test(!(compObj.ice_preferSecure(true) < compObj.ice_preferSecure(false))) - + compObj1 = communicator.stringToProxy("foo:tcp -h 127.0.0.1 -p 10000") compObj2 = communicator.stringToProxy("foo:tcp -h 127.0.0.1 -p 10001") test(compObj1 != compObj2) @@ -642,7 +642,7 @@ def allTests(communicator) rescue Ice::EndpointParseException end - # Legal TCP endpoint expressed as opaque endpoint + # Legal TCP endpoint expressed as opaque endpoint. p1 = communicator.stringToProxy("test:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMeouAAAQJwAAAA==") pstr = communicator.proxyToString(p1) test(pstr == "test -t:tcp -h 127.0.0.1 -p 12010 -t 10000") @@ -654,7 +654,7 @@ def allTests(communicator) # 1.0 TCP endpoint encoded with 1.1 encoding. p2 = communicator.stringToProxy("test: opaque -t 1 -e 1.1 -v CTEyNy4wLjAuMeouAAAQJwAAAAEAAQA=") test(communicator.proxyToString(p2) == "test -t:tcp -h 127.0.0.1 -p 12010 -t 10000") - + # Working? if communicator.getProperties().getPropertyAsInt("Ice.IPv6") == 0 ssl = communicator.getProperties().getProperty("Ice.Default.Protocol") == "ssl" diff --git a/rb/test/Ice/slicing/exceptions/AllTests.rb b/rb/test/Ice/slicing/exceptions/AllTests.rb index 489135ba803..26702ae5e4a 100644 --- a/rb/test/Ice/slicing/exceptions/AllTests.rb +++ b/rb/test/Ice/slicing/exceptions/AllTests.rb @@ -7,7 +7,7 @@ # # ********************************************************************** -Ice::loadSlice('-I. --all ClientPrivate.ice') +Ice::loadSlice('Test.ice') def test(b) if !b diff --git a/rb/test/Ice/slicing/exceptions/ClientPrivate.ice b/rb/test/Ice/slicing/exceptions/ClientPrivate.ice deleted file mode 100644 index 029e6d5d37e..00000000000 --- a/rb/test/Ice/slicing/exceptions/ClientPrivate.ice +++ /dev/null @@ -1,32 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2012 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. -// -// ********************************************************************** - -#pragma once - -#include <Test.ice> - -module Test -{ - -class PreservedClass extends BaseClass -{ - string pc; -}; - -exception Preserved1 extends KnownPreservedDerived -{ - BaseClass p1; -}; - -exception Preserved2 extends Preserved1 -{ - BaseClass p2; -}; - -}; diff --git a/rb/test/Ice/slicing/objects/AllTests.rb b/rb/test/Ice/slicing/objects/AllTests.rb index 8e753e18057..774e4702a12 100644 --- a/rb/test/Ice/slicing/objects/AllTests.rb +++ b/rb/test/Ice/slicing/objects/AllTests.rb @@ -728,7 +728,7 @@ def allTests(communicator) # # Send an object that will have multiple preserved slices in the server. - # The object will be sliced to Preserved for the 1.0 encoding. + # The object will be sliced to PDerived for the 1.0 encoding. # pcd = Test::PCDerived3.new() pcd.pi = 3 @@ -749,7 +749,7 @@ def allTests(communicator) r = t.exchangePBase(pcd) if t.ice_getEncodingVersion() == Ice::Encoding_1_0 test(!r.is_a?(Test::PCDerived3)) - test(r.is_a?(Test::Preserved)) + test(r.is_a?(Test::PDerived)) test(r.pi == 3) else test(r.is_a?(Test::PCDerived3)) |