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