FileDataStorageManager.java 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  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.utils.FileStorageUtils;
  28. import com.owncloud.android.utils.Log_OC;
  29. import android.accounts.Account;
  30. import android.content.ContentProviderClient;
  31. import android.content.ContentProviderOperation;
  32. import android.content.ContentProviderResult;
  33. import android.content.ContentResolver;
  34. import android.content.ContentUris;
  35. import android.content.ContentValues;
  36. import android.content.OperationApplicationException;
  37. import android.database.Cursor;
  38. import android.net.Uri;
  39. import android.os.RemoteException;
  40. public class FileDataStorageManager {
  41. public static final int ROOT_PARENT_ID = 0;
  42. private ContentResolver mContentResolver;
  43. private ContentProviderClient mContentProviderClient;
  44. private Account mAccount;
  45. private static String TAG = FileDataStorageManager.class.getSimpleName();
  46. public FileDataStorageManager(Account account, ContentResolver cr) {
  47. mContentProviderClient = null;
  48. mContentResolver = cr;
  49. mAccount = account;
  50. }
  51. public FileDataStorageManager(Account account, ContentProviderClient cp) {
  52. mContentProviderClient = cp;
  53. mContentResolver = null;
  54. mAccount = account;
  55. }
  56. public void setAccount(Account account) {
  57. mAccount = account;
  58. }
  59. public Account getAccount() {
  60. return mAccount;
  61. }
  62. public void setContentResolver(ContentResolver cr) {
  63. mContentResolver = cr;
  64. }
  65. public ContentResolver getContentResolver() {
  66. return mContentResolver;
  67. }
  68. public void setContentProviderClient(ContentProviderClient cp) {
  69. mContentProviderClient = cp;
  70. }
  71. public ContentProviderClient getContentProviderClient() {
  72. return mContentProviderClient;
  73. }
  74. public OCFile getFileByPath(String path) {
  75. Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
  76. OCFile file = null;
  77. if (c.moveToFirst()) {
  78. file = createFileInstance(c);
  79. }
  80. c.close();
  81. if (file == null && OCFile.ROOT_PATH.equals(path)) {
  82. return createRootDir(); // root should always exist
  83. }
  84. return file;
  85. }
  86. public OCFile getFileById(long id) {
  87. Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
  88. OCFile file = null;
  89. if (c.moveToFirst()) {
  90. file = createFileInstance(c);
  91. }
  92. c.close();
  93. return file;
  94. }
  95. public OCFile getFileByLocalPath(String path) {
  96. Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
  97. OCFile file = null;
  98. if (c.moveToFirst()) {
  99. file = createFileInstance(c);
  100. }
  101. c.close();
  102. return file;
  103. }
  104. public boolean fileExists(long id) {
  105. return fileExists(ProviderTableMeta._ID, String.valueOf(id));
  106. }
  107. public boolean fileExists(String path) {
  108. return fileExists(ProviderTableMeta.FILE_PATH, path);
  109. }
  110. public Vector<OCFile> getFolderContent(OCFile f) {
  111. if (f != null && f.isFolder() && f.getFileId() != -1) {
  112. return getFolderContent(f.getFileId());
  113. } else {
  114. return new Vector<OCFile>();
  115. }
  116. }
  117. public Vector<OCFile> getFolderImages(OCFile folder) {
  118. Vector<OCFile> ret = new Vector<OCFile>();
  119. if (folder != null) {
  120. // TODO better implementation, filtering in the access to database (if possible) instead of here
  121. Vector<OCFile> tmp = getFolderContent(folder);
  122. OCFile current = null;
  123. for (int i=0; i<tmp.size(); i++) {
  124. current = tmp.get(i);
  125. if (current.isImage()) {
  126. ret.add(current);
  127. }
  128. }
  129. }
  130. return ret;
  131. }
  132. public boolean saveFile(OCFile file) {
  133. boolean overriden = false;
  134. ContentValues cv = new ContentValues();
  135. cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
  136. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
  137. cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
  138. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
  139. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
  140. cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
  141. //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
  142. cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
  143. cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
  144. if (!file.isFolder())
  145. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
  146. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  147. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
  148. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
  149. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
  150. cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  151. boolean sameRemotePath = fileExists(file.getRemotePath());
  152. if (sameRemotePath ||
  153. fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
  154. OCFile oldFile = null;
  155. if (sameRemotePath) {
  156. oldFile = getFileByPath(file.getRemotePath());
  157. file.setFileId(oldFile.getFileId());
  158. } else {
  159. oldFile = getFileById(file.getFileId());
  160. }
  161. overriden = true;
  162. if (getContentResolver() != null) {
  163. getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
  164. ProviderTableMeta._ID + "=?",
  165. new String[] { String.valueOf(file.getFileId()) });
  166. } else {
  167. try {
  168. getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
  169. cv, ProviderTableMeta._ID + "=?",
  170. new String[] { String.valueOf(file.getFileId()) });
  171. } catch (RemoteException e) {
  172. Log_OC.e(TAG,
  173. "Fail to insert insert file to database "
  174. + e.getMessage());
  175. }
  176. }
  177. } else {
  178. Uri result_uri = null;
  179. if (getContentResolver() != null) {
  180. result_uri = getContentResolver().insert(
  181. ProviderTableMeta.CONTENT_URI_FILE, cv);
  182. } else {
  183. try {
  184. result_uri = getContentProviderClient().insert(
  185. ProviderTableMeta.CONTENT_URI_FILE, cv);
  186. } catch (RemoteException e) {
  187. Log_OC.e(TAG,
  188. "Fail to insert insert file to database "
  189. + e.getMessage());
  190. }
  191. }
  192. if (result_uri != null) {
  193. long new_id = Long.parseLong(result_uri.getPathSegments()
  194. .get(1));
  195. file.setFileId(new_id);
  196. }
  197. }
  198. if (file.isFolder()) {
  199. updateFolderSize(file.getFileId());
  200. } else {
  201. updateFolderSize(file.getParentId());
  202. }
  203. return overriden;
  204. }
  205. /**
  206. * Inserts or updates the list of files contained in a given folder.
  207. *
  208. * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
  209. * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
  210. *
  211. * @param folder
  212. * @param files
  213. * @param removeNotUpdated
  214. */
  215. public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
  216. Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
  217. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
  218. // prepare operations to insert or update files to save in the given folder
  219. for (OCFile file : updatedFiles) {
  220. ContentValues cv = new ContentValues();
  221. cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
  222. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
  223. cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
  224. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
  225. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
  226. cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
  227. //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
  228. cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
  229. cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
  230. if (!file.isFolder()) {
  231. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
  232. }
  233. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  234. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
  235. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
  236. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
  237. cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  238. boolean existsByPath = fileExists(file.getRemotePath());
  239. if (existsByPath || fileExists(file.getFileId())) {
  240. // updating an existing file
  241. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  242. withValues(cv).
  243. withSelection( ProviderTableMeta._ID + "=?",
  244. new String[] { String.valueOf(file.getFileId()) })
  245. .build());
  246. } else {
  247. // adding a new file
  248. operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
  249. }
  250. }
  251. // prepare operations to remove files in the given folder
  252. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
  253. String [] whereArgs = null;
  254. for (OCFile file : filesToRemove) {
  255. if (file.getParentId() == folder.getFileId()) {
  256. whereArgs = new String[]{mAccount.name, file.getRemotePath()};
  257. //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
  258. if (file.isFolder()) {
  259. operations.add(ContentProviderOperation
  260. .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
  261. .build());
  262. // TODO remove local folder
  263. } else {
  264. operations.add(ContentProviderOperation
  265. .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
  266. .build());
  267. if (file.isDown()) {
  268. new File(file.getStoragePath()).delete();
  269. // TODO move the deletion of local contents after success of deletions
  270. }
  271. }
  272. }
  273. }
  274. // update metadata of folder
  275. ContentValues cv = new ContentValues();
  276. cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
  277. cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
  278. cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
  279. cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0); // FileContentProvider calculates the right size
  280. cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
  281. cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
  282. cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
  283. cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
  284. cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
  285. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
  286. cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
  287. cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
  288. cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
  289. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  290. withValues(cv).
  291. withSelection( ProviderTableMeta._ID + "=?",
  292. new String[] { String.valueOf(folder.getFileId()) })
  293. .build());
  294. // apply operations in batch
  295. ContentProviderResult[] results = null;
  296. Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
  297. try {
  298. if (getContentResolver() != null) {
  299. results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  300. } else {
  301. results = getContentProviderClient().applyBatch(operations);
  302. }
  303. } catch (OperationApplicationException e) {
  304. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  305. } catch (RemoteException e) {
  306. Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  307. }
  308. // update new id in file objects for insertions
  309. if (results != null) {
  310. long newId;
  311. Iterator<OCFile> filesIt = updatedFiles.iterator();
  312. OCFile file = null;
  313. for (int i=0; i<results.length; i++) {
  314. if (filesIt.hasNext()) {
  315. file = filesIt.next();
  316. } else {
  317. file = null;
  318. }
  319. if (results[i].uri != null) {
  320. newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
  321. //updatedFiles.get(i).setFileId(newId);
  322. if (file != null) {
  323. file.setFileId(newId);
  324. }
  325. }
  326. }
  327. }
  328. updateFolderSize(folder.getFileId());
  329. }
  330. /**
  331. *
  332. * @param id
  333. */
  334. private void updateFolderSize(long id) {
  335. if (id > FileDataStorageManager.ROOT_PARENT_ID) {
  336. Log_OC.d(TAG, "Updating size of " + id);
  337. if (getContentResolver() != null) {
  338. getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR,
  339. new ContentValues(), // won't be used, but cannot be null; crashes in KLP
  340. ProviderTableMeta._ID + "=?",
  341. new String[] { String.valueOf(id) });
  342. } else {
  343. try {
  344. getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR,
  345. new ContentValues(), // won't be used, but cannot be null; crashes in KLP
  346. ProviderTableMeta._ID + "=?",
  347. new String[] { String.valueOf(id) });
  348. } catch (RemoteException e) {
  349. Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
  350. }
  351. }
  352. } else {
  353. Log_OC.e(TAG, "not updating size for folder " + id);
  354. }
  355. }
  356. public void removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
  357. if (file != null) {
  358. if (file.isFolder()) {
  359. removeFolder(file, removeDBData, removeLocalCopy);
  360. } else {
  361. if (removeDBData) {
  362. //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
  363. Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
  364. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
  365. String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
  366. if (getContentProviderClient() != null) {
  367. try {
  368. getContentProviderClient().delete(file_uri, where, whereArgs);
  369. } catch (RemoteException e) {
  370. e.printStackTrace();
  371. }
  372. } else {
  373. getContentResolver().delete(file_uri, where, whereArgs);
  374. }
  375. updateFolderSize(file.getParentId());
  376. }
  377. if (removeLocalCopy && file.isDown()) {
  378. boolean success = new File(file.getStoragePath()).delete();
  379. if (!removeDBData && success) {
  380. // maybe unnecessary, but should be checked TODO remove if unnecessary
  381. file.setStoragePath(null);
  382. saveFile(file);
  383. }
  384. }
  385. }
  386. }
  387. }
  388. public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
  389. if (folder != null && folder.isFolder()) {
  390. if (removeDBData && folder.getFileId() != -1) {
  391. removeFolderInDb(folder);
  392. }
  393. if (removeLocalContent) {
  394. File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
  395. removeLocalFolder(localFolder);
  396. }
  397. }
  398. }
  399. private void removeFolderInDb(OCFile folder) {
  400. Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId()); // URI for recursive deletion
  401. String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
  402. String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
  403. if (getContentProviderClient() != null) {
  404. try {
  405. getContentProviderClient().delete(folder_uri, where, whereArgs);
  406. } catch (RemoteException e) {
  407. e.printStackTrace();
  408. }
  409. } else {
  410. getContentResolver().delete(folder_uri, where, whereArgs);
  411. }
  412. updateFolderSize(folder.getParentId());
  413. }
  414. private void removeLocalFolder(File folder) {
  415. if (folder.exists()) {
  416. File[] files = folder.listFiles();
  417. if (files != null) {
  418. for (File file : files) {
  419. if (file.isDirectory()) {
  420. removeLocalFolder(file);
  421. } else {
  422. file.delete();
  423. }
  424. }
  425. }
  426. folder.delete();
  427. }
  428. }
  429. /**
  430. * Updates database for a folder that was moved to a different location.
  431. *
  432. * TODO explore better (faster) implementations
  433. * TODO throw exceptions up !
  434. */
  435. public void moveFolder(OCFile folder, String newPath) {
  436. // TODO check newPath
  437. if (folder != null && folder.isFolder() && folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())) {
  438. /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
  439. Cursor c = null;
  440. if (getContentProviderClient() != null) {
  441. try {
  442. c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI,
  443. null,
  444. ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
  445. new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
  446. } catch (RemoteException e) {
  447. Log_OC.e(TAG, e.getMessage());
  448. }
  449. } else {
  450. c = getContentResolver().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. }
  455. /// 2. prepare a batch of update operations to change all the descendants
  456. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
  457. int lengthOfOldPath = folder.getRemotePath().length();
  458. String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
  459. int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
  460. if (c.moveToFirst()) {
  461. do {
  462. ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
  463. OCFile child = createFileInstance(c);
  464. cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
  465. if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
  466. cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
  467. }
  468. operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
  469. withValues(cv).
  470. withSelection( ProviderTableMeta._ID + "=?",
  471. new String[] { String.valueOf(child.getFileId()) })
  472. .build());
  473. } while (c.moveToNext());
  474. }
  475. c.close();
  476. /// 3. apply updates in batch
  477. try {
  478. if (getContentResolver() != null) {
  479. getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  480. } else {
  481. getContentProviderClient().applyBatch(operations);
  482. }
  483. } catch (OperationApplicationException e) {
  484. Log_OC.e(TAG, "Fail to update descendants of " + folder.getFileId() + " in database", e);
  485. } catch (RemoteException e) {
  486. Log_OC.e(TAG, "Fail to update desendants of " + folder.getFileId() + " in database", e);
  487. }
  488. }
  489. }
  490. private Vector<OCFile> getFolderContent(long parentId) {
  491. Vector<OCFile> ret = new Vector<OCFile>();
  492. Uri req_uri = Uri.withAppendedPath(
  493. ProviderTableMeta.CONTENT_URI_DIR,
  494. String.valueOf(parentId));
  495. Cursor c = null;
  496. if (getContentProviderClient() != null) {
  497. try {
  498. c = getContentProviderClient().query(req_uri, null,
  499. ProviderTableMeta.FILE_PARENT + "=?" ,
  500. new String[] { String.valueOf(parentId)}, null);
  501. } catch (RemoteException e) {
  502. Log_OC.e(TAG, e.getMessage());
  503. return ret;
  504. }
  505. } else {
  506. c = getContentResolver().query(req_uri, null,
  507. ProviderTableMeta.FILE_PARENT + "=?" ,
  508. new String[] { String.valueOf(parentId)}, null);
  509. }
  510. if (c.moveToFirst()) {
  511. do {
  512. OCFile child = createFileInstance(c);
  513. ret.add(child);
  514. } while (c.moveToNext());
  515. }
  516. c.close();
  517. Collections.sort(ret);
  518. return ret;
  519. }
  520. private OCFile createRootDir() {
  521. OCFile file = new OCFile(OCFile.ROOT_PATH);
  522. file.setMimetype("DIR");
  523. file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
  524. saveFile(file);
  525. return file;
  526. }
  527. private boolean fileExists(String cmp_key, String value) {
  528. Cursor c;
  529. if (getContentResolver() != null) {
  530. c = getContentResolver()
  531. .query(ProviderTableMeta.CONTENT_URI,
  532. null,
  533. cmp_key + "=? AND "
  534. + ProviderTableMeta.FILE_ACCOUNT_OWNER
  535. + "=?",
  536. new String[] { value, mAccount.name }, null);
  537. } else {
  538. try {
  539. c = getContentProviderClient().query(
  540. ProviderTableMeta.CONTENT_URI,
  541. null,
  542. cmp_key + "=? AND "
  543. + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
  544. new String[] { value, mAccount.name }, null);
  545. } catch (RemoteException e) {
  546. Log_OC.e(TAG,
  547. "Couldn't determine file existance, assuming non existance: "
  548. + e.getMessage());
  549. return false;
  550. }
  551. }
  552. boolean retval = c.moveToFirst();
  553. c.close();
  554. return retval;
  555. }
  556. private Cursor getCursorForValue(String key, String value) {
  557. Cursor c = null;
  558. if (getContentResolver() != null) {
  559. c = getContentResolver()
  560. .query(ProviderTableMeta.CONTENT_URI,
  561. null,
  562. key + "=? AND "
  563. + ProviderTableMeta.FILE_ACCOUNT_OWNER
  564. + "=?",
  565. new String[] { value, mAccount.name }, null);
  566. } else {
  567. try {
  568. c = getContentProviderClient().query(
  569. ProviderTableMeta.CONTENT_URI,
  570. null,
  571. key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
  572. + "=?", new String[] { value, mAccount.name },
  573. null);
  574. } catch (RemoteException e) {
  575. Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
  576. c = null;
  577. }
  578. }
  579. return c;
  580. }
  581. private OCFile createFileInstance(Cursor c) {
  582. OCFile file = null;
  583. if (c != null) {
  584. file = new OCFile(c.getString(c
  585. .getColumnIndex(ProviderTableMeta.FILE_PATH)));
  586. file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
  587. file.setParentId(c.getLong(c
  588. .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
  589. file.setMimetype(c.getString(c
  590. .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
  591. if (!file.isFolder()) {
  592. file.setStoragePath(c.getString(c
  593. .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
  594. if (file.getStoragePath() == null) {
  595. // 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
  596. File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
  597. if (f.exists()) {
  598. file.setStoragePath(f.getAbsolutePath());
  599. file.setLastSyncDateForData(f.lastModified());
  600. }
  601. }
  602. }
  603. file.setFileLength(c.getLong(c
  604. .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
  605. file.setCreationTimestamp(c.getLong(c
  606. .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
  607. file.setModificationTimestamp(c.getLong(c
  608. .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
  609. file.setModificationTimestampAtLastSyncForData(c.getLong(c
  610. .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)));
  611. file.setLastSyncDateForProperties(c.getLong(c
  612. .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
  613. file.setLastSyncDateForData(c.getLong(c.
  614. getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
  615. file.setKeepInSync(c.getInt(
  616. c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
  617. file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
  618. }
  619. return file;
  620. }
  621. }