Granted that accounts different only in port number won't mix their files in the...
[pub/Android/ownCloud.git] / src / eu / alefzero / owncloud / datamodel / FileDataStorageManager.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012 Bartek Przybylski
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 package eu.alefzero.owncloud.datamodel;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Vector;
27
28 import eu.alefzero.owncloud.db.ProviderMeta;
29 import eu.alefzero.owncloud.db.ProviderMeta.ProviderTableMeta;
30 import eu.alefzero.owncloud.files.services.FileDownloader;
31 import android.accounts.Account;
32 import android.content.ContentProviderClient;
33 import android.content.ContentProviderOperation;
34 import android.content.ContentProviderResult;
35 import android.content.ContentResolver;
36 import android.content.ContentValues;
37 import android.content.OperationApplicationException;
38 import android.database.Cursor;
39 import android.net.Uri;
40 import android.os.Environment;
41 import android.os.RemoteException;
42 import android.util.Log;
43
44 public class FileDataStorageManager implements DataStorageManager {
45
46 private ContentResolver mContentResolver;
47 private ContentProviderClient mContentProvider;
48 private Account mAccount;
49
50 private static String TAG = "FileDataStorageManager";
51
52 public FileDataStorageManager(Account account, ContentResolver cr) {
53 mContentProvider = null;
54 mContentResolver = cr;
55 mAccount = account;
56 }
57
58 public FileDataStorageManager(Account account, ContentProviderClient cp) {
59 mContentProvider = cp;
60 mContentResolver = null;
61 mAccount = account;
62 }
63
64 @Override
65 public OCFile getFileByPath(String path) {
66 Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
67 OCFile file = null;
68 if (c.moveToFirst()) {
69 file = createFileInstance(c);
70 }
71 c.close();
72 return file;
73 }
74
75 @Override
76 public OCFile getFileById(long id) {
77 Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
78 OCFile file = null;
79 if (c.moveToFirst()) {
80 file = createFileInstance(c);
81 }
82 c.close();
83 return file;
84 }
85
86 @Override
87 public boolean fileExists(long id) {
88 return fileExists(ProviderTableMeta._ID, String.valueOf(id));
89 }
90
91 @Override
92 public boolean fileExists(String path) {
93 return fileExists(ProviderTableMeta.FILE_PATH, path);
94 }
95
96 @Override
97 public boolean saveFile(OCFile file) {
98 boolean overriden = false;
99 ContentValues cv = new ContentValues();
100 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
101 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
102 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
103 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
104 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
105 if (file.getParentId() != 0)
106 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
107 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
108 if (!file.isDirectory())
109 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
110 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
111 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate());
112 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
113
114 if (fileExists(file.getRemotePath())) {
115 OCFile oldFile = getFileByPath(file.getRemotePath());
116 if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
117 file.setStoragePath(oldFile.getStoragePath());
118 if (!file.isDirectory());
119 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
120 file.setFileId(oldFile.getFileId());
121
122 overriden = true;
123 if (getContentResolver() != null) {
124 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
125 ProviderTableMeta._ID + "=?",
126 new String[] { String.valueOf(file.getFileId()) });
127 } else {
128 try {
129 getContentProvider().update(ProviderTableMeta.CONTENT_URI,
130 cv, ProviderTableMeta._ID + "=?",
131 new String[] { String.valueOf(file.getFileId()) });
132 } catch (RemoteException e) {
133 Log.e(TAG,
134 "Fail to insert insert file to database "
135 + e.getMessage());
136 }
137 }
138 } else {
139 Uri result_uri = null;
140 if (getContentResolver() != null) {
141 result_uri = getContentResolver().insert(
142 ProviderTableMeta.CONTENT_URI_FILE, cv);
143 } else {
144 try {
145 result_uri = getContentProvider().insert(
146 ProviderTableMeta.CONTENT_URI_FILE, cv);
147 } catch (RemoteException e) {
148 Log.e(TAG,
149 "Fail to insert insert file to database "
150 + e.getMessage());
151 }
152 }
153 if (result_uri != null) {
154 long new_id = Long.parseLong(result_uri.getPathSegments()
155 .get(1));
156 file.setFileId(new_id);
157 }
158 }
159
160 if (file.isDirectory() && file.needsUpdatingWhileSaving())
161 for (OCFile f : getDirectoryContent(file))
162 saveFile(f);
163
164 return overriden;
165 }
166
167
168 @Override
169 public void saveFiles(List<OCFile> files) {
170
171 Iterator<OCFile> filesIt = files.iterator();
172 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
173 OCFile file = null;
174
175 // prepare operations to perform
176 while (filesIt.hasNext()) {
177 file = filesIt.next();
178 ContentValues cv = new ContentValues();
179 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
180 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
181 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
182 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
183 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
184 if (file.getParentId() != 0)
185 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
186 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
187 if (!file.isDirectory())
188 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
189 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
190 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate());
191 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
192
193 if (fileExists(file.getRemotePath())) {
194 OCFile tmpfile = getFileByPath(file.getRemotePath());
195 file.setStoragePath(tmpfile.getStoragePath());
196 if (!file.isDirectory());
197 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
198 file.setFileId(tmpfile.getFileId());
199
200 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
201 withValues(cv).
202 withSelection( ProviderTableMeta._ID + "=?",
203 new String[] { String.valueOf(file.getFileId()) })
204 .build());
205
206 } else {
207 operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
208 }
209 }
210
211 // apply operations in batch
212 ContentProviderResult[] results = null;
213 try {
214 if (getContentResolver() != null) {
215 results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
216
217 } else {
218 results = getContentProvider().applyBatch(operations);
219 }
220
221 } catch (OperationApplicationException e) {
222 Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
223
224 } catch (RemoteException e) {
225 Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
226 }
227
228 // update new id in file objects for insertions
229 if (results != null) {
230 long newId;
231 for (int i=0; i<results.length; i++) {
232 if (results[i].uri != null) {
233 newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
234 files.get(i).setFileId(newId);
235 //Log.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
236 }
237 }
238 }
239
240 for (OCFile aFile : files) {
241 if (aFile.isDirectory() && aFile.needsUpdatingWhileSaving())
242 saveFiles(getDirectoryContent(aFile));
243 }
244
245 }
246
247 public void setAccount(Account account) {
248 mAccount = account;
249 }
250
251 public Account getAccount() {
252 return mAccount;
253 }
254
255 public void setContentResolver(ContentResolver cr) {
256 mContentResolver = cr;
257 }
258
259 public ContentResolver getContentResolver() {
260 return mContentResolver;
261 }
262
263 public void setContentProvider(ContentProviderClient cp) {
264 mContentProvider = cp;
265 }
266
267 public ContentProviderClient getContentProvider() {
268 return mContentProvider;
269 }
270
271 public Vector<OCFile> getDirectoryContent(OCFile f) {
272 if (f != null && f.isDirectory() && f.getFileId() != -1) {
273 Vector<OCFile> ret = new Vector<OCFile>();
274
275 Uri req_uri = Uri.withAppendedPath(
276 ProviderTableMeta.CONTENT_URI_DIR,
277 String.valueOf(f.getFileId()));
278 Cursor c = null;
279
280 if (getContentProvider() != null) {
281 try {
282 c = getContentProvider().query(req_uri, null,
283 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
284 new String[] { mAccount.name }, null);
285 } catch (RemoteException e) {
286 Log.e(TAG, e.getMessage());
287 return ret;
288 }
289 } else {
290 c = getContentResolver().query(req_uri, null,
291 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
292 new String[] { mAccount.name }, null);
293 }
294
295 if (c.moveToFirst()) {
296 do {
297 OCFile child = createFileInstance(c);
298 ret.add(child);
299 } while (c.moveToNext());
300 }
301
302 c.close();
303
304 Collections.sort(ret);
305
306 return ret;
307 }
308 return null;
309 }
310
311 private boolean fileExists(String cmp_key, String value) {
312 Cursor c;
313 if (getContentResolver() != null) {
314 c = getContentResolver()
315 .query(ProviderTableMeta.CONTENT_URI,
316 null,
317 cmp_key + "=? AND "
318 + ProviderTableMeta.FILE_ACCOUNT_OWNER
319 + "=?",
320 new String[] { value, mAccount.name }, null);
321 } else {
322 try {
323 c = getContentProvider().query(
324 ProviderTableMeta.CONTENT_URI,
325 null,
326 cmp_key + "=? AND "
327 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
328 new String[] { value, mAccount.name }, null);
329 } catch (RemoteException e) {
330 Log.e(TAG,
331 "Couldn't determine file existance, assuming non existance: "
332 + e.getMessage());
333 return false;
334 }
335 }
336 boolean retval = c.moveToFirst();
337 c.close();
338 return retval;
339 }
340
341 private Cursor getCursorForValue(String key, String value) {
342 Cursor c = null;
343 if (getContentResolver() != null) {
344 c = getContentResolver()
345 .query(ProviderTableMeta.CONTENT_URI,
346 null,
347 key + "=? AND "
348 + ProviderTableMeta.FILE_ACCOUNT_OWNER
349 + "=?",
350 new String[] { value, mAccount.name }, null);
351 } else {
352 try {
353 c = getContentProvider().query(
354 ProviderTableMeta.CONTENT_URI,
355 null,
356 key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
357 + "=?", new String[] { value, mAccount.name },
358 null);
359 } catch (RemoteException e) {
360 Log.e(TAG, "Could not get file details: " + e.getMessage());
361 c = null;
362 }
363 }
364 return c;
365 }
366
367 private OCFile createFileInstance(Cursor c) {
368 OCFile file = null;
369 if (c != null) {
370 file = new OCFile(c.getString(c
371 .getColumnIndex(ProviderTableMeta.FILE_PATH)));
372 file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
373 file.setParentId(c.getLong(c
374 .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
375 file.setMimetype(c.getString(c
376 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
377 if (!file.isDirectory()) {
378 file.setStoragePath(c.getString(c
379 .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
380 if (file.getStoragePath() == null) {
381 // try to find existing file and bind it with current account
382 File f = new File(FileDownloader.getSavePath(mAccount.name) + file.getRemotePath());
383 if (f.exists())
384 file.setStoragePath(f.getAbsolutePath());
385 }
386 }
387 file.setFileLength(c.getLong(c
388 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
389 file.setCreationTimestamp(c.getLong(c
390 .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
391 file.setModificationTimestamp(c.getLong(c
392 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
393 file.setLastSyncDate(c.getLong(c
394 .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
395 file.setKeepInSync(c.getInt(
396 c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
397 }
398 return file;
399 }
400
401 public void removeFile(OCFile file) {
402 Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
403 if (getContentProvider() != null) {
404 try {
405 getContentProvider().delete(file_uri,
406 ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
407 new String[]{mAccount.name});
408 } catch (RemoteException e) {
409 e.printStackTrace();
410 }
411 } else {
412 getContentResolver().delete(file_uri,
413 ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
414 new String[]{mAccount.name});
415 }
416 if (file.isDown()) {
417 new File(file.getStoragePath()).delete();
418 }
419 }
420
421 }