FileContentProvider.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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.HashMap;
  20. import com.owncloud.android.Log_OC;
  21. import com.owncloud.android.R;
  22. import com.owncloud.android.db.ProviderMeta;
  23. import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
  24. import android.content.ContentProvider;
  25. import android.content.ContentUris;
  26. import android.content.ContentValues;
  27. import android.content.Context;
  28. import android.content.UriMatcher;
  29. import android.database.Cursor;
  30. import android.database.SQLException;
  31. import android.database.sqlite.SQLiteDatabase;
  32. import android.database.sqlite.SQLiteOpenHelper;
  33. import android.database.sqlite.SQLiteQueryBuilder;
  34. import android.net.Uri;
  35. import android.text.TextUtils;
  36. /**
  37. * The ContentProvider for the ownCloud App.
  38. *
  39. * @author Bartek Przybylski
  40. *
  41. */
  42. public class FileContentProvider extends ContentProvider {
  43. private DataBaseHelper mDbHelper;
  44. private static HashMap<String, String> mProjectionMap;
  45. static {
  46. mProjectionMap = new HashMap<String, String>();
  47. mProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
  48. mProjectionMap.put(ProviderTableMeta.FILE_PARENT,
  49. ProviderTableMeta.FILE_PARENT);
  50. mProjectionMap.put(ProviderTableMeta.FILE_PATH,
  51. ProviderTableMeta.FILE_PATH);
  52. mProjectionMap.put(ProviderTableMeta.FILE_NAME,
  53. ProviderTableMeta.FILE_NAME);
  54. mProjectionMap.put(ProviderTableMeta.FILE_CREATION,
  55. ProviderTableMeta.FILE_CREATION);
  56. mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
  57. ProviderTableMeta.FILE_MODIFIED);
  58. mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
  59. ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA);
  60. mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
  61. ProviderTableMeta.FILE_CONTENT_LENGTH);
  62. mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
  63. ProviderTableMeta.FILE_CONTENT_TYPE);
  64. mProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
  65. ProviderTableMeta.FILE_STORAGE_PATH);
  66. mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
  67. ProviderTableMeta.FILE_LAST_SYNC_DATE);
  68. mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
  69. ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);
  70. mProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
  71. ProviderTableMeta.FILE_KEEP_IN_SYNC);
  72. mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
  73. ProviderTableMeta.FILE_ACCOUNT_OWNER);
  74. }
  75. private static final int SINGLE_FILE = 1;
  76. private static final int DIRECTORY = 2;
  77. private static final int ROOT_DIRECTORY = 3;
  78. private UriMatcher mUriMatcher;
  79. // static {
  80. // mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  81. // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, null, ROOT_DIRECTORY);
  82. // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/", SINGLE_FILE);
  83. // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/#", SINGLE_FILE);
  84. // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
  85. // }
  86. @Override
  87. public int delete(Uri uri, String where, String[] whereArgs) {
  88. SQLiteDatabase db = mDbHelper.getWritableDatabase();
  89. int count = 0;
  90. switch (mUriMatcher.match(uri)) {
  91. case SINGLE_FILE:
  92. count = db.delete(ProviderTableMeta.DB_NAME,
  93. ProviderTableMeta._ID
  94. + "="
  95. + uri.getPathSegments().get(1)
  96. + (!TextUtils.isEmpty(where) ? " AND (" + where
  97. + ")" : ""), whereArgs);
  98. break;
  99. case ROOT_DIRECTORY:
  100. count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
  101. break;
  102. default:
  103. throw new IllegalArgumentException("Unknown uri: " + uri.toString());
  104. }
  105. getContext().getContentResolver().notifyChange(uri, null);
  106. return count;
  107. }
  108. @Override
  109. public String getType(Uri uri) {
  110. switch (mUriMatcher.match(uri)) {
  111. case ROOT_DIRECTORY:
  112. return ProviderTableMeta.CONTENT_TYPE;
  113. case SINGLE_FILE:
  114. return ProviderTableMeta.CONTENT_TYPE_ITEM;
  115. default:
  116. throw new IllegalArgumentException("Unknown Uri id."
  117. + uri.toString());
  118. }
  119. }
  120. @Override
  121. public Uri insert(Uri uri, ContentValues values) {
  122. if (mUriMatcher.match(uri) != SINGLE_FILE &&
  123. mUriMatcher.match(uri) != ROOT_DIRECTORY) {
  124. throw new IllegalArgumentException("Unknown uri id: " + uri);
  125. }
  126. SQLiteDatabase db = mDbHelper.getWritableDatabase();
  127. long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
  128. if (rowId > 0) {
  129. Uri insertedFileUri = ContentUris.withAppendedId(
  130. ProviderTableMeta.CONTENT_URI_FILE, rowId);
  131. getContext().getContentResolver().notifyChange(insertedFileUri,
  132. null);
  133. return insertedFileUri;
  134. }
  135. throw new SQLException("ERROR " + uri);
  136. }
  137. @Override
  138. public boolean onCreate() {
  139. mDbHelper = new DataBaseHelper(getContext());
  140. String authority = getContext().getResources().getString(R.string.authority);
  141. mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  142. mUriMatcher.addURI(authority, null, ROOT_DIRECTORY);
  143. mUriMatcher.addURI(authority, "file/", SINGLE_FILE);
  144. mUriMatcher.addURI(authority, "file/#", SINGLE_FILE);
  145. mUriMatcher.addURI(authority, "dir/#", DIRECTORY);
  146. return true;
  147. }
  148. @Override
  149. public Cursor query(Uri uri, String[] projection, String selection,
  150. String[] selectionArgs, String sortOrder) {
  151. SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
  152. sqlQuery.setTables(ProviderTableMeta.DB_NAME);
  153. sqlQuery.setProjectionMap(mProjectionMap);
  154. switch (mUriMatcher.match(uri)) {
  155. case ROOT_DIRECTORY:
  156. break;
  157. case DIRECTORY:
  158. sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "="
  159. + uri.getPathSegments().get(1));
  160. break;
  161. case SINGLE_FILE:
  162. if (uri.getPathSegments().size() > 1) {
  163. sqlQuery.appendWhere(ProviderTableMeta._ID + "="
  164. + uri.getPathSegments().get(1));
  165. }
  166. break;
  167. default:
  168. throw new IllegalArgumentException("Unknown uri id: " + uri);
  169. }
  170. String order;
  171. if (TextUtils.isEmpty(sortOrder)) {
  172. order = ProviderTableMeta.DEFAULT_SORT_ORDER;
  173. } else {
  174. order = sortOrder;
  175. }
  176. SQLiteDatabase db = mDbHelper.getReadableDatabase();
  177. // DB case_sensitive
  178. db.execSQL("PRAGMA case_sensitive_like = true");
  179. Cursor c = sqlQuery.query(db, projection, selection, selectionArgs,
  180. null, null, order);
  181. c.setNotificationUri(getContext().getContentResolver(), uri);
  182. return c;
  183. }
  184. @Override
  185. public int update(Uri uri, ContentValues values, String selection,
  186. String[] selectionArgs) {
  187. return mDbHelper.getWritableDatabase().update(
  188. ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
  189. }
  190. class DataBaseHelper extends SQLiteOpenHelper {
  191. public DataBaseHelper(Context context) {
  192. super(context, ProviderMeta.DB_NAME, null, ProviderMeta.DB_VERSION);
  193. }
  194. @Override
  195. public void onCreate(SQLiteDatabase db) {
  196. // files table
  197. Log_OC.i("SQL", "Entering in onCreate");
  198. db.execSQL("CREATE TABLE " + ProviderTableMeta.DB_NAME + "("
  199. + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
  200. + ProviderTableMeta.FILE_NAME + " TEXT, "
  201. + ProviderTableMeta.FILE_PATH + " TEXT, "
  202. + ProviderTableMeta.FILE_PARENT + " INTEGER, "
  203. + ProviderTableMeta.FILE_CREATION + " INTEGER, "
  204. + ProviderTableMeta.FILE_MODIFIED + " INTEGER, "
  205. + ProviderTableMeta.FILE_CONTENT_TYPE + " TEXT, "
  206. + ProviderTableMeta.FILE_CONTENT_LENGTH + " INTEGER, "
  207. + ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "
  208. + ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "
  209. + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
  210. + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
  211. + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
  212. + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER );"
  213. );
  214. }
  215. @Override
  216. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  217. Log_OC.i("SQL", "Entering in onUpgrade");
  218. boolean upgraded = false;
  219. if (oldVersion == 1 && newVersion >= 2) {
  220. Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade");
  221. db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
  222. " ADD COLUMN " + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER " +
  223. " DEFAULT 0");
  224. upgraded = true;
  225. }
  226. if (oldVersion < 3 && newVersion >= 3) {
  227. Log_OC.i("SQL", "Entering in the #2 ADD in onUpgrade");
  228. db.beginTransaction();
  229. try {
  230. db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
  231. " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " +
  232. " DEFAULT 0");
  233. // assume there are not local changes pending to upload
  234. db.execSQL("UPDATE " + ProviderTableMeta.DB_NAME +
  235. " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + System.currentTimeMillis() +
  236. " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
  237. upgraded = true;
  238. db.setTransactionSuccessful();
  239. } finally {
  240. db.endTransaction();
  241. }
  242. }
  243. if (oldVersion < 4 && newVersion >= 4) {
  244. Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade");
  245. db.beginTransaction();
  246. try {
  247. db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
  248. " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER " +
  249. " DEFAULT 0");
  250. db.execSQL("UPDATE " + ProviderTableMeta.DB_NAME +
  251. " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED +
  252. " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
  253. upgraded = true;
  254. db.setTransactionSuccessful();
  255. } finally {
  256. db.endTransaction();
  257. }
  258. }
  259. if (!upgraded)
  260. Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
  261. }
  262. }
  263. }