summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2011-10-18 16:37:14 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2011-10-18 17:04:43 +0200
commite117672b52b1cb4fffeaac2f198f1692028a6ccb (patch)
tree642269015a3efac148065a89d0e1e935eb8168bb
parent6cd467bc551fe94eada76cf77d4f4e1c20225081 (diff)
D-Bus API: allow setting different configs in the same sessiondbus-named-configs
Forcing D-Bus API users to start a new session for each config that they want to modify adds considerable complexity to clients, in particular for local sync. Relaxing that requirements is easy because the current implementation already only runs one session at a time. It's also only a minor restriction for future improvements: sessions which request access to all configs cannot run in parallel with other sessions. Thus this patch adds Session.SetNamedConfig() and (for the sake of completeness) Session.GetNamedConfig(). Temporary config changes via SetNamedConfig() are harder to implement and not currently supported. They are part of the API though, just in case.
-rw-r--r--src/dbus/interfaces/syncevo-server-full.xml12
-rw-r--r--src/dbus/interfaces/syncevo-session-full.xml30
-rw-r--r--src/dbus/server/read-operations.cpp21
-rw-r--r--src/dbus/server/read-operations.h5
-rw-r--r--src/dbus/server/server.cpp1
-rw-r--r--src/dbus/server/session.cpp41
-rw-r--r--src/dbus/server/session.h5
-rwxr-xr-xtest/test-dbus.py57
8 files changed, 154 insertions, 18 deletions
diff --git a/src/dbus/interfaces/syncevo-server-full.xml b/src/dbus/interfaces/syncevo-server-full.xml
index d872b9c7..94e7fa5f 100644
--- a/src/dbus/interfaces/syncevo-server-full.xml
+++ b/src/dbus/interfaces/syncevo-server-full.xml
@@ -96,6 +96,13 @@
"evolutionuser", "evolutionpassword"; semantic is unchanged
</doc:definition>
</doc:item>
+
+ <doc:item><doc:term>NamedConfig</doc:term>
+ <doc:definition>Session.Get/SetNamedConfig()
+ are implemented
+ </doc:definition>
+ </doc:item>
+
</doc:list>
</doc:para>
</doc:description>
@@ -485,10 +492,13 @@
<doc:item><doc:term>no-sync</doc:term>
<doc:definition>session will not be used for running a synchronization</doc:definition>
</doc:item>
+ <doc:item><doc:term>all-configs</doc:term>
+ <doc:definition>session will provide read/write access to all configurations, via Get/SetNamedConfig()</doc:definition>
+ </doc:item>
</doc:list>
</doc:description></doc:doc>
<arg type="s" name="config" direction="in">
- <doc:doc><doc:summary>name of configuration to be created or used in session</doc:summary></doc:doc>
+ <doc:doc><doc:summary>name of configuration to be created or used in session; typically this will be empty when used in combination with 'all-configs' and Get/SetNamedConfig()</doc:summary></doc:doc>
</arg>
<arg type="as" name="flags" direction="in">
<doc:doc><doc:summary>optional flags</doc:summary></doc:doc>
diff --git a/src/dbus/interfaces/syncevo-session-full.xml b/src/dbus/interfaces/syncevo-session-full.xml
index ec6a4229..eee4562f 100644
--- a/src/dbus/interfaces/syncevo-session-full.xml
+++ b/src/dbus/interfaces/syncevo-session-full.xml
@@ -48,9 +48,9 @@
</method>
<method name="GetConfig">
- <doc:doc><doc:description>Get the configuration of the server</doc:description></doc:doc>
+ <doc:doc><doc:description>Get the configuration identified by the name given to StartSession()</doc:description></doc:doc>
<arg type="b" name="tmplate" direction="in">
- <doc:doc><doc:summary>if TRUE, will return a matching template configuration, otherwise will return a matching server configuration</doc:summary></doc:doc>
+ <doc:doc><doc:summary>if TRUE, will return a matching template configuration, otherwise will return the stored configuration</doc:summary></doc:doc>
</arg>
<arg type="a{sa{ss}}" name="configuration" direction="out">
<doc:doc><doc:summary>server configuration</doc:summary></doc:doc>
@@ -107,6 +107,32 @@
<annotation name="com.trolltech.QtDBus.QtTypeName.In2" value="QStringMultiMap"/>
</method>
+ <method name="GetNamedConfig">
+ <doc:doc><doc:description>Get the configuration identified by
+ the name given in the first argument; same as
+ Server.GetConfig(), provided again in Session for the sake of
+ completeness</doc:description></doc:doc>
+ <arg type="s" name="name" direction="in">
+ <doc:doc><doc:summary>configuration name</doc:summary></doc:doc>
+ </arg>
+ <arg type="b" name="tmplate" direction="in"/>
+ <arg type="a{sa{ss}}" name="configuration" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QStringMultiMap"/>
+ </method>
+
+ <method name="SetNamedConfig">
+ <doc:doc><doc:description>Same as SetConfig() except that the modified configuration is named explicitly</doc:description></doc:doc>
+ <arg type="s" name="name" direction="in">
+ <doc:doc><doc:summary>configuration name; if exactly the same as in StartSession() or StartSessionWithFlags(), then SetNamedConfig() behaves exactly like SetConfig() and none of the constraints for SetNamedConfig() apply</doc:summary></doc:doc>
+ </arg>
+ <arg type="b" name="update" direction="in"/>
+ <arg type="b" name="temporary" direction="in">
+ <doc:doc><doc:summary>temporary changes of the configuration are currently only supported for the configuration chosen when creating the session</doc:summary></doc:doc>
+ </arg>
+ <arg type="a{sa{ss}}" name="configuration" direction="in"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In2" value="QStringMultiMap"/>
+ </method>
+
<method name="GetReports">
<doc:doc><doc:description>Get synchronization reports for the server</doc:description></doc:doc>
<arg type="u" name="start" direction="in">
diff --git a/src/dbus/server/read-operations.cpp b/src/dbus/server/read-operations.cpp
index ccada95a..2d2078d6 100644
--- a/src/dbus/server/read-operations.cpp
+++ b/src/dbus/server/read-operations.cpp
@@ -97,6 +97,13 @@ boost::shared_ptr<DBusUserInterface> ReadOperations::getLocalConfig(const string
void ReadOperations::getConfig(bool getTemplate,
Config_t &config)
{
+ getNamedConfig(m_configName, getTemplate, config);
+}
+
+void ReadOperations::getNamedConfig(const std::string &configName,
+ bool getTemplate,
+ Config_t &config)
+{
map<string, string> localConfigs;
boost::shared_ptr<SyncConfig> dbusConfig;
boost::shared_ptr<DBusUserInterface> dbusUI;
@@ -107,7 +114,7 @@ void ReadOperations::getConfig(bool getTemplate,
string peer, context;
boost::shared_ptr<SyncConfig::TemplateDescription> peerTemplate =
- m_server.getPeerTempl(m_configName);
+ m_server.getPeerTempl(configName);
if(peerTemplate) {
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(peerTemplate->m_templateId),
peer, context);
@@ -137,13 +144,13 @@ void ReadOperations::getConfig(bool getTemplate,
syncURL = "obex-bt://";
syncURL += peerTemplate->m_deviceId;
} else {
- SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_configName),
+ SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(configName),
peer, context);
dbusConfig = SyncConfig::createPeerTemplate(peer);
}
if(!dbusConfig.get()) {
- SE_THROW_EXCEPTION(NoSuchConfig, "No template '" + m_configName + "' found");
+ SE_THROW_EXCEPTION(NoSuchConfig, "No template '" + configName + "' found");
}
// use the shared properties from the right context as filter
@@ -166,11 +173,11 @@ void ReadOperations::getConfig(bool getTemplate,
}
syncConfig = dbusConfig.get();
} else {
- dbusUI = getLocalConfig(m_configName);
+ dbusUI = getLocalConfig(configName);
//try to check password and read password from gnome keyring if possible
ConfigPropertyRegistry& registry = SyncConfig::getRegistry();
BOOST_FOREACH(const ConfigProperty *prop, registry) {
- prop->checkPassword(*dbusUI, m_configName, *dbusUI->getProperties());
+ prop->checkPassword(*dbusUI, configName, *dbusUI->getProperties());
}
list<string> configuredSources = dbusUI->getSyncSources();
BOOST_FOREACH(const string &sourceName, configuredSources) {
@@ -178,7 +185,7 @@ void ReadOperations::getConfig(bool getTemplate,
SyncSourceNodes sourceNodes = dbusUI->getSyncSourceNodes(sourceName);
BOOST_FOREACH(const ConfigProperty *prop, registry) {
- prop->checkPassword(*dbusUI, m_configName, *dbusUI->getProperties(),
+ prop->checkPassword(*dbusUI, configName, *dbusUI->getProperties(),
sourceName, sourceNodes.getProperties());
}
}
@@ -213,7 +220,7 @@ void ReadOperations::getConfig(bool getTemplate,
localConfigs.insert(make_pair("ConsumerReady", "1"));
}
- // insert 'configName' of the chosen config (m_configName is not normalized)
+ // insert 'configName' of the chosen config (configName is not normalized)
localConfigs.insert(pair<string, string>("configName", syncConfig->getConfigName()));
config.insert(pair<string,map<string, string> >("", localConfigs));
diff --git a/src/dbus/server/read-operations.h b/src/dbus/server/read-operations.h
index eecd2281..7ebae2e8 100644
--- a/src/dbus/server/read-operations.h
+++ b/src/dbus/server/read-operations.h
@@ -61,6 +61,11 @@ public:
void getConfig(bool getTemplate,
Config_t &config);
+ /** implementation of D-Bus GetNamedConfig() for configuration named in parameter */
+ void getNamedConfig(const std::string &configName,
+ bool getTemplate,
+ Config_t &config);
+
/** implementation of D-Bus GetReports() for m_configName as server configuration */
void getReports(uint32_t start, uint32_t count,
Reports_t &reports);
diff --git a/src/dbus/server/server.cpp b/src/dbus/server/server.cpp
index 408b9e74..1ccfffdd 100644
--- a/src/dbus/server/server.cpp
+++ b/src/dbus/server/server.cpp
@@ -73,6 +73,7 @@ vector<string> Server::getCapabilities()
capabilities.push_back("ConfigChanged");
capabilities.push_back("GetConfigName");
+ capabilities.push_back("NamedConfig");
capabilities.push_back("Notifications");
capabilities.push_back("Version");
capabilities.push_back("SessionFlags");
diff --git a/src/dbus/server/session.cpp b/src/dbus/server/session.cpp
index 4c4d4df4..0c7a4430 100644
--- a/src/dbus/server/session.cpp
+++ b/src/dbus/server/session.cpp
@@ -28,6 +28,8 @@
#include "client.h"
#include "dbus-sync.h"
+#include <boost/foreach.hpp>
+
using namespace GDBusCXX;
SE_BEGIN_CXX
@@ -114,9 +116,17 @@ static void setSyncFilters(const ReadOperations::Config_t &config,FilterConfigNo
}
}
}
+
void Session::setConfig(bool update, bool temporary,
const ReadOperations::Config_t &config)
{
+ setNamedConfig(m_configName, update, temporary, config);
+}
+
+void Session::setNamedConfig(const std::string &configName,
+ bool update, bool temporary,
+ const ReadOperations::Config_t &config)
+{
if (!m_active) {
SE_THROW_EXCEPTION(InvalidCall, "session is not active, call not allowed at this time");
}
@@ -124,11 +134,30 @@ void Session::setConfig(bool update, bool temporary,
string msg = StringPrintf("%s started, cannot change configuration at this time", runOpToString(m_runOperation).c_str());
SE_THROW_EXCEPTION(InvalidCall, msg);
}
+ // avoid the check if effect is the same as setConfig()
+ if (m_configName != configName) {
+ bool found = false;
+ BOOST_FOREACH(const std::string &flag, m_flags) {
+ if (boost::iequals(flag, "all-configs")) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ SE_THROW_EXCEPTION(InvalidCall,
+ "SetNameConfig() only allowed in 'all-configs' sessions");
+ }
+
+ if (temporary) {
+ SE_THROW_EXCEPTION(InvalidCall,
+ "SetNameConfig() with temporary config change only supported for config named when starting the session");
+ }
+ }
- m_server.getPresenceStatus().updateConfigPeers (m_configName, config);
+ m_server.getPresenceStatus().updateConfigPeers (configName, config);
/** check whether we need remove the entire configuration */
if(!update && !temporary && config.empty()) {
- boost::shared_ptr<SyncConfig> syncConfig(new SyncConfig(getConfigName()));
+ boost::shared_ptr<SyncConfig> syncConfig(new SyncConfig(configName));
if(syncConfig.get()) {
syncConfig->remove();
m_setConfig = true;
@@ -166,10 +195,10 @@ void Session::setConfig(bool update, bool temporary,
m_tempConfig = true;
} else {
/* need to save configurations */
- boost::shared_ptr<SyncConfig> from(new SyncConfig(getConfigName()));
+ boost::shared_ptr<SyncConfig> from(new SyncConfig(configName));
/* if it is not clear mode and config does not exist, an error throws */
if(update && !from->exists()) {
- SE_THROW_EXCEPTION(NoSuchConfig, "The configuration '" + getConfigName() + "' doesn't exist" );
+ SE_THROW_EXCEPTION(NoSuchConfig, "The configuration '" + configName + "' doesn't exist" );
}
if(!update) {
list<string> sources = from->getSyncSources();
@@ -202,7 +231,7 @@ void Session::setConfig(bool update, bool temporary,
for ( it = sourceFilters.begin(); it != sourceFilters.end(); it++ ) {
from->setConfigFilter(false, it->first, it->second);
}
- boost::shared_ptr<DBusSync> syncConfig(new DBusSync(getConfigName(), *this));
+ boost::shared_ptr<DBusSync> syncConfig(new DBusSync(configName, *this));
syncConfig->prepareConfigForWrite();
syncConfig->copy(*from, NULL);
@@ -432,7 +461,9 @@ Session::Session(Server &server,
add(this, &Session::getNormalConfigName, "GetConfigName");
add(static_cast<ReadOperations *>(this), &ReadOperations::getConfigs, "GetConfigs");
add(static_cast<ReadOperations *>(this), &ReadOperations::getConfig, "GetConfig");
+ add(static_cast<ReadOperations *>(this), &ReadOperations::getNamedConfig, "GetNamedConfig");
add(this, &Session::setConfig, "SetConfig");
+ add(this, &Session::setNamedConfig, "SetNamedConfig");
add(static_cast<ReadOperations *>(this), &ReadOperations::getReports, "GetReports");
add(static_cast<ReadOperations *>(this), &ReadOperations::checkSource, "CheckSource");
add(static_cast<ReadOperations *>(this), &ReadOperations::getDatabases, "GetDatabases");
diff --git a/src/dbus/server/session.h b/src/dbus/server/session.h
index 2bbd9503..8d014fde 100644
--- a/src/dbus/server/session.h
+++ b/src/dbus/server/session.h
@@ -367,6 +367,11 @@ public:
void setConfig(bool update, bool temporary,
const ReadOperations::Config_t &config);
+ /** Session.SetNamedConfig() */
+ void setNamedConfig(const std::string &configName,
+ bool update, bool temporary,
+ const ReadOperations::Config_t &config);
+
typedef StringMap SourceModes_t;
/** Session.Sync() */
void sync(const std::string &mode, const SourceModes_t &source_modes);
diff --git a/test/test-dbus.py b/test/test-dbus.py
index 60aed1a6..4c1f614c 100755
--- a/test/test-dbus.py
+++ b/test/test-dbus.py
@@ -554,9 +554,9 @@ class DBusUtil(Timeout):
DBusUtil.quit_events = []
return (sessionpath, session)
- def setUpSession(self, config):
+ def setUpSession(self, config, flags=[]):
"""stores ready session in self.sessionpath and self.session"""
- self.sessionpath, self.session = self.createSession(config, True)
+ self.sessionpath, self.session = self.createSession(config, True, flags)
def progressChanged(self, *args):
'''subclasses override this method to write specified callbacks for ProgressChanged signals
@@ -757,7 +757,7 @@ class TestDBusServer(unittest.TestCase, DBusUtil):
"""TestDBusServer.testCapabilities - Server.Capabilities()"""
capabilities = self.server.GetCapabilities()
capabilities.sort()
- self.assertEqual(capabilities, ['ConfigChanged', 'DatabaseProperties', 'GetConfigName', 'Notifications', 'SessionAttach', 'SessionFlags', 'Version'])
+ self.assertEqual(capabilities, ['ConfigChanged', 'DatabaseProperties', 'GetConfigName', 'NamedConfig', 'Notifications', 'SessionAttach', 'SessionFlags', 'Version'])
def testVersions(self):
"""TestDBusServer.testVersions - Server.GetVersions()"""
@@ -969,6 +969,57 @@ class TestDBusServerTerm(unittest.TestCase, DBusUtil):
else:
self.fail("no exception thrown")
+class TestNamedConfig(unittest.TestCase, DBusUtil):
+ """Tests for Set/GetNamedConfig"""
+
+ def setUp(self):
+ self.setUpServer()
+
+ def run(self, result):
+ self.runTest(result)
+
+ def testSetNamedConfigError(self):
+ """TestDBusSession.testSetNamedConfigError - SetNamedConfig() only allowed in 'all-configs' sessions"""
+ self.setUpSession("")
+ try:
+ self.session.SetNamedConfig("foobar", False, False, {})
+ except dbus.DBusException, ex:
+ self.assertEqual(str(ex),
+ "org.syncevolution.InvalidCall: SetNameConfig() only allowed in 'all-configs' sessions")
+ else:
+ self.fail("no exception thrown")
+
+ def testSetNamedConfigErrorTemporary(self):
+ """TestDBusSession.testSetNamedConfigErrorTemporary - SetNamedConfig() only implemented for session config"""
+ self.setUpSession("foo", [ "all-configs" ])
+ try:
+ self.session.SetNamedConfig("foobar", False, True, {})
+ except dbus.DBusException, ex:
+ self.assertEqual(str(ex),
+ "org.syncevolution.InvalidCall: SetNameConfig() with temporary config change only supported for config named when starting the session")
+ else:
+ self.fail("no exception thrown")
+ self.session.Detach()
+
+ self.setUpSession("")
+ self.session.SetNamedConfig("", False, True, {})
+
+ def testSetNamedConfig(self):
+ """TestDBusSession.testSetNamedConfig - create two different configs in one session"""
+ self.setUpSession("", [ "all-configs" ])
+
+ fooConfig = {"": {"username": "foo", "configName": "foo"}}
+ barConfig = {"": {"username": "bar", "configName": "bar"}}
+
+ self.session.SetNamedConfig("foo", False, False, fooConfig)
+ self.session.SetNamedConfig("bar", False, False, barConfig)
+
+ self.assertEqual(fooConfig, self.server.GetConfig("foo", False))
+ self.assertEqual(barConfig, self.server.GetConfig("bar", False))
+
+ self.assertEqual(fooConfig, self.session.GetNamedConfig("foo", False))
+ self.assertEqual(barConfig, self.session.GetNamedConfig("bar", False))
+
class Connman (dbus.service.Object):
count = 0