ActiveSync: boiler plate code with empty function bodies

Compiles inside SyncEvolution, see README.
Sync session and design outlined in the ActiveSyncSource.h
header file for the main class, ActiveSyncSource.

activesyncd commit ID:
ec8071ae67c107f32305c6d47f176210421c17c7
This commit is contained in:
Patrick Ohly 2011-06-18 15:16:47 +02:00
parent 1f3f3bdd53
commit 6ba4b8680d
4 changed files with 511 additions and 0 deletions

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2007-2009 Patrick Ohly <patrick.ohly@gmx.de>
* Copyright (C) 2009 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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef ENABLE_ACTIVESYNC
#include "ActiveSyncSource.h"
#include <syncevo/declarations.h>
SE_BEGIN_CXX
void ActiveSyncSource::enableServerMode()
{
SyncSourceAdmin::init(m_operations, this);
SyncSourceBlob::init(m_operations, getCacheDir());
}
bool ActiveSyncSource::serverModeEnabled() const
{
return m_operations.m_loadAdminData;
}
void ActiveSyncSource::open()
{
// TODO: extract account ID and throw error if missing
}
void ActiveSyncSource::close()
{
}
void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string &resumeToken)
{
// TODO: incremental sync (non-empty token) or start from scratch
// TODO: Test that we really get an empty token here for an unexpected slow
// sync. If not, we'll start an incremental sync here and later the engine
// will ask us for older, unmodified item content which we won't have.
}
std::string ActiveSyncSource::endSync(bool success)
{
// let engine do incremental sync next time or start from scratch
// in case of failure
return success ? m_currentSyncKey : "";
}
void ActiveSyncSource::deleteItem(const string &luid)
{
// TODO: send delete request
// remove from item list
// update key
}
SyncSourceSerialize::InsertItemResult ActiveSyncSource::insertItem(const std::string &luid, const std::string &item)
{
SyncSourceSerialize::InsertItemResult res;
// distinguish between update (existing luid)
// or creation (empty luid)
if (luid.empty()) {
// TODO: send item to server
// add to item list
} else {
// update item on server
}
// update key
return res;
}
void ActiveSyncSource::readItem(const std::string &luid, std::string &item)
{
// TODO: return straight from cache
}
SE_END_CXX
#endif /* ENABLE_ACTIVESYNC */
#ifdef ENABLE_MODULES
# include "ActiveSyncSourceRegister.cpp"
#endif

View File

