X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/938c78466b89ee30d439462ded5b4b25c79190ce..a72d7bfe2160a47a3fd49c08d72933a49e9e1519:/src/com/owncloud/android/datamodel/FileDataStorageManager.java diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index 7bb29d46..69f36eac 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -1,10 +1,10 @@ /* ownCloud Android client application * Copyright (C) 2012 Bartek Przybylski + * Copyright (C) 2012-2013 ownCloud Inc. * * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,9 +25,11 @@ import java.util.Iterator; import java.util.List; import java.util.Vector; +import com.owncloud.android.DisplayUtils; +import com.owncloud.android.Log_OC; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; -import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.utils.FileStorageUtils; import android.accounts.Account; import android.content.ContentProviderClient; @@ -38,9 +40,7 @@ import android.content.ContentValues; import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; -import android.os.Environment; import android.os.RemoteException; -import android.util.Log; public class FileDataStorageManager implements DataStorageManager { @@ -70,6 +70,18 @@ public class FileDataStorageManager implements DataStorageManager { file = createFileInstance(c); } c.close(); + if (file == null && OCFile.PATH_SEPARATOR.equals(path)) { + return createRootDir(); // root should always exist + } + return file; + } + + + private OCFile createRootDir() { + OCFile file = new OCFile(OCFile.PATH_SEPARATOR); + file.setMimetype("DIR"); + file.setParentId(DataStorageManager.ROOT_PARENT_ID); + saveFile(file); return file; } @@ -84,6 +96,16 @@ public class FileDataStorageManager implements DataStorageManager { return file; } + public OCFile getFileByLocalPath(String path) { + Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path); + OCFile file = null; + if (c.moveToFirst()) { + file = createFileInstance(c); + } + c.close(); + return file; + } + @Override public boolean fileExists(long id) { return fileExists(ProviderTableMeta._ID, String.valueOf(id)); @@ -99,6 +121,7 @@ public class FileDataStorageManager implements DataStorageManager { boolean overriden = false; ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); + cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData()); cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype()); @@ -109,16 +132,18 @@ public class FileDataStorageManager implements DataStorageManager { if (!file.isDirectory()) cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate()); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData()); cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0); - if (fileExists(file.getRemotePath())) { - OCFile oldFile = getFileByPath(file.getRemotePath()); - if (file.getStoragePath() == null && oldFile.getStoragePath() != null) - file.setStoragePath(oldFile.getStoragePath()); - if (!file.isDirectory()); - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); - file.setFileId(oldFile.getFileId()); + boolean sameRemotePath = fileExists(file.getRemotePath()); + if (sameRemotePath || + fileExists(file.getFileId()) ) { // for renamed files; no more delete and create + + if (sameRemotePath) { + OCFile oldFile = getFileByPath(file.getRemotePath()); + file.setFileId(oldFile.getFileId()); + } overriden = true; if (getContentResolver() != null) { @@ -131,7 +156,7 @@ public class FileDataStorageManager implements DataStorageManager { cv, ProviderTableMeta._ID + "=?", new String[] { String.valueOf(file.getFileId()) }); } catch (RemoteException e) { - Log.e(TAG, + Log_OC.e(TAG, "Fail to insert insert file to database " + e.getMessage()); } @@ -146,7 +171,7 @@ public class FileDataStorageManager implements DataStorageManager { result_uri = getContentProvider().insert( ProviderTableMeta.CONTENT_URI_FILE, cv); } catch (RemoteException e) { - Log.e(TAG, + Log_OC.e(TAG, "Fail to insert insert file to database " + e.getMessage()); } @@ -155,20 +180,23 @@ public class FileDataStorageManager implements DataStorageManager { long new_id = Long.parseLong(result_uri.getPathSegments() .get(1)); file.setFileId(new_id); - } + } } if (file.isDirectory() && file.needsUpdatingWhileSaving()) for (OCFile f : getDirectoryContent(file)) saveFile(f); - + + Log_OC.d(TAG, ".........file Time= " + DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp())); + updateSubtreeSize(file.getParentId()); + return overriden; } @Override public void saveFiles(List files) { - + Iterator filesIt = files.iterator(); ArrayList operations = new ArrayList(files.size()); OCFile file = null; @@ -178,6 +206,7 @@ public class FileDataStorageManager implements DataStorageManager { file = filesIt.next(); ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); + cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData()); cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype()); @@ -188,44 +217,54 @@ public class FileDataStorageManager implements DataStorageManager { if (!file.isDirectory()) cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate()); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData()); cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0); if (fileExists(file.getRemotePath())) { - OCFile tmpfile = getFileByPath(file.getRemotePath()); - file.setStoragePath(tmpfile.getStoragePath()); + OCFile oldFile = getFileByPath(file.getRemotePath()); + file.setFileId(oldFile.getFileId()); + operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). + withValues(cv). + withSelection( ProviderTableMeta._ID + "=?", + new String[] { String.valueOf(file.getFileId()) }) + .build()); + + } else if (fileExists(file.getFileId())) { + OCFile oldFile = getFileById(file.getFileId()); + if (file.getStoragePath() == null && oldFile.getStoragePath() != null) + file.setStoragePath(oldFile.getStoragePath()); if (!file.isDirectory()); - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); - file.setFileId(tmpfile.getFileId()); + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). withValues(cv). withSelection( ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(file.getFileId()) }) - .build()); - + new String[] { String.valueOf(file.getFileId()) }) + .build()); + } else { operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build()); } } - + // apply operations in batch ContentProviderResult[] results = null; try { if (getContentResolver() != null) { results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations); - + } else { results = getContentProvider().applyBatch(operations); } - + } catch (OperationApplicationException e) { - Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage()); - + Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage()); + } catch (RemoteException e) { - Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage()); + Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage()); } - + // update new id in file objects for insertions if (results != null) { long newId; @@ -233,7 +272,7 @@ public class FileDataStorageManager implements DataStorageManager { if (results[i].uri != null) { newId = Long.parseLong(results[i].uri.getPathSegments().get(1)); files.get(i).setFileId(newId); - //Log.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath()); + //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath()); } } } @@ -244,7 +283,7 @@ public class FileDataStorageManager implements DataStorageManager { } } - + public void setAccount(Account account) { mAccount = account; } @@ -269,9 +308,10 @@ public class FileDataStorageManager implements DataStorageManager { return mContentProvider; } + @Override public Vector getDirectoryContent(OCFile f) { + Vector ret = new Vector(); if (f != null && f.isDirectory() && f.getFileId() != -1) { - Vector ret = new Vector(); Uri req_uri = Uri.withAppendedPath( ProviderTableMeta.CONTENT_URI_DIR, @@ -284,7 +324,7 @@ public class FileDataStorageManager implements DataStorageManager { ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", new String[] { mAccount.name }, null); } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); + Log_OC.e(TAG, e.getMessage()); return ret; } } else { @@ -301,12 +341,11 @@ public class FileDataStorageManager implements DataStorageManager { } c.close(); - + Collections.sort(ret); - - return ret; + } - return null; + return ret; } private boolean fileExists(String cmp_key, String value) { @@ -318,7 +357,7 @@ public class FileDataStorageManager implements DataStorageManager { cmp_key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[] { value, mAccount.name }, null); } else { try { c = getContentProvider().query( @@ -326,9 +365,9 @@ public class FileDataStorageManager implements DataStorageManager { null, cmp_key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[] { value, mAccount.name }, null); } catch (RemoteException e) { - Log.e(TAG, + Log_OC.e(TAG, "Couldn't determine file existance, assuming non existance: " + e.getMessage()); return false; @@ -348,17 +387,17 @@ public class FileDataStorageManager implements DataStorageManager { key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[] { value, mAccount.name }, null); } else { try { c = getContentProvider().query( ProviderTableMeta.CONTENT_URI, null, key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER - + "=?", new String[] { value, mAccount.name }, + + "=?", new String[] { value, mAccount.name }, null); } catch (RemoteException e) { - Log.e(TAG, "Could not get file details: " + e.getMessage()); + Log_OC.e(TAG, "Could not get file details: " + e.getMessage()); c = null; } } @@ -379,10 +418,12 @@ public class FileDataStorageManager implements DataStorageManager { file.setStoragePath(c.getString(c .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH))); if (file.getStoragePath() == null) { - // try to find existing file and bind it with current account - File f = new File(FileDownloader.getSavePath(mAccount.name) + file.getRemotePath()); - if (f.exists()) + // 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 + File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); + if (f.exists()) { file.setStoragePath(f.getAbsolutePath()); + file.setLastSyncDateForData(f.lastModified()); + } } } file.setFileLength(c.getLong(c @@ -391,32 +432,257 @@ public class FileDataStorageManager implements DataStorageManager { .getColumnIndex(ProviderTableMeta.FILE_CREATION))); file.setModificationTimestamp(c.getLong(c .getColumnIndex(ProviderTableMeta.FILE_MODIFIED))); - file.setLastSyncDate(c.getLong(c + file.setModificationTimestampAtLastSyncForData(c.getLong(c + .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA))); + file.setLastSyncDateForProperties(c.getLong(c .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE))); + file.setLastSyncDateForData(c.getLong(c. + getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA))); file.setKeepInSync(c.getInt( - c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false); + c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false); } return file; } - + + @Override public void removeFile(OCFile file, boolean removeLocalCopy) { Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId()); if (getContentProvider() != null) { try { getContentProvider().delete(file_uri, - ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?", - new String[]{mAccount.name}); + ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?", + new String[]{mAccount.name}); } catch (RemoteException e) { e.printStackTrace(); } } else { getContentResolver().delete(file_uri, - ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?", - new String[]{mAccount.name}); + ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?", + new String[]{mAccount.name}); } if (file.isDown() && removeLocalCopy) { new File(file.getStoragePath()).delete(); } + if (file.isDirectory() && removeLocalCopy) { + File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); + if (f.exists() && f.isDirectory() && (f.list() == null || f.list().length == 0)) { + f.delete(); + } + } + + updateSubtreeSize(file.getParentId()); + } + + @Override + public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent) { + // TODO consider possible failures + if (dir != null && dir.isDirectory() && dir.getFileId() != -1) { + Vector children = getDirectoryContent(dir); + if (children.size() > 0) { + OCFile child = null; + for (int i=0; i operations = new ArrayList(c.getCount()); + int lengthOfOldPath = dir.getRemotePath().length(); + String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name); + int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath; + if (c.moveToFirst()) { + do { + ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object + OCFile child = createFileInstance(c); + cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath)); + if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) { + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath)); + } + operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). + withValues(cv). + withSelection( ProviderTableMeta._ID + "=?", + new String[] { String.valueOf(child.getFileId()) }) + .build()); + } while (c.moveToNext()); + } + c.close(); + + /// 3. apply updates in batch + try { + if (getContentResolver() != null) { + getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations); + + } else { + getContentProvider().applyBatch(operations); + } + + } catch (OperationApplicationException e) { + Log_OC.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e); + + } catch (RemoteException e) { + Log_OC.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", e); + } + + } + } + + @Override + public Vector getDirectoryImages(OCFile directory) { + Vector ret = new Vector(); + if (directory != null) { + // TODO better implementation, filtering in the access to database (if possible) instead of here + Vector tmp = getDirectoryContent(directory); + OCFile current = null; + for (int i=0; i getFilesbyParent(long parentId) { + + Vector ret = new Vector(); + + Uri req_uri = Uri.withAppendedPath( + ProviderTableMeta.CONTENT_URI_DIR, + String.valueOf(parentId)); + Cursor c = null; + + if (getContentProvider() != null) { + try { + c = getContentProvider().query(req_uri, null, + ProviderTableMeta.FILE_PARENT + "=?" , + new String[] { String.valueOf(parentId)}, null); + } catch (RemoteException e) { + Log_OC.e(TAG, e.getMessage()); + return ret; + } + } else { + c = getContentResolver().query(req_uri, null, + ProviderTableMeta.FILE_PARENT + "=?" , + new String[] { String.valueOf(parentId)}, null); + } + + if (c.moveToFirst()) { + do { + OCFile child = createFileInstance(c); + ret.add(child); + } while (c.moveToNext()); + } + + c.close(); + + Collections.sort(ret); + + return ret; + } + + /** + * Calculate and save the folderSize on DB + * @param id + */ + @Override + public void saveFolderSize(long id) { + long folderSize = 0; + + Vector files = getFilesbyParent(id); + + Log_OC.d(TAG, "Folder " + String.valueOf(id) + "--- Number of Files = " + String.valueOf(files.size())); + + for (OCFile f: files) + { + folderSize = folderSize + f.getFileLength(); + Log_OC.d(TAG, "Folder Size = " + String.valueOf(folderSize)); + } + + updatefolderSize(id, folderSize); + } + + /** + * Update the size value of a folder on DB + */ + @Override + public int updatefolderSize(long id, long size) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size); + int result = getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?", + new String[] { String.valueOf(id) }); + return result; } + /** + * Update the size of a subtree of folder from a file to the root + * @param parentId: parent of the file + */ + private void updateSubtreeSize(long parentId) { + + OCFile file; + + while (parentId != 0) { + + Log_OC.d(TAG, "parent = " + parentId); + // Update the size of the parent + saveFolderSize(parentId); + + // search the next parent + file = getFileById(parentId); + parentId = file.getParentId(); + + } + + } + }