FileContentProvider.java 35 KB

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