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