@ -0,0 +1,222 @@
/*
* Copyright (C) 2007-2009 Patrick Ohly <patrick.ohly@gmx.de>
* Copyright (C) 2011 Patrick Ohly <patrick.ohly@intel.com>
*
* 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
*/
#ifndef INCL_ACTIVESYNCSOURCE
#define INCL_ACTIVESYNCSOURCE
#include <syncevo/SyncSource.h>
#include <syncevo/PrefixConfigNode.h>
#include <syncevo/SafeConfigNode.h>
#include <boost/bind.hpp>
#include <string>
#include <map>
// TODO: include header files instead
typedef enum {
EAS_ITEM_FOLDER=0,
EAS_ITEM_MAIL,
EAS_ITEM_CALENDAR, ///< iCalendar 2.0 VEVENT
EAS_ITEM_CONTACT, ///< vCard 3.0 contact
EAS_ITEM_TODO, ///< iCalendar 2.0 VTODO
EAS_ITEM_JOURNAL, ///< iCalendar 2.0 VJOURNAL
//TODO: add all other items here
EAS_ITEM_LAST
}EasItemType;
#include <syncevo/declarations.h>
SE_BEGIN_CXX
#ifdef ENABLE_ACTIVESYNC
/**
* Synchronizes contacts, events, tasks and journals with an
* ActiveSync server. Sub-classes provide the necessary specialization
* for different data formats.
*
* Data is exchanged between ActiveSyncSource, ActiveSync library, and
* Synthesis engine as vCard 3.0 and iCalendar 2.0 format. The
* standard contact and calendar profile is used, with ACTIVESYNC set
* as sub-rule. This influences how the Synthesis engine converts to
* and from its internal format. See KDE in
* src/syncevo/profiles/datatypes/01vcard-profile.xml for an extensive
* example how that works.
*
* Each item is a single calendar item, in other words, multiple
* VEVENTs with the same UID are treated as separate items.
*
* A sync session is done like this:
* - The Synthesis sync anchor directly maps to the
* ActiveSync sync key.
* - In SyncSourceSession::beginSync() (inherited from TestingSyncSource),
* the ActiveSync library is asked for changes (for a non-empty key)
* or all items (empty key).
* - The returned item IDs are stored in SyncSourceChanges.
* Only the server's IDs are used. They map 1:1 with the "luid" in
* the SyncSource API and the Synthesis engine.
* Because a full list of all existing items is expected,
* ActiveSyncSource maintains a list of all known items
* in the params.m_nodes.getTrackingNode() that it gets
* for that purpose.
* - The returned item content is cached in a local content cache
* and returns items from that when asked to via
* SyncSourceSerialize.
* - As items are added/remove/updated, the content cache, the list
* of IDs, and the sync key are updated. The expectation is
* that any changes made by other ActiveSync server clients
* will be reported when asking for changes based on that updated
* key without including changes made by our own client, even
* when these changes happen concurrently.
* TODO: write a test program to verify that assumption.
* - At the end of the sync, the updated ID list is stored and
* the updated sync key is returned to the Synthesis engine.
* - If anything goes wrong, a fatal error is returned to the
* Synthesis engine, which then invalidates the sync key and
* thus forces a slow sync in the next session.
* TODO: investigate more intelligent ways of recovering.
* The problem will be that trying again with the original
* sync key will return changes made by the client itself
* as part of the incomplete sync session.
*
* The command line item manipulation operations
* (--import/export/update/print-items/delete-items) always start a
* session without a sync key and thus (with the current API) have to
* download all items before doing anything.
* TODO: optimize that
*/
class ActiveSyncSource :
public TestingSyncSource, // == SyncSourceSession, SyncSourceChanges, SyncSourceDelete, SyncSourceSerialize
// TODO: implement SyncSourceLogging to get nicer debug and command line output
// virtual public SyncSourceLogging,
virtual public SyncSourceAdmin,
virtual public SyncSourceBlob
{
public:
ActiveSyncSource(const SyncSourceParams &params) :
TestingSyncSource(params),
// Ensure that arbitrary keys can be stored (SafeConfigNode) and
// that we use a common prefix, so that we can use the key/value store
// also for other keys if the need ever arises).
m_ids(new PrefixConfigNode("item-",
boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.getTrackingNode()))))
{
}
protected:
/* partial implementation of SyncSource */
virtual void enableServerMode();
virtual bool serverModeEnabled() const;
virtual Databases getDatabases() { return Databases(); } // not supported
virtual void open();
virtual void close();
virtual std::string getPeerMimeType() const { return getMimeType(); }
/* implementation of SyncSourceSession */
virtual void beginSync(const std::string &lastToken, const std::string &resumeToken);
virtual std::string endSync(bool success);
/* implementation of SyncSourceDelete */
virtual void deleteItem(const string &luid);
/* partial implementation of SyncSourceSerialize */
virtual std::string getMimeType() const = 0;
virtual std::string getMimeVersion() const = 0;
virtual InsertItemResult insertItem(const std::string &luid, const std::string &item);
virtual void readItem(const std::string &luid, std::string &item);
private:
/** smart pointer holding reference to EasSyncHandler during session */
// TODO: include headers - eptr<EasSyncHandler, GObject> m_handler;
/** original sync key, set when session starts */
std::string m_startSyncKey;
/** current sync key, set when session starts and updated as changes are made */
std::string m_currentSyncKey;
/** server-side IDs of all items, updated as changes are reported and/or are made */
boost::shared_ptr<ConfigNode> m_ids;
/** cache of all items, filled at begin of session and updated as changes are made */
std::map<std::string, std::string> m_items;
};
class ActiveSyncContactSource : public ActiveSyncSource
{
public:
ActiveSyncContactSource(const SyncSourceParams &params) :
ActiveSyncSource(params)
{}
protected:
/* partial implementation of SyncSourceSerialize */
virtual std::string getMimeType() const { return "text/vcard"; }
virtual std::string getMimeVersion() const { return "3.0"; }
#if 0 // currently disabled, and thus using the same conversion as the Evolution backend
void getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments)
{
TrackingSyncSource::getSynthesisInfo(info, fragments);
/** enable the ActiveSync X- extensions in the Synthesis<->backend conversion */
info.m_backendRule = "ACTIVESYNC";
/*
* Disable the default VCARD_BEFOREWRITE_SCRIPT_EVOLUTION.
* If any KDE-specific transformations via such a script
* are needed, it can be named here and then defined by appending
* to the fragments.
*/
info.m_beforeWriteScript = ""; // "$VCARD_BEFOREWRITE_SCRIPT_KDE;";
// fragments.m_datatypes["VCARD_BEFOREWRITE_SCRIPT_KDE"] = "<macro name=\"VCARD_BEFOREWRITE_SCRIPT_KDE\"><![DATA[ ... ]]></macro>";
}
#endif
};
/**
* used for all iCalendar 2.0 items (events, todos, journals)
*/
class ActiveSyncCalendarSource : public ActiveSyncSource
{
EasItemType m_type;
public:
ActiveSyncCalendarSource(const SyncSourceParams &params, EasItemType type) :
ActiveSyncSource(params),
m_type(type)
{}
protected:
/* partial implementation of SyncSourceSerialize */
virtual std::string getMimeType() const { return "text/calendar"; }
virtual std::string getMimeVersion() const { return "2.0"; }
};
#endif // ENABLE_ACTIVESYNC
SE_END_CXX
#endif // INCL_ACTIVESYNCSOURCE

