[tracker/wip/carlosg/sparql1.1: 1/7] libtracker-sparql: Add TrackerEndpointDBus



commit 3a64e5ef97678a73dc814a12bc4b3e865b415230
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Aug 4 14:28:08 2019 +0200

    libtracker-sparql: Add TrackerEndpointDBus
    
    This object allows exporting a sparql connection at a given DBus connection
    and object path.

 src/libtracker-sparql-backend/tracker-sparql-2.map |   1 +
 .../libtracker-sparql-intermediate-c.vapi          |  10 +
 src/libtracker-sparql/meson.build                  |   6 +-
 src/libtracker-sparql/tracker-endpoint-dbus.c      | 610 +++++++++++++++++++++
 src/libtracker-sparql/tracker-endpoint-dbus.h      |  41 ++
 src/libtracker-sparql/tracker-endpoint.c           | 118 ++++
 src/libtracker-sparql/tracker-endpoint.h           |  41 ++
 src/libtracker-sparql/tracker-sparql.h             |   2 +
 8 files changed, 828 insertions(+), 1 deletion(-)
---
diff --git a/src/libtracker-sparql-backend/tracker-sparql-2.map 
b/src/libtracker-sparql-backend/tracker-sparql-2.map
index 3dee56514..efc773aa8 100644
--- a/src/libtracker-sparql-backend/tracker-sparql-2.map
+++ b/src/libtracker-sparql-backend/tracker-sparql-2.map
@@ -11,6 +11,7 @@ global:
   tracker_namespace_manager_*;
   tracker_resource_*;
   tracker_notifier_*;
+  tracker_endpoint_*;
 local:
   *;
 };
diff --git a/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi 
b/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi
index 25800f0cf..0c18473c2 100644
--- a/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi
+++ b/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi
@@ -100,4 +100,14 @@ namespace Tracker {
                        public string get_location ();
                }
        }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-endpoint.h")]
+       public class Endpoint : GLib.Object {
+               Sparql.Connection get_sparql_connection ();
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-endpoint-dbus.h")]
+       public class EndpointDBus : GLib.Object, GLib.Initable {
+               public EndpointDBus (Sparql.Connection sparql_conn, GLib.DBusConnection? dbus_conn, string 
object_path, GLib.Cancellable? cancellable) throws GLib.Error;
+       }
 }
diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build
index 20fa8c35c..71b5f0272 100644
--- a/src/libtracker-sparql/meson.build
+++ b/src/libtracker-sparql/meson.build
@@ -55,6 +55,8 @@ tracker_sparql_generated_header = custom_target('tracker-sparql-generated-header
 # Now build the C parts ...
 
 libtracker_sparql_c_sources = files(
+    'tracker-endpoint.c',
+    'tracker-endpoint-dbus.c',
     'tracker-namespace-manager.c',
     'tracker-notifier.c',
     'tracker-resource.c',
@@ -63,6 +65,8 @@ libtracker_sparql_c_sources = files(
 )
 
 libtracker_sparql_c_public_headers = files(
+    'tracker-endpoint.h',
+    'tracker-endpoint-dbus.h',
     'tracker-namespace-manager.h',
     'tracker-notifier.h',
     'tracker-resource.h',
@@ -70,7 +74,7 @@ libtracker_sparql_c_public_headers = files(
 )
 
 libtracker_sparql_intermediate_c = static_library('tracker-sparql-intermediate-c',
-    enums_c, enums_h,
+    enums_c, enums_h, tracker_sparql_generated_header[0],
     libtracker_sparql_c_sources,
     dependencies: [tracker_common_dep, json_glib],
     link_with: libtracker_sparql_intermediate_vala,
diff --git a/src/libtracker-sparql/tracker-endpoint-dbus.c b/src/libtracker-sparql/tracker-endpoint-dbus.c
new file mode 100644
index 000000000..975e5baed
--- /dev/null
+++ b/src/libtracker-sparql/tracker-endpoint-dbus.c
@@ -0,0 +1,610 @@
+/*
+ * Copyright (C) 2019, Red Hat, Inc
+ *
+ * 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>
+ */
+
+#include "config.h"
+
+#include "tracker-endpoint-dbus.h"
+
+#include <gio/gio.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <gio/gunixfdlist.h>
+
+static const gchar introspection_xml[] =
+       "<node>"
+       "  <interface name='org.freedesktop.Tracker1.Endpoint'>"
+       "    <method name='Query'>"
+       "      <arg type='as' name='anon_graphs' direction='in' />"
+       "      <arg type='as' name='named_graphs' direction='in' />"
+       "      <arg type='s' name='query' direction='in' />"
+       "      <arg type='h' name='output_stream' direction='in' />"
+       "      <arg type='as' name='result' direction='out' />"
+       "    </method>"
+       "    <method name='Update'>"
+       "      <arg type='as' name='anon_graphs' direction='in' />"
+       "      <arg type='as' name='named_graphs' direction='in' />"
+       "      <arg type='h' name='input_stream' direction='in' />"
+       "    </method>"
+       "    <method name='UpdateArray'>"
+       "      <arg type='as' name='anon_graphs' direction='in' />"
+       "      <arg type='as' name='named_graphs' direction='in' />"
+       "      <arg type='h' name='input_stream' direction='in' />"
+       "    </method>"
+       "    <method name='UpdateBlank'>"
+       "      <arg type='as' name='anon_graphs' direction='in' />"
+       "      <arg type='as' name='named_graphs' direction='in' />"
+       "      <arg type='h' name='input_stream' direction='in' />"
+       "      <arg type='aaa{ss}' name='result' direction='out' />"
+       "    </method>"
+       "    <signal name='GraphUpdate'>"
+       "      <arg type='a(ii)' name='updates' />"
+       "    </signal>"
+       "  </interface>"
+       "</node>";
+
+enum {
+       PROP_0,
+       PROP_DBUS_CONNECTION,
+       PROP_OBJECT_PATH,
+       N_PROPS
+};
+
+struct _TrackerEndpointDBus {
+       TrackerEndpoint parent_instance;
+       GDBusConnection *dbus_connection;
+       gchar *object_path;
+       guint register_id;
+       GDBusNodeInfo *node_info;
+       GCancellable *cancellable;
+};
+
+typedef struct {
+       TrackerEndpointDBus *endpoint;
+       GDBusMethodInvocation *invocation;
+       GDataOutputStream *data_stream;
+} QueryRequest;
+
+typedef struct {
+       TrackerEndpointDBus *endpoint;
+       GDBusMethodInvocation *invocation;
+       GDataInputStream *input_stream;
+       GPtrArray *queries;
+       gboolean array_update;
+       gint num_queries;
+       gint cur_query;
+} UpdateRequest;
+
+GParamSpec *props[N_PROPS] = { 0 };
+
+static void tracker_endpoint_dbus_initable_iface_init (GInitableIface *iface);
+
+static void read_update_cb       (GObject      *object,
+                                  GAsyncResult *res,
+                                  gpointer      user_data);
+static void read_update_blank_cb (GObject      *object,
+                                  GAsyncResult *res,
+                                  gpointer      user_data);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerEndpointDBus, tracker_endpoint_dbus, TRACKER_TYPE_ENDPOINT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, tracker_endpoint_dbus_initable_iface_init))
+
+static QueryRequest *
+query_request_new (TrackerEndpointDBus   *endpoint,
+                   GDBusMethodInvocation *invocation,
+                   int                    fd)
+{
+       GOutputStream *stream, *buffered_stream;
+       QueryRequest *request;
+
+       request = g_new0 (QueryRequest, 1);
+       request->invocation = g_object_ref (invocation);
+       request->endpoint = endpoint;
+
+       stream = g_unix_output_stream_new (fd, TRUE);
+       buffered_stream = g_buffered_output_stream_new_sized (stream,
+                                                             getpagesize ());
+
+       request->data_stream = g_data_output_stream_new (buffered_stream);
+       g_data_output_stream_set_byte_order (request->data_stream,
+                                            G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+
+       g_object_unref (buffered_stream);
+       g_object_unref (stream);
+
+       return request;
+}
+
+static void
+query_request_free (QueryRequest *request)
+{
+       g_output_stream_close (G_OUTPUT_STREAM (request->data_stream),
+                              NULL, NULL);
+
+       g_object_unref (request->invocation);
+       g_object_unref (request->data_stream);
+       g_free (request);
+}
+
+static UpdateRequest *
+update_request_new (TrackerEndpointDBus   *endpoint,
+                    GDBusMethodInvocation *invocation,
+                    gboolean               array_update,
+                    int                    input)
+{
+       UpdateRequest *request;
+       GInputStream *stream;
+
+       request = g_new0 (UpdateRequest, 1);
+       request->invocation = g_object_ref (invocation);
+       request->endpoint = endpoint;
+       request->cur_query = 0;
+       request->array_update = array_update;
+       request->queries = g_ptr_array_new_with_free_func (g_free);
+
+       stream = g_unix_input_stream_new (input, TRUE);
+       request->input_stream = g_data_input_stream_new (stream);
+       g_buffered_input_stream_set_buffer_size (G_BUFFERED_INPUT_STREAM (request->input_stream),
+                                                getpagesize ());
+       g_data_input_stream_set_byte_order (request->input_stream,
+                                           G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+       g_object_unref (stream);
+
+       if (array_update)
+               request->num_queries = g_data_input_stream_read_int32 (request->input_stream, NULL, NULL);
+       else
+               request->num_queries = 1;
+
+       return request;
+}
+
+static gboolean
+update_request_read_next (UpdateRequest       *request,
+                          GAsyncReadyCallback  cb)
+{
+       gchar *buffer;
+       gint buffer_size;
+
+       if (request->cur_query >= request->num_queries)
+               return FALSE;
+
+       request->cur_query++;
+       buffer_size = g_data_input_stream_read_int32 (request->input_stream, NULL, NULL);
+       buffer = g_new0 (char, buffer_size + 1);
+       g_ptr_array_add (request->queries, buffer);
+
+       g_input_stream_read_all_async (G_INPUT_STREAM (request->input_stream),
+                                      buffer,
+                                      buffer_size,
+                                      G_PRIORITY_DEFAULT,
+                                      request->endpoint->cancellable,
+                                      cb, request);
+       return TRUE;
+}
+
+static void
+update_request_free (UpdateRequest *request)
+{
+       g_input_stream_close (G_INPUT_STREAM (request->input_stream),
+                             NULL, NULL);
+
+       g_ptr_array_unref (request->queries);
+       g_object_unref (request->invocation);
+       g_object_unref (request->input_stream);
+       g_free (request);
+}
+
+static void
+query_cb (GObject      *object,
+          GAsyncResult *res,
+          gpointer      user_data)
+{
+       QueryRequest *request = user_data;
+       TrackerSparqlCursor *cursor;
+       GError *error = NULL;
+       const gchar **values = NULL;
+       const gchar **variable_names = NULL;
+       glong *offsets = NULL;
+       gint i, n_columns = 0;
+
+       cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (object),
+                                                        res, &error);
+       if (!cursor)
+               goto error;
+
+       n_columns = tracker_sparql_cursor_get_n_columns (cursor);
+       variable_names = g_new0 (const gchar *, n_columns + 1);
+       values = g_new0 (const char *, n_columns);
+       offsets = g_new0 (glong, n_columns);
+
+       for (i = 0; i < n_columns; i++)
+               variable_names[i] = tracker_sparql_cursor_get_variable_name (cursor, i);
+
+       while (tracker_sparql_cursor_next (cursor, NULL, &error)) {
+               glong cur_offset = -1;
+
+               g_data_output_stream_put_int32 (request->data_stream, n_columns, NULL, NULL);
+
+               for (i = 0; i < n_columns; i++) {
+                       glong len;
+
+                       g_data_output_stream_put_int32 (request->data_stream,
+                                                       tracker_sparql_cursor_get_value_type (cursor, i),
+                                                       NULL, NULL);
+                       values[i] = tracker_sparql_cursor_get_string (cursor, i, &len);
+                       len++;
+                       cur_offset += len;
+                       offsets[i] = cur_offset;
+               }
+
+               for (i = 0; i < n_columns; i++) {
+                       g_data_output_stream_put_int32 (request->data_stream,
+                                                       offsets[i], NULL, NULL);
+               }
+
+               for (i = 0; i < n_columns; i++) {
+                       g_data_output_stream_put_string (request->data_stream,
+                                                        values[i] ? values[i] : "",
+                                                        NULL, NULL);
+                       g_data_output_stream_put_byte (request->data_stream, 0, NULL, NULL);
+               }
+       }
+
+error:
+       if (error)
+               g_dbus_method_invocation_return_gerror (request->invocation, error);
+       else
+               g_dbus_method_invocation_return_value (request->invocation, g_variant_new ("(^as)", 
variable_names));
+
+       g_free (variable_names);
+       g_free (values);
+       g_free (offsets);
+       g_clear_object (&cursor);
+
+       query_request_free (request);
+}
+
+static void
+update_cb (GObject      *object,
+           GAsyncResult *res,
+           gpointer      user_data)
+{
+       UpdateRequest *request = user_data;
+       GError *error = NULL;
+
+       tracker_sparql_connection_update_array_finish (TRACKER_SPARQL_CONNECTION (object),
+                                                      res, &error);
+       if (error) {
+               g_dbus_method_invocation_return_gerror (request->invocation, error);
+       } else {
+               g_dbus_method_invocation_return_value (request->invocation, NULL);
+       }
+
+       update_request_free (request);
+}
+
+static void
+read_update_cb (GObject      *object,
+                GAsyncResult *res,
+                gpointer      user_data)
+{
+       TrackerSparqlConnection *conn;
+       UpdateRequest *request = user_data;
+       GError *error = NULL;
+
+       if (!g_input_stream_read_all_finish (G_INPUT_STREAM (object),
+                                            res, NULL, &error)) {
+               g_dbus_method_invocation_return_gerror (request->invocation, error);
+               update_request_free (request);
+               return;
+       }
+
+       if (!update_request_read_next (request, read_update_cb)) {
+               conn = tracker_endpoint_get_sparql_connection (TRACKER_ENDPOINT (request->endpoint));
+               tracker_sparql_connection_update_array_async (conn,
+                                                             (gchar **) request->queries->pdata,
+                                                             request->queries->len,
+                                                             G_PRIORITY_DEFAULT,
+                                                             request->endpoint->cancellable,
+                                                             update_cb,
+                                                             request);
+       }
+}
+
+static void
+update_blank_cb (GObject      *object,
+                 GAsyncResult *res,
+                 gpointer      user_data)
+{
+       UpdateRequest *request = user_data;
+       GError *error = NULL;
+       GVariant *results;
+
+       results = tracker_sparql_connection_update_blank_finish (TRACKER_SPARQL_CONNECTION (object),
+                                                                res, &error);
+       if (results)
+               g_dbus_method_invocation_return_value (request->invocation, results);
+       else
+               g_dbus_method_invocation_return_gerror (request->invocation, error);
+
+       update_request_free (request);
+}
+
+static void
+read_update_blank_cb (GObject      *object,
+                      GAsyncResult *res,
+                      gpointer      user_data)
+{
+       TrackerSparqlConnection *conn;
+       UpdateRequest *request = user_data;
+       GError *error = NULL;
+
+       if (!g_input_stream_read_all_finish (G_INPUT_STREAM (object),
+                                            res, NULL, &error)) {
+               g_dbus_method_invocation_return_gerror (request->invocation, error);
+               update_request_free (request);
+               return;
+       }
+
+       conn = tracker_endpoint_get_sparql_connection (TRACKER_ENDPOINT (request->endpoint));
+       tracker_sparql_connection_update_blank_async (conn,
+                                                     g_ptr_array_index (request->queries, 0),
+                                                     G_PRIORITY_DEFAULT,
+                                                     request->endpoint->cancellable,
+                                                     update_blank_cb,
+                                                     request);
+}
+
+static void
+endpoint_dbus_iface_method_call (GDBusConnection       *connection,
+                                 const gchar           *sender,
+                                 const gchar           *object_path,
+                                 const gchar           *interface_name,
+                                 const gchar           *method_name,
+                                 GVariant              *parameters,
+                                 GDBusMethodInvocation *invocation,
+                                 gpointer               user_data)
+{
+       TrackerEndpointDBus *endpoint_dbus = user_data;
+       TrackerSparqlConnection *conn;
+       GUnixFDList *fd_list;
+       GError *error = NULL;
+       gchar *query;
+       gint handle, fd = -1;
+
+       conn = tracker_endpoint_get_sparql_connection (TRACKER_ENDPOINT (endpoint_dbus));
+       fd_list = g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation));
+
+       if (g_strcmp0 (method_name, "Query") == 0) {
+               /* FIXME: Anon/named graphs are ignored ATM */
+               g_variant_get (parameters, "(asassh)", NULL, NULL, &query, &handle);
+
+               if (fd_list)
+                       fd = g_unix_fd_list_get (fd_list, handle, &error);
+
+               if (fd < 0) {
+                       g_dbus_method_invocation_return_error (invocation,
+                                                              G_DBUS_ERROR,
+                                                              G_DBUS_ERROR_INVALID_ARGS,
+                                                              "Did not get a file descriptor");
+               } else {
+                       QueryRequest *request;
+
+                       request = query_request_new (endpoint_dbus, invocation, fd);
+                       tracker_sparql_connection_query_async (conn,
+                                                              query,
+                                                              endpoint_dbus->cancellable,
+                                                              query_cb,
+                                                              request);
+               }
+
+               g_free (query);
+       } else if (g_strcmp0 (method_name, "Update") == 0 ||
+                  g_strcmp0 (method_name, "UpdateArray") == 0) {
+               /* FIXME: Anon/named graphs are ignored ATM */
+               g_variant_get (parameters, "(asash)", NULL, NULL, &handle);
+
+               if (fd_list)
+                       fd = g_unix_fd_list_get (fd_list, handle, &error);
+
+               if (fd < 0) {
+                       g_dbus_method_invocation_return_error (invocation,
+                                                              G_DBUS_ERROR,
+                                                              G_DBUS_ERROR_INVALID_ARGS,
+                                                              "Did not get a file descriptor");
+               } else {
+                       UpdateRequest *request;
+
+                       request = update_request_new (endpoint_dbus, invocation,
+                                                     g_strcmp0 (method_name, "UpdateArray") == 0,
+                                                     fd);
+                       update_request_read_next (request, read_update_cb);
+               }
+       } else if (g_strcmp0 (method_name, "UpdateBlank") == 0) {
+               /* FIXME: Anon/named graphs are ignored ATM */
+               g_variant_get (parameters, "(asash)", NULL, NULL, &handle);
+
+               if (fd_list)
+                       fd = g_unix_fd_list_get (fd_list, handle, &error);
+
+               if (fd < 0) {
+                       g_dbus_method_invocation_return_error (invocation,
+                                                              G_DBUS_ERROR,
+                                                              G_DBUS_ERROR_INVALID_ARGS,
+                                                              "Did not get a file descriptor");
+               } else {
+                       UpdateRequest *request;
+
+                       request = update_request_new (endpoint_dbus, invocation, FALSE, fd);
+                       update_request_read_next (request, read_update_blank_cb);
+               }
+       } else {
+               g_dbus_method_invocation_return_error (invocation,
+                                                      G_DBUS_ERROR,
+                                                      G_DBUS_ERROR_UNKNOWN_METHOD,
+                                                      "Unknown method '%s'", method_name);
+       }
+}
+
+static gboolean
+tracker_endpoint_dbus_initable_init (GInitable     *initable,
+                                     GCancellable  *cancellable,
+                                     GError       **error)
+{
+       TrackerEndpointDBus *endpoint_dbus = TRACKER_ENDPOINT_DBUS (initable);
+
+       endpoint_dbus->node_info = g_dbus_node_info_new_for_xml (introspection_xml,
+                                                                error);
+       if (!endpoint_dbus->node_info)
+               return FALSE;
+
+       endpoint_dbus->register_id =
+               g_dbus_connection_register_object (endpoint_dbus->dbus_connection,
+                                                  endpoint_dbus->object_path,
+                                                  endpoint_dbus->node_info->interfaces[0],
+                                                  &(GDBusInterfaceVTable) {
+                                                          endpoint_dbus_iface_method_call,
+                                                          NULL,
+                                                          NULL
+                                                  },
+                                                  endpoint_dbus,
+                                                  NULL,
+                                                  error);
+       return TRUE;
+}
+
+static void
+tracker_endpoint_dbus_initable_iface_init (GInitableIface *iface)
+{
+       iface->init = tracker_endpoint_dbus_initable_init;
+}
+
+static void
+tracker_endpoint_dbus_finalize (GObject *object)
+{
+       TrackerEndpointDBus *endpoint_dbus = TRACKER_ENDPOINT_DBUS (object);
+
+       g_cancellable_cancel (endpoint_dbus->cancellable);
+
+       if (endpoint_dbus->register_id != 0) {
+               g_dbus_connection_unregister_object (endpoint_dbus->dbus_connection,
+                                                    endpoint_dbus->register_id);
+               endpoint_dbus->register_id = 0;
+       }
+
+       g_clear_object (&endpoint_dbus->cancellable);
+       g_clear_object (&endpoint_dbus->dbus_connection);
+       g_clear_pointer (&endpoint_dbus->object_path, g_free);
+       g_clear_pointer (&endpoint_dbus->node_info,
+                        g_dbus_node_info_unref);
+
+       G_OBJECT_CLASS (tracker_endpoint_dbus_parent_class)->finalize (object);
+}
+
+static void
+tracker_endpoint_dbus_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+       TrackerEndpointDBus *endpoint_dbus = TRACKER_ENDPOINT_DBUS (object);
+
+       switch (prop_id) {
+       case PROP_DBUS_CONNECTION:
+               endpoint_dbus->dbus_connection = g_value_dup_object (value);
+               break;
+       case PROP_OBJECT_PATH:
+               endpoint_dbus->object_path = g_value_dup_string (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_endpoint_dbus_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+       TrackerEndpointDBus *endpoint_dbus = TRACKER_ENDPOINT_DBUS (object);
+
+       switch (prop_id) {
+       case PROP_DBUS_CONNECTION:
+               g_value_set_object (value, endpoint_dbus->dbus_connection);
+               break;
+       case PROP_OBJECT_PATH:
+               g_value_set_string (value, endpoint_dbus->object_path);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_endpoint_dbus_class_init (TrackerEndpointDBusClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = tracker_endpoint_dbus_finalize;
+       object_class->set_property = tracker_endpoint_dbus_set_property;
+       object_class->get_property = tracker_endpoint_dbus_get_property;
+
+       props[PROP_DBUS_CONNECTION] =
+               g_param_spec_object ("dbus-connection",
+                                    "DBus connection",
+                                    "DBus connection",
+                                    G_TYPE_DBUS_CONNECTION,
+                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+       props[PROP_OBJECT_PATH] =
+               g_param_spec_string ("object-path",
+                                    "DBus object path",
+                                    "DBus object path",
+                                    NULL,
+                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+tracker_endpoint_dbus_init (TrackerEndpointDBus *endpoint)
+{
+}
+
+TrackerEndpointDBus *
+tracker_endpoint_dbus_new (TrackerSparqlConnection  *sparql_connection,
+                           GDBusConnection          *dbus_connection,
+                           const gchar              *object_path,
+                           GCancellable             *cancellable,
+                           GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_SPARQL_IS_CONNECTION (sparql_connection), NULL);
+       g_return_val_if_fail (G_IS_DBUS_CONNECTION (dbus_connection), NULL);
+       g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return g_initable_new (TRACKER_TYPE_ENDPOINT_DBUS, cancellable, error,
+                              "dbus-connection", dbus_connection,
+                              "sparql-connection", sparql_connection,
+                              "object-path", object_path,
+                              NULL);
+}
diff --git a/src/libtracker-sparql/tracker-endpoint-dbus.h b/src/libtracker-sparql/tracker-endpoint-dbus.h
new file mode 100644
index 000000000..d7902ca8a
--- /dev/null
+++ b/src/libtracker-sparql/tracker-endpoint-dbus.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019, Red Hat, Inc
+ *
+ * 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>
+ */
+
+#ifndef __TRACKER_ENDPOINT_DBUS_H__
+#define __TRACKER_ENDPOINT_DBUS_H__
+
+#if !defined (__LIBTRACKER_SPARQL_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "only <libtracker-sparql/tracker-sparql.h> must be included directly."
+#endif
+
+#include <libtracker-sparql/tracker-endpoint.h>
+
+#define TRACKER_TYPE_ENDPOINT_DBUS tracker_endpoint_dbus_get_type()
+G_DECLARE_FINAL_TYPE (TrackerEndpointDBus, tracker_endpoint_dbus, TRACKER, ENDPOINT_DBUS, TrackerEndpoint)
+
+TrackerEndpointDBus *
+tracker_endpoint_dbus_new (TrackerSparqlConnection  *sparql_connection,
+                           GDBusConnection          *dbus_connection,
+                           const gchar              *object_path,
+                           GCancellable             *cancellable,
+                           GError                  **error);
+
+#endif /* __TRACKER_ENDPOINT_DBUS_H__ */
diff --git a/src/libtracker-sparql/tracker-endpoint.c b/src/libtracker-sparql/tracker-endpoint.c
new file mode 100644
index 000000000..3efdb966c
--- /dev/null
+++ b/src/libtracker-sparql/tracker-endpoint.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019, Red Hat, Inc
+ *
+ * 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>
+ */
+
+#include "config.h"
+
+#include "tracker-endpoint.h"
+
+enum {
+       PROP_0,
+       PROP_SPARQL_CONNECTION,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0 };
+
+typedef struct {
+       TrackerSparqlConnection *sparql_connection;
+} TrackerEndpointPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (TrackerEndpoint, tracker_endpoint, G_TYPE_OBJECT)
+
+static void
+tracker_endpoint_finalize (GObject *object)
+{
+       TrackerEndpoint *endpoint = TRACKER_ENDPOINT (object);
+       TrackerEndpointPrivate *priv = tracker_endpoint_get_instance_private (endpoint);
+
+       g_clear_object (&priv->sparql_connection);
+
+       G_OBJECT_CLASS (tracker_endpoint_parent_class)->finalize (object);
+}
+
+static void
+tracker_endpoint_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+       TrackerEndpoint *endpoint = TRACKER_ENDPOINT (object);
+       TrackerEndpointPrivate *priv = tracker_endpoint_get_instance_private (endpoint);
+
+       switch (prop_id) {
+       case PROP_SPARQL_CONNECTION:
+               priv->sparql_connection = g_value_dup_object (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_endpoint_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+       TrackerEndpoint *endpoint = TRACKER_ENDPOINT (object);
+       TrackerEndpointPrivate *priv = tracker_endpoint_get_instance_private (endpoint);
+
+       switch (prop_id) {
+       case PROP_SPARQL_CONNECTION:
+               g_value_set_object (value, priv->sparql_connection);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_endpoint_class_init (TrackerEndpointClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = tracker_endpoint_finalize;
+       object_class->set_property = tracker_endpoint_set_property;
+       object_class->get_property = tracker_endpoint_get_property;
+
+       props[PROP_SPARQL_CONNECTION] =
+               g_param_spec_object ("sparql-connection",
+                                    "Sparql connection",
+                                    "Sparql connection",
+                                    TRACKER_SPARQL_TYPE_CONNECTION,
+                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+       g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+tracker_endpoint_init (TrackerEndpoint *endpoint)
+{
+}
+
+TrackerSparqlConnection *
+tracker_endpoint_get_sparql_connection (TrackerEndpoint *endpoint)
+{
+       TrackerEndpointPrivate *priv = tracker_endpoint_get_instance_private (endpoint);
+
+       return priv->sparql_connection;
+}
diff --git a/src/libtracker-sparql/tracker-endpoint.h b/src/libtracker-sparql/tracker-endpoint.h
new file mode 100644
index 000000000..d665b74da
--- /dev/null
+++ b/src/libtracker-sparql/tracker-endpoint.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019, Red Hat, Inc
+ *
+ * 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>
+ */
+
+#ifndef __TRACKER_ENDPOINT_H__
+#define __TRACKER_ENDPOINT_H__
+
+#if !defined (__LIBTRACKER_SPARQL_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "only <libtracker-sparql/tracker-sparql.h> must be included directly."
+#endif
+
+#include <glib-object.h>
+#include <libtracker-sparql/tracker-generated.h>
+
+#define TRACKER_TYPE_ENDPOINT tracker_endpoint_get_type()
+G_DECLARE_DERIVABLE_TYPE (TrackerEndpoint, tracker_endpoint, TRACKER, ENDPOINT, GObject)
+
+struct _TrackerEndpointClass {
+       GObjectClass parent_class;
+};
+
+TrackerSparqlConnection * tracker_endpoint_get_sparql_connection (TrackerEndpoint *endpoint);
+
+#endif /* __TRACKER_ENDPOINT_H__ */
diff --git a/src/libtracker-sparql/tracker-sparql.h b/src/libtracker-sparql/tracker-sparql.h
index 693895011..a87122e4d 100644
--- a/src/libtracker-sparql/tracker-sparql.h
+++ b/src/libtracker-sparql/tracker-sparql.h
@@ -22,6 +22,8 @@
 
 #define __LIBTRACKER_SPARQL_INSIDE__
 
+#include <libtracker-sparql/tracker-endpoint.h>
+#include <libtracker-sparql/tracker-endpoint-dbus.h>
 #include <libtracker-sparql/tracker-version.h>
 #include <libtracker-sparql/tracker-ontologies.h>
 #include <libtracker-sparql/tracker-resource.h>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]