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