View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
* Copyright (C) 2009 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 "ActiveSyncSource.h"
#ifdef ENABLE_UNIT_TESTS
# include <cppunit/extensions/TestFactoryRegistry.h>
# include <cppunit/extensions/HelperMacros.h>
#endif
#include <syncevo/declarations.h>
SE_BEGIN_CXX
static SyncSource *createSource(const SyncSourceParams &params)
{
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
bool isMe;
isMe = sourceType.m_backend == "ActiveSync Address Book";
if (isMe) {
return
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncContactSource(params)
#else
RegisterSyncSource::InactiveSource
#endif
;
}
isMe = sourceType.m_backend == "ActiveSync Events";
if (isMe) {
return
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncCalendarSource(params, EAS_ITEM_CALENDAR)
#else
RegisterSyncSource::InactiveSource
#endif
;
}
isMe = sourceType.m_backend == "ActiveSync Todos";
if (isMe) {
return
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncCalendarSource(params, EAS_ITEM_TODO)
#else
RegisterSyncSource::InactiveSource
#endif
;
}
isMe = sourceType.m_backend == "ActiveSync Memos";
if (isMe) {
return
#ifdef ENABLE_ACTIVESYNC
new ActiveSyncCalendarSource(params, EAS_ITEM_JOURNAL)
#else
RegisterSyncSource::InactiveSource
#endif
;
}
return NULL;
}
static RegisterSyncSource registerMe("ActiveSync",
#ifdef ENABLE_ACTIVESYNC
true,
#else
false,
#endif
createSource,
"ActiveSync Address Book = eas-contacts\n"
"ActiveSync Events = eas-events\n"
"ActiveSync Todos = eas-todos\n"
"ActiveSync Memos = eas-memos",
Values() +
(Aliases("ActiveSync Address Book") + "eas-contacts") +
(Aliases("ActiveSync Events") + "eas-events") +
(Aliases("ActiveSync Todos") + "eas-todos") +
(Aliases("ActiveSync Memos") + "eas-memos"));
#ifdef ENABLE_ACTIVESYNC
#ifdef ENABLE_UNIT_TESTS
class ActiveSyncsTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ActiveSyncsTest);
CPPUNIT_TEST(testInstantiate);
CPPUNIT_TEST_SUITE_END();
protected:
void testInstantiate() {
boost::shared_ptr<SyncSource> source;
source.reset(SyncSource::createTestingSource("contacts", "ActiveSync Address Book", true));
source.reset(SyncSource::createTestingSource("events", "ActiveSync Events", true));
source.reset(SyncSource::createTestingSource("todos", "ActiveSync Todos", true));
source.reset(SyncSource::createTestingSource("memos", "ActiveSync Memos", true));
}
};
SYNCEVOLUTION_TEST_SUITE_REGISTRATION(ActiveSyncsTest);
#endif // ENABLE_UNIT_TESTS
#ifdef ENABLE_INTEGRATION_TESTS
namespace {
#if 0
}
#endif
static class ActiveSyncContactTest : public RegisterSyncSourceTest {
public:
ActiveSyncContactTest() :
RegisterSyncSourceTest("eas_contact", // name of test => Client::Source::eas_contact"
"eds_contact" // name of test cases: inherit from EDS, override below
) {}
virtual void updateConfig(ClientTestConfig &config) const
{
// override default eds_contact test config
config.type = "eas-contacts";
// TODO: provide comprehensive set of vCard 3.0 contacts as they are understood by the ActiveSync library
// config.testcases = "testcases/eas_contact.vcf";
}
} ActiveSyncContactTest;
static class ActiveSyncEventTest : public RegisterSyncSourceTest {
public:
ActiveSyncEventTest() :
RegisterSyncSourceTest("eas_event", "eds_event")
{}
virtual void updateConfig(ClientTestConfig &config) const
{
}
} ActiveSyncEventTest;
static class ActiveSyncTodoTest : public RegisterSyncSourceTest {
public:
ActiveSyncTodoTest() :
RegisterSyncSourceTest("eas_todo", "eds_todo")
{}
virtual void updateConfig(ClientTestConfig &config) const
{
}
} ActiveSyncTodoTest;
static class ActiveSyncMemoTest : public RegisterSyncSourceTest {
public:
ActiveSyncMemoTest() :
RegisterSyncSourceTest("eas_memo", "eds_memo")
{}
virtual void updateConfig(ClientTestConfig &config) const
{
}
} ActiveSyncMemoTest;
}
#endif // ENABLE_INTEGRATION_TESTS
#endif // ENABLE_ACTIVESYNC
SE_END_CXX

View File

@ -0,0 +1,8 @@
To compile this backend as part of SyncEvolution, ensure that this directory
is visible at src/backends/activesync (symlink or copy), run ./autogen.sh at
the top level, and use --enable-activesync in configure.
To compile as part of the activesync repo, please add a configure
script which uses syncevolution.pc to find include files and libs. The
Makefile.am here might already work. Set ENABLE_ACTIVESYNC in your config.h.