void Nuria::RestfulHttpNode::registerAnnotatedHandlers () { this->d_ptr->loaded = true; if (!this->d_ptr->metaObject) { this->d_ptr->metaObject = MetaObject::byName (metaObject ()->className ()); if (!this->d_ptr->metaObject) { nError() << "Failed to auto-find meta object of class" << metaObject ()->className (); return; } } // MetaObject *meta = this->d_ptr->metaObject; for (int i = 0; i < meta->methodCount (); i++) { MetaMethod method = meta->method (i); registerMetaMethod (method); } }
void GwObjectHost::harvestServiceOriginatingObjects(Message& msg, TransportSocketPtr sender) { Signature signature; { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); MetaObject* metaObject = NULL; const Signature& (MetaMethod::*signatureGetter)() const = NULL; if (msg.type() == Message::Type_Reply || msg.type() == Message::Type_Error) { std::map<ServiceId, std::map<ObjectId, MetaObject> >::iterator sit = _servicesMetaObjects.find(msg.service()); if (msg.function() == Message::BoundObjectFunction_MetaObject && sit->second.find(msg.object()) == sit->second.end()) { boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); _servicesMetaObjects[msg.service()][Message::GenericObject_Main] = extractReturnedMetaObject(msg, sender); return; } metaObject = &_servicesMetaObjects[msg.service()][msg.object()]; signatureGetter = &MetaMethod::returnSignature; } else if (msg.type() == Message::Type_Call || msg.type() == Message::Type_Post) { // if a service does a CALL, he does so on a user-supplied object. std::map<GwObjectId, MetaObject>::iterator mit = _objectsMetaObjects.find(msg.object()); assert(mit != _objectsMetaObjects.end()); metaObject = &mit->second; signatureGetter = &MetaMethod::parametersSignature; } const MetaMethod* method = metaObject->method(msg.function()); if (!method) return; signature = (method->*signatureGetter)(); } if (!hasObjectsSomewhere(signature)) { // no object can be here return; } AnyReference passed = msg.value(signature, sender); StreamContext filler; MockObjectHost host(Message::Service_Server); Message dummy; // we don't want to pollute the original message and potentially change valid id // of contained objects, so we do it in an unrelated message. dummy.setValue(passed, signature, &host, &filler); const ObjectHost::ObjectMap& objects = host.objects(); std::map<ObjectId, MetaObject> newServicesMetaObject; for (ObjectHost::ObjectMap::const_iterator it = objects.begin(), end = objects.end(); it != end; ++it) { ServiceBoundObject* sbo = static_cast<ServiceBoundObject*>(it->second.get()); RemoteObject* ro = static_cast<RemoteObject*>(sbo->object().asGenericObject()->value); // We set an empty transportsocket. // Otherwise when we destroy `passed` below, the remoteobject // will attempt to send back home a `terminate` message, which we don't want. // By setting a null socket the object will stay alive on the remote end. ro->setTransportSocket(TransportSocketPtr()); newServicesMetaObject[ro->object()] = ro->metaObject(); } { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); _servicesMetaObjects[msg.service()].insert(newServicesMetaObject.begin(), newServicesMetaObject.end()); } passed.destroy(); }