[tracker] Add libtracker-remote
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker] Add libtracker-remote
- Date: Sun, 20 Nov 2016 16:45:37 +0000 (UTC)
commit 2b63b4b33a1a80bbd5ebeeaadd26f3cdf2c58846
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Mar 20 12:50:38 2016 +0100
Add libtracker-remote
This is yet another libtracker-sparql backend to connect to remote
HTTP SPARQL endpoints. Connections are made explicitly through the
tracker_sparql_connection_remote_new() API call, passing a server
to connect to. This commit introduces support for
application/sparql-results+json as specified in
https://www.w3.org/TR/sparql11-results-json/. XML format will be
handled next.
Just readonly queries are supported, and provided there's no
authentication schemes.
https://bugzilla.gnome.org/show_bug.cgi?id=773031
configure.ac | 10 ++
src/Makefile.am | 1 +
src/libtracker-remote/Makefile.am | 34 +++++
src/libtracker-remote/tracker-json-cursor.vala | 139 ++++++++++++++++++++
src/libtracker-remote/tracker-remote.vala | 80 +++++++++++
src/libtracker-sparql-backend/Makefile.am | 6 +-
src/libtracker-sparql-backend/tracker-backend.vala | 4 +
src/libtracker-sparql/tracker-connection.vala | 10 ++
8 files changed, 283 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d7ce9a2..25dcc2e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -232,6 +232,8 @@ GSTREAMER_REQUIRED=0.10.31
GUPNP_DLNA_REQUIRED=0.9.4
LIBPNG_REQUIRED=1.2
LIBMEDIAART_REQUIRED=1.9.0
+JSON_GLIB_REQUIRED=1.0
+LIBSOUP_REQUIRED=2.40
# 3.6.11 for sqlite_backup API
# 3.6.16 to fix test failures
@@ -285,6 +287,13 @@ LIBTRACKER_DIRECT_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
PKG_CHECK_MODULES(LIBTRACKER_DIRECT, [$LIBTRACKER_DIRECT_REQUIRED])
+# Check requirements for libtracker-remote
+LIBTRACKER_REMOTE_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
+ libsoup-2.4 >= $LIBSOUP_REQUIRED
+ json-glib-1.0 >= $JSON_GLIB_REQUIRED"
+
+PKG_CHECK_MODULES(LIBTRACKER_REMOTE, [$LIBTRACKER_REMOTE_REQUIRED])
+
# Check requirements for libtracker-extract
LIBTRACKER_EXTRACT_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
gio-unix-2.0 >= $GLIB_REQUIRED
@@ -2622,6 +2631,7 @@ AC_CONFIG_FILES([
src/libtracker-control/tracker-control.pc
src/libtracker-data/Makefile
src/libtracker-direct/Makefile
+ src/libtracker-remote/Makefile
src/libtracker-sparql-backend/Makefile
src/libtracker-fts/Makefile
src/libtracker-extract/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index ae3be69..532165a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS = \
libtracker-bus \
libtracker-data \
libtracker-direct \
+ libtracker-remote \
libtracker-sparql-backend \
libtracker-extract \
libtracker-miner \
diff --git a/src/libtracker-remote/Makefile.am b/src/libtracker-remote/Makefile.am
new file mode 100644
index 0000000..b92ddc2
--- /dev/null
+++ b/src/libtracker-remote/Makefile.am
@@ -0,0 +1,34 @@
+noinst_LTLIBRARIES = libtracker-remote.la
+
+AM_VALAFLAGS = \
+ --includedir=libtracker-remote \
+ --header tracker-remote.h \
+ --vapi tracker-remote.vapi \
+ --pkg gio-2.0 \
+ --pkg libsoup-2.4 \
+ --pkg json-glib-1.0 \
+ $(BUILD_VALAFLAGS) \
+ $(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi
+
+AM_CPPFLAGS = \
+ $(BUILD_VALACFLAGS) \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ $(LIBTRACKER_REMOTE_CFLAGS)
+
+libtracker_remote_la_SOURCES = \
+ tracker-json-cursor.vala \
+ tracker-remote.vala
+
+libtracker_remote_la_LIBADD = \
+ $(BUILD_LIBS) \
+ $(LIBTRACKER_REMOTE_LIBS)
+
+noinst_HEADERS = \
+ tracker-remote.h
+
+BUILT_SOURCES = \
+ libtracker_remote_la_vala.stamp
+
+DISTCLEANFILES = \
+ libtracker_remote_la_vala.stamp
diff --git a/src/libtracker-remote/tracker-json-cursor.vala b/src/libtracker-remote/tracker-json-cursor.vala
new file mode 100644
index 0000000..e464947
--- /dev/null
+++ b/src/libtracker-remote/tracker-json-cursor.vala
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+public class Tracker.Remote.JsonCursor : Tracker.Sparql.Cursor {
+ internal Json.Parser _parser;
+ internal Json.Array _vars;
+ internal Json.Array _results;
+ internal Json.Object _cur_row;
+ internal uint _cur_idx = 0;
+ internal bool _started_iterating = false;
+
+ const string XSD_NS = "http://www.w3.org/2001/XMLSchema#";
+
+ public JsonCursor (string document, long length) throws GLib.Error {
+ var parser = new Json.Parser ();
+ parser.load_from_data (document, length);
+
+ var root = parser.get_root ().get_object ();
+ var head = root.get_object_member ("head");
+ var results = root.get_object_member ("results");
+
+ _parser = parser;
+ _vars = head.get_array_member ("vars");
+ _results = results.get_array_member ("bindings");
+ _started_iterating = false;
+ }
+
+ public override int n_columns {
+ get { return (int) _vars.get_length (); }
+ }
+
+ public override Sparql.ValueType get_value_type (int column) requires (_cur_row != null) {
+ var col_node = _cur_row.get_member (get_variable_name (column));
+
+ if (col_node == null)
+ return Sparql.ValueType.UNBOUND;
+
+ var object = col_node.get_object ();//_cur_row.get_object_member (get_variable_name (column));
+ unowned string str = object.get_string_member ("type");
+
+ switch (str) {
+ case "uri":
+ return Sparql.ValueType.URI;
+ case "bnode":
+ return Sparql.ValueType.BLANK_NODE;
+ case "literal": {
+ var node = object.get_member ("datatype");
+
+ if (node == null)
+ return Sparql.ValueType.STRING;
+
+ str = node.get_string ();
+
+ switch (str) {
+ case XSD_NS + "byte":
+ case XSD_NS + "int":
+ case XSD_NS + "integer":
+ case XSD_NS + "long":
+ return Sparql.ValueType.INTEGER;
+ case XSD_NS + "decimal":
+ case XSD_NS + "double":
+ return Sparql.ValueType.DOUBLE;
+ case XSD_NS + "dateTime":
+ return Sparql.ValueType.DATETIME;
+ default:
+ return Sparql.ValueType.STRING;
+ }
+ }
+
+ default:
+ return Sparql.ValueType.STRING;
+ }
+ }
+
+ public override unowned string? get_variable_name (int column) {
+ return _vars.get_string_element (column);
+ }
+
+ public override unowned string? get_string (int column, out long length = null) requires (_cur_row !=
null) {
+ var col_node = _cur_row.get_member (get_variable_name (column));
+ length = 0;
+
+ if (col_node == null)
+ return null;
+
+ var object = col_node.get_object ();
+
+ if (object == null)
+ return null;
+
+ unowned string str = object.get_string_member ("value");
+ length = str.length;
+ return str;
+ }
+
+ public override bool next (Cancellable? cancellable = null) throws IOError, GLib.Error {
+ if (_started_iterating)
+ _cur_idx++;
+
+ if (_cur_idx >= _results.get_length ())
+ return false;
+
+ if (cancellable != null && cancellable.is_cancelled ())
+ throw new IOError.CANCELLED ("Operation was cancelled");
+
+ _started_iterating = true;
+ _cur_row = _results.get_object_element (_cur_idx);
+ return true;
+ }
+
+ public async override bool next_async (Cancellable? cancellable = null) throws IOError, GLib.Error {
+ return next (cancellable);
+ }
+
+ public override void rewind () {
+ _started_iterating = false;
+ }
+
+ public override void close () {
+ }
+}
diff --git a/src/libtracker-remote/tracker-remote.vala b/src/libtracker-remote/tracker-remote.vala
new file mode 100644
index 0000000..395b1f6
--- /dev/null
+++ b/src/libtracker-remote/tracker-remote.vala
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+public class Tracker.Remote.Connection : Tracker.Sparql.Connection {
+ internal Soup.Session _session;
+ internal string _base_uri;
+
+ const string JSON_TYPE = "application/sparql-results+json";
+
+ public Connection (string base_uri) {
+ _base_uri = base_uri;
+ _session = new Soup.Session ();
+ }
+
+ private Soup.Message create_request (string sparql) {
+ var uri = _base_uri + sparql;
+ var message = new Soup.Message ("GET", uri);
+ var headers = message.request_headers;
+
+ headers.append ("Accept", JSON_TYPE);
+
+ return message;
+ }
+
+ private Sparql.Cursor create_cursor (Soup.Message message) throws GLib.Error, Sparql.Error {
+ string document = (string) message.response_body.flatten ().data;
+
+ if (message.status_code != Soup.Status.OK) {
+ throw new Sparql.Error.UNSUPPORTED ("Unhandled status code %u, document is: %s",
+ message.status_code, document);
+ }
+
+ var headers = message.response_headers;
+ var content_type = headers.get_content_type (null);
+ long length = document.length;
+
+ if (content_type == JSON_TYPE) {
+ return new Tracker.Remote.JsonCursor (document, length);
+ } else {
+ throw new Sparql.Error.UNSUPPORTED ("Unknown content type '%s', document is: %s",
content_type, document);
+ }
+ }
+
+ public override Sparql.Cursor query (string sparql, Cancellable? cancellable) throws GLib.Error,
Sparql.Error, IOError {
+ var message = create_request (sparql);
+
+ _session.send_message (message);
+
+ if (cancellable != null && cancellable.is_cancelled ())
+ throw new IOError.CANCELLED ("Operation was cancelled");
+
+ return create_cursor (message);
+ }
+
+ public async override Sparql.Cursor query_async (string sparql, Cancellable? cancellable) throws
GLib.Error, Sparql.Error, IOError {
+ var message = create_request (sparql);
+
+ yield _session.send_async (message, cancellable);
+
+ return create_cursor (message);
+ }
+}
diff --git a/src/libtracker-sparql-backend/Makefile.am b/src/libtracker-sparql-backend/Makefile.am
index 0db7186..8d7934d 100644
--- a/src/libtracker-sparql-backend/Makefile.am
+++ b/src/libtracker-sparql-backend/Makefile.am
@@ -5,12 +5,14 @@ AM_VALAFLAGS = \
$(BUILD_VALAFLAGS) \
$(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi \
$(top_srcdir)/src/libtracker-bus/tracker-bus.vapi \
- $(top_srcdir)/src/libtracker-direct/tracker-direct.vapi
+ $(top_srcdir)/src/libtracker-direct/tracker-direct.vapi \
+ $(top_srcdir)/src/libtracker-remote/tracker-remote.vapi
AM_CPPFLAGS = \
$(BUILD_VALACFLAGS) \
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
+ $(LIBTRACKER_REMOTE_CFLAGS) \
$(LIBTRACKER_SPARQL_CFLAGS)
libtracker_sparql_@TRACKER_API_VERSION@_la_SOURCES = \
@@ -20,7 +22,9 @@ libtracker_sparql_@TRACKER_API_VERSION@_la_LIBADD = \
$(top_builddir)/src/libtracker-sparql/libtracker-sparql.la \
$(top_builddir)/src/libtracker-bus/libtracker-bus.la \
$(top_builddir)/src/libtracker-direct/libtracker-direct.la \
+ $(top_builddir)/src/libtracker-remote/libtracker-remote.la \
$(BUILD_LIBS) \
+ $(LIBTRACKER_REMOTE_LIBS) \
$(LIBTRACKER_SPARQL_LIBS)
libtracker_sparql_@TRACKER_API_VERSION@_la_LDFLAGS = \
diff --git a/src/libtracker-sparql-backend/tracker-backend.vala
b/src/libtracker-sparql-backend/tracker-backend.vala
index e3fdc2f..6d7e982 100644
--- a/src/libtracker-sparql-backend/tracker-backend.vala
+++ b/src/libtracker-sparql-backend/tracker-backend.vala
@@ -409,3 +409,7 @@ public async static Tracker.Sparql.Connection tracker_sparql_connection_get_dire
public static Tracker.Sparql.Connection tracker_sparql_connection_get_direct (Cancellable? cancellable =
null) throws Tracker.Sparql.Error, IOError, DBusError, SpawnError {
return Tracker.Sparql.Backend.get_internal (cancellable);
}
+
+public static Tracker.Sparql.Connection tracker_sparql_connection_remote_new (string url_base) {
+ return new Tracker.Remote.Connection (url_base);
+}
diff --git a/src/libtracker-sparql/tracker-connection.vala b/src/libtracker-sparql/tracker-connection.vala
index ad97f98..b6e7fe9 100644
--- a/src/libtracker-sparql/tracker-connection.vala
+++ b/src/libtracker-sparql/tracker-connection.vala
@@ -211,6 +211,16 @@ public abstract class Tracker.Sparql.Connection : Object {
public extern static new Connection get_direct (Cancellable? cancellable = null) throws Sparql.Error,
IOError, DBusError, SpawnError;
/**
+ * tracker_sparql_connection_remote_new:
+ *
+ * Returns: a new remote #TrackerSparqlConnection. Call g_object_unref() on the
+ * object when no longer used.
+ *
+ * Since: 1.12
+ */
+ public extern static new Connection remote_new (string uri_base);
+
+ /**
* tracker_sparql_connection_query:
* @self: a #TrackerSparqlConnection
* @sparql: string containing the SPARQL query
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]