summaryrefslogtreecommitdiff
path: root/src/dbus/server/pim/manager.cpp
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2012-09-05 11:17:40 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2012-10-25 16:43:46 +0200
commita8118eff89a37298ae69fbd48a9f509c994d94c1 (patch)
tree2beff47cf2902782f75993ad0855027582440406 /src/dbus/server/pim/manager.cpp
parent7651b432c29e71f13e90748d8793238dbdc4c178 (diff)
PIM Manager: initial D-Bus binding
Adds a subset of the D-Bus API to syncevo-dbus-server. Views are resources that are attached to the client and thus get destroyed automatically when the client disconnects from D-Bus. In addition, failures for calls to the client's ViewAgent delete the view. In this case, the client stays connected, because it might only have destroyed one agent with others still active.
Diffstat (limited to 'src/dbus/server/pim/manager.cpp')
-rw-r--r--src/dbus/server/pim/manager.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/dbus/server/pim/manager.cpp b/src/dbus/server/pim/manager.cpp
new file mode 100644
index 00000000..28110f90
--- /dev/null
+++ b/src/dbus/server/pim/manager.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * 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) version 3.
+ *
+ * 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
+ */
+
+#include "manager.h"
+#include "../resource.h"
+#include "../client.h"
+
+SE_BEGIN_CXX
+
+static const char * const MANAGER_SERVICE = "org._01.pim.contacts";
+static const char * const MANAGER_PATH = "/org/01/pim/contacts";
+static const char * const MANAGER_IFACE = "org._01.pim.contacts.Manager";
+static const char * const AGENT_IFACE = "org._01.pim.contacts.ViewAgent";
+static const char * const CONTROL_IFACE = "org._01.pim.contacts.ViewControl";
+
+Manager::Manager(const boost::shared_ptr<Server> &server) :
+ DBusObjectHelper(server->getConnection(),
+ MANAGER_PATH,
+ MANAGER_IFACE),
+ m_server(server)
+{
+ // TODO: claim MANAGER_SERVICE name on connection
+
+ // Prevent automatic shut down during idle times, because we need
+ // to keep our unified address book available.
+ m_server->autoTermRef();
+}
+
+
+void Manager::init()
+{
+ // TODO: restore sort order
+ m_sortOrder = "first/last";
+ initFolks();
+ initSorting();
+
+ add(this, &Manager::start, "Start");
+ add(this, &Manager::stop, "Stop");
+ add(this, &Manager::setSortOrder, "SetSortOrder");
+ add(this, &Manager::getSortOrder, "GetSortOrder");
+ add(this, &Manager::search, "Search");
+
+ // Ready, make it visible via D-Bus.
+ activate();
+}
+
+void Manager::initFolks()
+{
+ m_folks = IndividualAggregator::create();
+}
+
+void Manager::initSorting()
+{
+ // TODO: mirror m_sortOrder in m_folks main view
+}
+
+Manager::~Manager()
+{
+ m_server->autoTermUnref();
+}
+
+boost::shared_ptr<Manager> Manager::create(const boost::shared_ptr<Server> &server)
+{
+ boost::shared_ptr<Manager> manager(new Manager(server));
+ manager->m_self = manager;
+ manager->init();
+ return manager;
+}
+
+boost::shared_ptr<GDBusCXX::DBusObjectHelper> CreateContactManager(const boost::shared_ptr<Server> &server)
+{
+ return Manager::create(server);
+}
+
+void Manager::start()
+{
+ m_folks->start();
+}
+
+void Manager::stop()
+{
+ // TODO: if there are no active searches, then recreate aggregator
+ if (true) {
+ initFolks();
+ initSorting();
+ }
+}
+
+void Manager::setSortOrder(const std::string &order)
+{
+ // TODO: check string and change order,
+ // store persistently
+ m_sortOrder = order;
+ initSorting();
+}
+
+/**
+ * Connects a normal IndividualView to a D-Bus client.
+ * Provides the org.01.pim.contacts.ViewControl API.
+ */
+class ViewResource : public Resource, public GDBusCXX::DBusObjectHelper
+{
+ static unsigned int m_counter;
+
+ boost::weak_ptr<ViewResource> m_self;
+ GDBusCXX::DBusRemoteObject m_viewAgent;
+ boost::shared_ptr<IndividualView> m_view;
+ boost::weak_ptr<Client> m_owner;
+ GDBusCXX::DBusClientCall0 m_contactsModified,
+ m_contactsAdded,
+ m_contactsRemoved;
+
+ ViewResource(const boost::shared_ptr<IndividualView> view,
+ const boost::shared_ptr<Client> &owner,
+ GDBusCXX::connection_type *connection,
+ const GDBusCXX::Caller_t &ID,
+ const GDBusCXX::DBusObject_t &agentPath) :
+ GDBusCXX::DBusObjectHelper(connection,
+ StringPrintf("%s/view%d", MANAGER_PATH, m_counter++),
+ CONTROL_IFACE),
+ m_viewAgent(connection,
+ agentPath,
+ AGENT_IFACE,
+ ID),
+ m_view(view),
+ m_owner(owner),
+ // use ViewAgent interface
+ m_contactsModified(m_viewAgent, "ContactsModified"),
+ m_contactsAdded(m_viewAgent, "ContactsAdded"),
+ m_contactsRemoved(m_viewAgent, "ContactsRemoved")
+ {}
+
+ /**
+ * Invokes one of m_contactsModified/Added/Removed. A failure of
+ * the asynchronous call indicates that the client is dead and
+ * that its view can be purged.
+ */
+ void sendChange(const GDBusCXX::DBusClientCall0 &call,
+ int start, int count)
+ {
+ call.start(boost::bind(ViewResource::sendDone,
+ m_self,
+ _1));
+ }
+
+ /**
+ * Used as callback for sending changes to the ViewAgent. Only
+ * holds weak references and thus does not prevent deleting view
+ * or client.
+ */
+ static void sendDone(const boost::weak_ptr<ViewResource> &self,
+ const std::string &error)
+ {
+ if (!error.empty()) {
+ // remove view because it is no longer needed
+ SE_LOG_DEBUG(NULL, NULL, "ViewAgent method call failed, deleting view: %s", error.c_str());
+ boost::shared_ptr<ViewResource> r = self.lock();
+ if (r) {
+ r->close();
+ }
+ }
+ }
+
+ void init(boost::shared_ptr<ViewResource> self)
+ {
+ m_self = self;
+
+ // activate D-Bus interface
+ add(this, &ViewResource::readContacts, "ReadContacts");
+ add(this, &ViewResource::close, "Close");
+ add(this, &ViewResource::refineSearch, "RefineSearch");
+ activate();
+
+ // TODO: aggregate changes into batches
+ m_view->m_modifiedSignal.connect(IndividualView::ChangeSignal_t::slot_type(&ViewResource::sendChange,
+ this,
+ boost::cref(m_contactsModified),
+ _1,
+ 1).track(self));
+ m_view->m_addedSignal.connect(IndividualView::ChangeSignal_t::slot_type(&ViewResource::sendChange,
+ this,
+ boost::cref(m_contactsAdded),
+ _1,
+ 1).track(self));
+ m_view->m_removedSignal.connect(IndividualView::ChangeSignal_t::slot_type(&ViewResource::sendChange,
+ this,
+ boost::cref(m_contactsRemoved),
+ _1,
+ 1).track(self));
+
+ }
+
+public:
+ static boost::shared_ptr<ViewResource> create(const boost::shared_ptr<IndividualView> &view,
+ const boost::shared_ptr<Client> &owner,
+ GDBusCXX::connection_type *connection,
+ const GDBusCXX::Caller_t &ID,
+ const GDBusCXX::DBusObject_t &agentPath)
+ {
+ boost::shared_ptr<ViewResource> viewResource(new ViewResource(view, owner,
+ connection,
+ ID,
+ agentPath));
+ viewResource->init(viewResource);
+ return viewResource;
+ }
+
+ /** org.01.pim.contacts.ViewControl.ReadContacts() */
+ void readContacts(int start, int count, std::vector<FolksIndividualCXX> &contacts)
+ {
+ // TODO
+ SE_THROW("not implemented");
+ }
+
+ /** org.01.pim.contacts.ViewControl.Close() */
+ void close()
+ {
+ // Removing the resource from its owner will drop the last
+ // reference and delete it when we return.
+ boost::shared_ptr<ViewResource> r = m_self.lock();
+ if (r) {
+ boost::shared_ptr<Client> c = m_owner.lock();
+ if (c) {
+ c->detach(r.get());
+ }
+ }
+ }
+
+ /** ViewControl.RefineSearch() */
+ void refineSearch(const StringMap &filter)
+ {
+ // TODO
+ SE_THROW("not implemented");
+ }
+};
+unsigned int ViewResource::m_counter;
+
+GDBusCXX::DBusObject_t Manager::search(const GDBusCXX::Caller_t &ID,
+ const boost::shared_ptr<GDBusCXX::Watch> &watch,
+ const StringMap &filter,
+ const GDBusCXX::DBusObject_t &agentPath)
+{
+ // Create and track view which is owned by the caller.
+ boost::shared_ptr<Client> client = m_server->addClient(ID, watch);
+
+ boost::shared_ptr<IndividualView> view;
+ // TODO: parse filter
+ view = m_folks->getMainView();
+
+ boost::shared_ptr<ViewResource> viewResource(ViewResource::create(view,
+ client,
+ getConnection(),
+ ID,
+ agentPath));
+ client->attach(boost::shared_ptr<Resource>(viewResource));
+
+ // created local resource
+ return viewResource->getPath();
+}
+
+SE_END_CXX