diff options
author | Benoit Foucher <benoit@zeroc.com> | 2012-06-12 16:50:58 +0200 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2012-06-12 16:50:58 +0200 |
commit | b2c3f4fe51800183e78db500b1e91d0135689caf (patch) | |
tree | f515d08d95609db34b4a6b2c898a488e5fe6be4d /cpp | |
parent | demo fixes (diff) | |
download | ice-b2c3f4fe51800183e78db500b1e91d0135689caf.tar.bz2 ice-b2c3f4fe51800183e78db500b1e91d0135689caf.tar.xz ice-b2c3f4fe51800183e78db500b1e91d0135689caf.zip |
Fixed support unknown types in unknown optionals
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/include/Ice/BasicStream.h | 2 | ||||
-rw-r--r-- | cpp/include/Ice/Exception.h | 3 | ||||
-rw-r--r-- | cpp/include/Ice/ObjectF.h | 2 | ||||
-rw-r--r-- | cpp/include/Ice/SlicedData.h | 28 | ||||
-rw-r--r-- | cpp/include/Ice/Stream.h | 2 | ||||
-rw-r--r-- | cpp/include/IceUtil/Optional.h | 6 | ||||
-rwxr-xr-x | cpp/src/Ice/BasicStream.cpp | 58 | ||||
-rw-r--r-- | cpp/src/Ice/Exception.cpp | 14 | ||||
-rw-r--r-- | cpp/src/Ice/SlicedData.cpp | 64 | ||||
-rw-r--r-- | cpp/src/slice2cpp/Gen.cpp | 3 | ||||
-rw-r--r-- | cpp/test/Ice/optional/AllTests.cpp | 83 | ||||
-rw-r--r-- | cpp/test/Ice/optional/Test.ice | 2 | ||||
-rw-r--r-- | cpp/test/Ice/optional/TestI.cpp | 6 | ||||
-rw-r--r-- | cpp/test/Ice/optional/TestI.h | 2 | ||||
-rw-r--r-- | cpp/test/Ice/slicing/objects/AllTests.cpp | 34 | ||||
-rw-r--r-- | cpp/test/Ice/slicing/objects/ServerPrivate.ice | 6 | ||||
-rw-r--r-- | cpp/test/Ice/slicing/objects/TestI.cpp | 9 |
17 files changed, 255 insertions, 69 deletions
diff --git a/cpp/include/Ice/BasicStream.h b/cpp/include/Ice/BasicStream.h index faf6044e641..da2f4228a05 100644 --- a/cpp/include/Ice/BasicStream.h +++ b/cpp/include/Ice/BasicStream.h @@ -260,7 +260,7 @@ public: // Read remaining encapsulation optionals. This returns // true if the optionals end with the end marker. The end // marker indicates that there are more to read from the - // encapsuliation: object instances. In this case, don't + // encapsulation: object instances. In this case, don't // bother reading the objects, just skip to the end of the // encapsulation. // diff --git a/cpp/include/Ice/Exception.h b/cpp/include/Ice/Exception.h index d8ffd574f1c..cdc6bb8155c 100644 --- a/cpp/include/Ice/Exception.h +++ b/cpp/include/Ice/Exception.h @@ -14,6 +14,7 @@ #include <Ice/Config.h> #include <Ice/Format.h> #include <Ice/Handle.h> +#include <Ice/ObjectF.h> namespace IceInternal { @@ -23,7 +24,7 @@ class BasicStream; namespace Ex { -ICE_API void throwUOE(const ::std::string&, const ::std::string&); +ICE_API void throwUOE(const ::std::string&, const ::Ice::ObjectPtr&); ICE_API void throwMemoryLimitException(const char*, int, size_t, size_t); ICE_API void throwMarshalException(const char*, int, const std::string&); diff --git a/cpp/include/Ice/ObjectF.h b/cpp/include/Ice/ObjectF.h index b4c4be1a55e..5946be23dd0 100644 --- a/cpp/include/Ice/ObjectF.h +++ b/cpp/include/Ice/ObjectF.h @@ -19,7 +19,7 @@ namespace Ice class Object; ICE_API Object* upCast(Object*); typedef IceInternal::Handle< Object > ObjectPtr; -ICE_API void __patch(ObjectPtr& obj, ObjectPtr& v); +ICE_API void __patch(ObjectPtr&, ObjectPtr&); } diff --git a/cpp/include/Ice/SlicedData.h b/cpp/include/Ice/SlicedData.h index 2295592925f..9fae788d674 100644 --- a/cpp/include/Ice/SlicedData.h +++ b/cpp/include/Ice/SlicedData.h @@ -11,8 +11,7 @@ #define ICE_SLICED_DATA_H #include <Ice/SlicedDataF.h> -#include <Ice/ObjectF.h> -#include <Ice/GCShared.h> +#include <Ice/Object.h> namespace Ice { @@ -70,6 +69,31 @@ public: void __addObject(IceInternal::GCCountMap&); }; +// +// Unknown sliced object holds instance of unknown type. +// +class ICE_API UnknownSlicedObject : public Object, private IceInternal::GCShared +{ +public: + + UnknownSlicedObject(const std::string&); + + const std::string& getUnknownTypeId() const; + + virtual void __addObject(::IceInternal::GCCountMap&); + virtual bool __usesGC(); + virtual void __gcReachable(::IceInternal::GCCountMap&) const; + virtual void __gcClear(); + + virtual void __write(::IceInternal::BasicStream*) const; + virtual void __read(::IceInternal::BasicStream*); + +private: + + const std::string _unknownTypeId; + SlicedDataPtr _slicedData; +}; + } #endif diff --git a/cpp/include/Ice/Stream.h b/cpp/include/Ice/Stream.h index ab889addb7f..c895e571cc5 100644 --- a/cpp/include/Ice/Stream.h +++ b/cpp/include/Ice/Stream.h @@ -46,7 +46,7 @@ public: _v = ::IceInternal::Handle<T>::dynamicCast(p); if(p && !_v) { - IceInternal::Ex::throwUOE(T::ice_staticId(), p->ice_id()); + IceInternal::Ex::throwUOE(T::ice_staticId(), p); } } diff --git a/cpp/include/IceUtil/Optional.h b/cpp/include/IceUtil/Optional.h index 17c7ffa6a81..f6f2613fd08 100644 --- a/cpp/include/IceUtil/Optional.h +++ b/cpp/include/IceUtil/Optional.h @@ -153,6 +153,12 @@ private: bool _isSet; }; +template<class T> inline Optional<T> +makeOptional(const T& v) +{ + return Optional<T>(v); +} + template<typename T> inline void Optional<T>::throwOptionalNotSetException(const char* file, int line) const { diff --git a/cpp/src/Ice/BasicStream.cpp b/cpp/src/Ice/BasicStream.cpp index e08d7ad9b49..ddd4dfa60ac 100755 --- a/cpp/src/Ice/BasicStream.cpp +++ b/cpp/src/Ice/BasicStream.cpp @@ -2312,12 +2312,19 @@ IceInternal::BasicStream::EncapsDecoder::throwException(const UserExceptionFacto traceSlicing("exception", _typeId, _slicingCat, _stream->instance()->initializationData().logger); } + // + // Slice off what we don't understand. + // + skipSlice(); + + // + // If this is the last slice, raise an exception and stop un-marshalling. + // if(_sliceFlags & FLAG_IS_LAST_SLICE) { throw NoExceptionFactoryException(__FILE__, __LINE__, "", "unknown exception type `" + mostDerivedId + "'"); } - skipSlice(); // Slice off what we don't understand. try { startSlice(); @@ -2654,12 +2661,10 @@ IceInternal::BasicStream::EncapsDecoder::readInstance() while(true) { // - // For the 1.0 encoding, the type ID for the base Object class marks - // the last slice. For later encodings, an empty type ID means the - // class was marshaled in the compact format and therefore cannot be - // sliced. + // For the 1.0 encoding, the type ID for the base Object class + // marks the last slice. // - if(_typeId.empty() || _typeId == Object::ice_staticId()) + if(_typeId == Object::ice_staticId()) { throw NoObjectFactoryException(__FILE__, __LINE__, "", mostDerivedId); } @@ -2709,32 +2714,41 @@ IceInternal::BasicStream::EncapsDecoder::readInstance() } // - // If object slicing is disabled, or if the flags indicate that this is the - // last slice (for encodings >= 1.1), we raise NoObjectFactoryException. + // Performance sensitive, so we use lazy initialization for tracing. // - if(!_sliceObjects) + if(_traceSlicing == -1) { - throw NoObjectFactoryException(__FILE__, __LINE__, "object slicing is disabled", _typeId); + _traceSlicing = _stream->instance()->traceLevels()->slicing; + _slicingCat = _stream->instance()->traceLevels()->slicingCat; } - else if(_sliceFlags & FLAG_IS_LAST_SLICE) + if(_traceSlicing > 0) { - throw NoObjectFactoryException(__FILE__, __LINE__, "", _typeId); + traceSlicing("class", _typeId, _slicingCat, _stream->instance()->initializationData().logger); } // - // Performance sensitive, so we use lazy initialization for tracing. + // If object slicing is disabled, stop un-marshalling. // - if(_traceSlicing == -1) + if(!_sliceObjects) { - _traceSlicing = _stream->instance()->traceLevels()->slicing; - _slicingCat = _stream->instance()->traceLevels()->slicingCat; + throw NoObjectFactoryException(__FILE__, __LINE__, "object slicing is disabled", _typeId); } - if(_traceSlicing > 0) + + // + // Slice off what we don't understand. + // + skipSlice(); + + // + // If this is the last slice, keep the object as an opaque + // UnknownSlicedData object. + // + if(_sliceFlags & FLAG_IS_LAST_SLICE) { - traceSlicing("class", _typeId, _slicingCat, _stream->instance()->initializationData().logger); + v = new UnknownSlicedObject(mostDerivedId); + break; } - skipSlice(); // Slice off what we don't understand. startSlice(); // Read next Slice header for next iteration. } @@ -2828,7 +2842,9 @@ IceInternal::BasicStream::EncapsDecoder::skipSlice() } else { - throw MarshalException(__FILE__, __LINE__, "compact format prevents slicing"); + throw MarshalException(__FILE__, + __LINE__, + "compact format prevents slicing (the sender should use the sliced format instead)"); } if(_encaps->encoding != Encoding_1_0) @@ -2899,7 +2915,7 @@ IceInternal::BasicStream::EncapsDecoder::readSlicedData() { throw MarshalException(__FILE__, __LINE__, "invalid id in object indirection table"); } - addPatchEntry(id, &patchHandle<Ice::Object>, &_slices[n]->objects[j++]); + addPatchEntry(id, &patchHandle<Object>, &_slices[n]->objects[j++]); } } diff --git a/cpp/src/Ice/Exception.cpp b/cpp/src/Ice/Exception.cpp index 002851f917d..a205af22a78 100644 --- a/cpp/src/Ice/Exception.cpp +++ b/cpp/src/Ice/Exception.cpp @@ -26,8 +26,20 @@ namespace Ex { void -throwUOE(const string& expectedType, const string& type) +throwUOE(const string& expectedType, const ObjectPtr& v) { + // + // If the object is an unknown sliced object, we didn't find an + // object factory, in this case raise a NoObjectFactoryException + // instead. + // + UnknownSlicedObject* uso = dynamic_cast<UnknownSlicedObject*>(v.get()); + if(uso) + { + throw NoObjectFactoryException(__FILE__, __LINE__, "", uso->getUnknownTypeId()); + } + + string type = v->ice_id(); throw Ice::UnexpectedObjectException(__FILE__, __LINE__, "expected element of type `" + expectedType + "' but received '" + type, type, expectedType); diff --git a/cpp/src/Ice/SlicedData.cpp b/cpp/src/Ice/SlicedData.cpp index 72409a2d79c..568c55a7585 100644 --- a/cpp/src/Ice/SlicedData.cpp +++ b/cpp/src/Ice/SlicedData.cpp @@ -9,6 +9,7 @@ #include <Ice/SlicedData.h> #include <Ice/Object.h> +#include <Ice/BasicStream.h> using namespace std; using namespace Ice; @@ -69,3 +70,66 @@ Ice::SlicedData::__addObject(IceInternal::GCCountMap& m) ++pos->second; } } + +Ice::UnknownSlicedObject::UnknownSlicedObject(const string& unknownTypeId) : _unknownTypeId(unknownTypeId) +{ +} + +const string& +Ice::UnknownSlicedObject::getUnknownTypeId() const +{ + return _unknownTypeId; +} + +void +Ice::UnknownSlicedObject::__addObject(IceInternal::GCCountMap& _c) +{ + IceInternal::GCCountMap::iterator pos = _c.find(this); + if(pos == _c.end()) + { + _c[this] = 1; + } + else + { + ++pos->second; + } +} + +bool +Ice::UnknownSlicedObject::__usesGC() +{ + return true; +} + +void +Ice::UnknownSlicedObject::__gcReachable(IceInternal::GCCountMap& _c) const +{ + if(_slicedData) + { + _slicedData->__addObject(_c); + } +} + +void +Ice::UnknownSlicedObject::__gcClear() +{ + if(_slicedData) + { + _slicedData->__decRefUnsafe(); + _slicedData.__clearHandleUnsafe(); + } +} + +void +Ice::UnknownSlicedObject::__write(IceInternal::BasicStream* __os) const +{ + __os->startWriteObject(_slicedData); + __os->endWriteObject(); +} + +void +Ice::UnknownSlicedObject::__read(IceInternal::BasicStream* __is) +{ + __is->startReadObject(); + _slicedData = __is->endReadObject(true); +} diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 54091b39450..fd34162a680 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -423,7 +423,6 @@ Slice::Gen::generate(const UnitPtr& p) if(p->hasContentsWithMetaData("preserve-slice")) { H << "\n#include <Ice/SlicedDataF.h>"; - C << "\n#include <Ice/SlicedData.h>"; } @@ -4165,7 +4164,7 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) C << nl << "handle = " << scope << p->name() << "Ptr::dynamicCast(v);"; C << nl << "if(v && !handle)"; C << sb; - C << nl << "IceInternal::Ex::throwUOE(" << scoped << "::ice_staticId(), v->ice_id());"; + C << nl << "IceInternal::Ex::throwUOE(" << scoped << "::ice_staticId(), v);"; C << eb; C << eb; diff --git a/cpp/test/Ice/optional/AllTests.cpp b/cpp/test/Ice/optional/AllTests.cpp index f1566cff448..dff7d6a6d52 100644 --- a/cpp/test/Ice/optional/AllTests.cpp +++ b/cpp/test/Ice/optional/AllTests.cpp @@ -638,39 +638,58 @@ allTests(const Ice::CommunicatorPtr& communicator, bool collocated) if(communicator->getProperties()->getPropertyAsInt("Ice.Default.SlicedFormat") > 0) { cout << "testing marshalling with unknown class slices... " << flush; - CPtr c = new C(); - c->ss = "test"; - c->ms = "testms"; - out = Ice::createOutputStream(communicator); - out->startEncapsulation(); - out->write(c); - out->endEncapsulation(); - out->finished(inEncaps); - factory->setEnabled(true); - test(initial->ice_invoke("pingPong", Ice::Normal, inEncaps, outEncaps)); - in = Ice::createInputStream(communicator, outEncaps); - in->startEncapsulation(); - in->read(obj); - in->endEncapsulation(); - test(dynamic_cast<CObjectReader*>(obj.get())); - factory->setEnabled(false); + { + CPtr c = new C(); + c->ss = "test"; + c->ms = "testms"; + out = Ice::createOutputStream(communicator); + out->startEncapsulation(); + out->write(c); + out->endEncapsulation(); + out->finished(inEncaps); + factory->setEnabled(true); + test(initial->ice_invoke("pingPong", Ice::Normal, inEncaps, outEncaps)); + in = Ice::createInputStream(communicator, outEncaps); + in->startEncapsulation(); + in->read(obj); + in->endEncapsulation(); + test(dynamic_cast<CObjectReader*>(obj.get())); + factory->setEnabled(false); + + factory->setEnabled(true); + out = Ice::createOutputStream(communicator); + out->startEncapsulation(); + Ice::ObjectPtr d = new DObjectWriter(); + out->write(d); + out->endEncapsulation(); + out->finished(inEncaps); + test(initial->ice_invoke("pingPong", Ice::Normal, inEncaps, outEncaps)); + in = Ice::createInputStream(communicator, outEncaps); + in->startEncapsulation(); + in->read(obj); + in->endEncapsulation(); + test(obj && dynamic_cast<DObjectReader*>(obj.get())); + dynamic_cast<DObjectReader*>(obj.get())->check(); + factory->setEnabled(false); + } + cout << "ok" << endl; - factory->setEnabled(true); - out = Ice::createOutputStream(communicator); - out->startEncapsulation(); - Ice::ObjectPtr d = new DObjectWriter(); - out->write(d); - out->endEncapsulation(); - out->finished(inEncaps); - test(initial->ice_invoke("pingPong", Ice::Normal, inEncaps, outEncaps)); - in = Ice::createInputStream(communicator, outEncaps); - in->startEncapsulation(); - in->read(obj); - in->endEncapsulation(); - test(obj && dynamic_cast<DObjectReader*>(obj.get())); - dynamic_cast<DObjectReader*>(obj.get())->check(); - factory->setEnabled(false); - + cout << "testing optionals with unknown classes..." << flush; + { + APtr a = new A(); + + out = Ice::createOutputStream(communicator); + out->startEncapsulation(); + out->write(a); + out->write(1, IceUtil::makeOptional(Ice::ObjectPtr(new DObjectWriter))); + out->endEncapsulation(); + out->finished(inEncaps); + test(initial->ice_invoke("opClassAndUnknownOptional", Ice::Normal, inEncaps, outEncaps)); + + in = Ice::createInputStream(communicator, outEncaps); + in->startEncapsulation(); + in->endEncapsulation(); + } cout << "ok" << endl; } diff --git a/cpp/test/Ice/optional/Test.ice b/cpp/test/Ice/optional/Test.ice index d42e89a0daf..32142d8df71 100644 --- a/cpp/test/Ice/optional/Test.ice +++ b/cpp/test/Ice/optional/Test.ice @@ -170,6 +170,8 @@ class Initial ["cpp:range"] optional(1) VarStructSeq opVarStructSeq(["cpp:range"] optional(2) VarStructSeq p1, out ["cpp:range"] optional(3) VarStructSeq p3); + + void opClassAndUnknownOptional(A p); }; }; diff --git a/cpp/test/Ice/optional/TestI.cpp b/cpp/test/Ice/optional/TestI.cpp index 2e9a0f113dc..4e7251af410 100644 --- a/cpp/test/Ice/optional/TestI.cpp +++ b/cpp/test/Ice/optional/TestI.cpp @@ -145,3 +145,9 @@ InitialI::opVarStructSeq(const Optional<pair<VarStructSeq::const_iterator, VarSt } return p3; } + +void +InitialI::opClassAndUnknownOptional(const APtr& a, const Ice::Current&) +{ +} + diff --git a/cpp/test/Ice/optional/TestI.h b/cpp/test/Ice/optional/TestI.h index 12106c070f6..e6d5d07c60b 100644 --- a/cpp/test/Ice/optional/TestI.h +++ b/cpp/test/Ice/optional/TestI.h @@ -77,6 +77,8 @@ public: ::Test::VarStructSeq::const_iterator> >&, IceUtil::Optional< ::Test::VarStructSeq>&, const ::Ice::Current& = ::Ice::Current()); + + virtual void opClassAndUnknownOptional(const Test::APtr&, const Ice::Current&); }; #endif diff --git a/cpp/test/Ice/slicing/objects/AllTests.cpp b/cpp/test/Ice/slicing/objects/AllTests.cpp index 788e96e5235..df60d9c967e 100644 --- a/cpp/test/Ice/slicing/objects/AllTests.cpp +++ b/cpp/test/Ice/slicing/objects/AllTests.cpp @@ -111,19 +111,31 @@ public: } void - response_SUnknownAsObject(const Ice::ObjectPtr& o) + response_SUnknownAsObject10(const Ice::ObjectPtr& o) { test(false); } void - exception_SUnknownAsObject(const Ice::Exception& exc) + exception_SUnknownAsObject10(const Ice::Exception& exc) { test(exc.ice_name() == "Ice::NoObjectFactoryException"); called(); } void + response_SUnknownAsObject11(const Ice::ObjectPtr& o) + { + called(); + } + + void + exception_SUnknownAsObject11(const Ice::Exception& exc) + { + test(false); + } + + void response_oneElementCycle(const BPtr& b) { test(b); @@ -531,10 +543,11 @@ testUOO(const TestIntfPrx& test) try { o = test->SUnknownAsObject(); - test(false); + test(test->ice_getEncodingVersion() != Ice::Encoding_1_0); } catch(const Ice::NoObjectFactoryException&) { + test(test->ice_getEncodingVersion() == Ice::Encoding_1_0); } catch(...) { @@ -748,9 +761,18 @@ allTests(const Ice::CommunicatorPtr& communicator) try { CallbackPtr cb = new Callback; - test->begin_SUnknownAsObject( - newCallback_TestIntf_SUnknownAsObject( - cb, &Callback::response_SUnknownAsObject, &Callback::exception_SUnknownAsObject)); + if(test->ice_getEncodingVersion() == Ice::Encoding_1_0) + { + test->begin_SUnknownAsObject( + newCallback_TestIntf_SUnknownAsObject( + cb, &Callback::response_SUnknownAsObject10, &Callback::exception_SUnknownAsObject10)); + } + else + { + test->begin_SUnknownAsObject( + newCallback_TestIntf_SUnknownAsObject( + cb, &Callback::response_SUnknownAsObject11, &Callback::exception_SUnknownAsObject11)); + } cb->check(); } catch(...) diff --git a/cpp/test/Ice/slicing/objects/ServerPrivate.ice b/cpp/test/Ice/slicing/objects/ServerPrivate.ice index 6e8f9557888..ea648958fc3 100644 --- a/cpp/test/Ice/slicing/objects/ServerPrivate.ice +++ b/cpp/test/Ice/slicing/objects/ServerPrivate.ice @@ -42,11 +42,17 @@ exception UnknownDerivedException extends BaseException D2 pd2; }; +class MyClass +{ + int i; +}; + ["preserve-slice"] class PSUnknown extends Preserved { string psu; PNode graph; + MyClass cl; }; ["preserve-slice"] diff --git a/cpp/test/Ice/slicing/objects/TestI.cpp b/cpp/test/Ice/slicing/objects/TestI.cpp index 1de496b5072..5152ea712ea 100644 --- a/cpp/test/Ice/slicing/objects/TestI.cpp +++ b/cpp/test/Ice/slicing/objects/TestI.cpp @@ -283,13 +283,19 @@ TestI::exchangePBase(const Test::PBasePtr& pb, const Ice::Current&) } Test::PreservedPtr -TestI::PBSUnknownAsPreserved(const Ice::Current&) +TestI::PBSUnknownAsPreserved(const Ice::Current& current) { PSUnknownPtr r = new PSUnknown; r->pi = 5; r->ps = "preserved"; r->psu = "unknown"; r->graph = 0; + if(current.encoding != Ice::Encoding_1_0) + { + // 1.0 encoding doesn't support un-marshalling unknown classes even if referenced + // from unread slice. + r->cl = new MyClass(15); + } return r; } @@ -309,6 +315,7 @@ TestI::checkPBSUnknown(const Test::PreservedPtr& p, const Ice::Current& current) test(pu->pi == 5); test(pu->ps == "preserved"); test(pu->psu == "unknown"); + test(pu->cl && pu->cl->i == 15); test(!pu->graph); } } |