lib: Adding explicit default constructor for JLDirectoryEntry.
[barry.git] / desktop / src / osconfig.cc
blob59fccdb6cd039d4c73b8e2f94365890c428350cd
1 ///
2 /// \file osconfig.cc
3 /// Class which detects a set of available or known devices
4 /// in an opensync-able system.
5 ///
7 /*
8 Copyright (C) 2009-2012, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "osconfig.h"
24 #include "os40.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <algorithm>
30 #include "i18n.h"
32 using namespace std;
34 namespace OpenSync { namespace Config {
36 //////////////////////////////////////////////////////////////////////////////
37 // Unsupported config class
39 std::string Unsupported::AppName()
41 return _C("Unsupported");
45 //////////////////////////////////////////////////////////////////////////////
46 // Barry config class
48 Barry::Barry(const ::Barry::Pin &pin)
49 : m_debug_mode(false)
50 , m_pin(pin)
52 if( !m_pin.Valid() )
53 throw std::logic_error(_C("Barry config must have valid pin number."));
56 Barry::Barry(Converter *load_converter, const Member &member)
57 : m_debug_mode(false)
59 load_converter->Load(*this, member);
61 // check that the loaded pin is valid... if not, it is
62 // likely safe to assume that something is horribly wrong.
63 // in the case where the Application wishes to add a new
64 // barry plugin, it should use the Pin constructor.
65 // if you *really* need to try to salvage an old
66 // corrupt config, you can always do the
67 // converter->Load(barry_obj) manually, and pick out
68 // the left overs.
70 if( !m_pin.Valid() ) {
71 std::ostringstream oss;
72 oss << _C("Unable to load pin number from Barry plugin config. Consider this group corrupt, or not fully configured: ") << member;
73 throw LoadError(oss.str());
78 //////////////////////////////////////////////////////////////////////////////
79 // Group class
81 Group::Group(const std::string &group_name,
82 OpenSync::API &api,
83 unsigned throw_mask)
84 : m_group_name(group_name)
86 Load(api, throw_mask);
89 Group::Group(const std::string &group_name)
90 : m_group_name(group_name)
94 // Checks for OSCG_THROW_ON_NO_BARRY and OSCG_THROW_ON_MULTIPLE_BARRIES
95 void Group::BarryCheck(OpenSync::API &api,
96 const std::string &group_name,
97 const member_list_type &members,
98 unsigned throw_mask)
100 if( ! (throw_mask & (OSCG_THROW_ON_NO_BARRY | OSCG_THROW_ON_MULTIPLE_BARRIES) ) )
101 return; // nothing to do
103 int found = 0;
104 std::string barry_name = Config::Barry::PluginName(api);
105 member_list_type::const_iterator b = members.begin(), e = members.end();
106 for( ; b != e; ++b ) {
107 if( b->plugin_name == barry_name )
108 found++;
111 if( found == 0 && (throw_mask & OSCG_THROW_ON_NO_BARRY) ) {
112 throw LoadError(
113 string_vprintf(_C("No Barry plugins found in group '%s' and OSCG_THROW_ON_NO_BARRY is set."), group_name.c_str()));
116 if( found > 1 && (throw_mask & OSCG_THROW_ON_MULTIPLE_BARRIES) ) {
117 throw LoadError(
118 string_vprintf(_C("Found %d Barry plugins in group '%s' and OSCG_THROW_ON_MULTIPLE_BARRIES is set."), found, group_name.c_str()));
122 bool Group::GroupMatchesExistingConfig(OpenSync::API &api)
124 member_list_type members;
125 api.GetMembers(m_group_name, members);
127 // what needs to match:
129 // - number of connected Config::Plugin objects in our
130 // list must match number of members in config
131 // - each member ID must match along with the plugin_name
132 // of each member
135 // check totals match
136 if( (unsigned) GetConnectedCount() != members.size() ) {
137 barryverbose("Connected count of " << GetConnectedCount() << " does not match member count of " << members.size());
138 return false;
141 // cycle through our own vector, matching against each member_id
142 // in the members list
143 const_iterator ci = begin(), ce = end();
144 for( ; ci != ce; ++ci ) {
145 if( (*ci)->GetMemberId() == -1 )
146 continue;
148 Member *m = members.Find( (*ci)->GetMemberId() );
149 if( !m ) {
150 barryverbose("Can't match member ID: " << (*ci)->GetMemberId() );
151 return false;
154 if( m->plugin_name != (*ci)->GetPluginName(api) ) {
155 barryverbose("Plugin names don't match: "
156 << m->plugin_name << ", "
157 << (*ci)->GetPluginName(api));
158 return false;
162 return true;
165 bool Group::HasUnsupportedPlugins() const
167 const_iterator b = begin(), e = end();
168 for( ; b != e; ++b ) {
169 if( (*b)->IsUnsupported() )
170 return true;
172 return false;
175 bool Group::HasBarryPlugins() const
177 const_iterator b = begin(), e = end();
178 for( ; b != e; ++b ) {
179 if( (*b)->GetAppName() == Config::Barry::AppName() )
180 return true;
182 return false;
185 bool Group::GroupExists(OpenSync::API &api) const
187 // does m_group_name exist in the API list?
188 string_list_type groups;
189 api.GetGroupNames(groups);
190 return std::find(groups.begin(), groups.end(), m_group_name) != groups.end();
193 bool Group::AllConfigured(OpenSync::API &api) const
195 const_iterator b = begin(), e = end();
196 for( ; b != e; ++b ) {
197 if( !(*b)->IsConfigured(api) )
198 return false;
200 return true;
203 int Group::GetConnectedCount() const
205 int count = 0;
206 const_iterator b = begin(), e = end();
207 for( ; b != e; ++b ) {
208 if( (*b)->GetMemberId() != -1 )
209 count++;
211 return count;
214 pst_type Group::GetSupportedSyncTypes(OpenSync::API &api) const
216 pst_type types = PST_ALL;
218 const_iterator b = begin(), e = end();
219 for( ; b != e; ++b ) {
220 types &= (*b)->GetSupportedSyncTypes(api);
223 return types;
226 std::string Group::GetAppNames() const
228 std::string names;
230 const_iterator b = begin(), e = end();
231 for( ; b != e; ++b ) {
232 std::string name = (*b)->GetAppName();
233 if( name != Config::Barry::AppName() ) {
234 if( names.size() )
235 names += ", ";
236 names += name;
240 return names;
243 OpenSync::Config::Barry& Group::GetBarryPlugin()
245 return const_cast<OpenSync::Config::Barry&> ( const_cast<const Group*> (this)->GetBarryPlugin() );
248 const OpenSync::Config::Barry& Group::GetBarryPlugin() const
250 const_iterator b = begin(), e = end();
251 for( ; b != e; ++b ) {
252 if( (*b)->GetAppName() == Config::Barry::AppName() )
253 return dynamic_cast<const OpenSync::Config::Barry&> (*(*b));
256 // not found
257 throw std::logic_error("No Barry Plugins in Group");
260 OpenSync::Config::Plugin* Group::GetNonBarryPlugin()
262 return const_cast<OpenSync::Config::Plugin*> ( const_cast<const Group*> (this)->GetNonBarryPlugin() );
265 const OpenSync::Config::Plugin* Group::GetNonBarryPlugin() const
267 const_iterator b = begin(), e = end();
268 for( ; b != e; ++b ) {
269 if( (*b)->GetAppName() != Config::Barry::AppName() )
270 return (*b).get();
273 return 0;
276 void Group::DisconnectMembers()
278 iterator b = begin(), e = end();
279 for( ; b != e; ++b ) {
280 (*b)->SetMemberId(-1);
284 void Group::Load(OpenSync::API &api, unsigned throw_mask)
286 Load(m_group_name, api, throw_mask);
289 void Group::Load(const std::string &src_group_name,
290 OpenSync::API &api,
291 unsigned throw_mask)
293 member_list_type members;
294 api.GetMembers(src_group_name, members);
296 BarryCheck(api, src_group_name, members, throw_mask);
298 member_list_type::const_iterator b = members.begin(), e = members.end();
299 for( ; b != e; ++b ) {
300 Converter &converter = api.GetConverter();
301 Converter::plugin_ptr p = converter.CreateAndLoadPlugin(*b);
302 p->SetMemberId(b->id);
304 if( p->IsUnsupported() && (throw_mask & OSCG_THROW_ON_UNSUPPORTED) ) {
305 throw LoadError(
306 string_vprintf(_C("Unsupported plugin '%s' in group '%s' and OSCG_THROW_ON_UNSUPPORTED is set."),
307 b->plugin_name.c_str(),
308 src_group_name.c_str()));
311 // everything looks ok, add the plugin to our list
312 push_back(p);
316 void Group::ResetGroupName(const std::string &new_group_name)
318 m_group_name = new_group_name;
321 void Group::AddPlugin(OpenSync::Config::Plugin *plugin)
323 plugin_ptr pp(plugin);
324 push_back(pp);
327 void Group::DeletePlugin(iterator i, OpenSync::API &api)
329 // is this plugin connected to a previously saved group config?
330 if( (*i)->GetMemberId() != -1 ) {
331 // this plugin has a member ID... only OpenSync 0.40 can
332 // delete members like that... do we have 40 support?
333 OpenSync::OpenSync40 *api40 = dynamic_cast<OpenSync::OpenSync40*> (&api);
334 if( !api40 ) {
335 // not version 0.40... can't do it capt'n!
336 throw DeleteError(_C("Cannot delete individual members from an OpenSync group with versions < 0.40."));
339 // so... we have the capability... check that the plugin
340 // name of the ID in the group matches what we think it
341 // should be
343 member_list_type members;
344 api40->GetMembers(m_group_name, members);
346 Member *m = members.Find( (*i)->GetMemberId() );
347 if( !m ) {
348 throw DeleteError(string_vprintf(_C("Tried to delete non-existent member ID %ld (%s) from group '%s'"),
349 (*i)->GetMemberId(),
350 (*i)->GetPluginName(api).c_str(),
351 m_group_name.c_str()));
354 if( m->plugin_name != (*i)->GetPluginName(api) ) {
355 throw DeleteError(string_vprintf(_C("Tried to delete member ID %ld using plugin '%s' from group '%s', but the existing member uses plugin '%s'"),
356 (*i)->GetMemberId(),
357 (*i)->GetPluginName(api).c_str(),
358 m_group_name.c_str(),
359 m->plugin_name.c_str()));
362 // so far so good... try deleting it
363 api40->DeleteMember(m_group_name, (*i)->GetMemberId());
366 // remove from our own array
367 erase(i);
370 void Group::Save(OpenSync::API &api)
372 if( GroupExists(api) ) {
373 // groups already exists, so need to confirm that our
374 // connected plugins match the existing member_ids and
375 // plugin names in the group's member list
376 if( !GroupMatchesExistingConfig(api) ) {
377 throw SaveError(string_vprintf(_C("Tried to overwrite group '%s' with a Group set that did not match in ID's and plugin names."),
378 m_group_name.c_str()));
381 else {
382 // group does not exist, so create it if needed
383 if( size() )
384 api.AddGroup(m_group_name);
387 // cycle through all plugins and save them all
388 iterator b = begin(), e = end();
389 for( ; b != e; ++b ) {
390 Config::Plugin &p = *(*b);
392 if( p.GetMemberId() == -1 ) {
393 // this plugin has never been saved yet, so
394 // add it fresh
395 long newid = api.AddMember(m_group_name,
396 p.GetPluginName(api), "");
397 p.SetMemberId(newid);
400 // save config
401 p.Save(api, m_group_name);
405 bool Group::Compare(const Group &other) const
407 // size of group equal?
408 if( size() != other.size() )
409 return false;
411 // name of group?
412 if( m_group_name != other.m_group_name )
413 return false;
415 // cycle through all plugins, searching for a match in other
416 const_iterator i = begin();
417 for( ; i != end(); ++i ) {
418 bool sametype, equal;
419 bool match = false;
421 // search other for a match
422 const_iterator oi = other.begin();
423 for( ; oi != other.end(); ++oi ) {
424 if( (match = (*i)->Compare(*(*oi), sametype, equal)) )
425 break;
428 if( !match )
429 return false;
432 return true;
435 Group::group_ptr Group::Clone() const
437 group_ptr g( new Group(m_group_name) );
439 // clone all plugins
440 const_iterator b = begin(), e = end();
441 for( ; b != e; ++b ) {
442 plugin_ptr p( (*b)->Clone() );
443 g->push_back(p);
446 return g;
449 }} // namespace OpenSync::Config