diff options
Diffstat (limited to 'ruby/src')
-rw-r--r-- | ruby/src/IceRuby/Communicator.cpp | 54 | ||||
-rw-r--r-- | ruby/src/IceRuby/Init.cpp | 2 | ||||
-rw-r--r-- | ruby/src/IceRuby/Makefile | 4 | ||||
-rw-r--r-- | ruby/src/IceRuby/ObjectFactory.cpp | 140 | ||||
-rw-r--r-- | ruby/src/IceRuby/ObjectFactory.h | 50 | ||||
-rw-r--r-- | ruby/src/IceRuby/Operation.cpp | 73 | ||||
-rw-r--r-- | ruby/src/IceRuby/Types.cpp | 184 | ||||
-rw-r--r-- | ruby/src/IceRuby/Types.h | 163 | ||||
-rw-r--r-- | ruby/src/IceRuby/Util.cpp | 8 | ||||
-rw-r--r-- | ruby/src/IceRuby/Util.h | 2 | ||||
-rw-r--r-- | ruby/src/IceRuby/ValueFactoryManager.cpp | 432 | ||||
-rw-r--r-- | ruby/src/IceRuby/ValueFactoryManager.h | 100 |
12 files changed, 825 insertions, 387 deletions
diff --git a/ruby/src/IceRuby/Communicator.cpp b/ruby/src/IceRuby/Communicator.cpp index 7a7635c1dbf..3d90f420464 100644 --- a/ruby/src/IceRuby/Communicator.cpp +++ b/ruby/src/IceRuby/Communicator.cpp @@ -10,11 +10,12 @@ #include <Communicator.h> #include <ImplicitContext.h> #include <Logger.h> -#include <ObjectFactory.h> #include <Properties.h> #include <Proxy.h> #include <Types.h> #include <Util.h> +#include <ValueFactoryManager.h> +#include <IceUtil/DisableWarnings.h> #include <Ice/Communicator.h> #include <Ice/Initialize.h> #include <Ice/Locator.h> @@ -37,9 +38,9 @@ IceRuby_Communicator_mark(Ice::CommunicatorPtr* p) assert(p); try { - ObjectFactoryPtr pof = ObjectFactoryPtr::dynamicCast((*p)->findObjectFactory("")); - assert(pof); - pof->mark(); + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*p)->getValueFactoryManager()); + assert(vfm); + vfm->markSelf(); } catch(const Ice::CommunicatorDestroyedException&) { @@ -128,6 +129,7 @@ IceRuby_initialize(int argc, VALUE* argv, VALUE self) seq.insert(seq.begin(), getString(progName)); data.compactIdResolver = new IdResolver; + data.valueFactoryManager = new ValueFactoryManager; if(hasArgs) { @@ -181,7 +183,7 @@ IceRuby_initialize(int argc, VALUE* argv, VALUE self) throw; } - + // // Replace the contents of the given argument list with the filtered arguments. // @@ -205,9 +207,6 @@ IceRuby_initialize(int argc, VALUE* argv, VALUE self) } delete[] av; - ObjectFactoryPtr factory = new ObjectFactory; - communicator->addObjectFactory(factory, ""); - VALUE result = Data_Wrap_Struct(_communicatorClass, IceRuby_Communicator_mark, IceRuby_Communicator_free, new Ice::CommunicatorPtr(communicator)); @@ -256,12 +255,19 @@ extern "C" VALUE IceRuby_Communicator_destroy(VALUE self) { + Ice::CommunicatorPtr p = getCommunicator(self); + + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(p->getValueFactoryManager()); + assert(vfm); + ICE_RUBY_TRY { - Ice::CommunicatorPtr p = getCommunicator(self); p->destroy(); } ICE_RUBY_CATCH + + vfm->destroy(); + return Qnil; } @@ -371,7 +377,7 @@ IceRuby_Communicator_proxyToProperty(VALUE self, VALUE obj, VALUE str) volatile VALUE value = createString(q->second); callRuby(rb_hash_aset, result, key, value); } - return result; + return result; } ICE_RUBY_CATCH return Qnil; @@ -414,10 +420,10 @@ IceRuby_Communicator_addObjectFactory(VALUE self, VALUE factory, VALUE id) ICE_RUBY_TRY { Ice::CommunicatorPtr p = getCommunicator(self); - ObjectFactoryPtr pof = ObjectFactoryPtr::dynamicCast(p->findObjectFactory("")); - assert(pof); + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(p->getValueFactoryManager()); + assert(vfm); string idstr = getString(id); - pof->add(factory, idstr); + vfm->addObjectFactory(factory, idstr); } ICE_RUBY_CATCH return Qnil; @@ -430,10 +436,25 @@ IceRuby_Communicator_findObjectFactory(VALUE self, VALUE id) ICE_RUBY_TRY { Ice::CommunicatorPtr p = getCommunicator(self); - ObjectFactoryPtr pof = ObjectFactoryPtr::dynamicCast(p->findObjectFactory("")); - assert(pof); + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(p->getValueFactoryManager()); + assert(vfm); string idstr = getString(id); - return pof->find(idstr); + return vfm->findObjectFactory(idstr); + } + ICE_RUBY_CATCH + return Qnil; +} + +extern "C" +VALUE +IceRuby_Communicator_getValueFactoryManager(VALUE self) +{ + ICE_RUBY_TRY + { + Ice::CommunicatorPtr p = getCommunicator(self); + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(p->getValueFactoryManager()); + assert(vfm); + return vfm->getObject(); } ICE_RUBY_CATCH return Qnil; @@ -596,6 +617,7 @@ IceRuby::initCommunicator(VALUE iceModule) rb_define_method(_communicatorClass, "identityToString", CAST_METHOD(IceRuby_Communicator_identityToString), 1); rb_define_method(_communicatorClass, "addObjectFactory", CAST_METHOD(IceRuby_Communicator_addObjectFactory), 2); rb_define_method(_communicatorClass, "findObjectFactory", CAST_METHOD(IceRuby_Communicator_findObjectFactory), 1); + rb_define_method(_communicatorClass, "getValueFactoryManager", CAST_METHOD(IceRuby_Communicator_getValueFactoryManager), 0); rb_define_method(_communicatorClass, "getImplicitContext", CAST_METHOD(IceRuby_Communicator_getImplicitContext), 0); rb_define_method(_communicatorClass, "getProperties", CAST_METHOD(IceRuby_Communicator_getProperties), 0); rb_define_method(_communicatorClass, "getLogger", CAST_METHOD(IceRuby_Communicator_getLogger), 0); diff --git a/ruby/src/IceRuby/Init.cpp b/ruby/src/IceRuby/Init.cpp index 26f915275fb..5520de7d9fe 100644 --- a/ruby/src/IceRuby/Init.cpp +++ b/ruby/src/IceRuby/Init.cpp @@ -17,6 +17,7 @@ #include <Types.h> #include <Connection.h> #include <Endpoint.h> +#include <ValueFactoryManager.h> using namespace std; using namespace IceRuby; @@ -54,6 +55,7 @@ ICE_DECLSPEC_EXPORT Init_IceRuby() initUtil(iceModule); initConnection(iceModule); initEndpoint(iceModule); + initValueFactoryManager(iceModule); } } diff --git a/ruby/src/IceRuby/Makefile b/ruby/src/IceRuby/Makefile index 2cb6e3a8c30..ccbdc362991 100644 --- a/ruby/src/IceRuby/Makefile +++ b/ruby/src/IceRuby/Makefile @@ -20,13 +20,13 @@ OBJS = Communicator.o \ ImplicitContext.o \ Init.o \ Logger.o \ - ObjectFactory.o \ Operation.o \ Properties.o \ Proxy.o \ Slice.o \ Types.o \ - Util.o + Util.o \ + ValueFactoryManager.o include $(top_srcdir)/config/Make.rules diff --git a/ruby/src/IceRuby/ObjectFactory.cpp b/ruby/src/IceRuby/ObjectFactory.cpp deleted file mode 100644 index 2c2282b7fe2..00000000000 --- a/ruby/src/IceRuby/ObjectFactory.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. -// -// This copy of Ice is licensed to you under the terms described in the -// ICE_LICENSE file included in this distribution. -// -// ********************************************************************** - -#include <ObjectFactory.h> -#include <Types.h> -#include <Util.h> -#include <Ice/LocalException.h> - -using namespace std; -using namespace IceRuby; - -IceRuby::ObjectFactory::ObjectFactory() -{ -} - -IceRuby::ObjectFactory::~ObjectFactory() -{ - assert(_factoryMap.empty()); -} - -Ice::ObjectPtr -IceRuby::ObjectFactory::create(const string& id) -{ - Lock sync(*this); - - // - // Get the type information. - // - ClassInfoPtr info; - if(id == Ice::Object::ice_staticId()) - { - // - // When the ID is that of Ice::Object, it indicates that the stream has not - // found a factory and is providing us an opportunity to preserve the object. - // - info = lookupClassInfo("::Ice::UnknownSlicedObject"); - } - else - { - info = lookupClassInfo(id); - } - - if(!info) - { - return 0; - } - - // - // Check if the application has registered a factory for this id. - // - FactoryMap::iterator p = _factoryMap.find(id); - if(p != _factoryMap.end()) - { - // - // Invoke the create method on the Ruby factory object. - // - volatile VALUE str = createString(id); - volatile VALUE obj = callRuby(rb_funcall, p->second, rb_intern("create"), 1, str); - if(NIL_P(obj)) - { - return 0; - } - return new ObjectReader(obj, info); - } - - // - // Instantiate the object. - // - volatile VALUE obj = callRuby(rb_class_new_instance, 0, reinterpret_cast<VALUE*>(0), info->rubyClass); - assert(!NIL_P(obj)); - return new ObjectReader(obj, info); -} - -void -IceRuby::ObjectFactory::destroy() -{ - Lock sync(*this); - - for(FactoryMap::iterator p = _factoryMap.begin(); p != _factoryMap.end(); ++p) - { - // - // Invoke the destroy method on each registered Ruby factory. - // - try - { - callRuby(rb_funcall, p->second, rb_intern("destroy"), 0); - } - catch(const RubyException&) - { - // Ignore. - } - } - _factoryMap.clear(); -} - -void -IceRuby::ObjectFactory::add(VALUE factory, const string& id) -{ - Lock sync(*this); - - FactoryMap::iterator p = _factoryMap.find(id); - if(p != _factoryMap.end()) - { - Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); - ex.kindOfObject = "object factory"; - ex.id = id; - throw ex; - } - - _factoryMap.insert(FactoryMap::value_type(id, factory)); -} - -VALUE -IceRuby::ObjectFactory::find(const string& id) -{ - Lock sync(*this); - - FactoryMap::iterator p = _factoryMap.find(id); - if(p == _factoryMap.end()) - { - return Qnil; - } - - return p->second; -} - -void -IceRuby::ObjectFactory::mark() -{ - for(FactoryMap::iterator p = _factoryMap.begin(); p != _factoryMap.end(); ++p) - { - rb_gc_mark(p->second); - } -} diff --git a/ruby/src/IceRuby/ObjectFactory.h b/ruby/src/IceRuby/ObjectFactory.h deleted file mode 100644 index a677ad51833..00000000000 --- a/ruby/src/IceRuby/ObjectFactory.h +++ /dev/null @@ -1,50 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2016 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. -// -// ********************************************************************** - -#ifndef ICE_RUBY_OBJECT_FACTORY_H -#define ICE_RUBY_OBJECT_FACTORY_H - -#include <Config.h> -#include <Ice/ObjectF.h> -#include <Ice/ObjectFactory.h> -#include <IceUtil/Mutex.h> - -namespace IceRuby -{ - -// -// Each communicator registers an instance of ObjectFactory as its -// default object factory. This instance delegates to registered Ruby -// objects, and instantiates concrete classes when no factory is present. -// -class ObjectFactory : public Ice::ObjectFactory, public IceUtil::Mutex -{ -public: - - ObjectFactory(); - ~ObjectFactory(); - - virtual Ice::ObjectPtr create(const std::string&); - - virtual void destroy(); - - void add(VALUE, const std::string&); - VALUE find(const std::string&); - void mark(); - -private: - - typedef std::map<std::string, VALUE> FactoryMap; - FactoryMap _factoryMap; -}; -typedef IceUtil::Handle<ObjectFactory> ObjectFactoryPtr; - -} - -#endif diff --git a/ruby/src/IceRuby/Operation.cpp b/ruby/src/IceRuby/Operation.cpp index 2f4d34210ca..55de1f69c0e 100644 --- a/ruby/src/IceRuby/Operation.cpp +++ b/ruby/src/IceRuby/Operation.cpp @@ -71,7 +71,7 @@ private: void convertParams(VALUE, ParamInfoList&, int, bool&); ParamInfoPtr convertParam(VALUE, int); - void prepareRequest(const Ice::ObjectPrx&, VALUE, Ice::OutputStreamPtr&, pair<const Ice::Byte*, const Ice::Byte*>&); + void prepareRequest(const Ice::ObjectPrx&, VALUE, Ice::OutputStream*, pair<const Ice::Byte*, const Ice::Byte*>&); VALUE unmarshalResults(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); VALUE unmarshalException(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&); bool validateException(VALUE) const; @@ -79,27 +79,18 @@ private: }; typedef IceUtil::Handle<OperationI> OperationIPtr; -class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +class UserExceptionFactory : public Ice::UserExceptionFactory { public: - UserExceptionReaderFactoryI(const Ice::CommunicatorPtr& communicator) : - _communicator(communicator) - { - } - - virtual void createAndThrow(const string& id) const + virtual void createAndThrow(const string& id) { ExceptionInfoPtr info = lookupExceptionInfo(id); if(info) { - throw ExceptionReader(_communicator, info); + throw ExceptionReader(info); } } - -private: - - const Ice::CommunicatorPtr _communicator; }; } @@ -299,9 +290,9 @@ IceRuby::OperationI::invoke(const Ice::ObjectPrx& proxy, VALUE args, VALUE hctx) // // Marshal the input parameters to a byte sequence. // - Ice::OutputStreamPtr os; + Ice::OutputStream os(communicator); pair<const Ice::Byte*, const Ice::Byte*> params; - prepareRequest(proxy, args, os, params); + prepareRequest(proxy, args, &os, params); if(!_deprecateMessage.empty()) { @@ -409,7 +400,7 @@ IceRuby::OperationI::convertParam(VALUE v, int pos) } void -IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, Ice::OutputStreamPtr& os, +IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, Ice::OutputStream* os, pair<const Ice::Byte*, const Ice::Byte*>& params) { params.first = params.second = static_cast<const Ice::Byte*>(0); @@ -430,7 +421,6 @@ IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, Ice // // Marshal the in parameters. // - os = Ice::createOutputStream(proxy->ice_getCommunicator()); os->startEncapsulation(proxy->ice_getEncodingVersion(), _format); ObjectMap objectMap; @@ -503,17 +493,17 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: // Unmarshal the results. If there is more than one value to be returned, then return them // in a tuple of the form (result, outParam1, ...). Otherwise just return the value. // - Ice::InputStreamPtr is = Ice::wrapInputStream(communicator, bytes); + Ice::InputStream is(communicator, bytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); - is->startEncapsulation(); + is.startEncapsulation(); ParamInfoList::iterator p; @@ -526,7 +516,7 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: if(!info->optional) { void* closure = reinterpret_cast<void*>(info->pos); - info->type->unmarshal(is, info, results, closure, false); + info->type->unmarshal(&is, info, results, closure, false); } } @@ -537,7 +527,7 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: { assert(_returnType->pos == 0); void* closure = reinterpret_cast<void*>(_returnType->pos); - _returnType->type->unmarshal(is, _returnType, results, closure, false); + _returnType->type->unmarshal(&is, _returnType, results, closure, false); } // @@ -546,10 +536,10 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: for(p = _optionalOutParams.begin(); p != _optionalOutParams.end(); ++p) { ParamInfoPtr info = *p; - if(is->readOptional(info->tag, info->type->optionalFormat())) + if(is.readOptional(info->tag, info->type->optionalFormat())) { void* closure = reinterpret_cast<void*>(info->pos); - info->type->unmarshal(is, info, results, closure, true); + info->type->unmarshal(&is, info, results, closure, true); } else { @@ -559,12 +549,12 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: if(_returnsClasses) { - is->readPendingObjects(); + is.readPendingObjects(); } - is->endEncapsulation(); + is.endEncapsulation(); - util.update(); + util.updateSlicedData(); return results; } @@ -572,37 +562,37 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice: VALUE IceRuby::OperationI::unmarshalException(const vector<Ice::Byte>& bytes, const Ice::CommunicatorPtr& communicator) { - Ice::InputStreamPtr is = Ice::wrapInputStream(communicator, bytes); + Ice::InputStream is(communicator, bytes); // - // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // Store a pointer to a local StreamUtil object as the stream's closure. // This is necessary to support object unmarshaling (see ObjectReader). // - SlicedDataUtil util; - assert(!is->closure()); - is->closure(&util); + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); - is->startEncapsulation(); + is.startEncapsulation(); try { - Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(communicator); - is->throwException(factory); + Ice::UserExceptionFactoryPtr factory = new UserExceptionFactory; + is.throwException(factory); } catch(const ExceptionReader& r) { - is->endEncapsulation(); + is.endEncapsulation(); volatile VALUE ex = r.getException(); if(validateException(ex)) { - util.update(); + util.updateSlicedData(); Ice::SlicedDataPtr slicedData = r.getSlicedData(); if(slicedData) { - SlicedDataUtil::setMember(ex, slicedData); + StreamUtil::setSlicedDataMember(ex, slicedData); } return ex; @@ -622,7 +612,6 @@ IceRuby::OperationI::unmarshalException(const vector<Ice::Byte>& bytes, const Ic #ifdef __SUNPRO_CC return 0; #endif - } bool diff --git a/ruby/src/IceRuby/Types.cpp b/ruby/src/IceRuby/Types.cpp index 8ca6e29cffa..228154401d6 100644 --- a/ruby/src/IceRuby/Types.cpp +++ b/ruby/src/IceRuby/Types.cpp @@ -13,7 +13,9 @@ #include <IceUtil/InputUtil.h> #include <IceUtil/OutputUtil.h> #include <IceUtil/ScopedArray.h> +#include <Ice/InputStream.h> #include <Ice/LocalException.h> +#include <Ice/OutputStream.h> #include <Ice/SlicedData.h> #include <list> #include <limits> @@ -63,22 +65,6 @@ public: }; static InfoMapDestroyer infoMapDestroyer; -class ReadObjectCallback : public Ice::ReadObjectCallback -{ -public: - - ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, VALUE, void*); - - virtual void invoke(const Ice::ObjectPtr&); - -private: - - ClassInfoPtr _info; - UnmarshalCallbackPtr _cb; - VALUE _target; - void* _closure; -}; - string escapeString(const string& str) { @@ -184,16 +170,16 @@ addExceptionInfo(const string& id, const ExceptionInfoPtr& info) } // -// SlicedDataUtil implementation +// StreamUtil implementation // -VALUE IceRuby::SlicedDataUtil::_slicedDataType = Qnil; -VALUE IceRuby::SlicedDataUtil::_sliceInfoType = Qnil; +VALUE IceRuby::StreamUtil::_slicedDataType = Qnil; +VALUE IceRuby::StreamUtil::_sliceInfoType = Qnil; -IceRuby::SlicedDataUtil::SlicedDataUtil() +IceRuby::StreamUtil::StreamUtil() { } -IceRuby::SlicedDataUtil::~SlicedDataUtil() +IceRuby::StreamUtil::~StreamUtil() { // // Make sure we break any cycles among the ObjectReaders in preserved slices. @@ -216,23 +202,29 @@ IceRuby::SlicedDataUtil::~SlicedDataUtil() } void -IceRuby::SlicedDataUtil::add(const ObjectReaderPtr& reader) +IceRuby::StreamUtil::add(const ReadObjectCallbackPtr& callback) +{ + _callbacks.push_back(callback); +} + +void +IceRuby::StreamUtil::add(const ObjectReaderPtr& reader) { assert(reader->getSlicedData()); _readers.insert(reader); } void -IceRuby::SlicedDataUtil::update() +IceRuby::StreamUtil::updateSlicedData() { for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) { - setMember((*p)->getObject(), (*p)->getSlicedData()); + setSlicedDataMember((*p)->getObject(), (*p)->getSlicedData()); } } void -IceRuby::SlicedDataUtil::setMember(VALUE obj, const Ice::SlicedDataPtr& slicedData) +IceRuby::StreamUtil::setSlicedDataMember(VALUE obj, const Ice::SlicedDataPtr& slicedData) { // // Create a Ruby equivalent of the SlicedData object. @@ -325,7 +317,7 @@ IceRuby::SlicedDataUtil::setMember(VALUE obj, const Ice::SlicedDataPtr& slicedDa // named _ice_slicedData which is an instance of the Ruby class Ice::SlicedData. // Ice::SlicedDataPtr -IceRuby::SlicedDataUtil::getMember(VALUE obj, ObjectMap* objectMap) +IceRuby::StreamUtil::getSlicedDataMember(VALUE obj, ObjectMap* objectMap) { Ice::SlicedDataPtr slicedData; @@ -544,7 +536,7 @@ IceRuby::PrimitiveInfo::optionalFormat() const } void -IceRuby::PrimitiveInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap*, bool) +IceRuby::PrimitiveInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap*, bool) { switch(kind) { @@ -625,7 +617,7 @@ IceRuby::PrimitiveInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectM } void -IceRuby::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, +IceRuby::PrimitiveInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool) { volatile VALUE val = Qnil; @@ -814,7 +806,7 @@ IceRuby::EnumInfo::optionalFormat() const } void -IceRuby::EnumInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap*, bool) +IceRuby::EnumInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap*, bool) { assert(callRuby(rb_obj_is_instance_of, p, rubyClass) == Qtrue); // validate() should have caught this. @@ -832,7 +824,7 @@ IceRuby::EnumInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap*, } void -IceRuby::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, +IceRuby::EnumInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool) { Ice::Int val = is->readEnum(maxValue); @@ -995,7 +987,7 @@ IceRuby::StructInfo::usesClasses() const } void -IceRuby::StructInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) +IceRuby::StructInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap* objectMap, bool optional) { assert(NIL_P(p) || callRuby(rb_obj_is_kind_of, p, rubyClass) == Qtrue); // validate() should have caught this. @@ -1041,7 +1033,7 @@ IceRuby::StructInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* } void -IceRuby::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, +IceRuby::StructInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool optional) { volatile VALUE obj = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), rubyClass); @@ -1178,7 +1170,7 @@ IceRuby::SequenceInfo::usesClasses() const } void -IceRuby::SequenceInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) +IceRuby::SequenceInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap* objectMap, bool optional) { PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType); @@ -1256,7 +1248,7 @@ IceRuby::SequenceInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMa } void -IceRuby::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, +IceRuby::SequenceInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool optional) { if(optional) @@ -1355,7 +1347,7 @@ IceRuby::SequenceInfo::destroy() } void -IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALUE p, const Ice::OutputStreamPtr& os) +IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALUE p, Ice::OutputStream* os) { volatile VALUE arr = Qnil; volatile VALUE str = Qnil; @@ -1517,14 +1509,14 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU { seq[i] = getString(RARRAY_PTR(arr)[i]); } - os->write(seq, true); + os->write(&seq[0], &seq[0] + seq.size()); break; } } } void -IceRuby::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, const Ice::InputStreamPtr& is, +IceRuby::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure) { volatile VALUE result = Qnil; @@ -1721,7 +1713,7 @@ namespace { struct DictionaryMarshalIterator : public IceRuby::HashIterator { - DictionaryMarshalIterator(const IceRuby::DictionaryInfoPtr& d, const Ice::OutputStreamPtr o, IceRuby::ObjectMap* m) + DictionaryMarshalIterator(const IceRuby::DictionaryInfoPtr& d, Ice::OutputStream* o, IceRuby::ObjectMap* m) : dict(d), os(o), objectMap(m) { } @@ -1732,13 +1724,13 @@ struct DictionaryMarshalIterator : public IceRuby::HashIterator } IceRuby::DictionaryInfoPtr dict; - Ice::OutputStreamPtr os; + Ice::OutputStream* os; IceRuby::ObjectMap* objectMap; }; } void -IceRuby::DictionaryInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) +IceRuby::DictionaryInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap* objectMap, bool optional) { volatile VALUE hash = Qnil; @@ -1791,7 +1783,7 @@ IceRuby::DictionaryInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, Object } void -IceRuby::DictionaryInfo::marshalElement(VALUE key, VALUE value, const Ice::OutputStreamPtr& os, ObjectMap* objectMap) +IceRuby::DictionaryInfo::marshalElement(VALUE key, VALUE value, Ice::OutputStream* os, ObjectMap* objectMap) { if(!keyType->validate(key)) { @@ -1808,7 +1800,7 @@ IceRuby::DictionaryInfo::marshalElement(VALUE key, VALUE value, const Ice::Outpu } void -IceRuby::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, +IceRuby::DictionaryInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool optional) { if(optional) @@ -2062,7 +2054,7 @@ IceRuby::ClassInfo::usesClasses() const } void -IceRuby::ClassInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool) +IceRuby::ClassInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap* objectMap, bool) { if(!defined) { @@ -2071,7 +2063,8 @@ IceRuby::ClassInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* if(NIL_P(p)) { - os->writeObject(0); + Ice::ObjectPtr nil; + os->write(nil); return; } @@ -2097,19 +2090,40 @@ IceRuby::ClassInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* // // Give the writer to the stream. The stream will eventually call write() on it. // - os->writeObject(writer); + os->write(writer); +} + +namespace +{ + +void +patchObject(void* addr, const Ice::ObjectPtr& v) +{ + ReadObjectCallback* cb = static_cast<ReadObjectCallback*>(addr); + assert(cb); + cb->invoke(v); +} + } void -IceRuby::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, - void* closure, bool) +IceRuby::ClassInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool) { if(!defined) { throw RubyException(rb_eRuntimeError, "class %s is declared but not defined", id.c_str()); } - is->readObject(new ReadObjectCallback(this, cb, target, closure)); + // + // This callback is notified when the Slice value is actually read. The StreamUtil object + // attached to the stream keeps a reference to the callback object to ensure it lives + // long enough. + // + ReadObjectCallbackPtr rocb = new ReadObjectCallback(this, cb, target, closure); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); + assert(util); + util->add(rocb); + is->read(patchObject, rocb.get()); } void @@ -2336,7 +2350,7 @@ IceRuby::ProxyInfo::optionalFormat() const } void -IceRuby::ProxyInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional) +IceRuby::ProxyInfo::marshal(VALUE p, Ice::OutputStream* os, ObjectMap*, bool optional) { Ice::OutputStream::size_type sizePos = -1; if(optional) @@ -2361,7 +2375,7 @@ IceRuby::ProxyInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap*, } void -IceRuby::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, VALUE target, +IceRuby::ProxyInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, VALUE target, void* closure, bool optional) { if(optional) @@ -2446,7 +2460,7 @@ IceRuby::ObjectWriter::ice_preMarshal() } void -IceRuby::ObjectWriter::write(const Ice::OutputStreamPtr& os) const +IceRuby::ObjectWriter::__write(Ice::OutputStream* os) const { Ice::SlicedDataPtr slicedData; @@ -2455,7 +2469,7 @@ IceRuby::ObjectWriter::write(const Ice::OutputStreamPtr& os) const // // Retrieve the SlicedData object that we stored as a hidden member of the Ruby object. // - slicedData = SlicedDataUtil::getMember(_object, const_cast<ObjectMap*>(_map)); + slicedData = StreamUtil::getSlicedDataMember(_object, const_cast<ObjectMap*>(_map)); } os->startObject(slicedData); @@ -2480,7 +2494,13 @@ IceRuby::ObjectWriter::write(const Ice::OutputStreamPtr& os) const } void -IceRuby::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemberList& members) const +IceRuby::ObjectWriter::__read(Ice::InputStream*) +{ + assert(false); +} + +void +IceRuby::ObjectWriter::writeMembers(Ice::OutputStream* os, const DataMemberList& members) const { for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { @@ -2531,7 +2551,13 @@ IceRuby::ObjectReader::ice_postUnmarshal() } void -IceRuby::ObjectReader::read(const Ice::InputStreamPtr& is) +IceRuby::ObjectReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IceRuby::ObjectReader::__read(Ice::InputStream* is) { is->startObject(); @@ -2581,7 +2607,7 @@ IceRuby::ObjectReader::read(const Ice::InputStreamPtr& is) if(_slicedData) { - SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure()); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); assert(util); util->add(this); @@ -2679,7 +2705,7 @@ IceRuby::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) // ExceptionInfo implementation. // VALUE -IceRuby::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is) +IceRuby::ExceptionInfo::unmarshal(Ice::InputStream* is) { volatile VALUE obj = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), rubyClass); @@ -2789,8 +2815,8 @@ IceRuby::ExceptionInfo::printMembers(VALUE value, IceUtilInternal::Output& out, // // ExceptionReader implementation. // -IceRuby::ExceptionReader::ExceptionReader(const Ice::CommunicatorPtr& communicator, const ExceptionInfoPtr& info) : - Ice::UserExceptionReader(communicator), _info(info) +IceRuby::ExceptionReader::ExceptionReader(const ExceptionInfoPtr& info) : + _info(info) { } @@ -2799,34 +2825,20 @@ IceRuby::ExceptionReader::~ExceptionReader() { } -void -IceRuby::ExceptionReader::read(const Ice::InputStreamPtr& is) const -{ - is->startException(); - - const_cast<VALUE&>(_ex) = _info->unmarshal(is); - - const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); -} - -bool -IceRuby::ExceptionReader::usesClasses() const -{ - return _info->usesClasses; -} - string -IceRuby::ExceptionReader::ice_name() const +IceRuby::ExceptionReader::ice_id() const { return _info->id; } +#ifndef ICE_CPP11_MAPPING Ice::UserException* IceRuby::ExceptionReader::ice_clone() const { assert(false); return 0; } +#endif void IceRuby::ExceptionReader::ice_throw() const @@ -2834,6 +2846,28 @@ IceRuby::ExceptionReader::ice_throw() const throw *this; } +void +IceRuby::ExceptionReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IceRuby::ExceptionReader::__read(Ice::InputStream* is) +{ + is->startException(); + + const_cast<VALUE&>(_ex) = _info->unmarshal(is); + + const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); +} + +bool +IceRuby::ExceptionReader::__usesClasses() const +{ + return _info->usesClasses; +} + VALUE IceRuby::ExceptionReader::getException() const { diff --git a/ruby/src/IceRuby/Types.h b/ruby/src/IceRuby/Types.h index d93ec58e7d9..809b34aed0c 100644 --- a/ruby/src/IceRuby/Types.h +++ b/ruby/src/IceRuby/Types.h @@ -12,7 +12,9 @@ #include <Config.h> #include <Util.h> -#include <Ice/Stream.h> +#include <Ice/FactoryTable.h> +#include <Ice/Object.h> +#include <Ice/SlicedData.h> #include <IceUtil/OutputUtil.h> namespace IceRuby @@ -40,31 +42,6 @@ typedef std::map<VALUE, Ice::ObjectPtr> ObjectMap; class ObjectReader; typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; -// -// This class keeps track of Ruby objects (instances of Slice classes -// and exceptions) that have preserved slices. -// -class SlicedDataUtil -{ -public: - - SlicedDataUtil(); - ~SlicedDataUtil(); - - void add(const ObjectReaderPtr&); - - void update(); - - static void setMember(VALUE, const Ice::SlicedDataPtr&); - static Ice::SlicedDataPtr getMember(VALUE, ObjectMap*); - -private: - - std::set<ObjectReaderPtr> _readers; - static VALUE _slicedDataType; - static VALUE _sliceInfoType; -}; - struct PrintObjectHistory { int index; @@ -95,6 +72,64 @@ public: typedef IceUtil::Handle<UnmarshalCallback> UnmarshalCallbackPtr; // +// ReadObjectCallback retains all of the information necessary to store an unmarshaled +// Slice value as a Ruby object. +// +class ReadObjectCallback : public IceUtil::Shared +{ +public: + + ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, VALUE, void*); + + void invoke(const ::Ice::ObjectPtr&); + +private: + + ClassInfoPtr _info; + UnmarshalCallbackPtr _cb; + VALUE _target; + void* _closure; +}; +typedef IceUtil::Handle<ReadObjectCallback> ReadObjectCallbackPtr; + +// +// This class assists during unmarshaling of Slice classes and exceptions. +// We attach an instance to a stream. +// +class StreamUtil +{ +public: + + StreamUtil(); + ~StreamUtil(); + + // + // Keep a reference to a ReadObjectCallback for patching purposes. + // + void add(const ReadObjectCallbackPtr&); + + // + // Keep track of object instances that have preserved slices. + // + void add(const ObjectReaderPtr&); + + // + // Updated the sliced data information for all stored object instances. + // + void updateSlicedData(); + + static void setSlicedDataMember(VALUE, const Ice::SlicedDataPtr&); + static Ice::SlicedDataPtr getSlicedDataMember(VALUE, ObjectMap*); + +private: + + std::vector<ReadObjectCallbackPtr> _callbacks; + std::set<ObjectReaderPtr> _readers; + static VALUE _slicedDataType; + static VALUE _sliceInfoType; +}; + +// // Base class for type information. // class TypeInfo : public UnmarshalCallback @@ -125,8 +160,8 @@ public: // The marshal and unmarshal functions can raise Ice exceptions, and may raise // AbortMarshaling if an error occurs. // - virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool) = 0; - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool) = 0; + virtual void marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool) = 0; + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool) = 0; virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*) = 0; }; @@ -162,8 +197,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); + virtual void marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -192,8 +227,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); + virtual void marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -238,8 +273,8 @@ public: 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 marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -276,8 +311,8 @@ public: 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 marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void unmarshaled(VALUE, VALUE, void*); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -289,8 +324,8 @@ public: private: - void marshalPrimitiveSequence(const PrimitiveInfoPtr&, VALUE, const Ice::OutputStreamPtr&); - void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, + void marshalPrimitiveSequence(const PrimitiveInfoPtr&, VALUE, Ice::OutputStream*); + void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*); }; typedef IceUtil::Handle<SequenceInfo> SequenceInfoPtr; @@ -314,9 +349,9 @@ public: 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*); + virtual void marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); + void marshalElement(VALUE, VALUE, Ice::OutputStream*, ObjectMap*); virtual void unmarshaled(VALUE, VALUE, void*); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -365,8 +400,8 @@ public: 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 marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -410,8 +445,8 @@ public: virtual int wireSize() const; virtual Ice::OptionalFormat optionalFormat() const; - virtual void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*, bool); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, VALUE, void*, bool); + virtual void marshal(VALUE, Ice::OutputStream*, ObjectMap*, bool); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, VALUE, void*, bool); virtual void print(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -431,7 +466,7 @@ class ExceptionInfo : public IceUtil::Shared { public: - VALUE unmarshal(const Ice::InputStreamPtr&); + VALUE unmarshal(Ice::InputStream*); void print(VALUE, IceUtilInternal::Output&); void printMembers(VALUE, IceUtilInternal::Output&, PrintObjectHistory*); @@ -448,7 +483,7 @@ public: // // ObjectWriter wraps a Ruby object for marshaling. // -class ObjectWriter : public Ice::ObjectWriter +class ObjectWriter : public Ice::Object { public: @@ -457,11 +492,12 @@ public: virtual void ice_preMarshal(); - virtual void write(const Ice::OutputStreamPtr&) const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); private: - void writeMembers(const Ice::OutputStreamPtr&, const DataMemberList&) const; + void writeMembers(Ice::OutputStream*, const DataMemberList&) const; VALUE _object; ObjectMap* _map; @@ -471,7 +507,7 @@ private: // // ObjectReader unmarshals the state of an Ice object. // -class ObjectReader : public Ice::ObjectReader +class ObjectReader : public Ice::Object { public: @@ -480,7 +516,8 @@ public: virtual void ice_postUnmarshal(); - virtual void read(const Ice::InputStreamPtr&); + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); virtual ClassInfoPtr getInfo() const; @@ -498,24 +535,36 @@ private: // // ExceptionReader creates a Ruby user exception and unmarshals it. // -class ExceptionReader : public Ice::UserExceptionReader +class ExceptionReader : public Ice::UserException { public: - ExceptionReader(const Ice::CommunicatorPtr&, const ExceptionInfoPtr&); + ExceptionReader(const ExceptionInfoPtr&); ~ExceptionReader() throw(); - virtual void read(const Ice::InputStreamPtr&) const; - virtual bool usesClasses() const; - - virtual std::string ice_name() const; + virtual std::string ice_id() const; +#ifndef ICE_CPP11_MAPPING virtual Ice::UserException* ice_clone() const; +#endif virtual void ice_throw() const; + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + + virtual bool __usesClasses() const; + VALUE getException() const; Ice::SlicedDataPtr getSlicedData() const; + using Ice::UserException::__read; + using Ice::UserException::__write; + +protected: + + virtual void __writeImpl(Ice::OutputStream*) const {} + virtual void __readImpl(Ice::InputStream*) {} + private: ExceptionInfoPtr _info; diff --git a/ruby/src/IceRuby/Util.cpp b/ruby/src/IceRuby/Util.cpp index 6b9ba1314d7..e297c258c03 100644 --- a/ruby/src/IceRuby/Util.cpp +++ b/ruby/src/IceRuby/Util.cpp @@ -311,7 +311,7 @@ IceRuby::createString(const string& str) namespace { -template <typename T> +template <typename T> struct RubyCallArgs { volatile VALUE val; @@ -699,7 +699,7 @@ setExceptionMembers(const Ice::LocalException& ex, VALUE p) m = createEncodingVersion(e.supported); callRuby(rb_iv_set, p, "@supported", m); } - catch(const Ice::NoObjectFactoryException& e) + catch(const Ice::NoValueFactoryException& e) { volatile VALUE v; v = createString(e.reason); @@ -761,7 +761,7 @@ IceRuby::convertLocalException(const Ice::LocalException& ex) // try { - string name = ex.ice_name(); + string name = ex.ice_id().substr(2); volatile VALUE cls = callRuby(rb_path2class, name.c_str()); if(NIL_P(cls)) { @@ -777,7 +777,7 @@ IceRuby::convertLocalException(const Ice::LocalException& ex) } catch(...) { - string msg = "failure occurred while converting exception " + ex.ice_name(); + string msg = "failure occurred while converting exception " + ex.ice_id(); return rb_exc_new2(rb_eRuntimeError, msg.c_str()); } } diff --git a/ruby/src/IceRuby/Util.h b/ruby/src/IceRuby/Util.h index 40054f909d5..1cd6ea08c34 100644 --- a/ruby/src/IceRuby/Util.h +++ b/ruby/src/IceRuby/Util.h @@ -492,7 +492,7 @@ VALUE convertLocalException(const Ice::LocalException&); } \ catch(const ::Ice::Exception& ex) \ { \ - string __ice_msg = "unknown Ice exception: " + ex.ice_name(); \ + string __ice_msg = "unknown Ice exception: " + ex.ice_id(); \ ICE_RUBY_RETHROW(rb_exc_new2(rb_eRuntimeError, __ice_msg.c_str())); \ } \ catch(const std::bad_alloc& ex) \ diff --git a/ruby/src/IceRuby/ValueFactoryManager.cpp b/ruby/src/IceRuby/ValueFactoryManager.cpp new file mode 100644 index 00000000000..ee235bb9272 --- /dev/null +++ b/ruby/src/IceRuby/ValueFactoryManager.cpp @@ -0,0 +1,432 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <ValueFactoryManager.h> +#include <Types.h> +#include <Util.h> +#include <Ice/LocalException.h> + +using namespace std; +using namespace IceRuby; + +static VALUE _valueFactoryManagerClass; + +namespace +{ + +ClassInfoPtr +getClassInfo(const string& id) +{ + ClassInfoPtr info; + + if(id == Ice::Object::ice_staticId()) + { + // + // When the ID is that of Ice::Object, it indicates that the stream has not + // found a factory and is providing us an opportunity to preserve the object. + // + info = lookupClassInfo("::Ice::UnknownSlicedObject"); + } + else + { + info = lookupClassInfo(id); + } + + return info; +} + +} + +extern "C" +void +IceRuby_ValueFactoryManager_mark(ValueFactoryManagerPtr* p) +{ + assert(p); + (*p)->mark(); +} + +extern "C" +void +IceRuby_ValueFactoryManager_free(ValueFactoryManagerPtr* p) +{ + assert(p); + delete p; +} + +IceRuby::ValueFactoryManager::ValueFactoryManager() +{ + // + // Create a Ruby wrapper around this object. Note that this is a cyclic reference. + // + _self = Data_Wrap_Struct(_valueFactoryManagerClass, IceRuby_ValueFactoryManager_mark, + IceRuby_ValueFactoryManager_free, new ValueFactoryManagerPtr(this)); + + _defaultFactory = new DefaultValueFactory; +} + +IceRuby::ValueFactoryManager::~ValueFactoryManager() +{ + assert(_factories.empty()); +} + +void +IceRuby::ValueFactoryManager::add(const Ice::ValueFactoryPtr& f, const string& id) +{ + Lock lock(*this); + + if(id.empty()) + { + if(_defaultFactory->getDelegate()) + { + throw Ice::AlreadyRegisteredException(__FILE__, __LINE__, "value factory", id); + } + + _defaultFactory->setDelegate(f); + } + else + { + FactoryMap::iterator p = _factories.find(id); + if(p != _factories.end()) + { + throw Ice::AlreadyRegisteredException(__FILE__, __LINE__, "value factory", id); + } + + _factories.insert(FactoryMap::value_type(id, f)); + } +} + +Ice::ValueFactoryPtr +IceRuby::ValueFactoryManager::find(const string& id) const +{ + Lock lock(*this); + + if(id.empty()) + { + return _defaultFactory; + } + + FactoryMap::const_iterator p = _factories.find(id); + if(p != _factories.end()) + { + return p->second; + } + + return 0; +} + +void +IceRuby::ValueFactoryManager::addValueFactory(VALUE f, const string& id) +{ + ICE_RUBY_TRY + { + add(new FactoryWrapper(f, false), id); + } + ICE_RUBY_CATCH +} + +VALUE +IceRuby::ValueFactoryManager::findValueFactory(const string& id) const +{ + Ice::ValueFactoryPtr f = find(id); + if(f) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(f); + if(w) + { + return w->getObject(); + } + } + + return Qnil; +} + +void +IceRuby::ValueFactoryManager::addObjectFactory(VALUE f, const string& id) +{ + ICE_RUBY_TRY + { + add(new FactoryWrapper(f, true), id); + } + ICE_RUBY_CATCH +} + +VALUE +IceRuby::ValueFactoryManager::findObjectFactory(const string& id) const +{ + Ice::ValueFactoryPtr f = find(id); + if(f) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(f); + if(w && w->isObjectFactory()) + { + return w->getObject(); + } + } + + return Qnil; +} + +void +IceRuby::ValueFactoryManager::mark() +{ + Lock lock(*this); + + for(FactoryMap::iterator p = _factories.begin(); p != _factories.end(); ++p) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(p->second); + if(w) + { + w->mark(); + } + } + + _defaultFactory->mark(); +} + +void +IceRuby::ValueFactoryManager::markSelf() +{ + Lock lock(*this); + + if(!NIL_P(_self)) + { + rb_gc_mark(_self); + } +} + +VALUE +IceRuby::ValueFactoryManager::getObject() const +{ + return _self; +} + +void +IceRuby::ValueFactoryManager::destroy() +{ + FactoryMap factories; + + { + Lock lock(*this); + + factories.swap(_factories); + + _self = Qnil; + } + + for(FactoryMap::iterator p = factories.begin(); p != factories.end(); ++p) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(p->second); + if(w) + { + w->destroy(); + } + } + + _defaultFactory->destroy(); +} + +IceRuby::FactoryWrapper::FactoryWrapper(VALUE factory, bool isObjectFactory) : + _factory(factory), + _isObjectFactory(isObjectFactory) +{ +} + +Ice::ValuePtr +IceRuby::FactoryWrapper::create(const string& id) +{ + // + // Get the type information. + // + ClassInfoPtr info = getClassInfo(id); + + if(!info) + { + return 0; + } + + // + // Invoke the create method on the Ruby factory object. + // + volatile VALUE str = createString(id); + volatile VALUE obj = callRuby(rb_funcall, _factory, rb_intern("create"), 1, str); + if(NIL_P(obj)) + { + return 0; + } + + return new ObjectReader(obj, info); +} + +VALUE +IceRuby::FactoryWrapper::getObject() const +{ + return _factory; +} + +bool +IceRuby::FactoryWrapper::isObjectFactory() const +{ + return _isObjectFactory; +} + +void +IceRuby::FactoryWrapper::mark() +{ + rb_gc_mark(_factory); +} + +void +IceRuby::FactoryWrapper::destroy() +{ + if(_isObjectFactory) + { + callRuby(rb_funcall, _factory, rb_intern("destroy"), 0); + } +} + +Ice::ValuePtr +IceRuby::DefaultValueFactory::create(const string& id) +{ + Ice::ValuePtr v; + + // + // Give the application-provided default factory a chance to create the object first. + // + if(_delegate) + { + v = _delegate->create(id); + if(v) + { + return v; + } + } + + // + // Get the type information. + // + ClassInfoPtr info = getClassInfo(id); + + if(!info) + { + return 0; + } + + // + // NOTE: We don't do this in Ruby because a generated class can be re-opened to define operations. + // + //// + //// If the requested type is an abstract class, then we give up. + //// + //if(info->isAbstract) + //{ + // return 0; + //} + + // + // Instantiate the object. + // + volatile VALUE obj = callRuby(rb_class_new_instance, 0, reinterpret_cast<VALUE*>(0), info->rubyClass); + assert(!NIL_P(obj)); + return new ObjectReader(obj, info); +} + +void +IceRuby::DefaultValueFactory::setDelegate(const Ice::ValueFactoryPtr& d) +{ + _delegate = d; +} + +VALUE +IceRuby::DefaultValueFactory::getObject() const +{ + if(_delegate) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(_delegate); + if(w) + { + return w->getObject(); + } + } + + return Qnil; +} + +void +IceRuby::DefaultValueFactory::mark() +{ + if(_delegate) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(_delegate); + if(w) + { + w->mark(); + } + } +} + +void +IceRuby::DefaultValueFactory::destroy() +{ + if(_delegate) + { + FactoryWrapperPtr w = FactoryWrapperPtr::dynamicCast(_delegate); + if(w) + { + w->destroy(); + } + } + + _delegate = 0; +} + +extern "C" +VALUE +IceRuby_ValueFactoryManager_add(VALUE self, VALUE factory, VALUE id) +{ + ICE_RUBY_TRY + { + ValueFactoryManagerPtr* p = reinterpret_cast<ValueFactoryManagerPtr*>(DATA_PTR(self)); + assert(p); + + string type = getString(id); + (*p)->addValueFactory(factory, type); + } + ICE_RUBY_CATCH + return Qnil; +} + +extern "C" +VALUE +IceRuby_ValueFactoryManager_find(VALUE self, VALUE id) +{ + ICE_RUBY_TRY + { + ValueFactoryManagerPtr* p = reinterpret_cast<ValueFactoryManagerPtr*>(DATA_PTR(self)); + assert(p); + + string type = getString(id); + return (*p)->findValueFactory(type); + } + ICE_RUBY_CATCH + return Qnil; +} + +bool +IceRuby::initValueFactoryManager(VALUE iceModule) +{ + _valueFactoryManagerClass = rb_define_class_under(iceModule, "ValueFactoryManagerI", rb_cObject); + + // + // Instance methods. + // + rb_define_method(_valueFactoryManagerClass, "add", CAST_METHOD(IceRuby_ValueFactoryManager_add), 2); + rb_define_method(_valueFactoryManagerClass, "find", CAST_METHOD(IceRuby_ValueFactoryManager_find), 1); + + return true; +} diff --git a/ruby/src/IceRuby/ValueFactoryManager.h b/ruby/src/IceRuby/ValueFactoryManager.h new file mode 100644 index 00000000000..d0b79d23528 --- /dev/null +++ b/ruby/src/IceRuby/ValueFactoryManager.h @@ -0,0 +1,100 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 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. +// +// ********************************************************************** + +#ifndef ICE_RUBY_OBJECT_FACTORY_H +#define ICE_RUBY_OBJECT_FACTORY_H + +#include <Config.h> +#include <Ice/ValueFactory.h> +#include <IceUtil/Mutex.h> + +namespace IceRuby +{ + +bool initValueFactoryManager(VALUE); + +class FactoryWrapper : public Ice::ValueFactory +{ +public: + + FactoryWrapper(VALUE, bool); + + virtual Ice::ValuePtr create(const std::string&); + + VALUE getObject() const; + + bool isObjectFactory() const; + + void mark(); + + void destroy(); + +protected: + + VALUE _factory; + bool _isObjectFactory; +}; +typedef IceUtil::Handle<FactoryWrapper> FactoryWrapperPtr; + +class DefaultValueFactory : public Ice::ValueFactory +{ +public: + + virtual Ice::ValuePtr create(const std::string&); + + void setDelegate(const Ice::ValueFactoryPtr&); + Ice::ValueFactoryPtr getDelegate() const { return _delegate; } + + VALUE getObject() const; + + void mark(); + + void destroy(); + +private: + + Ice::ValueFactoryPtr _delegate; +}; +typedef IceUtil::Handle<DefaultValueFactory> DefaultValueFactoryPtr; + +class ValueFactoryManager : public Ice::ValueFactoryManager, public IceUtil::Mutex +{ +public: + + ValueFactoryManager(); + ~ValueFactoryManager(); + + virtual void add(const Ice::ValueFactoryPtr&, const std::string&); + virtual Ice::ValueFactoryPtr find(const std::string&) const; + + void addValueFactory(VALUE, const std::string&); + VALUE findValueFactory(const std::string&) const; + void addObjectFactory(VALUE, const std::string&); + VALUE findObjectFactory(const std::string&) const; + + void mark(); + void markSelf(); + + VALUE getObject() const; + + void destroy(); + +private: + + typedef std::map<std::string, Ice::ValueFactoryPtr> FactoryMap; + + VALUE _self; + FactoryMap _factories; + DefaultValueFactoryPtr _defaultFactory; +}; +typedef IceUtil::Handle<ValueFactoryManager> ValueFactoryManagerPtr; + +} + +#endif |