diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-11-09 16:22:47 -0800 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-11-09 16:22:47 -0800 |
commit | 493caea19fd83663eb03b4eeaf7714f99ac07b97 (patch) | |
tree | 39f8b7dc983394288cb25961a0907ebe0b0f5847 | |
parent | ICE-4914 - Update Database/Oracle demos (diff) | |
download | ice-493caea19fd83663eb03b4eeaf7714f99ac07b97.tar.bz2 ice-493caea19fd83663eb03b4eeaf7714f99ac07b97.tar.xz ice-493caea19fd83663eb03b4eeaf7714f99ac07b97.zip |
ICE-4930 - fixes for scripting languages
43 files changed, 685 insertions, 65 deletions
diff --git a/cpp/include/Ice/Stream.h b/cpp/include/Ice/Stream.h index b9119787ecb..67dd4610343 100644 --- a/cpp/include/Ice/Stream.h +++ b/cpp/include/Ice/Stream.h @@ -63,6 +63,7 @@ public: ~UserExceptionReader() throw(); virtual void read(const InputStreamPtr&) const = 0; + virtual bool usesClasses() const = 0; virtual ::std::string ice_name() const = 0; virtual UserException* ice_clone() const = 0; @@ -71,6 +72,8 @@ public: virtual void __write(IceInternal::BasicStream*) const; virtual void __read(IceInternal::BasicStream*); + virtual bool __usesClasses() const; + #ifdef __SUNPRO_CC using UserException::__read; using UserException::__write; @@ -402,6 +405,7 @@ public: ~UserExceptionWriter() throw(); virtual void write(const OutputStreamPtr&) const = 0; + virtual bool usesClasses() const = 0; virtual ::std::string ice_name() const = 0; virtual UserException* ice_clone() const = 0; @@ -410,6 +414,8 @@ public: virtual void __write(IceInternal::BasicStream*) const; virtual void __read(IceInternal::BasicStream*); + virtual bool __usesClasses() const; + #ifdef __SUNPRO_CC using UserException::__read; using UserException::__write; diff --git a/cpp/include/Slice/Parser.h b/cpp/include/Slice/Parser.h index 3c24cdcf520..38c27bd3b14 100644 --- a/cpp/include/Slice/Parser.h +++ b/cpp/include/Slice/Parser.h @@ -601,8 +601,8 @@ public: void setExceptionList(const ExceptionList&); virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; - bool sendsClasses() const; - bool returnsClasses() const; + bool sendsClasses(bool) const; + bool returnsClasses(bool) const; bool returnsData() const; int attributes() const; FormatType format() const; @@ -723,7 +723,7 @@ public: virtual bool isLocal() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; - bool usesClasses() const; + bool usesClasses(bool) const; bool hasDefaultValues() const; bool inheritsMetaData(const std::string&) const; virtual std::string kindOf() const; diff --git a/cpp/src/Ice/Stream.cpp b/cpp/src/Ice/Stream.cpp index 58d98324113..c483a261a56 100644 --- a/cpp/src/Ice/Stream.cpp +++ b/cpp/src/Ice/Stream.cpp @@ -28,6 +28,12 @@ Ice::UserExceptionReader::__readImpl(::IceInternal::BasicStream*) assert(false); // Should never be called. } +bool +Ice::UserExceptionReader::__usesClasses() const +{ + return usesClasses(); +} + void Ice::UserExceptionWriter::__writeImpl(::IceInternal::BasicStream*) const { @@ -39,3 +45,9 @@ Ice::UserExceptionWriter::__readImpl(::IceInternal::BasicStream*) { assert(false); // Should never be called. } + +bool +Ice::UserExceptionWriter::__usesClasses() const +{ + return usesClasses(); +} diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index a0855fc7771..673a9a0d222 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -3969,19 +3969,19 @@ Slice::Exception::uses(const ContainedPtr&) const } bool -Slice::Exception::usesClasses() const +Slice::Exception::usesClasses(bool includeOptional) const { DataMemberList dml = dataMembers(); for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i) { - if((*i)->type()->usesClasses()) + if((*i)->type()->usesClasses() && (includeOptional || !(*i)->optional())) { return true; } } if(_base) { - return _base->usesClasses(); + return _base->usesClasses(includeOptional); } return false; } @@ -5131,12 +5131,12 @@ Slice::Operation::uses(const ContainedPtr& contained) const } bool -Slice::Operation::sendsClasses() const +Slice::Operation::sendsClasses(bool includeOptional) const { ParamDeclList pdl = parameters(); for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i) { - if(!(*i)->isOutParam() && (*i)->type()->usesClasses()) + if(!(*i)->isOutParam() && (*i)->type()->usesClasses() && (includeOptional || !(*i)->optional())) { return true; } @@ -5145,17 +5145,17 @@ Slice::Operation::sendsClasses() const } bool -Slice::Operation::returnsClasses() const +Slice::Operation::returnsClasses(bool includeOptional) const { TypePtr t = returnType(); - if(t && t->usesClasses()) + if(t && t->usesClasses() && (includeOptional || !_returnIsOptional)) { return true; } ParamDeclList pdl = parameters(); for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i) { - if((*i)->isOutParam() && (*i)->type()->usesClasses()) + if((*i)->isOutParam() && (*i)->type()->usesClasses() && (includeOptional || !(*i)->optional())) { return true; } diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index f7e0f4b615f..c9463b8c32a 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -877,9 +877,9 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) C << nl << "throw *this;"; C << eb; - if(!p->isLocal() && p->usesClasses()) + if(!p->isLocal() && p->usesClasses(false)) { - if(!base || (base && !base->usesClasses())) + if(!base || (base && !base->usesClasses(false))) { H << sp << nl << "virtual bool __usesClasses() const;"; @@ -2170,7 +2170,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) { C << nl << "::IceInternal::BasicStream* __os = __result->__startWriteParams(" << opFormatTypeToString(p) <<");"; writeMarshalCode(C, inParams, 0, TypeContextInParam); - if(p->sendsClasses()) + if(p->sendsClasses(false)) { C << nl << "__os->writePendingObjects();"; } @@ -2237,7 +2237,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) { C << nl << "::IceInternal::BasicStream* __is = __result->__startReadParams();"; writeUnmarshalCode(C, outParams, p, _useWstring | TypeContextAMIEnd); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { C << nl << "__is->readPendingObjects();"; } @@ -2307,7 +2307,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) { C << nl << "::IceInternal::BasicStream* __is = __result->__startReadParams();"; writeUnmarshalCode(C, outParams, p, _useWstring | TypeContextAMIPrivateEnd); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { C << nl << "__is->readPendingObjects();"; } @@ -2729,7 +2729,7 @@ Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p) C << sb; C << nl<< "::IceInternal::BasicStream* __os = __og.startWriteParams(" << opFormatTypeToString(p) << ");"; writeMarshalCode(C, inParams, 0, TypeContextInParam); - if(p->sendsClasses()) + if(p->sendsClasses(false)) { C << nl << "__os->writePendingObjects();"; } @@ -2815,7 +2815,7 @@ Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p) { C << nl << "::IceInternal::BasicStream* __is = __og.startReadParams();"; writeUnmarshalCode(C, outParams, p); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { C << nl << "__is->readPendingObjects();"; } @@ -4272,7 +4272,7 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) C << nl << "::IceInternal::BasicStream* __is = __inS.startReadParams();"; writeAllocateCode(C, inParams, 0, _useWstring | TypeContextInParam); writeUnmarshalCode(C, inParams, 0, TypeContextInParam); - if(p->sendsClasses()) + if(p->sendsClasses(false)) { C << nl << "__is->readPendingObjects();"; } @@ -4300,7 +4300,7 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) C << nl << "::IceInternal::BasicStream* __os = __inS.__startWriteParams(" << opFormatTypeToString(p) << ");"; writeMarshalCode(C, outParams, p); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { C << nl << "__os->writePendingObjects();"; } @@ -4334,7 +4334,7 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) C << nl << "::IceInternal::BasicStream* __is = __inS.startReadParams();"; writeAllocateCode(C, inParams, 0, _useWstring | TypeContextInParam); writeUnmarshalCode(C, inParams, 0, TypeContextInParam); - if(p->sendsClasses()) + if(p->sendsClasses(false)) { C << nl << "__is->readPendingObjects();"; } @@ -5929,7 +5929,7 @@ Slice::Gen::AsyncImplVisitor::visitOperation(const OperationPtr& p) C << sb; C << nl << "::IceInternal::BasicStream* __os = __startWriteParams(" << opFormatTypeToString(p) << ");"; writeMarshalCode(C, outParams, p, TypeContextInParam); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { C << nl << "__os->writePendingObjects();"; } diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 3e6290ad7c8..c910332a141 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -870,7 +870,7 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream) } } writeMarshalUnmarshalParams(inParams, 0, false); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { _out << nl << "is__.readPendingObjects();"; } @@ -944,7 +944,7 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream) _out << nl << "IceInternal.BasicStream os__ = inS__.startWriteParams__(" << opFormatTypeToString(op) << ");"; writeMarshalUnmarshalParams(outParams, op, true); - if(op->returnsClasses()) + if(op->returnsClasses(false)) { _out << nl << "os__.writePendingObjects();"; } @@ -3608,7 +3608,7 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) _out << eb; } - if((!base || (base && !base->usesClasses())) && p->usesClasses()) + if((!base || (base && !base->usesClasses(false))) && p->usesClasses(false)) { _out << sp; emitGeneratedCodeAttribute(); @@ -4993,7 +4993,7 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) } } writeMarshalUnmarshalParams(outParams, op, false); - if(op->returnsClasses()) + if(op->returnsClasses(false)) { _out << nl << "is__.readPendingObjects();"; } @@ -5060,7 +5060,7 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) _out << nl << "IceInternal.BasicStream os__ = result__.startWriteParams__(" << opFormatTypeToString(op) << ");"; writeMarshalUnmarshalParams(inParams, 0, true); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { _out << nl << "os__.writePendingObjects();"; } @@ -5947,7 +5947,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) _out << sb; _out << nl << "IceInternal.BasicStream os__ = og__.startWriteParams(" << opFormatTypeToString(op) << ");"; writeMarshalUnmarshalParams(inParams, 0, true); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { _out << nl << "os__.writePendingObjects();"; } @@ -6049,7 +6049,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) } } writeMarshalUnmarshalParams(outParams, op, false); - if(op->returnsClasses()) + if(op->returnsClasses(false)) { _out << nl << "is__.readPendingObjects();"; } @@ -6573,7 +6573,7 @@ Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p) _out << sb; _out << nl << "IceInternal.BasicStream os__ = startWriteParams__(" << opFormatTypeToString(p) << ");"; writeMarshalUnmarshalParams(outParams, p, true); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { _out << nl << "os__.writePendingObjects();"; } diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index e5dc96633cc..5d8c60fad01 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -991,7 +991,7 @@ Slice::JavaVisitor::writeDispatchAndMarshalling(Output& out, const ClassDefPtr& } iter = 0; writeMarshalUnmarshalParams(out, package, inParams, 0, iter, false, true, true); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { out << nl << "__is.readPendingObjects();"; } @@ -1056,7 +1056,7 @@ Slice::JavaVisitor::writeDispatchAndMarshalling(Output& out, const ClassDefPtr& out << nl << "IceInternal.BasicStream __os = __inS.__startWriteParams(" << opFormatTypeToString(op) << ");"; writeMarshalUnmarshalParams(out, package, outParams, op, iter, true, optionalMapping, true); - if(op->returnsClasses()) + if(op->returnsClasses(false)) { out << nl << "__os.writePendingObjects();"; } @@ -1134,7 +1134,7 @@ Slice::JavaVisitor::writeDispatchAndMarshalling(Output& out, const ClassDefPtr& } } writeMarshalUnmarshalParams(out, package, inParams, 0, iter, false, true, true); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { out << nl << "__is.readPendingObjects();"; } @@ -3366,9 +3366,9 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) out << eb; } - if(p->usesClasses()) + if(p->usesClasses(false)) { - if(!base || (base && !base->usesClasses())) + if(!base || (base && !base->usesClasses(false))) { out << sp << nl << "public boolean" << nl << "__usesClasses()"; out << sb; @@ -4473,7 +4473,7 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) } } writeMarshalUnmarshalParams(out, package, pl, 0, iter, true, optionalMapping); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { out << nl << "__os.writePendingObjects();"; } @@ -4552,7 +4552,7 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) } } writeMarshalUnmarshalParams(out, package, pl, op, iter, false, true); - if(op->returnsClasses()) + if(op->returnsClasses(false)) { out << nl << "__is.readPendingObjects();"; } @@ -5485,7 +5485,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) out << sb; out << nl << "IceInternal.BasicStream __os = __og.startWriteParams(" << opFormatTypeToString(op) << ");"; writeMarshalUnmarshalParams(out, package, inParams, 0, iter, true, optionalMapping); - if(op->sendsClasses()) + if(op->sendsClasses(false)) { out << nl << "__os.writePendingObjects();"; } @@ -5532,7 +5532,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) { out << nl << "IceInternal.BasicStream __is = __og.startReadParams();"; writeMarshalUnmarshalParams(out, package, outParams, op, iter, false, true); - if(op->returnsClasses()) + if(op->returnsClasses(false)) { out << nl << "__is.readPendingObjects();"; } @@ -6602,7 +6602,7 @@ Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p) out << nl << "IceInternal.BasicStream __os = this.__startWriteParams(" << opFormatTypeToString(p) << ");"; writeMarshalUnmarshalParams(out, classPkg, outParams, p, iter, true, optionalMapping, false); - if(p->returnsClasses()) + if(p->returnsClasses(false)) { out << nl << "__os.writePendingObjects();"; } diff --git a/cpp/test/Ice/objects/AllTests.cpp b/cpp/test/Ice/objects/AllTests.cpp index 04b56d01a83..c4522b7a5e0 100644 --- a/cpp/test/Ice/objects/AllTests.cpp +++ b/cpp/test/Ice/objects/AllTests.cpp @@ -215,7 +215,7 @@ allTests(const Ice::CommunicatorPtr& communicator, bool collocated) initial->setI(h); cout << "ok" << endl; - cout << "testing sequences..." << flush; + cout << "testing sequences... " << flush; BaseSeq inS, outS, retS; retS = initial->opBaseSeq(inS, outS); diff --git a/cpp/test/Ice/objects/TestI.cpp b/cpp/test/Ice/objects/TestI.cpp index 246864b2019..12cd0e1915c 100644 --- a/cpp/test/Ice/objects/TestI.cpp +++ b/cpp/test/Ice/objects/TestI.cpp @@ -210,7 +210,6 @@ InitialI::setI(const IPtr&, const Ice::Current&) { } - BaseSeq InitialI::opBaseSeq(const BaseSeq& inSeq, BaseSeq& outSeq, const Ice::Current&) { diff --git a/cpp/test/Ice/optional/AllTests.cpp b/cpp/test/Ice/optional/AllTests.cpp index 22c0d3cdb3c..6719dca601e 100644 --- a/cpp/test/Ice/optional/AllTests.cpp +++ b/cpp/test/Ice/optional/AllTests.cpp @@ -548,6 +548,19 @@ allTests(const Ice::CommunicatorPtr& communicator, bool collocated) in->endEncapsulation(); test(obj && dynamic_cast<TestObjectReader*>(obj.get())); factory->setEnabled(false); + + // + // Use the 1.0 encoding with operations whose only class parameters are optional. + // + IceUtil::Optional<OneOptionalPtr> oo(new OneOptional(53)); + initial->sendOptionalClass(true, oo); + initial->ice_encodingVersion(Ice::Encoding_1_0)->sendOptionalClass(true, oo); + + initial->returnOptionalClass(true, oo); + test(oo); + initial->ice_encodingVersion(Ice::Encoding_1_0)->returnOptionalClass(true, oo); + test(!oo); + cout << "ok" << endl; cout << "testing marshalling of large containers with fixed size elements..." << flush; @@ -1092,6 +1105,21 @@ allTests(const Ice::CommunicatorPtr& communicator, bool collocated) test(ex.b == string("test")); test((*ex.o)->a = 53); } + + try + { + // + // Use the 1.0 encoding with an exception whose only class members are optional. + // + initial->ice_encodingVersion(Ice::Encoding_1_0)-> + opOptionalException(30, string("test"), OneOptionalPtr(new OneOptional(53))); + } + catch(const OptionalException& ex) + { + test(!ex.a); + test(!ex.b); + test(!ex.o); + } } cout << "ok" << endl; diff --git a/cpp/test/Ice/optional/Test.ice b/cpp/test/Ice/optional/Test.ice index baea70cb293..d693ae649a2 100644 --- a/cpp/test/Ice/optional/Test.ice +++ b/cpp/test/Ice/optional/Test.ice @@ -138,6 +138,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -253,6 +254,10 @@ class Initial void opClassAndUnknownOptional(A p); + void sendOptionalClass(bool req, optional(1) OneOptional o); + + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); diff --git a/cpp/test/Ice/optional/TestI.cpp b/cpp/test/Ice/optional/TestI.cpp index b40ee6cf67d..f26194e934a 100644 --- a/cpp/test/Ice/optional/TestI.cpp +++ b/cpp/test/Ice/optional/TestI.cpp @@ -344,6 +344,17 @@ InitialI::opClassAndUnknownOptional(const APtr& a, const Ice::Current&) { } +void +InitialI::sendOptionalClass(bool, const Optional<OneOptionalPtr>&, const Ice::Current&) +{ +} + +void +InitialI::returnOptionalClass(bool, Optional<OneOptionalPtr>& o, const Ice::Current&) +{ + o = new OneOptional(53); +} + bool InitialI::supportsRequiredParams(const Ice::Current&) { diff --git a/cpp/test/Ice/optional/TestI.h b/cpp/test/Ice/optional/TestI.h index 2114639de63..aab81137006 100644 --- a/cpp/test/Ice/optional/TestI.h +++ b/cpp/test/Ice/optional/TestI.h @@ -172,6 +172,10 @@ public: virtual void opClassAndUnknownOptional(const Test::APtr&, const Ice::Current&); + virtual void sendOptionalClass(bool, const IceUtil::Optional<Test::OneOptionalPtr>&, const Ice::Current&); + + virtual void returnOptionalClass(bool, IceUtil::Optional<Test::OneOptionalPtr>&, const Ice::Current&); + virtual bool supportsRequiredParams(const Ice::Current&); virtual bool supportsJavaSerializable(const Ice::Current&); diff --git a/java/test/Ice/optional/AMDInitialI.java b/java/test/Ice/optional/AMDInitialI.java index 69b7a0b3dae..9a67487788c 100644 --- a/java/test/Ice/optional/AMDInitialI.java +++ b/java/test/Ice/optional/AMDInitialI.java @@ -485,6 +485,19 @@ public final class AMDInitialI extends Initial } public void + sendOptionalClass_async(AMD_Initial_sendOptionalClass cb, boolean req, Ice.Optional<OneOptional> o, + Ice.Current current) + { + cb.ice_response(); + } + + public void + returnOptionalClass_async(AMD_Initial_returnOptionalClass cb, boolean req, Ice.Current current) + { + cb.ice_response(new Ice.Optional<OneOptional>(new OneOptional(53))); + } + + public void supportsRequiredParams_async(AMD_Initial_supportsRequiredParams cb, Ice.Current current) { cb.ice_response(true); diff --git a/java/test/Ice/optional/AllTests.java b/java/test/Ice/optional/AllTests.java index 95e2a815d43..4782a02b03f 100644 --- a/java/test/Ice/optional/AllTests.java +++ b/java/test/Ice/optional/AllTests.java @@ -383,6 +383,19 @@ public class AllTests test(cb.obj != null && cb.obj instanceof TestObjectReader); factory.setEnabled(false); + // + // Use the 1.0 encoding with operations whose only class parameters are optional. + // + Ice.Optional<OneOptional> oo = new Ice.Optional<OneOptional>(new OneOptional(53)); + initial.sendOptionalClass(true, oo); + InitialPrx initial2 = (InitialPrx)initial.ice_encodingVersion(Ice.Util.Encoding_1_0); + initial2.sendOptionalClass(true, oo); + + initial.returnOptionalClass(true, oo); + test(oo.isSet()); + initial2.returnOptionalClass(true, oo); + test(!oo.isSet()); + out.println("ok"); out.print("testing marshaling of large containers with fixed size elements... "); @@ -2068,6 +2081,23 @@ public class AllTests try { + // + // Use the 1.0 encoding with an exception whose only class members are optional. + // + Ice.IntOptional a = new Ice.IntOptional(30); + Ice.Optional<String> b = new Ice.Optional<String>("test"); + Ice.Optional<OneOptional> o = new Ice.Optional<OneOptional>(new OneOptional(53)); + initial2.opOptionalException(a, b, o); + } + catch(OptionalException ex) + { + test(!ex.hasA()); + test(!ex.hasB()); + test(!ex.hasO()); + } + + try + { Ice.IntOptional a = new Ice.IntOptional(); Ice.Optional<String> b = new Ice.Optional<String>(); Ice.Optional<OneOptional> o = new Ice.Optional<OneOptional>(); diff --git a/java/test/Ice/optional/InitialI.java b/java/test/Ice/optional/InitialI.java index e07bb4a1a2c..d16c997c82d 100644 --- a/java/test/Ice/optional/InitialI.java +++ b/java/test/Ice/optional/InitialI.java @@ -534,6 +534,17 @@ public final class InitialI extends Initial { } + public void + sendOptionalClass(boolean req, Ice.Optional<OneOptional> o, Ice.Current current) + { + } + + public void + returnOptionalClass(boolean req, Ice.Optional<OneOptional> o, Ice.Current current) + { + o.set(new OneOptional(53)); + } + public boolean supportsRequiredParams(Ice.Current current) { diff --git a/java/test/Ice/optional/Test.ice b/java/test/Ice/optional/Test.ice index 3fbe93fbfff..b506ae5303e 100644 --- a/java/test/Ice/optional/Test.ice +++ b/java/test/Ice/optional/Test.ice @@ -137,6 +137,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -282,6 +283,12 @@ class Initial void opClassAndUnknownOptional(A p); + ["java:optional"] + void sendOptionalClass(bool req, optional(1) OneOptional o); + + ["java:optional"] + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); diff --git a/java/test/Ice/optional/TestAMD.ice b/java/test/Ice/optional/TestAMD.ice index bfdfd0e175e..acb84d0dc02 100644 --- a/java/test/Ice/optional/TestAMD.ice +++ b/java/test/Ice/optional/TestAMD.ice @@ -137,6 +137,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -282,6 +283,12 @@ class Initial void opClassAndUnknownOptional(A p); + ["java:optional"] + void sendOptionalClass(bool req, optional(1) OneOptional o); + + ["java:optional"] + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); diff --git a/php/src/IcePHP/Operation.cpp b/php/src/IcePHP/Operation.cpp index 82e5bc7a6d8..4dee27a4ae2 100644 --- a/php/src/IcePHP/Operation.cpp +++ b/php/src/IcePHP/Operation.cpp @@ -80,13 +80,15 @@ public: ParamInfoList optionalOutParams; ParamInfoPtr returnType; ExceptionInfoList exceptions; + bool sendsClasses; + bool returnsClasses; int numParams; private: zend_internal_function* _zendFunction; - static void convertParams(zval*, ParamInfoList& TSRMLS_DC); + static void convertParams(zval*, ParamInfoList&, bool& TSRMLS_DC); static ParamInfoPtr convertParam(zval*, int TSRMLS_DC); static void getArgInfo(zend_arg_info&, const ParamInfoPtr&, bool); }; @@ -220,17 +222,19 @@ IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::Operati // // inParams // + sendsClasses = false; if(in) { - convertParams(in, inParams TSRMLS_CC); + convertParams(in, inParams, sendsClasses TSRMLS_CC); } // // outParams // + returnsClasses = false; if(out) { - convertParams(out, outParams TSRMLS_CC); + convertParams(out, outParams, returnsClasses TSRMLS_CC); } // @@ -239,6 +243,10 @@ IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::Operati if(ret) { returnType = convertParam(ret, 0 TSRMLS_CC); + if(!returnsClasses) + { + returnsClasses = returnType->type->usesClasses(); + } } numParams = static_cast<int>(inParams.size() + outParams.size()); @@ -355,7 +363,7 @@ IcePHP::OperationI::function() } void -IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params TSRMLS_DC) +IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params, bool& usesClasses TSRMLS_DC) { assert(Z_TYPE_P(p) == IS_ARRAY); HashTable* arr = Z_ARRVAL_P(p); @@ -366,7 +374,12 @@ IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params TSRMLS_DC) while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - params.push_back(convertParam(*val, i TSRMLS_CC)); + ParamInfoPtr param = convertParam(*val, i TSRMLS_CC); + params.push_back(param); + if(!param->optional && !usesClasses) + { + usesClasses = param->type->usesClasses(); + } zend_hash_move_forward_ex(arr, &pos); ++i; } @@ -521,6 +534,11 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::ByteSeq& byt } } + if(_op->sendsClasses) + { + os->writePendingObjects(); + } + os->endEncapsulation(); os->finished(bytes); } @@ -596,7 +614,7 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, ParamInfoPtr info = *p; ResultCallbackPtr cb = new ResultCallback; - if(info->tag == _op->returnType->tag) + if(_op->returnType && info->tag == _op->returnType->tag) { retCallback = cb; } @@ -615,6 +633,11 @@ IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, } } + if(_op->returnsClasses) + { + is->readPendingObjects(); + } + is->endEncapsulation(); util.update(TSRMLS_C); diff --git a/php/src/IcePHP/Types.cpp b/php/src/IcePHP/Types.cpp index 323bd1d3e90..976073c3217 100644 --- a/php/src/IcePHP/Types.cpp +++ b/php/src/IcePHP/Types.cpp @@ -583,6 +583,12 @@ IcePHP::TypeInfo::TypeInfo() { } +bool +IcePHP::TypeInfo::usesClasses() const +{ + return false; +} + void IcePHP::TypeInfo::unmarshaled(zval*, zval*, void* TSRMLS_DC) { @@ -1305,6 +1311,20 @@ IcePHP::StructInfo::optionalFormat() const return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IcePHP::StructInfo::usesClasses() const +{ + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + if((*p)->type->usesClasses()) + { + return true; + } + } + + return false; +} + void IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC) { @@ -1462,6 +1482,12 @@ IcePHP::SequenceInfo::optionalFormat() const return elementType->variableLength() ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IcePHP::SequenceInfo::usesClasses() const +{ + return elementType->usesClasses(); +} + void IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC) { @@ -2015,6 +2041,12 @@ IcePHP::DictionaryInfo::optionalFormat() const return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IcePHP::DictionaryInfo::usesClasses() const +{ + return valueType->usesClasses(); +} + void IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional TSRMLS_DC) { @@ -2436,6 +2468,12 @@ IcePHP::ClassInfo::optionalFormat() const return Ice::OptionalFormatSize; } +bool +IcePHP::ClassInfo::usesClasses() const +{ + return true; +} + void IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool TSRMLS_DC) { @@ -3284,6 +3322,12 @@ IcePHP::ExceptionReader::read(const Ice::InputStreamPtr& is) const const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); } +bool +IcePHP::ExceptionReader::usesClasses() const +{ + return _info->usesClasses; +} + string IcePHP::ExceptionReader::ice_name() const { @@ -3633,6 +3677,19 @@ ZEND_FUNCTION(IcePHP_defineException) convertDataMembers(members, ex->members, ex->optionalMembers, true TSRMLS_CC); } + ex->usesClasses = false; + + // + // Only examine the required members to see if any use classes. + // + for(DataMemberList::iterator p = ex->members.begin(); p != ex->members.end(); ++p) + { + if(!ex->usesClasses) + { + ex->usesClasses = (*p)->type->usesClasses(); + } + } + ex->zce = nameToClass(ex->name TSRMLS_CC); assert(!getExceptionInfo(ex->id TSRMLS_CC)); diff --git a/php/src/IcePHP/Types.h b/php/src/IcePHP/Types.h index d3d4825e3eb..f682d0f3cf4 100644 --- a/php/src/IcePHP/Types.h +++ b/php/src/IcePHP/Types.h @@ -117,6 +117,8 @@ public: virtual int wireSize() const = 0; virtual Ice::OptionalFormat optionalFormat() const = 0; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC); // Default implementation is assert(false). virtual void destroy(); @@ -239,6 +241,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); @@ -276,6 +280,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); @@ -314,6 +320,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); @@ -385,6 +393,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool TSRMLS_DC); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, zval*, void*, bool TSRMLS_DC); @@ -468,6 +478,7 @@ public: ExceptionInfoPtr base; DataMemberList members; DataMemberList optionalMembers; + bool usesClasses; zend_class_entry* zce; }; @@ -550,6 +561,7 @@ public: ~ExceptionReader() throw(); virtual void read(const Ice::InputStreamPtr&) const; + virtual bool usesClasses() const; virtual std::string ice_name() const; virtual ExceptionReader* ice_clone() const; diff --git a/php/test/Ice/objects/Client.php b/php/test/Ice/objects/Client.php index 5af9c43ce11..82961397cae 100644 --- a/php/test/Ice/objects/Client.php +++ b/php/test/Ice/objects/Client.php @@ -354,6 +354,15 @@ function allTests($communicator) $initial->setI($h); echo "ok\n"; + echo "testing sequences... "; + flush(); + $outS = null; + $initial->opBaseSeq(array(), $outS); + + $retS = $initial->opBaseSeq(array(new Test_Base()), $outS); + test(count($retS) == 1 && count($outS) == 1); + echo "ok\n"; + echo "testing UnexpectedObjectException... "; flush(); $ref = "uoet:default -p 12010"; diff --git a/php/test/Ice/objects/Test.ice b/php/test/Ice/objects/Test.ice index 1758598a2ca..5768ef51606 100644 --- a/php/test/Ice/objects/Test.ice +++ b/php/test/Ice/objects/Test.ice @@ -12,6 +12,22 @@ module Test { +struct S +{ + string str; +}; + +class Base +{ + S theS; + string str; +}; + +class AbstractBase extends Base +{ + void op(); +}; + class B; class C; @@ -75,10 +91,11 @@ class H implements I { }; +sequence<Base> BaseSeq; + class Initial { void shutdown(); - B getB1(); B getB2(); C getC(); @@ -93,6 +110,8 @@ class Initial I getH(); void setI(I theI); + + BaseSeq opBaseSeq(BaseSeq inSeq, out BaseSeq outSeq); }; class Empty diff --git a/php/test/Ice/optional/Client.php b/php/test/Ice/optional/Client.php index f3f8b469da4..cdd0a032d5e 100644 --- a/php/test/Ice/optional/Client.php +++ b/php/test/Ice/optional/Client.php @@ -32,6 +32,7 @@ function test($b) function allTests($communicator) { global $NS; + global $Ice_Encoding_1_0; $enum = $NS ? constant("Test\\MyEnum::MyEnumMember") : constant("Test_MyEnum::MyEnumMember"); @@ -325,6 +326,18 @@ function allTests($communicator) test($mo9->bos == Ice_Unset); + // + // Use the 1.0 encoding with operations whose only class parameters are optional. + // + $oo = new $oocls(53); + $initial->sendOptionalClass(true, $oo); + $initial->ice_encodingVersion($Ice_Encoding_1_0)->sendOptionalClass(true, $oo); + + $initial->returnOptionalClass(true, $oo); + test($oo != Ice_Unset); + $initial->ice_encodingVersion($Ice_Encoding_1_0)->returnOptionalClass(true, $oo); + test($oo == Ice_Unset); + echo "ok\n"; echo "testing marshaling of large containers with fixed size elements... "; @@ -670,6 +683,20 @@ function allTests($communicator) try { + // + // Use the 1.0 encoding with an exception whose only class members are optional. + // + $initial->ice_encodingVersion($Ice_Encoding_1_0)->opOptionalException(30, "test", new $oocls(53)); + } + catch(Exception $ex) + { + test($ex->a == Ice_Unset); + test($ex->b == Ice_Unset); + test($ex->o == Ice_Unset); + } + + try + { $initial->opDerivedException(Ice_Unset, Ice_Unset, Ice_Unset); } catch(Exception $ex) diff --git a/php/test/Ice/optional/Test.ice b/php/test/Ice/optional/Test.ice index 7f0342b8df4..8cc213df42c 100644 --- a/php/test/Ice/optional/Test.ice +++ b/php/test/Ice/optional/Test.ice @@ -136,6 +136,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -230,12 +231,18 @@ class Initial optional(1) VarStructSeq opVarStructSeq(optional(2) VarStructSeq p1, out optional(3) VarStructSeq p3); + optional(1) Serializable opSerializable(optional(2) Serializable p1, out optional(3) Serializable p3); + optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, out optional(3) StringIntDict p3); void opClassAndUnknownOptional(A p); + void sendOptionalClass(bool req, optional(1) OneOptional o); + + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp index 0cbbee3b77a..ea9bffcc263 100644 --- a/py/modules/IcePy/Operation.cpp +++ b/py/modules/IcePy/Operation.cpp @@ -77,13 +77,15 @@ public: ParamInfoPtr returnType; ExceptionInfoList exceptions; string dispatchName; + bool sendsClasses; + bool returnsClasses; bool pseudoOp; private: string _deprecateMessage; - static void convertParams(PyObject*, ParamInfoList&, int); + static void convertParams(PyObject*, ParamInfoList&, int, bool&); static ParamInfoPtr convertParam(PyObject*, int); }; typedef IceUtil::Handle<Operation> OperationPtr; @@ -1074,20 +1076,26 @@ IcePy::Operation::Operation(const char* n, PyObject* m, PyObject* sm, int amdFla // // returnType // + returnsClasses = false; if(ret != Py_None) { returnType = convertParam(ret, 0); + if(!returnType->optional) + { + returnsClasses = returnType->type->usesClasses(); + } } // // inParams // - convertParams(in, inParams, 0); + sendsClasses = false; + convertParams(in, inParams, 0, sendsClasses); // // outParams // - convertParams(out, outParams, returnType ? 1 : 0); + convertParams(out, outParams, returnType ? 1 : 0, returnsClasses); class SortFn { @@ -1153,7 +1161,7 @@ IcePy::Operation::deprecate(const string& msg) } void -IcePy::Operation::convertParams(PyObject* p, ParamInfoList& params, int posOffset) +IcePy::Operation::convertParams(PyObject* p, ParamInfoList& params, int posOffset, bool& usesClasses) { int sz = static_cast<int>(PyTuple_GET_SIZE(p)); for(int i = 0; i < sz; ++i) @@ -1161,6 +1169,10 @@ IcePy::Operation::convertParams(PyObject* p, ParamInfoList& params, int posOffse PyObject* item = PyTuple_GET_ITEM(p, i); ParamInfoPtr param = convertParam(item, i + posOffset); params.push_back(param); + if(!param->optional && !usesClasses) + { + usesClasses = param->type->usesClasses(); + } } } @@ -1555,6 +1567,11 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, vect } } + if(_op->sendsClasses) + { + os->writePendingObjects(); + } + os->endEncapsulation(); os->finished(bytes); } @@ -1643,6 +1660,11 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: } } + if(_op->returnsClasses) + { + is->readPendingObjects(); + } + is->endEncapsulation(); util.update(); @@ -3255,6 +3277,11 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con } } + if(_op->sendsClasses) + { + is->readPendingObjects(); + } + is->endEncapsulation(); util.update(); @@ -3458,6 +3485,11 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin } } + if(_op->returnsClasses) + { + os->writePendingObjects(); + } + os->endEncapsulation(); Ice::ByteSeq bytes; diff --git a/py/modules/IcePy/Types.cpp b/py/modules/IcePy/Types.cpp index 5cda768dd1c..84efd5d9081 100644 --- a/py/modules/IcePy/Types.cpp +++ b/py/modules/IcePy/Types.cpp @@ -503,6 +503,12 @@ IcePy::TypeInfo::TypeInfo() { } +bool +IcePy::TypeInfo::usesClasses() const +{ + return false; +} + void IcePy::TypeInfo::unmarshaled(PyObject*, PyObject*, void*) { @@ -1161,6 +1167,20 @@ IcePy::StructInfo::optionalFormat() const return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IcePy::StructInfo::usesClasses() const +{ + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + if((*p)->type->usesClasses()) + { + return true; + } + } + + return false; +} + void IcePy::StructInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, const Ice::StringSeq*) @@ -1325,6 +1345,12 @@ IcePy::SequenceInfo::optionalFormat() const return elementType->variableLength() ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IcePy::SequenceInfo::usesClasses() const +{ + return elementType->usesClasses(); +} + void IcePy::SequenceInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, const Ice::StringSeq* metaData) @@ -2219,6 +2245,12 @@ IcePy::CustomInfo::optionalFormat() const return Ice::OptionalFormatVSize; } +bool +IcePy::CustomInfo::usesClasses() const +{ + return false; +} + void IcePy::CustomInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool, const Ice::StringSeq* metaData) @@ -2385,6 +2417,12 @@ IcePy::DictionaryInfo::optionalFormat() const return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IcePy::DictionaryInfo::usesClasses() const +{ + return valueType->usesClasses(); +} + void IcePy::DictionaryInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, const Ice::StringSeq*) @@ -2647,6 +2685,12 @@ IcePy::ClassInfo::optionalFormat() const return Ice::OptionalFormatSize; } +bool +IcePy::ClassInfo::usesClasses() const +{ + return true; +} + void IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool, const Ice::StringSeq*) @@ -3467,6 +3511,12 @@ IcePy::ExceptionWriter::write(const Ice::OutputStreamPtr& os) const _info->marshal(_ex.get(), os, const_cast<ObjectMap*>(&_objects)); } +bool +IcePy::ExceptionWriter::usesClasses() const +{ + return _info->usesClasses; +} + string IcePy::ExceptionWriter::ice_name() const { @@ -3512,6 +3562,12 @@ IcePy::ExceptionReader::read(const Ice::InputStreamPtr& is) const const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); } +bool +IcePy::ExceptionReader::usesClasses() const +{ + return _info->usesClasses; +} + string IcePy::ExceptionReader::ice_name() const { @@ -4048,6 +4104,19 @@ IcePy_defineException(PyObject*, PyObject* args) convertDataMembers(members, info->members, info->optionalMembers, true); + info->usesClasses = false; + + // + // Only examine the required members to see if any use classes. + // + for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p) + { + if(!info->usesClasses) + { + info->usesClasses = (*p)->type->usesClasses(); + } + } + info->pythonType = type; Py_INCREF(type); diff --git a/py/modules/IcePy/Types.h b/py/modules/IcePy/Types.h index cf969fbb1f0..fe20b242976 100644 --- a/py/modules/IcePy/Types.h +++ b/py/modules/IcePy/Types.h @@ -107,6 +107,8 @@ public: virtual int wireSize() const = 0; virtual Ice::OptionalFormat optionalFormat() const = 0; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void unmarshaled(PyObject*, PyObject*, void*); // Default implementation is assert(false). virtual void destroy(); @@ -232,6 +234,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); @@ -268,6 +272,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); @@ -326,6 +332,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); @@ -356,6 +364,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); @@ -404,6 +414,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); @@ -477,6 +489,7 @@ public: ExceptionInfoPtr base; DataMemberList members; DataMemberList optionalMembers; + bool usesClasses; PyObjectHandle pythonType; private: @@ -545,6 +558,7 @@ public: ~ExceptionWriter() throw(); virtual void write(const Ice::OutputStreamPtr&) const; + virtual bool usesClasses() const; virtual std::string ice_name() const; virtual Ice::UserException* ice_clone() const; @@ -568,6 +582,7 @@ public: ~ExceptionReader() throw(); virtual void read(const Ice::InputStreamPtr&) const; + virtual bool usesClasses() const; virtual std::string ice_name() const; virtual Ice::UserException* ice_clone() const; diff --git a/py/test/Ice/objects/AllTests.py b/py/test/Ice/objects/AllTests.py index 97305076274..7316549b80b 100644 --- a/py/test/Ice/objects/AllTests.py +++ b/py/test/Ice/objects/AllTests.py @@ -184,6 +184,14 @@ def allTests(communicator, collocated): test(d.theB.theC.postUnmarshalInvoked()) print("ok") + sys.stdout.write("testing sequences... ") + sys.stdout.flush() + initial.opBaseSeq([]) + + retS, outS = initial.opBaseSeq([Test.Base()]) + test(len(retS) == 1 and len(outS) == 1) + print("ok") + if not collocated: sys.stdout.write("testing UnexpectedObjectException... ") sys.stdout.flush() diff --git a/py/test/Ice/objects/Test.ice b/py/test/Ice/objects/Test.ice index 120426ee074..c83b928c0c2 100644 --- a/py/test/Ice/objects/Test.ice +++ b/py/test/Ice/objects/Test.ice @@ -12,6 +12,22 @@ module Test { +struct S +{ + string str; +}; + +class Base +{ + S theS; + string str; +}; + +class AbstractBase extends Base +{ + void op(); +}; + class B; class C; @@ -75,6 +91,8 @@ class H implements I { }; +sequence<Base> BaseSeq; + class Initial { void shutdown(); @@ -92,6 +110,8 @@ class Initial I getH(); void setI(I theI); + + BaseSeq opBaseSeq(BaseSeq inSeq, out BaseSeq outSeq); }; }; diff --git a/py/test/Ice/objects/TestI.py b/py/test/Ice/objects/TestI.py index 7f1f2791c2f..7e8b2931e75 100644 --- a/py/test/Ice/objects/TestI.py +++ b/py/test/Ice/objects/TestI.py @@ -151,6 +151,9 @@ class InitialI(Test.Initial): def setI(self, i, current=None): pass + def opBaseSeq(self, inSeq, current=None): + return (inSeq, inSeq) + class UnexpectedObjectExceptionTestI(Test.UnexpectedObjectExceptionTest): def op(self, current=None): return Test.AlsoEmpty() diff --git a/py/test/Ice/optional/AllTests.py b/py/test/Ice/optional/AllTests.py index b5e25d02e36..c762a1188fb 100644 --- a/py/test/Ice/optional/AllTests.py +++ b/py/test/Ice/optional/AllTests.py @@ -306,6 +306,17 @@ def allTests(communicator): test(mo9.bos == Ice.Unset) + # + # Use the 1.0 encoding with operations whose only class parameters are optional. + # + initial.sendOptionalClass(True, Test.OneOptional(53)) + initial.ice_encodingVersion(Ice.Encoding_1_0).sendOptionalClass(True, Test.OneOptional(53)) + + r = initial.returnOptionalClass(True) + test(r != Ice.Unset) + r = initial.ice_encodingVersion(Ice.Encoding_1_0).returnOptionalClass(True) + test(r == Ice.Unset) + print("ok") sys.stdout.write("testing marshaling of large containers with fixed size elements... ") @@ -690,6 +701,16 @@ def allTests(communicator): test(ex.o.a == 53) try: + # + # Use the 1.0 encoding with an exception whose only class members are optional. + # + initial.ice_encodingVersion(Ice.Encoding_1_0).opOptionalException(30, "test", Test.OneOptional(53)) + except Test.OptionalException as ex: + test(ex.a == Ice.Unset) + test(ex.b == Ice.Unset) + test(ex.o == Ice.Unset) + + try: initial.opDerivedException(Ice.Unset, Ice.Unset, Ice.Unset) except Test.DerivedException as ex: test(ex.a == Ice.Unset) diff --git a/py/test/Ice/optional/Server.py b/py/test/Ice/optional/Server.py index 87fe29db70c..a3225fb8552 100755 --- a/py/test/Ice/optional/Server.py +++ b/py/test/Ice/optional/Server.py @@ -23,10 +23,10 @@ class InitialI(Test.Initial): return o def opOptionalException(self, a, b, o, current=None): - raise Test.OptionalException(a, b, o) + raise Test.OptionalException(False, a, b, o) def opDerivedException(self, a, b, o, current=None): - raise Test.DerivedException(a, b, o, b, o) + raise Test.DerivedException(False, a, b, o, b, o) def opRequiredException(self, a, b, o, current=None): e = Test.RequiredException() @@ -132,6 +132,12 @@ class InitialI(Test.Initial): def opClassAndUnknownOptional(self, p, current=None): pass + def sendOptionalClass(self, req, o, current=None): + pass + + def returnOptionalClass(self, req, current=None): + return Test.OneOptional(5) + def supportsRequiredParams(self, current=None): return False diff --git a/py/test/Ice/optional/ServerAMD.py b/py/test/Ice/optional/ServerAMD.py index 8d89cd6f533..11306afb888 100755 --- a/py/test/Ice/optional/ServerAMD.py +++ b/py/test/Ice/optional/ServerAMD.py @@ -24,10 +24,10 @@ class InitialI(Test.Initial): cb.ice_response(o) def opOptionalException_async(self, cb, a, b, o, current=None): - cb.ice_exception(Test.OptionalException(a, b, o)) + cb.ice_exception(Test.OptionalException(False, a, b, o)) def opDerivedException_async(self, cb, a, b, o, current=None): - cb.ice_exception(Test.DerivedException(a, b, o, b, o)) + cb.ice_exception(Test.DerivedException(False, a, b, o, b, o)) def opRequiredException_async(self, cb, a, b, o, current=None): e = Test.RequiredException() @@ -133,6 +133,12 @@ class InitialI(Test.Initial): def opClassAndUnknownOptional_async(self, cb, p, current=None): cb.ice_response() + def sendOptionalClass_async(self, cb, req, o, current=None): + cb.ice_response() + + def returnOptionalClass_async(self, cb, req, current=None): + cb.ice_response(Test.OneOptional(5)) + def supportsRequiredParams_async(self, cb, current=None): cb.ice_response(False) diff --git a/py/test/Ice/optional/Test.ice b/py/test/Ice/optional/Test.ice index 9783959248c..3d4bb6ac635 100644 --- a/py/test/Ice/optional/Test.ice +++ b/py/test/Ice/optional/Test.ice @@ -136,6 +136,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -238,6 +239,10 @@ class Initial void opClassAndUnknownOptional(A p); + void sendOptionalClass(bool req, optional(1) OneOptional o); + + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); diff --git a/py/test/Ice/optional/TestAMD.ice b/py/test/Ice/optional/TestAMD.ice index 005d58d4ce3..bbd6251eed9 100644 --- a/py/test/Ice/optional/TestAMD.ice +++ b/py/test/Ice/optional/TestAMD.ice @@ -136,6 +136,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -238,6 +239,10 @@ class Initial void opClassAndUnknownOptional(A p); + void sendOptionalClass(bool req, optional(1) OneOptional o); + + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); diff --git a/rb/src/IceRuby/Operation.cpp b/rb/src/IceRuby/Operation.cpp index 6cebeea2f55..f4e16f7c683 100644 --- a/rb/src/IceRuby/Operation.cpp +++ b/rb/src/IceRuby/Operation.cpp @@ -65,9 +65,11 @@ private: ParamInfoPtr _returnType; ExceptionInfoList _exceptions; string _dispatchName; + bool _sendsClasses; + bool _returnsClasses; string _deprecateMessage; - void convertParams(VALUE, ParamInfoList&, int); + void convertParams(VALUE, ParamInfoList&, int, bool&); ParamInfoPtr convertParam(VALUE, int); void prepareRequest(const Ice::ObjectPrx&, VALUE, vector<Ice::Byte>&); VALUE unmarshalResults(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); @@ -220,20 +222,26 @@ IceRuby::OperationI::OperationI(VALUE name, VALUE mode, VALUE sendMode, VALUE am // // returnType // + _returnsClasses = false; if(!NIL_P(returnType)) { _returnType = convertParam(returnType, 0); + if(!_returnType->optional) + { + _returnsClasses = _returnType->type->usesClasses(); + } } // // inParams // - convertParams(inParams, _inParams, 0); + _sendsClasses = false; + convertParams(inParams, _inParams, 0, _sendsClasses); // // outParams // - convertParams(outParams, _outParams, NIL_P(returnType) ? 0 : 1); + convertParams(outParams, _outParams, NIL_P(returnType) ? 0 : 1, _returnsClasses); class SortFn { @@ -368,7 +376,7 @@ IceRuby::OperationI::deprecate(const string& msg) } void -IceRuby::OperationI::convertParams(VALUE v, ParamInfoList& params, int posOffset) +IceRuby::OperationI::convertParams(VALUE v, ParamInfoList& params, int posOffset, bool& usesClasses) { assert(TYPE(v) == T_ARRAY); @@ -376,6 +384,10 @@ IceRuby::OperationI::convertParams(VALUE v, ParamInfoList& params, int posOffset { ParamInfoPtr param = convertParam(RARRAY_PTR(v)[i], i + posOffset); params.push_back(param); + if(!param->optional && !usesClasses) + { + usesClasses = param->type->usesClasses(); + } } } @@ -457,6 +469,11 @@ IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, vec } } + if(_sendsClasses) + { + os->writePendingObjects(); + } + os->endEncapsulation(); os->finished(bytes); } @@ -532,6 +549,11 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: } } + if(_returnsClasses) + { + is->readPendingObjects(); + } + is->endEncapsulation(); util.update(); diff --git a/rb/src/IceRuby/Types.cpp b/rb/src/IceRuby/Types.cpp index da4ec6df9f0..e8c7a21c3db 100644 --- a/rb/src/IceRuby/Types.cpp +++ b/rb/src/IceRuby/Types.cpp @@ -390,6 +390,12 @@ IceRuby::TypeInfo::TypeInfo() { } +bool +IceRuby::TypeInfo::usesClasses() const +{ + return false; +} + void IceRuby::TypeInfo::unmarshaled(VALUE, VALUE, void*) { @@ -939,6 +945,20 @@ IceRuby::StructInfo::optionalFormat() const return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IceRuby::StructInfo::usesClasses() const +{ + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + if((*p)->type->usesClasses()) + { + return true; + } + } + + return false; +} + void IceRuby::StructInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) { @@ -1092,6 +1112,12 @@ IceRuby::SequenceInfo::optionalFormat() const return elementType->variableLength() ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IceRuby::SequenceInfo::usesClasses() const +{ + return elementType->usesClasses(); +} + void IceRuby::SequenceInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) { @@ -1621,6 +1647,12 @@ IceRuby::DictionaryInfo::optionalFormat() const return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; } +bool +IceRuby::DictionaryInfo::usesClasses() const +{ + return valueType->usesClasses(); +} + namespace { struct DictionaryMarshalIterator : public IceRuby::HashIterator @@ -1956,6 +1988,12 @@ IceRuby::ClassInfo::optionalFormat() const return Ice::OptionalFormatSize; } +bool +IceRuby::ClassInfo::usesClasses() const +{ + return true; +} + void IceRuby::ClassInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool) { @@ -2683,6 +2721,12 @@ IceRuby::ExceptionReader::read(const Ice::InputStreamPtr& is) const const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); } +bool +IceRuby::ExceptionReader::usesClasses() const +{ + return _info->usesClasses; +} + string IceRuby::ExceptionReader::ice_name() const { @@ -2847,6 +2891,19 @@ IceRuby_defineException(VALUE /*self*/, VALUE id, VALUE type, VALUE preserve, VA convertDataMembers(members, info->members, info->optionalMembers, true); + info->usesClasses = false; + + // + // Only examine the required members to see if any use classes. + // + for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p) + { + if(!info->usesClasses) + { + info->usesClasses = (*p)->type->usesClasses(); + } + } + info->rubyClass = type; addExceptionInfo(info->id, info); diff --git a/rb/src/IceRuby/Types.h b/rb/src/IceRuby/Types.h index fa9c9a73ee6..9acf1e15d4d 100644 --- a/rb/src/IceRuby/Types.h +++ b/rb/src/IceRuby/Types.h @@ -109,6 +109,8 @@ public: virtual int wireSize() const = 0; virtual Ice::OptionalFormat optionalFormat() const = 0; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void unmarshaled(VALUE, VALUE, void*); // Default implementation is assert(false). virtual void destroy(); @@ -234,6 +236,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); @@ -269,6 +273,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void unmarshaled(VALUE, VALUE, void*); @@ -305,6 +311,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); void marshalElement(VALUE, VALUE, const Ice::OutputStreamPtr&, ObjectMap*); @@ -354,6 +362,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; + virtual bool usesClasses() const; // Default implementation returns false. + virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); @@ -429,6 +439,7 @@ public: ExceptionInfoPtr base; DataMemberList members; DataMemberList optionalMembers; + bool usesClasses; VALUE rubyClass; }; @@ -491,6 +502,7 @@ public: ~ExceptionReader() throw(); virtual void read(const Ice::InputStreamPtr&) const; + virtual bool usesClasses() const; virtual std::string ice_name() const; virtual Ice::UserException* ice_clone() const; diff --git a/rb/test/Ice/objects/AllTests.rb b/rb/test/Ice/objects/AllTests.rb index 767c70e036b..6994e62bf5c 100644 --- a/rb/test/Ice/objects/AllTests.rb +++ b/rb/test/Ice/objects/AllTests.rb @@ -200,6 +200,14 @@ def allTests(communicator) initial.setI(h) puts "ok" + print "testing sequences... " + STDOUT.flush + initial.opBaseSeq([]) + + retS, outS = initial.opBaseSeq([Test::Base.new]) + test(retS.length == 1 && outS.length == 1) + puts "ok" + print "testing UnexpectedObjectException... " STDOUT.flush ref = "uoet:default -p 12010" diff --git a/rb/test/Ice/objects/Test.ice b/rb/test/Ice/objects/Test.ice index f8b3d7df87f..c83b928c0c2 100644 --- a/rb/test/Ice/objects/Test.ice +++ b/rb/test/Ice/objects/Test.ice @@ -12,6 +12,22 @@ module Test { +struct S +{ + string str; +}; + +class Base +{ + S theS; + string str; +}; + +class AbstractBase extends Base +{ + void op(); +}; + class B; class C; @@ -75,14 +91,11 @@ class H implements I { }; -class K implements J -{ -}; +sequence<Base> BaseSeq; class Initial { void shutdown(); - B getB1(); B getB2(); C getC(); @@ -97,6 +110,8 @@ class Initial I getH(); void setI(I theI); + + BaseSeq opBaseSeq(BaseSeq inSeq, out BaseSeq outSeq); }; }; diff --git a/rb/test/Ice/optional/AllTests.rb b/rb/test/Ice/optional/AllTests.rb index e09a0c5317a..ff149b93781 100644 --- a/rb/test/Ice/optional/AllTests.rb +++ b/rb/test/Ice/optional/AllTests.rb @@ -300,6 +300,17 @@ def allTests(communicator) test(mo9.bos == Ice::Unset) + # + # Use the 1.0 encoding with operations whose only class parameters are optional. + # + initial.sendOptionalClass(true, Test::OneOptional.new(53)) + initial.ice_encodingVersion(Ice::Encoding_1_0).sendOptionalClass(true, Test::OneOptional.new(53)) + + r = initial.returnOptionalClass(true) + test(r != Ice::Unset) + r = initial.ice_encodingVersion(Ice::Encoding_1_0).returnOptionalClass(true) + test(r == Ice::Unset) + puts "ok" print "testing marshaling of large containers with fixed size elements... " @@ -633,6 +644,17 @@ def allTests(communicator) end begin + # + # Use the 1.0 encoding with an exception whose only class members are optional. + # + initial.ice_encodingVersion(Ice::Encoding_1_0).opOptionalException(30, "test", Test::OneOptional.new(53)) + rescue Test::OptionalException => ex + test(ex.a == Ice::Unset) + test(ex.b == Ice::Unset) + test(ex.o == Ice::Unset) + end + + begin initial.opDerivedException(Ice::Unset, Ice::Unset, Ice::Unset) rescue Test::DerivedException => ex test(ex.a == Ice::Unset) diff --git a/rb/test/Ice/optional/Test.ice b/rb/test/Ice/optional/Test.ice index 7f0342b8df4..8cc213df42c 100644 --- a/rb/test/Ice/optional/Test.ice +++ b/rb/test/Ice/optional/Test.ice @@ -136,6 +136,7 @@ class WD exception OptionalException { + bool req = false; optional(1) int a = 5; optional(2) string b; optional(50) OneOptional o; @@ -230,12 +231,18 @@ class Initial optional(1) VarStructSeq opVarStructSeq(optional(2) VarStructSeq p1, out optional(3) VarStructSeq p3); + optional(1) Serializable opSerializable(optional(2) Serializable p1, out optional(3) Serializable p3); + optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, out optional(3) StringIntDict p3); void opClassAndUnknownOptional(A p); + void sendOptionalClass(bool req, optional(1) OneOptional o); + + void returnOptionalClass(bool req, out optional(1) OneOptional o); + bool supportsRequiredParams(); bool supportsJavaSerializable(); |