Imported Upstream version 0.8~alpha1
[platform/upstream/syncevolution.git] / src / client-api / src / c++ / common / client / BriefcaseCacheSyncSource.cpp
1 /*
2  * Funambol is a mobile platform developed by Funambol, Inc. 
3  * Copyright (C) 2003 - 2007 Funambol, Inc.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Affero General Public License version 3 as published by
7  * the Free Software Foundation with the addition of the following permission 
8  * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
9  * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
10  * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
11  * 
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  * 
17  * You should have received a copy of the GNU Affero General Public License 
18  * along with this program; if not, see http://www.gnu.org/licenses or write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02110-1301 USA.
21  * 
22  * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
23  * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
24  * 
25  * The interactive user interfaces in modified source and object code versions
26  * of this program must display Appropriate Legal Notices, as required under
27  * Section 5 of the GNU Affero General Public License version 3.
28  * 
29  * In accordance with Section 7(b) of the GNU Affero General Public License
30  * version 3, these Appropriate Legal Notices must retain the display of the
31  * "Powered by Funambol" logo. If the display of the logo is not reasonably 
32  * feasible for technical reasons, the Appropriate Legal Notices must display
33  * the words "Powered by Funambol".
34  */
35 #include "spds/SyncItem.h"
36 #include "spds/SyncItemStatus.h"
37 #include "base/util/utils.h"
38 #include "base/Log.h"
39 #include "syncml/core/TagNames.h"
40 #include "base/util/ArrayListEnumeration.h"
41 #include "client/BriefcaseCacheSyncSource.h"
42
43
44 #define ERR_FILE_SYSTEM             1
45 #define ERR_NO_FILES_TO_SYNC        2
46 #define ERR_BAD_FILE_CONTENT        3
47
48
49 static StringBuffer getCompleteName(StringBuffer& dir, const WCHAR *name) {
50     
51     char* t = toMultibyte(name);
52     StringBuffer pathName(dir);
53     pathName += "/"; 
54     pathName += t;
55     delete [] t;
56     return pathName;
57     
58 }
59
60 BriefcaseCacheSyncSource::BriefcaseCacheSyncSource(
61                         const WCHAR* name,
62                         AbstractSyncSourceConfig* sc)
63     : CacheSyncSource(name, sc), dir(DEFAULT_BRIEFCASE_DIR) {
64    
65 }
66 /*
67 BriefcaseSyncSource::BriefcaseSyncSource(const BriefcaseSyncSource& s): 
68     syncMode(s.getSyncMode()),
69     lastSync(s.getLastSync()),
70     nextSync(s.getNextSync()),
71     lastAnchor(s.getLastAnchor()),
72     nextAnchor(s.getNextAnchor()),
73     filter(s.getFilter()),
74     dir(getDir()),
75     report(s.getReport())
76     {
77
78 }
79
80
81 BriefcaseSyncSource::BriefcaseSyncSource(const BriefcaseSyncSource& s) : TrackingSyncSource(s) {
82     
83     setSyncMode(s.getSyncMode());
84     setLastSync(s.getLastSync());
85     setNextSync(s.getNextSync());
86     setLastAnchor(s.getLastAnchor());
87     setNextAnchor(s.getNextAnchor());
88     setFilter(s.getFilter());    
89     setDir(getDir());
90     setReport(s.getReport());
91
92 }
93 */
94
95
96 BriefcaseCacheSyncSource::~BriefcaseCacheSyncSource() {}
97
98
99 int BriefcaseCacheSyncSource::removeAllItems() {
100     removeFileInDir(dir);
101     return 0;
102 }
103
104
105 int BriefcaseCacheSyncSource::parseFileData(FileData& file, SyncItem& item) {
106     
107     if (file.parse(item.getData(),item.getDataSize())) {
108         LOG.info("Error parsing item from server. Using its content directly");        
109         return 1;
110     } else {
111         return 0;
112     }
113 }
114
115 int BriefcaseCacheSyncSource::saveFileData(FileData& file) {
116     
117     StringBuffer completeName(getCompleteName(dir, file.getName()));
118     
119     int ret = STC_COMMAND_FAILED;
120     if (!saveFile(completeName, file.getBody(), file.getSize(), true)) {
121         LOG.info("Error saving file");        
122         return STC_COMMAND_FAILED;
123     } else {
124         return STC_OK;
125     }
126 }
127
128 int BriefcaseCacheSyncSource::saveFileData(SyncItem& item, bool isUpdate) {
129     
130     StringBuffer completeName(getCompleteName(dir, item.getKey()));
131     if (!isUpdate) { // it is an add
132          FILE *fh = fopen(completeName, "r");
133          if (fh) {
134             fclose(fh);     
135             return STC_ALREADY_EXISTS;
136          }
137     }   
138     if (!saveFile(completeName, (const char *)item.getData(), item.getDataSize(), true)) {
139         setErrorF(ERR_FILE_SYSTEM, "Error saving file %s", completeName.c_str());
140         LOG.error("%s", getLastErrorMsg());
141         report->setLastErrorCode(ERR_FILE_SYSTEM);
142         report->setLastErrorMsg(getLastErrorMsg());
143         report->setState(SOURCE_ERROR);
144         return STC_COMMAND_FAILED;
145     } 
146     
147     if (!isUpdate) {    
148         return STC_ITEM_ADDED;
149     } else {
150         return STC_OK;
151     }
152     
153 }
154
155 Enumeration* BriefcaseCacheSyncSource::getAllItemList() {
156     
157     //
158     // Get the list of the files that are in the directory
159     //
160     ArrayList currentKeys;
161     Enumeration* allKeys = NULL;        
162     int count;
163     char** fileNames = readDir((char*)dir.c_str(), &count);
164     LOG.info("The client number of files to sync are %i", count);
165     
166     for (int i = 0; i < count; i++) {
167         if (fileNames[i]) {
168             StringBuffer s(fileNames[i]);            
169             currentKeys.add(s);
170         }
171     }    
172
173     // delete fileNames
174     for (int i = 0; i < count; i++) {
175         delete [] fileNames[i]; fileNames[i] = NULL; 
176     }
177     if (fileNames != NULL) {
178         delete [] fileNames; fileNames = NULL;
179     }    
180
181     if (currentKeys.size() > 0) {
182         allKeys = new ArrayListEnumeration(currentKeys);
183     }
184     return allKeys;
185
186 }
187
188 /**
189 * Adds an item on the file system in the set directory.
190
191 */
192 int BriefcaseCacheSyncSource::insertItem(SyncItem& item) {
193     
194     int ret = STC_COMMAND_FAILED;
195     FileData file;
196     
197     if (parseFileData(file, item) == 0) {
198         if (file.getSize() >= 0) {   
199             ret = saveFileData(file);
200             if (ret = STC_COMMAND_FAILED) {
201                 return ret;
202             } else {
203                 item.setKey(file.getName());
204                 ret = STC_ITEM_ADDED;
205                 LOG.debug("Added item: %" WCHAR_PRINTF, file.getName());
206             }
207         }        
208     } else {
209         ret = saveFileData(item, false);        
210     }      
211     return ret;
212 }
213
214
215 int BriefcaseCacheSyncSource::removeItem(SyncItem& item) {
216     
217     const char* filename = toMultibyte(item.getKey());
218     removeFileInDir(dir, filename);
219     if (filename) { delete [] filename; filename = NULL; }
220     LOG.debug("Added deleted: %" WCHAR_PRINTF, item.getKey());
221
222     return STC_OK;
223
224 }
225 int BriefcaseCacheSyncSource::modifyItem(SyncItem& item) {
226     
227     int ret = STC_COMMAND_FAILED;
228     FileData file;
229     
230     if (parseFileData(file, item) == 0) {
231         if (file.getSize() >= 0) {   
232             ret = saveFileData(file);
233             if (ret = STC_COMMAND_FAILED) {
234                 return ret;
235             } else { // don't add the item if it doesn't exist
236                 //
237             }
238         }        
239     } else {
240          ret = saveFileData(item, true);    
241     }    
242     return ret;
243     
244 }
245
246 /**
247 * Get the content of an item given the key. It is used to populate
248 * the SyncItem before the engine uses it in the usual flow of the sync.
249 * It is used also by the itemHandler if needed 
250 * (i.e. in the cache implementation)
251 *
252 * @param key      the local key of the item
253 * @param size     OUT: the size of the content
254 */
255 void* BriefcaseCacheSyncSource::getItemContent(StringBuffer& key, size_t* size) {
256     
257     char* content = NULL;    
258     *size = 0;
259     WCHAR* t = toWideChar(key);
260     StringBuffer completeName(getCompleteName(dir, t));
261     if (readFile(completeName, &content, size, true)) {        
262         LOG.debug("Content succesfully read");   
263     } else {
264         LOG.error("Content of the file not read");   
265     }
266     delete [] t;
267     return content;
268
269 }
270
271
272 ArrayElement* BriefcaseCacheSyncSource::clone() {
273     /*
274     BriefcaseSyncSource* s = new BriefcaseSyncSource(*this);
275     return s;
276     */
277     BriefcaseCacheSyncSource* s = new BriefcaseCacheSyncSource(getName(), &(getConfig()));
278     s->assign(*this);
279     return s;
280 }
281
282 void BriefcaseCacheSyncSource::assign(BriefcaseCacheSyncSource& s) {
283     
284     setSyncMode(s.getSyncMode());
285     setLastSync(s.getLastSync());
286     setNextSync(s.getNextSync());
287     setLastAnchor(s.getLastAnchor());
288     setNextAnchor(s.getNextAnchor());
289     setFilter(s.getFilter());    
290     setDir(getDir());
291     setReport(s.getReport());
292
293 }