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