FileDataStorageManager.java 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. /* ownCloud Android client application
  2. * Copyright (C) 2012 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.datamodel;
  19. import java.io.File;
  20. import java.util.ArrayList;
  21. import java.util.Collection;
  22. import java.util.Collections;
  23. import java.util.Iterator;
  24. import java.util.Vector;
  25. import com.owncloud.android.MainApp;
  26. import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
  27. import com.owncloud.android.lib.operations.common.OCShare;
  28. import com.owncloud.android.lib.operations.common.ShareType;
  29. import com.owncloud.android.utils.FileStorageUtils;
  30. import com.owncloud.android.utils.Log_OC;
  31. import android.accounts.Account;
  32. import android.content.ContentProviderClient;
  33. import android.content.ContentProviderOperation;
  34. import android.content.ContentProviderResult;
  35. import android.content.ContentResolver;
  36. import android.content.ContentUris;
  37. import android.content.ContentValues;
  38. import android.content.OperationApplicationException;
  39. import android.database.Cursor;
  40. import android.net.Uri;
  41. import android.os.RemoteException;
  42. public class FileDataStorageManager {
  43. public static final int ROOT_PARENT_ID = 0;
  44. private ContentResolver mContentResolver;
  45. private ContentProviderClient mContentProviderClient;
  46. private Account mAccount;
  47. private static String TAG = FileDataStorageManager.class.getSimpleName();
  48. public FileDataStorageManager(Account account, ContentResolver cr) {
  49. mContentProviderClient = null;
  50. mContentResolver = cr;
  51. mAccount = account;
  52. }
  53. public FileDataStorageManager(Account account, ContentProviderClient cp) {
  54. mContentProviderClient = cp;
  55. mContentResolver = null;
  56. mAccount = account;
  57. }
  58. public void setAccount(Account account) {
  59. mAccount = account;
  60. }
  61. public Account getAccount() {
  62. return mAccount;
  63. }
  64. public void setContentResolver(ContentResolver cr) {
  65. mContentResolver = cr;
  66. }
  67. public ContentResolver getContentResolver() {
  68. return mContentResolver;
  69. }
  70. public void setContentProviderClient(ContentProviderClient cp) {
  71. mContentProviderClient = cp;
  72. }
  73. public ContentProviderClient getContentProviderClient() {
  74. return mContentProviderClient;
  75. }
  76. public OCFile getFileByPath(String path) {
  77. Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
  78. OCFile file = null;
  79. if (c.moveToFirst()) {
  80. file = createFileInstance(c);
  81. }
  82. c.close();
  83. if (file == null && OCFile.ROOT_PATH.equals(path)) {
  84. return createRootDir(); // root should always exist
  85. }
  86. return file;
  87. }
  88. public OCFile getFileById(long id) {
  89. Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
  90. OCFile file = null;
  91. if (c.moveToFirst()) {
  92. file = createFileInstance(c);
  93. }
  94. c.close();
  95. return file;
  96. }
  97. public OCFile getFileByLocalPath(String path) {
  98. Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
  99. OCFile file = null;
  100. if (c.moveToFirst()) {
  101. file = createFileInstance(c);
  102. }
  103. c.close();
  104. return file;
  105. }
  106. public boolean fileExists(long id) {
  107. return fileExists(ProviderTableMeta._ID, String.valueOf(id));
  108. }
  109. public boolean fileExists(String path) {
  110. return fileExists(ProviderTableMeta.FILE_PATH, path);
  111. }
  112. public Vector<OCFile> getFolderContent(OCFile f) {
  113. if (f != null && f.isFolder() && f.getFileId() != -1) {
  114. return getFolderContent(f.getFileId());
  115. } else {
  116. return new Vector<OCFile>();
  117. }
  118. }
  119. public Vector<OCFile> getFolderImages(OCFile folder) {
  120. Vector<OCFile> ret = new Vector<OCFile>();
  121. if (folder != null) {
  122. // TODO better implementation, filtering in the access to database (if possible) instead of here
  123. Vector<OCFile> tmp = getFolderContent(folder);
  124. OCFile current = null;
  125. for (int i=0; i<tmp.size(); i++) {
  126. current = tmp.get(i);
  127. if (current.isImage()) {
  128. ret.add(current);
  129. }
  130. }
  131. }
  132. return ret;
  133. }
  134. public boolean saveFile(OCFile file) {
  135. boolean overriden = false;
  136. ContentValues cv = new ContentValues();
  137. cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
  138. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
  139. cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
  140. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
  141. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
  142. cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
  143. //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
  144. cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
  145. cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
  146. if (!file.isFolder())
  147. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
  148. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  149. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
  150. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
  151. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
  152. cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  153. cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
  154. cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
  155. boolean sameRemotePath = fileExists(file.getRemotePath());
  156. if (sameRemotePath ||
  157. fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
  158. OCFile oldFile = null;
  159. if (sameRemotePath) {
  160. oldFile = getFileByPath(file.getRemotePath());
  161. file.setFileId(oldFile.getFileId());
  162. } else {
  163. oldFile = getFileById(file.getFileId());
  164. }
  165. overriden = true;
  166. if (getContentResolver() != null) {
  167. getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
  168. ProviderTableMeta._ID + "=?",
  169. new String[] { String.valueOf(file.getFileId()) });
  170. } else {
  171. try {
  172. getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
  173. cv, ProviderTableMeta._ID + "=?",
  174. new String[] { String.valueOf(file.getFileId()) });
  175. } catch (RemoteException e) {
  176. Log_OC.e(TAG,
  177. "Fail to insert insert file to database "
  178. + e.getMessage());
  179. }
  180. }
  181. } else {
  182. Uri result_uri = null;
  183. if (getContentResolver() != null) {
  184. result_uri = getContentResolver().insert(
  185. ProviderTableMeta.CONTENT_URI_FILE, cv);
  186. } else {
  187. try {
  188. result_uri = getContentProviderClient().insert(
  189. ProviderTableMeta.CONTENT_URI_FILE, cv);
  190. } catch (RemoteException e) {
  191. Log_OC.e(TAG,
  192. "Fail to insert insert file to database "
  193. + e.getMessage());
  194. }
  195. }
  196. if (result_uri != null) {
  197. long new_id = Long.parseLong(result_uri.getPathSegments()
  198. .get(1));
  199. file.setFileId(new_id);
  200. }
  201. }
  202. if (file.isFolder()) {
  203. updateFolderSize(file.getFileId());
  204. } else {
  205. updateFolderSize(file.getParentId());
  206. }
  207. return overriden;
  208. }
  209. /**
  210. * Inserts or updates the list of files contained in a given folder.
  211. *
  212. * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
  213. * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
  214. *
  215. * @param folder
  216. * @param files
  217. * @param removeNotUpdated
  218. */
  219. public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
  220. Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
  221. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
  222. // prepare operations to insert or update files to save in the given folder
  223. for (OCFile file : updatedFiles) {
  224. ContentValues cv = new ContentValues();
  225. cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
  226. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
  227. cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
  228. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
  229. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
  230. cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
  231. //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
  232. cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
  233. cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
  234. if (!file.isFolder()) {
  235. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
  236. }
  237. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  238. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
  239. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
  240. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
  241. cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  242. cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
  243. cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
  244. boolean existsByPath = fileExists(file.getRemotePath());
  245. if (existsByPath || fileExists(file.getFileId())) {
  246. // updating an existing file
  247. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  248. withValues(cv).
  249. withSelection( ProviderTableMeta._ID + "=?",
  250. new String[] { String.valueOf(file.getFileId()) })
  251. .build());
  252. } else {
  253. // adding a new file
  254. operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
  255. }
  256. }
  257. // prepare operations to remove files in the given folder
  258. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
  259. String [] whereArgs = null;
  260. for (OCFile file : filesToRemove) {
  261. if (file.getParentId() == folder.getFileId()) {
  262. whereArgs = new String[]{mAccount.name, file.getRemotePath()};
  263. //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
  264. if (file.isFolder()) {
  265. operations.add(ContentProviderOperation
  266. .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
  267. .build());
  268. // TODO remove local folder
  269. } else {
  270. operations.add(ContentProviderOperation
  271. .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
  272. .build());
  273. if (file.isDown()) {
  274. new File(file.getStoragePath()).delete();
  275. // TODO move the deletion of local contents after success of deletions
  276. }
  277. }
  278. }
  279. }
  280. // update metadata of folder
  281. ContentValues cv = new ContentValues();
  282. cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
  283. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
  284. cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
  285. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0); // FileContentProvider calculates the right size
  286. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
  287. cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
  288. cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
  289. cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
  290. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  291. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
  292. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
  293. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
  294. cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
  295. cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
  296. cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
  297. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  298. withValues(cv).
  299. withSelection( ProviderTableMeta._ID + "=?",
  300. new String[] { String.valueOf(folder.getFileId()) })
  301. .build());
  302. // apply operations in batch
  303. ContentProviderResult[] results = null;
  304. Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
  305. try {
  306. if (getContentResolver() != null) {
  307. results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  308. } else {
  309. results = getContentProviderClient().applyBatch(operations);
  310. }
  311. } catch (OperationApplicationException e) {
  312. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  313. } catch (RemoteException e) {
  314. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  315. }
  316. // update new id in file objects for insertions
  317. if (results != null) {
  318. long newId;
  319. Iterator<OCFile> filesIt = updatedFiles.iterator();
  320. OCFile file = null;
  321. for (int i=0; i<results.length; i++) {
  322. if (filesIt.hasNext()) {
  323. file = filesIt.next();
  324. } else {
  325. file = null;
  326. }
  327. if (results[i].uri != null) {
  328. newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
  329. //updatedFiles.get(i).setFileId(newId);
  330. if (file != null) {
  331. file.setFileId(newId);
  332. }
  333. }
  334. }
  335. }
  336. updateFolderSize(folder.getFileId());
  337. }
  338. /**
  339. *
  340. * @param id
  341. */
  342. private void updateFolderSize(long id) {
  343. if (id > FileDataStorageManager.ROOT_PARENT_ID) {
  344. Log_OC.d(TAG, "Updating size of " + id);
  345. if (getContentResolver() != null) {
  346. getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR,
  347. new ContentValues(), // won't be used, but cannot be null; crashes in KLP
  348. ProviderTableMeta._ID + "=?",
  349. new String[] { String.valueOf(id) });
  350. } else {
  351. try {
  352. getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR,
  353. new ContentValues(), // won't be used, but cannot be null; crashes in KLP
  354. ProviderTableMeta._ID + "=?",
  355. new String[] { String.valueOf(id) });
  356. } catch (RemoteException e) {
  357. Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
  358. }
  359. }
  360. } else {
  361. Log_OC.e(TAG, "not updating size for folder " + id);
  362. }
  363. }
  364. public void removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
  365. if (file != null) {
  366. if (file.isFolder()) {
  367. removeFolder(file, removeDBData, removeLocalCopy);
  368. } else {
  369. if (removeDBData) {
  370. //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
  371. Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
  372. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
  373. String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
  374. if (getContentProviderClient() != null) {
  375. try {
  376. getContentProviderClient().delete(file_uri, where, whereArgs);
  377. } catch (RemoteException e) {
  378. e.printStackTrace();
  379. }
  380. } else {
  381. getContentResolver().delete(file_uri, where, whereArgs);
  382. }
  383. updateFolderSize(file.getParentId());
  384. }
  385. if (removeLocalCopy && file.isDown() && file.getStoragePath() != null) {
  386. boolean success = new File(file.getStoragePath()).delete();
  387. if (!removeDBData && success) {
  388. // maybe unnecessary, but should be checked TODO remove if unnecessary
  389. file.setStoragePath(null);
  390. saveFile(file);
  391. }
  392. }
  393. }
  394. }
  395. }
  396. public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
  397. if (folder != null && folder.isFolder()) {
  398. if (removeDBData && folder.getFileId() != -1) {
  399. removeFolderInDb(folder);
  400. }
  401. if (removeLocalContent) {
  402. File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
  403. removeLocalFolder(localFolder);
  404. }
  405. }
  406. }
  407. private void removeFolderInDb(OCFile folder) {
  408. Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId()); // URI for recursive deletion
  409. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
  410. String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
  411. if (getContentProviderClient() != null) {
  412. try {
  413. getContentProviderClient().delete(folder_uri, where, whereArgs);
  414. } catch (RemoteException e) {
  415. e.printStackTrace();
  416. }
  417. } else {
  418. getContentResolver().delete(folder_uri, where, whereArgs);
  419. }
  420. updateFolderSize(folder.getParentId());
  421. }
  422. private void removeLocalFolder(File folder) {
  423. if (folder.exists()) {
  424. File[] files = folder.listFiles();
  425. if (files != null) {
  426. for (File file : files) {
  427. if (file.isDirectory()) {
  428. removeLocalFolder(file);
  429. } else {
  430. file.delete();
  431. }
  432. }
  433. }
  434. folder.delete();
  435. }
  436. }
  437. /**
  438. * Updates database for a folder that was moved to a different location.
  439. *
  440. * TODO explore better (faster) implementations
  441. * TODO throw exceptions up !
  442. */
  443. public void moveFolder(OCFile folder, String newPath) {
  444. // TODO check newPath
  445. if (folder != null && folder.isFolder() && folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())) {
  446. /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
  447. Cursor c = null;
  448. if (getContentProviderClient() != null) {
  449. try {
  450. c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI,
  451. null,
  452. ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
  453. new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
  454. } catch (RemoteException e) {
  455. Log_OC.e(TAG, e.getMessage());
  456. }
  457. } else {
  458. c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
  459. null,
  460. ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
  461. new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
  462. }
  463. /// 2. prepare a batch of update operations to change all the descendants
  464. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
  465. int lengthOfOldPath = folder.getRemotePath().length();
  466. String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
  467. int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
  468. if (c.moveToFirst()) {
  469. do {
  470. ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
  471. OCFile child = createFileInstance(c);
  472. cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
  473. if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
  474. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
  475. }
  476. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  477. withValues(cv).
  478. withSelection( ProviderTableMeta._ID + "=?",
  479. new String[] { String.valueOf(child.getFileId()) })
  480. .build());
  481. } while (c.moveToNext());
  482. }
  483. c.close();
  484. /// 3. apply updates in batch
  485. try {
  486. if (getContentResolver() != null) {
  487. getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  488. } else {
  489. getContentProviderClient().applyBatch(operations);
  490. }
  491. } catch (OperationApplicationException e) {
  492. Log_OC.e(TAG, "Fail to update descendants of " + folder.getFileId() + " in database", e);
  493. } catch (RemoteException e) {
  494. Log_OC.e(TAG, "Fail to update desendants of " + folder.getFileId() + " in database", e);
  495. }
  496. }
  497. }
  498. private Vector<OCFile> getFolderContent(long parentId) {
  499. Vector<OCFile> ret = new Vector<OCFile>();
  500. Uri req_uri = Uri.withAppendedPath(
  501. ProviderTableMeta.CONTENT_URI_DIR,
  502. String.valueOf(parentId));
  503. Cursor c = null;
  504. if (getContentProviderClient() != null) {
  505. try {
  506. c = getContentProviderClient().query(req_uri, null,
  507. ProviderTableMeta.FILE_PARENT + "=?" ,
  508. new String[] { String.valueOf(parentId)}, null);
  509. } catch (RemoteException e) {
  510. Log_OC.e(TAG, e.getMessage());
  511. return ret;
  512. }
  513. } else {
  514. c = getContentResolver().query(req_uri, null,
  515. ProviderTableMeta.FILE_PARENT + "=?" ,
  516. new String[] { String.valueOf(parentId)}, null);
  517. }
  518. if (c.moveToFirst()) {
  519. do {
  520. OCFile child = createFileInstance(c);
  521. ret.add(child);
  522. } while (c.moveToNext());
  523. }
  524. c.close();
  525. Collections.sort(ret);
  526. return ret;
  527. }
  528. private OCFile createRootDir() {
  529. OCFile file = new OCFile(OCFile.ROOT_PATH);
  530. file.setMimetype("DIR");
  531. file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
  532. saveFile(file);
  533. return file;
  534. }
  535. private boolean fileExists(String cmp_key, String value) {
  536. Cursor c;
  537. if (getContentResolver() != null) {
  538. c = getContentResolver()
  539. .query(ProviderTableMeta.CONTENT_URI,
  540. null,
  541. cmp_key + "=? AND "
  542. + ProviderTableMeta.FILE_ACCOUNT_OWNER
  543. + "=?",
  544. new String[] { value, mAccount.name }, null);
  545. } else {
  546. try {
  547. c = getContentProviderClient().query(
  548. ProviderTableMeta.CONTENT_URI,
  549. null,
  550. cmp_key + "=? AND "
  551. + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
  552. new String[] { value, mAccount.name }, null);
  553. } catch (RemoteException e) {
  554. Log_OC.e(TAG,
  555. "Couldn't determine file existance, assuming non existance: "
  556. + e.getMessage());
  557. return false;
  558. }
  559. }
  560. boolean retval = c.moveToFirst();
  561. c.close();
  562. return retval;
  563. }
  564. private Cursor getCursorForValue(String key, String value) {
  565. Cursor c = null;
  566. if (getContentResolver() != null) {
  567. c = getContentResolver()
  568. .query(ProviderTableMeta.CONTENT_URI,
  569. null,
  570. key + "=? AND "
  571. + ProviderTableMeta.FILE_ACCOUNT_OWNER
  572. + "=?",
  573. new String[] { value, mAccount.name }, null);
  574. } else {
  575. try {
  576. c = getContentProviderClient().query(
  577. ProviderTableMeta.CONTENT_URI,
  578. null,
  579. key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
  580. + "=?", new String[] { value, mAccount.name },
  581. null);
  582. } catch (RemoteException e) {
  583. Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
  584. c = null;
  585. }
  586. }
  587. return c;
  588. }
  589. private Cursor getShareCursorForValue(String key, String value) {
  590. Cursor c = null;
  591. if (getContentResolver() != null) {
  592. c = getContentResolver()
  593. .query(ProviderTableMeta.CONTENT_URI_SHARE,
  594. null,
  595. key + "=? AND "
  596. + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
  597. + "=?",
  598. new String[] { value, mAccount.name }, null);
  599. } else {
  600. try {
  601. c = getContentProviderClient().query(
  602. ProviderTableMeta.CONTENT_URI_SHARE,
  603. null,
  604. key + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
  605. + "=?", new String[] { value, mAccount.name },
  606. null);
  607. } catch (RemoteException e) {
  608. Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
  609. c = null;
  610. }
  611. }
  612. return c;
  613. }
  614. private OCFile createFileInstance(Cursor c) {
  615. OCFile file = null;
  616. if (c != null) {
  617. file = new OCFile(c.getString(c
  618. .getColumnIndex(ProviderTableMeta.FILE_PATH)));
  619. file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
  620. file.setParentId(c.getLong(c
  621. .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
  622. file.setMimetype(c.getString(c
  623. .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
  624. if (!file.isFolder()) {
  625. file.setStoragePath(c.getString(c
  626. .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
  627. if (file.getStoragePath() == null) {
  628. // try to find existing file and bind it with current account; - with the current update of SynchronizeFolderOperation, this won't be necessary anymore after a full synchronization of the account
  629. File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
  630. if (f.exists()) {
  631. file.setStoragePath(f.getAbsolutePath());
  632. file.setLastSyncDateForData(f.lastModified());
  633. }
  634. }
  635. }
  636. file.setFileLength(c.getLong(c
  637. .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
  638. file.setCreationTimestamp(c.getLong(c
  639. .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
  640. file.setModificationTimestamp(c.getLong(c
  641. .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
  642. file.setModificationTimestampAtLastSyncForData(c.getLong(c
  643. .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)));
  644. file.setLastSyncDateForProperties(c.getLong(c
  645. .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
  646. file.setLastSyncDateForData(c.getLong(c.
  647. getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
  648. file.setKeepInSync(c.getInt(
  649. c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
  650. file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
  651. file.setShareByLink(c.getInt(
  652. c.getColumnIndex(ProviderTableMeta.FILE_SHARE_BY_LINK)) == 1 ? true : false);
  653. file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
  654. }
  655. return file;
  656. }
  657. /**
  658. * Returns if the file/folder is shared by link or not
  659. * @param path Path of the file/folder
  660. * @return
  661. */
  662. public boolean isShareByLink(String path) {
  663. Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
  664. OCFile file = null;
  665. if (c.moveToFirst()) {
  666. file = createFileInstance(c);
  667. }
  668. c.close();
  669. return file.isShareByLink();
  670. }
  671. /**
  672. * Returns the public link of the file/folder
  673. * @param path Path of the file/folder
  674. * @return
  675. */
  676. public String getPublicLink(String path) {
  677. Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
  678. OCFile file = null;
  679. if (c.moveToFirst()) {
  680. file = createFileInstance(c);
  681. }
  682. c.close();
  683. return file.getPublicLink();
  684. }
  685. // Methods for Shares
  686. public boolean saveShare(OCShare share) {
  687. boolean overriden = false;
  688. ContentValues cv = new ContentValues();
  689. cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
  690. cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
  691. cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
  692. cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
  693. cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
  694. cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
  695. cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
  696. cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
  697. cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
  698. cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
  699. cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isDirectory() ? 1 : 0);
  700. cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
  701. cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
  702. cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
  703. boolean samePath = shareExists(share.getPath());
  704. if (samePath ||
  705. shareExists(share.getId())) { // for renamed files; no more delete and create
  706. OCShare oldFile = null;
  707. if (samePath) {
  708. oldFile = getShareByPath(share.getPath());
  709. share.setId(oldFile.getId());
  710. } else {
  711. oldFile = getShareById(share.getId());
  712. }
  713. overriden = true;
  714. if (getContentResolver() != null) {
  715. getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv,
  716. ProviderTableMeta._ID + "=?",
  717. new String[] { String.valueOf(share.getId()) });
  718. } else {
  719. try {
  720. getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE,
  721. cv, ProviderTableMeta._ID + "=?",
  722. new String[] { String.valueOf(share.getId()) });
  723. } catch (RemoteException e) {
  724. Log_OC.e(TAG,
  725. "Fail to insert insert file to database "
  726. + e.getMessage());
  727. }
  728. }
  729. } else {
  730. Uri result_uri = null;
  731. if (getContentResolver() != null) {
  732. result_uri = getContentResolver().insert(
  733. ProviderTableMeta.CONTENT_URI_SHARE, cv);
  734. } else {
  735. try {
  736. result_uri = getContentProviderClient().insert(
  737. ProviderTableMeta.CONTENT_URI_SHARE, cv);
  738. } catch (RemoteException e) {
  739. Log_OC.e(TAG,
  740. "Fail to insert insert file to database "
  741. + e.getMessage());
  742. }
  743. }
  744. if (result_uri != null) {
  745. long new_id = Long.parseLong(result_uri.getPathSegments()
  746. .get(1));
  747. share.setId(new_id);
  748. }
  749. }
  750. return overriden;
  751. }
  752. private OCShare getShareById(long id) {
  753. Cursor c = getShareCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
  754. OCShare share = null;
  755. if (c.moveToFirst()) {
  756. share = createShareInstance(c);
  757. }
  758. c.close();
  759. return share;
  760. }
  761. public OCShare getShareByPath(String path) {
  762. Cursor c = getShareCursorForValue(ProviderTableMeta.OCSHARES_PATH, path);
  763. OCShare share = null;
  764. if (c.moveToFirst()) {
  765. share = createShareInstance(c);
  766. }
  767. c.close();
  768. return share;
  769. }
  770. private OCShare createShareInstance(Cursor c) {
  771. OCShare share = null;
  772. if (c != null) {
  773. share = new OCShare(c.getString(c
  774. .getColumnIndex(ProviderTableMeta.OCSHARES_PATH)));
  775. share.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
  776. share.setFileSource(c.getLong(c
  777. .getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE)));
  778. share.setShareType(ShareType.fromValue(c.getInt(c
  779. .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE))));
  780. share.setPermissions(c.getInt(c
  781. .getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS)));
  782. share.setSharedDate(c.getLong(c
  783. .getColumnIndex(ProviderTableMeta.OCSHARES_SHARED_DATE)));
  784. share.setExpirationDate(c.getLong(c
  785. .getColumnIndex(ProviderTableMeta.OCSHARES_EXPIRATION_DATE)));
  786. share.setToken(c.getString(c
  787. .getColumnIndex(ProviderTableMeta.OCSHARES_TOKEN)));
  788. share.setSharedWithDisplayName(c.getString(c
  789. .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME)));
  790. share.setIsDirectory(c.getInt(
  791. c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false);
  792. share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
  793. share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
  794. }
  795. return share;
  796. }
  797. private boolean shareExists(String cmp_key, String value) {
  798. Cursor c;
  799. if (getContentResolver() != null) {
  800. c = getContentResolver()
  801. .query(ProviderTableMeta.CONTENT_URI_SHARE,
  802. null,
  803. cmp_key + "=? AND "
  804. + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
  805. + "=?",
  806. new String[] { value, mAccount.name }, null);
  807. } else {
  808. try {
  809. c = getContentProviderClient().query(
  810. ProviderTableMeta.CONTENT_URI_SHARE,
  811. null,
  812. cmp_key + "=? AND "
  813. + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
  814. new String[] { value, mAccount.name }, null);
  815. } catch (RemoteException e) {
  816. Log_OC.e(TAG,
  817. "Couldn't determine file existance, assuming non existance: "
  818. + e.getMessage());
  819. return false;
  820. }
  821. }
  822. boolean retval = c.moveToFirst();
  823. c.close();
  824. return retval;
  825. }
  826. public boolean shareExists(long id) {
  827. return shareExists(ProviderTableMeta._ID, String.valueOf(id));
  828. }
  829. public boolean shareExists(String path) {
  830. return shareExists(ProviderTableMeta.OCSHARES_PATH, path);
  831. }
  832. private void cleanSharedFiles() {
  833. ContentValues cv = new ContentValues();
  834. cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
  835. cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
  836. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
  837. String [] whereArgs = new String[]{mAccount.name};
  838. if (getContentResolver() != null) {
  839. getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
  840. } else {
  841. try {
  842. getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
  843. } catch (RemoteException e) {
  844. Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
  845. }
  846. }
  847. }
  848. private void cleanShares() {
  849. String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
  850. String [] whereArgs = new String[]{mAccount.name};
  851. if (getContentResolver() != null) {
  852. getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
  853. } else {
  854. try {
  855. getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
  856. } catch (RemoteException e) {
  857. Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
  858. }
  859. }
  860. }
  861. public void saveShares(Collection<OCShare> shares) {
  862. cleanShares();
  863. if (shares != null) {
  864. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(shares.size());
  865. // prepare operations to insert or update files to save in the given folder
  866. for (OCShare share : shares) {
  867. ContentValues cv = new ContentValues();
  868. cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
  869. cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
  870. cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
  871. cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
  872. cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
  873. cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
  874. cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
  875. cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
  876. cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
  877. cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
  878. cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isDirectory() ? 1 : 0);
  879. cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
  880. cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
  881. cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
  882. boolean existsByPath = shareExists(share.getPath());
  883. if (existsByPath || shareExists(share.getId())) {
  884. // updating an existing file
  885. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
  886. withValues(cv).
  887. withSelection( ProviderTableMeta._ID + "=?",
  888. new String[] { String.valueOf(share.getId()) })
  889. .build());
  890. } else {
  891. // adding a new file
  892. operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
  893. }
  894. }
  895. // apply operations in batch
  896. if (operations.size() > 0) {
  897. @SuppressWarnings("unused")
  898. ContentProviderResult[] results = null;
  899. Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
  900. try {
  901. if (getContentResolver() != null) {
  902. results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  903. } else {
  904. results = getContentProviderClient().applyBatch(operations);
  905. }
  906. } catch (OperationApplicationException e) {
  907. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  908. } catch (RemoteException e) {
  909. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  910. }
  911. }
  912. }
  913. }
  914. public void updateSharedFiles(Collection<OCFile> sharedFiles) {
  915. cleanSharedFiles();
  916. if (sharedFiles != null) {
  917. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(sharedFiles.size());
  918. // prepare operations to insert or update files to save in the given folder
  919. for (OCFile file : sharedFiles) {
  920. ContentValues cv = new ContentValues();
  921. cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
  922. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
  923. cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
  924. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
  925. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
  926. cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
  927. cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
  928. cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
  929. if (!file.isFolder()) {
  930. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
  931. }
  932. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  933. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
  934. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
  935. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
  936. cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  937. cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
  938. cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
  939. boolean existsByPath = fileExists(file.getRemotePath());
  940. if (existsByPath || fileExists(file.getFileId())) {
  941. // updating an existing file
  942. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  943. withValues(cv).
  944. withSelection( ProviderTableMeta._ID + "=?",
  945. new String[] { String.valueOf(file.getFileId()) })
  946. .build());
  947. } else {
  948. // adding a new file
  949. operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
  950. }
  951. }
  952. // apply operations in batch
  953. if (operations.size() > 0) {
  954. @SuppressWarnings("unused")
  955. ContentProviderResult[] results = null;
  956. Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
  957. try {
  958. if (getContentResolver() != null) {
  959. results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  960. } else {
  961. results = getContentProviderClient().applyBatch(operations);
  962. }
  963. } catch (OperationApplicationException e) {
  964. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  965. } catch (RemoteException e) {
  966. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  967. }
  968. }
  969. }
  970. }
  971. }