From 085f5e9c5eec12171596c47c0b70f6634dbc1402 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 29 May 2009 00:44:49 +0000 Subject: Node creation via HTTP. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2045 a436a847-0d15-0410-975c-d299462d15a1 --- src/client/ClientStore.cpp | 2 +- src/client/HTTPClientReceiver.cpp | 3 ++- src/client/HTTPEngineSender.cpp | 34 ++++++++++++++++++++++++++++++---- src/client/HTTPEngineSender.hpp | 12 ++++++++++-- src/client/client.cpp | 5 +++-- src/client/client.hpp | 6 ++++-- src/engine/HTTPClientSender.cpp | 29 +++++++++++++++++++++-------- src/engine/HTTPEngineReceiver.cpp | 15 +++++++-------- src/engine/QueuedEngineInterface.cpp | 9 ++++----- src/ingen/main.cpp | 5 +++-- src/serialisation/Parser.cpp | 18 ++++++++++++------ 11 files changed, 97 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index bb501079..7a2a4ef5 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -327,7 +327,7 @@ ClientStore::put(const URI& uri, const Resource::Properties& properties) p->set_properties(properties); add_object(p); } else { - cerr << "WARNING: Illegal port " << path << endl; + cerr << "WARNING: Port " << path << " is malformed" << endl; } } else { cerr << "WARNING: Ignoring object " << path << " with unknown type " diff --git a/src/client/HTTPClientReceiver.cpp b/src/client/HTTPClientReceiver.cpp index 6d0dbb1b..be1b6238 100644 --- a/src/client/HTTPClientReceiver.cpp +++ b/src/client/HTTPClientReceiver.cpp @@ -99,7 +99,7 @@ HTTPClientReceiver::Listener::Listener(HTTPClientReceiver* receiver, const std:: void HTTPClientReceiver::update(const std::string& str) { - cout << _parser->parse_update(_world, _target.get(), str, "."); + cout << _parser->parse_update(_world, _target.get(), str, ""); } void @@ -180,6 +180,7 @@ HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, voi } else { cerr << "UNKNOWN MESSAGE: " << path << endl; + me->update(msg->response_body->data); } } diff --git a/src/client/HTTPEngineSender.cpp b/src/client/HTTPEngineSender.cpp index 692d01fc..fa3509f6 100644 --- a/src/client/HTTPEngineSender.cpp +++ b/src/client/HTTPEngineSender.cpp @@ -17,8 +17,12 @@ #include #include +#include "raul/AtomRDF.hpp" +#include "redlandmm/Model.hpp" +#include "module/World.hpp" #include "HTTPEngineSender.hpp" + using namespace std; using namespace Raul; @@ -27,8 +31,9 @@ using namespace Shared; namespace Client { -HTTPEngineSender::HTTPEngineSender(const URI& engine_url) - : _engine_url(engine_url) +HTTPEngineSender::HTTPEngineSender(const World* world, const URI& engine_url) + : _world(*world->rdf_world) + , _engine_url(engine_url) , _id(0) , _enabled(true) { @@ -103,11 +108,32 @@ HTTPEngineSender::quit() // Object commands +void +HTTPEngineSender::message_callback(SoupSession* session, SoupMessage* msg, void* ptr) +{ + cerr << "HTTP CALLBACK" << endl; +} + void -HTTPEngineSender::put(const Raul::URI& path, - const Shared::Resource::Properties& properties) +HTTPEngineSender::put(const URI& uri, + const Resource::Properties& properties) { + const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); + const string full_uri = _engine_url.str() + "/" + path; + + Redland::Model model(_world); + for (Resource::Properties::const_iterator i = properties.begin(); i != properties.end(); ++i) + model.add_statement( + Redland::Resource(_world, path), + i->first.str(), + AtomRDF::atom_to_node(_world, i->second)); + + const string str = model.serialise_to_string(); + SoupMessage* msg = soup_message_new("PUT", full_uri.c_str()); + assert(msg); + soup_message_set_request(msg, "application/x-turtle", SOUP_MEMORY_COPY, str.c_str(), str.length()); + soup_session_send_message(_session, msg); } diff --git a/src/client/HTTPEngineSender.hpp b/src/client/HTTPEngineSender.hpp index 00df2d7e..b5f8cfa5 100644 --- a/src/client/HTTPEngineSender.hpp +++ b/src/client/HTTPEngineSender.hpp @@ -23,8 +23,12 @@ #include #include "raul/Path.hpp" #include "interface/EngineInterface.hpp" +#include "redlandmm/World.hpp" namespace Ingen { + +namespace Shared { class World; } + namespace Client { @@ -35,9 +39,10 @@ namespace Client { * * \ingroup IngenClient */ -class HTTPEngineSender : public Shared::EngineInterface { +class HTTPEngineSender : public Shared::EngineInterface +{ public: - HTTPEngineSender(const Raul::URI& engine_url); + HTTPEngineSender(const Shared::World* world, const Raul::URI& engine_url); ~HTTPEngineSender(); Raul::URI uri() const { return _engine_url; } @@ -115,7 +120,10 @@ public: void request_all_objects(); protected: + static void message_callback(SoupSession* session, SoupMessage* msg, void* ptr); + SoupSession* _session; + Redland::World& _world; const Raul::URI _engine_url; int _client_port; int32_t _id; diff --git a/src/client/client.cpp b/src/client/client.cpp index 3ced5f63..53d7810f 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -26,6 +26,7 @@ #include "HTTPEngineSender.hpp" #endif + using namespace std; namespace Ingen { @@ -33,7 +34,7 @@ namespace Client { SharedPtr -new_remote_interface(const std::string& url) +new_remote_interface(Ingen::Shared::World* world, const std::string& url) { const string scheme = url.substr(0, url.find(":")); @@ -47,7 +48,7 @@ new_remote_interface(const std::string& url) #ifdef HAVE_SOUP if (scheme == "http") { - HTTPEngineSender* hes = new HTTPEngineSender(url); + HTTPEngineSender* hes = new HTTPEngineSender(world, url); hes->attach(rand(), true); return SharedPtr(hes); } diff --git a/src/client/client.hpp b/src/client/client.hpp index b2543c22..9ad1423a 100644 --- a/src/client/client.hpp +++ b/src/client/client.hpp @@ -24,13 +24,15 @@ namespace Ingen { class Engine; -namespace Shared { class EngineInterface; } +namespace Shared { class EngineInterface; class World; } namespace Client { extern "C" { - SharedPtr new_remote_interface(const std::string& url); + SharedPtr new_remote_interface( + Shared::World* world, const std::string& url); + SharedPtr new_queued_interface(SharedPtr engine); } diff --git a/src/engine/HTTPClientSender.cpp b/src/engine/HTTPClientSender.cpp index 6735c164..d77f684e 100644 --- a/src/engine/HTTPClientSender.cpp +++ b/src/engine/HTTPClientSender.cpp @@ -16,6 +16,7 @@ */ #include +#include #include "raul/Atom.hpp" #include "raul/AtomRDF.hpp" #include "serialisation/Serialiser.hpp" @@ -28,17 +29,18 @@ using namespace Raul; namespace Ingen { +using namespace Shared; + void HTTPClientSender::response_ok(int32_t id) { - cout << "HTTP OK" << endl; } void HTTPClientSender::response_error(int32_t id, const std::string& msg) { - cout << "HTTP ERROR" << endl; + cout << "HTTP ERROR " << id << ": " << msg << endl; } @@ -50,10 +52,21 @@ HTTPClientSender::error(const std::string& msg) void -HTTPClientSender::put(const URI& path, - const Shared::Resource::Properties& properties) +HTTPClientSender::put(const URI& uri, + const Resource::Properties& properties) { - cerr << "HTTP CLIENT PUT " << path << endl; + const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); + const string full_uri = _url + "/" + path; + + Redland::Model model(*_engine.world()->rdf_world); + for (Resource::Properties::const_iterator i = properties.begin(); i != properties.end(); ++i) + model.add_statement( + Redland::Resource(*_engine.world()->rdf_world, path), + i->first.str(), + AtomRDF::atom_to_node(*_engine.world()->rdf_world, i->second)); + + const string str = model.serialise_to_string(); + send_chunk(str); } @@ -138,16 +151,16 @@ HTTPClientSender::activity(const Path& path) } #if 0 -static void null_deleter(const Shared::GraphObject*) {} +static void null_deleter(const GraphObject*) {} bool -HTTPClientSender::new_object(const Shared::GraphObject* object) +HTTPClientSender::new_object(const GraphObject* object) { SharedPtr serialiser = _engine.world()->serialiser; serialiser->start_to_string("/", ""); // FIXME: kludge // FIXME: engine boost dependency? - boost::shared_ptr obj((Shared::GraphObject*)object, null_deleter); + boost::shared_ptr obj((GraphObject*)object, null_deleter); serialiser->serialise(obj); string str = serialiser->finish(); send_chunk(str); diff --git a/src/engine/HTTPEngineReceiver.cpp b/src/engine/HTTPEngineReceiver.cpp index 61d74ada..b2d3ca99 100644 --- a/src/engine/HTTPEngineReceiver.cpp +++ b/src/engine/HTTPEngineReceiver.cpp @@ -153,6 +153,7 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const soup_message_set_status(msg, SOUP_STATUS_OK); soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, r.c_str(), r.length()); return; + } else if (path.substr(0, 6) == "/patch") { path = '/' + path.substr(6); @@ -167,15 +168,10 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const soup_message_set_status(msg, SOUP_STATUS_OK); soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, buf, strlen(buf)); return; - - } else { - soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_STATIC, - "Unknown path\n\n", 14); - return; } if (!Path::is_valid(path)) { + cerr << "HTTP BAD REQUEST" << endl; soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); const string& err = (boost::format("Bad path: %1%") % path).str(); soup_message_set_response(msg, "text/plain", SOUP_MEMORY_COPY, @@ -223,6 +219,7 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const // Be sure object doesn't exist Store::const_iterator start = store->find(path); if (start != store->end()) { + cerr << "HTTP CONFLICT" << endl; soup_message_set_status(msg, SOUP_STATUS_CONFLICT); return; } @@ -230,16 +227,18 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const // Get parser SharedPtr parser = me->_engine.world()->parser; if (!parser) { + cerr << "HTTP INTERNAL ERROR" << endl; soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } - //cout << "POST: " << msg->request_body->data << endl; + parser->parse_string(me->_engine.world(), me, msg->request_body->data, ""); // Load object soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); + } else if (msg->method == SOUP_METHOD_POST) { - //cout << "PUT: " << msg->request_body->data << endl; + cout << "POST" << endl; soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); } else { soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp index cce6bb9d..4873f21b 100644 --- a/src/engine/QueuedEngineInterface.cpp +++ b/src/engine/QueuedEngineInterface.cpp @@ -155,17 +155,16 @@ void QueuedEngineInterface::put(const URI& uri, const Resource::Properties& properties) { - size_t hash = uri.find("#"); - bool meta = (hash != string::npos); - Path path(meta ? (string("/") + uri.chop_start("#")) : uri.str()); + bool meta = uri.substr(0, 6) == "meta:#"; + URI subject(meta ? (string("path:/") + uri.substr(6)) : uri.str()); + /*cerr << "ENGINE PUT " << subject << " {" << endl; typedef Resource::Properties::const_iterator iterator; - /*cerr << "ENGINE PUT " << path << " (" << path << ") {" << endl; for (iterator i = properties.begin(); i != properties.end(); ++i) cerr << "\t" << i->first << " = " << i->second << " :: " << i->second.type() << endl; cerr << "}" << endl;*/ - push_queued(new SetMetadataEvent(_engine, _responder, now(), this, meta, path, properties)); + push_queued(new SetMetadataEvent(_engine, _responder, now(), this, meta, subject, properties)); } diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp index 647aa9dd..3ead6146 100644 --- a/src/ingen/main.cpp +++ b/src/ingen/main.cpp @@ -189,10 +189,11 @@ main(int argc, char** argv) /* If we don't have a local engine interface (for GUI), use network */ if (client_module && ! engine_interface) { - SharedPtr (*new_remote_interface)(const std::string&) = NULL; + SharedPtr (*new_remote_interface) + (Ingen::Shared::World*, const std::string&) = NULL; if (client_module->get_symbol("new_remote_interface", (void*&)new_remote_interface)) { - engine_interface = new_remote_interface(args.connect_arg); + engine_interface = new_remote_interface(world, args.connect_arg); } else { cerr << "Unable to find symbol 'new_remote_interface' in " "ingen_client module, aborting." << endl; diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index e01adc1f..50e00439 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -167,7 +167,7 @@ Parser::parse_update( target->del(object.to_string()); } - // Variable settings + // Properties query = Redland::Query(*world->rdf_world, "SELECT DISTINCT ?s ?p ?o WHERE {\n" "?s ?p ?o .\n" @@ -177,17 +177,19 @@ Parser::parse_update( for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Glib::Mutex::Lock lock(world->rdf_world->mutex()); - const string obj_uri((*i)["s"].to_string()); + string obj_uri((*i)["s"].to_string()); const string key(world->rdf_world->qualify((*i)["p"].to_string())); const Redland::Node& val_node((*i)["o"]); const Atom a(AtomRDF::node_to_atom(val_node)); + if (obj_uri.find(":") == string::npos) + obj_uri = "path:" + obj_uri; if (key != "") target->set_property(obj_uri, key, a); } // Connections - parse_connections(world, target, model, base_uri, "/"); + //parse_connections(world, target, model, base_uri, "/"); // Port values query = Redland::Query(*world->rdf_world, @@ -286,7 +288,7 @@ Parser::parse( } else if (rdf_class == node_class) { ret = parse_node(world, target, model, subject, path, data); } else if (rdf_class == in_port_class || rdf_class == out_port_class) { - cerr << "PARSE PORT" << endl; + parse_properties(world, target, model, subject, string("path:") + path, data); } if (!ret) { @@ -298,8 +300,12 @@ Parser::parse( root_path = ret; } else if (is_plugin) { - if (URI::is_valid(subject.to_string())) - parse_properties(world, target, model, subject, subject.to_string()); + string subject_str = subject.to_string(); + if (URI::is_valid(subject_str)) { + if (subject == document_uri) + subject_str = Path::root_uri; + parse_properties(world, target, model, subject, subject_str); + } } } -- cgit v1.2.1