Merge pull request #632 from wakeup/patch-1
[pub/Android/ownCloud.git] / src / com / owncloud / android / providers / FileContentProvider.java
1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
3 * Copyright (C) 2012-2013 ownCloud Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2,
7 * as published by the Free Software Foundation.
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.providers;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23
24 import com.owncloud.android.R;
25 import com.owncloud.android.db.ProviderMeta;
26 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
27 import com.owncloud.android.lib.common.utils.Log_OC;
28 import com.owncloud.android.lib.resources.shares.ShareType;
29
30
31
32 import android.content.ContentProvider;
33 import android.content.ContentProviderOperation;
34 import android.content.ContentProviderResult;
35 import android.content.ContentUris;
36 import android.content.ContentValues;
37 import android.content.Context;
38 import android.content.OperationApplicationException;
39 import android.content.UriMatcher;
40 import android.database.Cursor;
41 import android.database.SQLException;
42 import android.database.sqlite.SQLiteDatabase;
43 import android.database.sqlite.SQLiteOpenHelper;
44 import android.database.sqlite.SQLiteQueryBuilder;
45 import android.net.Uri;
46 import android.text.TextUtils;
47
48 /**
49 * The ContentProvider for the ownCloud App.
50 *
51 * @author Bartek Przybylski
52 * @author David A. Velasco
53 *
54 */
55 public class FileContentProvider extends ContentProvider {
56
57 private DataBaseHelper mDbHelper;
58
59 // Projection for filelist table
60 private static HashMap<String, String> mFileProjectionMap;
61 static {
62 mFileProjectionMap = new HashMap<String, String>();
63 mFileProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
64 mFileProjectionMap.put(ProviderTableMeta.FILE_PARENT,
65 ProviderTableMeta.FILE_PARENT);
66 mFileProjectionMap.put(ProviderTableMeta.FILE_PATH,
67 ProviderTableMeta.FILE_PATH);
68 mFileProjectionMap.put(ProviderTableMeta.FILE_NAME,
69 ProviderTableMeta.FILE_NAME);
70 mFileProjectionMap.put(ProviderTableMeta.FILE_CREATION,
71 ProviderTableMeta.FILE_CREATION);
72 mFileProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
73 ProviderTableMeta.FILE_MODIFIED);
74 mFileProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
75 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA);
76 mFileProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
77 ProviderTableMeta.FILE_CONTENT_LENGTH);
78 mFileProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
79 ProviderTableMeta.FILE_CONTENT_TYPE);
80 mFileProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
81 ProviderTableMeta.FILE_STORAGE_PATH);
82 mFileProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
83 ProviderTableMeta.FILE_LAST_SYNC_DATE);
84 mFileProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
85 ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);
86 mFileProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
87 ProviderTableMeta.FILE_KEEP_IN_SYNC);
88 mFileProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
89 ProviderTableMeta.FILE_ACCOUNT_OWNER);
90 mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG,
91 ProviderTableMeta.FILE_ETAG);
92 mFileProjectionMap.put(ProviderTableMeta.FILE_SHARE_BY_LINK,
93 ProviderTableMeta.FILE_SHARE_BY_LINK);
94 mFileProjectionMap.put(ProviderTableMeta.FILE_PUBLIC_LINK,
95 ProviderTableMeta.FILE_PUBLIC_LINK);
96 mFileProjectionMap.put(ProviderTableMeta.FILE_PERMISSIONS,
97 ProviderTableMeta.FILE_PERMISSIONS);
98 mFileProjectionMap.put(ProviderTableMeta.FILE_REMOTE_ID,
99 ProviderTableMeta.FILE_REMOTE_ID);
100 mFileProjectionMap.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
101 ProviderTableMeta.FILE_UPDATE_THUMBNAIL);
102 }
103
104 private static final int SINGLE_FILE = 1;
105 private static final int DIRECTORY = 2;
106 private static final int ROOT_DIRECTORY = 3;
107 private static final int SHARES = 4;
108
109 private static final String TAG = FileContentProvider.class.getSimpleName();
110
111 // Projection for ocshares table
112 private static HashMap<String, String> mOCSharesProjectionMap;
113 static {
114 mOCSharesProjectionMap = new HashMap<String, String>();
115 mOCSharesProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
116 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_FILE_SOURCE,
117 ProviderTableMeta.OCSHARES_FILE_SOURCE);
118 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE,
119 ProviderTableMeta.OCSHARES_ITEM_SOURCE);
120 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_TYPE,
121 ProviderTableMeta.OCSHARES_SHARE_TYPE);
122 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_WITH,
123 ProviderTableMeta.OCSHARES_SHARE_WITH);
124 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_PATH,
125 ProviderTableMeta.OCSHARES_PATH);
126 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_PERMISSIONS,
127 ProviderTableMeta.OCSHARES_PERMISSIONS);
128 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARED_DATE,
129 ProviderTableMeta.OCSHARES_SHARED_DATE);
130 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE,
131 ProviderTableMeta.OCSHARES_EXPIRATION_DATE);
132 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_TOKEN,
133 ProviderTableMeta.OCSHARES_TOKEN);
134 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
135 ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME);
136 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY,
137 ProviderTableMeta.OCSHARES_IS_DIRECTORY);
138 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_USER_ID,
139 ProviderTableMeta.OCSHARES_USER_ID);
140 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED,
141 ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED);
142 mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER,
143 ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
144 }
145
146 private UriMatcher mUriMatcher;
147
148 @Override
149 public int delete(Uri uri, String where, String[] whereArgs) {
150 //Log_OC.d(TAG, "Deleting " + uri + " at provider " + this);
151 int count = 0;
152 SQLiteDatabase db = mDbHelper.getWritableDatabase();
153 db.beginTransaction();
154 try {
155 count = delete(db, uri, where, whereArgs);
156 db.setTransactionSuccessful();
157 } finally {
158 db.endTransaction();
159 }
160 getContext().getContentResolver().notifyChange(uri, null);
161 return count;
162 }
163
164 private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
165 int count = 0;
166 switch (mUriMatcher.match(uri)) {
167 case SINGLE_FILE:
168 /*Cursor c = query(db, uri, null, where, whereArgs, null);
169 String remotePath = "(unexisting)";
170 if (c != null && c.moveToFirst()) {
171 remotePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH));
172 }
173 Log_OC.d(TAG, "Removing FILE " + remotePath);
174 */
175 count = db.delete(ProviderTableMeta.FILE_TABLE_NAME,
176 ProviderTableMeta._ID
177 + "="
178 + uri.getPathSegments().get(1)
179 + (!TextUtils.isEmpty(where) ? " AND (" + where
180 + ")" : ""), whereArgs);
181 /* just for log
182 if (c!=null) {
183 c.close();
184 }
185 */
186 break;
187 case DIRECTORY:
188 // deletion of folder is recursive
189 /*
190 Uri folderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, Long.parseLong(uri.getPathSegments().get(1)));
191 Cursor folder = query(db, folderUri, null, null, null, null);
192 String folderName = "(unknown)";
193 if (folder != null && folder.moveToFirst()) {
194 folderName = folder.getString(folder.getColumnIndex(ProviderTableMeta.FILE_PATH));
195 }
196 */
197 Cursor children = query(uri, null, null, null, null);
198 if (children != null && children.moveToFirst()) {
199 long childId;
200 boolean isDir;
201 //String remotePath;
202 while (!children.isAfterLast()) {
203 childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID));
204 isDir = "DIR".equals(children.getString(children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
205 //remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH));
206 if (isDir) {
207 count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), null, null);
208 } else {
209 count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), null, null);
210 }
211 children.moveToNext();
212 }
213 children.close();
214 } /*else {
215 Log_OC.d(TAG, "No child to remove in DIRECTORY " + folderName);
216 }
217 Log_OC.d(TAG, "Removing DIRECTORY " + folderName + " (or maybe not) ");
218 */
219 count += db.delete(ProviderTableMeta.FILE_TABLE_NAME,
220 ProviderTableMeta._ID
221 + "="
222 + uri.getPathSegments().get(1)
223 + (!TextUtils.isEmpty(where) ? " AND (" + where
224 + ")" : ""), whereArgs);
225 /* Just for log
226 if (folder != null) {
227 folder.close();
228 }*/
229 break;
230 case ROOT_DIRECTORY:
231 //Log_OC.d(TAG, "Removing ROOT!");
232 count = db.delete(ProviderTableMeta.FILE_TABLE_NAME, where, whereArgs);
233 break;
234 case SHARES:
235 count = db.delete(ProviderTableMeta.OCSHARES_TABLE_NAME, where, whereArgs);
236 break;
237 default:
238 //Log_OC.e(TAG, "Unknown uri " + uri);
239 throw new IllegalArgumentException("Unknown uri: " + uri.toString());
240 }
241 return count;
242 }
243
244
245 @Override
246 public String getType(Uri uri) {
247 switch (mUriMatcher.match(uri)) {
248 case ROOT_DIRECTORY:
249 return ProviderTableMeta.CONTENT_TYPE;
250 case SINGLE_FILE:
251 return ProviderTableMeta.CONTENT_TYPE_ITEM;
252 default:
253 throw new IllegalArgumentException("Unknown Uri id."
254 + uri.toString());
255 }
256 }
257
258 @Override
259 public Uri insert(Uri uri, ContentValues values) {
260 //Log_OC.d(TAG, "Inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
261 Uri newUri = null;
262 SQLiteDatabase db = mDbHelper.getWritableDatabase();
263 db.beginTransaction();
264 try {
265 newUri = insert(db, uri, values);
266 db.setTransactionSuccessful();
267 } finally {
268 db.endTransaction();
269 }
270 getContext().getContentResolver().notifyChange(newUri, null);
271 return newUri;
272 }
273
274 private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) {
275 switch (mUriMatcher.match(uri)){
276 case ROOT_DIRECTORY:
277 case SINGLE_FILE:
278 String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH);
279 String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER);
280 String[] projection = new String[] {ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, ProviderTableMeta.FILE_ACCOUNT_OWNER };
281 String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
282 String[] whereArgs = new String[] {remotePath, accountName};
283 Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null);
284 if (doubleCheck == null || !doubleCheck.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
285 long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values);
286 if (rowId > 0) {
287 Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
288 //Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
289 return insertedFileUri;
290 } else {
291 //Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
292 throw new SQLException("ERROR " + uri);
293 }
294 } else {
295 // file is already inserted; race condition, let's avoid a duplicated entry
296 Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)));
297 doubleCheck.close();
298
299 return insertedFileUri;
300 }
301
302 case SHARES:
303 String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH);
304 String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
305 String[] projectionShare = new String[] {ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, ProviderTableMeta.OCSHARES_ACCOUNT_OWNER };
306 String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
307 String[] whereArgsShare = new String[] {path, accountNameShare};
308 Uri insertedShareUri = null;
309 Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null);
310 if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
311 long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
312 if (rowId >0) {
313 insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
314 } else {
315 throw new SQLException("ERROR " + uri);
316
317 }
318 } else {
319 // file is already inserted; race condition, let's avoid a duplicated entry
320 insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong(doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)));
321 doubleCheckShare.close();
322 }
323 updateFilesTableAccordingToShareInsertion(db, uri, values);
324 return insertedShareUri;
325
326
327 default:
328 throw new IllegalArgumentException("Unknown uri id: " + uri);
329 }
330
331 }
332
333 private void updateFilesTableAccordingToShareInsertion(SQLiteDatabase db, Uri uri, ContentValues shareValues) {
334 ContentValues fileValues = new ContentValues();
335 fileValues.put(ProviderTableMeta.FILE_SHARE_BY_LINK,
336 ShareType.PUBLIC_LINK.getValue() == shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0);
337 String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
338 String[] whereArgsShare = new String[] {
339 shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH),
340 shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
341 };
342 db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, whereShare, whereArgsShare);
343 }
344
345
346 @Override
347 public boolean onCreate() {
348 mDbHelper = new DataBaseHelper(getContext());
349
350 String authority = getContext().getResources().getString(R.string.authority);
351 mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
352 mUriMatcher.addURI(authority, null, ROOT_DIRECTORY);
353 mUriMatcher.addURI(authority, "file/", SINGLE_FILE);
354 mUriMatcher.addURI(authority, "file/#", SINGLE_FILE);
355 mUriMatcher.addURI(authority, "dir/", DIRECTORY);
356 mUriMatcher.addURI(authority, "dir/#", DIRECTORY);
357 mUriMatcher.addURI(authority, "shares/", SHARES);
358 mUriMatcher.addURI(authority, "shares/#", SHARES);
359
360 return true;
361 }
362
363
364 @Override
365 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
366 Cursor result = null;
367 SQLiteDatabase db = mDbHelper.getReadableDatabase();
368 db.beginTransaction();
369 try {
370 result = query(db, uri, projection, selection, selectionArgs, sortOrder);
371 db.setTransactionSuccessful();
372 } finally {
373 db.endTransaction();
374 }
375 return result;
376 }
377
378 private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
379 SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
380
381 sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME);
382 sqlQuery.setProjectionMap(mFileProjectionMap);
383
384 switch (mUriMatcher.match(uri)) {
385 case ROOT_DIRECTORY:
386 break;
387 case DIRECTORY:
388 String folderId = uri.getPathSegments().get(1);
389 sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "="
390 + folderId);
391 break;
392 case SINGLE_FILE:
393 if (uri.getPathSegments().size() > 1) {
394 sqlQuery.appendWhere(ProviderTableMeta._ID + "="
395 + uri.getPathSegments().get(1));
396 }
397 break;
398 case SHARES:
399 sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME);
400 sqlQuery.setProjectionMap(mOCSharesProjectionMap);
401 if (uri.getPathSegments().size() > 1) {
402 sqlQuery.appendWhere(ProviderTableMeta._ID + "="
403 + uri.getPathSegments().get(1));
404 }
405 break;
406 default:
407 throw new IllegalArgumentException("Unknown uri id: " + uri);
408 }
409
410 String order;
411 if (TextUtils.isEmpty(sortOrder)) {
412 if (mUriMatcher.match(uri) == SHARES) {
413 order = ProviderTableMeta.OCSHARES_DEFAULT_SORT_ORDER;
414 } else {
415
416 order = ProviderTableMeta.FILE_DEFAULT_SORT_ORDER;
417 }
418 } else {
419 order = sortOrder;
420 }
421
422 // DB case_sensitive
423 db.execSQL("PRAGMA case_sensitive_like = true");
424 Cursor c = sqlQuery.query(db, projection, selection, selectionArgs, null, null, order);
425 c.setNotificationUri(getContext().getContentResolver(), uri);
426 return c;
427 }
428
429 @Override
430 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
431
432 //Log_OC.d(TAG, "Updating " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
433 int count = 0;
434 SQLiteDatabase db = mDbHelper.getWritableDatabase();
435 db.beginTransaction();
436 try {
437 count = update(db, uri, values, selection, selectionArgs);
438 db.setTransactionSuccessful();
439 } finally {
440 db.endTransaction();
441 }
442 getContext().getContentResolver().notifyChange(uri, null);
443 return count;
444 }
445
446
447
448 private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
449 switch (mUriMatcher.match(uri)) {
450 case DIRECTORY:
451 return 0; //updateFolderSize(db, selectionArgs[0]);
452 case SHARES:
453 return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs);
454 default:
455 return db.update(ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs);
456 }
457 }
458
459 /*
460 private int updateFolderSize(SQLiteDatabase db, String folderId) {
461 int count = 0;
462 String [] whereArgs = new String[] { folderId };
463
464 // read current size saved for the folder
465 long folderSize = 0;
466 long folderParentId = -1;
467 Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId);
468 String[] folderProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH, ProviderTableMeta.FILE_PARENT};
469 String folderWhere = ProviderTableMeta._ID + "=?";
470 Cursor folderCursor = query(db, selectFolderUri, folderProjection, folderWhere, whereArgs, null);
471 if (folderCursor != null && folderCursor.moveToFirst()) {
472 folderSize = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));;
473 folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));;
474 }
475 folderCursor.close();
476
477 // read and sum sizes of children
478 long childrenSize = 0;
479 Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId);
480 String[] childrenProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH, ProviderTableMeta.FILE_PARENT};
481 String childrenWhere = ProviderTableMeta.FILE_PARENT + "=?";
482 Cursor childrenCursor = query(db, selectChildrenUri, childrenProjection, childrenWhere, whereArgs, null);
483 if (childrenCursor != null && childrenCursor.moveToFirst()) {
484 while (!childrenCursor.isAfterLast()) {
485 childrenSize += childrenCursor.getLong(childrenCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));
486 childrenCursor.moveToNext();
487 }
488 }
489 childrenCursor.close();
490
491 // update if needed
492 if (folderSize != childrenSize) {
493 Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize);
494 ContentValues cv = new ContentValues();
495 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize);
496 count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs);
497
498 // propagate update until root
499 if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) {
500 Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId);
501 updateFolderSize(db, String.valueOf(folderParentId));
502 } else {
503 Log_OC.d("FileContentProvider", "NOT propagating to " + folderParentId);
504 }
505 } else {
506 Log_OC.d("FileContentProvider", "NOT updating, sizes are " + folderSize + " and " + childrenSize);
507 }
508 return count;
509 }
510 */
511
512 @Override
513 public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
514 Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" );
515 ContentProviderResult[] results = new ContentProviderResult[operations.size()];
516 int i=0;
517
518 SQLiteDatabase db = mDbHelper.getWritableDatabase();
519 db.beginTransaction(); // it's supposed that transactions can be nested
520 try {
521 for (ContentProviderOperation operation : operations) {
522 results[i] = operation.apply(this, results, i);
523 i++;
524 }
525 db.setTransactionSuccessful();
526 } finally {
527 db.endTransaction();
528 }
529 Log_OC.d("FileContentProvider", "applied batch in provider " + this);
530 return results;
531 }
532
533
534 class DataBaseHelper extends SQLiteOpenHelper {
535
536 public DataBaseHelper(Context context) {
537 super(context, ProviderMeta.DB_NAME, null, ProviderMeta.DB_VERSION);
538
539 }
540
541 @Override
542 public void onCreate(SQLiteDatabase db) {
543 // files table
544 Log_OC.i("SQL", "Entering in onCreate");
545 db.execSQL("CREATE TABLE " + ProviderTableMeta.FILE_TABLE_NAME + "("
546 + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
547 + ProviderTableMeta.FILE_NAME + " TEXT, "
548 + ProviderTableMeta.FILE_PATH + " TEXT, "
549 + ProviderTableMeta.FILE_PARENT + " INTEGER, "
550 + ProviderTableMeta.FILE_CREATION + " INTEGER, "
551 + ProviderTableMeta.FILE_MODIFIED + " INTEGER, "
552 + ProviderTableMeta.FILE_CONTENT_TYPE + " TEXT, "
553 + ProviderTableMeta.FILE_CONTENT_LENGTH + " INTEGER, "
554 + ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "
555 + ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "
556 + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
557 + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
558 + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
559 + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, "
560 + ProviderTableMeta.FILE_ETAG + " TEXT, "
561 + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER, "
562 + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT, "
563 + ProviderTableMeta.FILE_PERMISSIONS + " TEXT null,"
564 + ProviderTableMeta.FILE_REMOTE_ID + " TEXT null,"
565 + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER);" //boolean
566 );
567
568 // Create table ocshares
569 db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "("
570 + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
571 + ProviderTableMeta.OCSHARES_FILE_SOURCE + " INTEGER, "
572 + ProviderTableMeta.OCSHARES_ITEM_SOURCE + " INTEGER, "
573 + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, "
574 + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, "
575 + ProviderTableMeta.OCSHARES_PATH + " TEXT, "
576 + ProviderTableMeta.OCSHARES_PERMISSIONS+ " INTEGER, "
577 + ProviderTableMeta.OCSHARES_SHARED_DATE + " INTEGER, "
578 + ProviderTableMeta.OCSHARES_EXPIRATION_DATE + " INTEGER, "
579 + ProviderTableMeta.OCSHARES_TOKEN + " TEXT, "
580 + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, "
581 + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean
582 + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, "
583 + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER,"
584 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" );
585 }
586
587 @Override
588 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
589 Log_OC.i("SQL", "Entering in onUpgrade");
590 boolean upgraded = false;
591 if (oldVersion == 1 && newVersion >= 2) {
592 Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade");
593 db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
594 " ADD COLUMN " + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER " +
595 " DEFAULT 0");
596 upgraded = true;
597 }
598 if (oldVersion < 3 && newVersion >= 3) {
599 Log_OC.i("SQL", "Entering in the #2 ADD in onUpgrade");
600 db.beginTransaction();
601 try {
602 db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
603 " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " +
604 " DEFAULT 0");
605
606 // assume there are not local changes pending to upload
607 db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME +
608 " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + System.currentTimeMillis() +
609 " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
610
611 upgraded = true;
612 db.setTransactionSuccessful();
613 } finally {
614 db.endTransaction();
615 }
616 }
617 if (oldVersion < 4 && newVersion >= 4) {
618 Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade");
619 db.beginTransaction();
620 try {
621 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
622 " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER " +
623 " DEFAULT 0");
624
625 db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME +
626 " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED +
627 " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
628
629 upgraded = true;
630 db.setTransactionSuccessful();
631 } finally {
632 db.endTransaction();
633 }
634 }
635 if (!upgraded)
636 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
637
638 if (oldVersion < 5 && newVersion >= 5) {
639 Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade");
640 db.beginTransaction();
641 try {
642 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
643 " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " +
644 " DEFAULT NULL");
645
646 upgraded = true;
647 db.setTransactionSuccessful();
648 } finally {
649 db.endTransaction();
650 }
651 }
652 if (!upgraded)
653 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
654
655 if (oldVersion < 6 && newVersion >= 6) {
656 Log_OC.i("SQL", "Entering in the #5 ADD in onUpgrade");
657 db.beginTransaction();
658 try {
659 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
660 " ADD COLUMN " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER " +
661 " DEFAULT 0");
662
663 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
664 " ADD COLUMN " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT " +
665 " DEFAULT NULL");
666
667 // Create table ocshares
668 db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "("
669 + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
670 + ProviderTableMeta.OCSHARES_FILE_SOURCE + " INTEGER, "
671 + ProviderTableMeta.OCSHARES_ITEM_SOURCE + " INTEGER, "
672 + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, "
673 + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, "
674 + ProviderTableMeta.OCSHARES_PATH + " TEXT, "
675 + ProviderTableMeta.OCSHARES_PERMISSIONS+ " INTEGER, "
676 + ProviderTableMeta.OCSHARES_SHARED_DATE + " INTEGER, "
677 + ProviderTableMeta.OCSHARES_EXPIRATION_DATE + " INTEGER, "
678 + ProviderTableMeta.OCSHARES_TOKEN + " TEXT, "
679 + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, "
680 + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean
681 + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, "
682 + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER,"
683 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" );
684
685 upgraded = true;
686 db.setTransactionSuccessful();
687 } finally {
688 db.endTransaction();
689 }
690 }
691 if (!upgraded)
692 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
693
694 if (oldVersion < 7 && newVersion >= 7) {
695 Log_OC.i("SQL", "Entering in the #7 ADD in onUpgrade");
696 db.beginTransaction();
697 try {
698 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
699 " ADD COLUMN " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT " +
700 " DEFAULT NULL");
701
702 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
703 " ADD COLUMN " + ProviderTableMeta.FILE_REMOTE_ID + " TEXT " +
704 " DEFAULT NULL");
705
706 upgraded = true;
707 db.setTransactionSuccessful();
708 } finally {
709 db.endTransaction();
710 }
711 }
712 if (!upgraded)
713 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
714
715 if (oldVersion < 8 && newVersion >= 8) {
716 Log_OC.i("SQL", "Entering in the #8 ADD in onUpgrade");
717 db.beginTransaction();
718 try {
719 db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
720 " ADD COLUMN " + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER " +
721 " DEFAULT 0");
722
723 upgraded = true;
724 db.setTransactionSuccessful();
725 } finally {
726 db.endTransaction();
727 }
728 }
729 if (!upgraded)
730 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
731 }
732 }
733
734 }