<activity android:name=".ui.activity.PreferencesNewSessionewSession" >
</activity>
- <activity android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
+ <activity android:name=".ui.preview.PreviewImageActivity" />
- <activity android:name="com.owncloud.android.ui.preview.PreviewVideoActivity"
+ <activity android:name=".ui.preview.PreviewVideoActivity"
android:label="@string/app_name"
android:theme="@style/Theme.ownCloud.Fullscreen" >
</activity>
<service android:name=".media.MediaService" />
<activity android:name=".ui.activity.PinCodeActivity" />
- <activity android:name="com.owncloud.android.extensions.ExtensionsAvailableActivity"></activity>
- <activity android:name="com.owncloud.android.extensions.ExtensionsListActivity"></activity>
<activity android:name=".ui.activity.AccountSelectActivity" android:uiOptions="none" android:label="@string/prefs_accounts"></activity>
<activity android:name=".ui.activity.ConflictsResolveActivity"/>
<activity android:name=".ui.activity.GenericExplanationActivity"/>
import java.util.Stack;
import java.util.Vector;
- import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountAuthenticator;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileUploader;
+
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.widget.SimpleAdapter;
import android.widget.Toast;
-import com.owncloud.android.authentication.AccountAuthenticator;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileUploader;
-
-import com.owncloud.android.R;
-
/**
* This can be used to upload things to an ownCloud instance.
*
private ArrayList<Parcelable> mStreamsToUpload;
private boolean mCreateDir;
private String mUploadPath;
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
private OCFile mFile;
private final static int DIALOG_NO_ACCOUNT = 0;
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// click on folder in the list
Log_OC.d(TAG, "on item click");
- Vector<OCFile> tmpfiles = mStorageManager.getDirectoryContent(mFile);
+ Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile);
if (tmpfiles.size() <= 0) return;
// filter on dirtype
Vector<OCFile> files = new Vector<OCFile>();
for (OCFile f : tmpfiles)
- if (f.isDirectory())
+ if (f.isFolder())
files.add(f);
if (files.size() < position) {
throw new IndexOutOfBoundsException("Incorrect item selected");
mFile = mStorageManager.getFileByPath(full_path);
if (mFile != null) {
- Vector<OCFile> files = mStorageManager.getDirectoryContent(mFile);
+ Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
for (OCFile f : files) {
HashMap<String, Object> h = new HashMap<String, Object>();
- if (f.isDirectory()) {
+ if (f.isFolder()) {
h.put("dirname", f.getFileName());
data.add(h);
}
import java.io.File;
import java.util.ArrayList;
+ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
- import java.util.List;
import java.util.Vector;
import com.owncloud.android.Log_OC;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
import com.owncloud.android.utils.FileStorageUtils;
+
import android.accounts.Account;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
+ import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
- public class FileDataStorageManager implements DataStorageManager {
+ public class FileDataStorageManager {
+
+ public static final int ROOT_PARENT_ID = 0;
private ContentResolver mContentResolver;
- private ContentProviderClient mContentProvider;
+ private ContentProviderClient mContentProviderClient;
private Account mAccount;
- private static String TAG = "FileDataStorageManager";
+ private static String TAG = FileDataStorageManager.class.getSimpleName();
+
public FileDataStorageManager(Account account, ContentResolver cr) {
- mContentProvider = null;
+ mContentProviderClient = null;
mContentResolver = cr;
mAccount = account;
}
public FileDataStorageManager(Account account, ContentProviderClient cp) {
- mContentProvider = cp;
+ mContentProviderClient = cp;
mContentResolver = null;
mAccount = account;
}
- @Override
+
+ public void setAccount(Account account) {
+ mAccount = account;
+ }
+
+ public Account getAccount() {
+ return mAccount;
+ }
+
+ public void setContentResolver(ContentResolver cr) {
+ mContentResolver = cr;
+ }
+
+ public ContentResolver getContentResolver() {
+ return mContentResolver;
+ }
+
+ public void setContentProviderClient(ContentProviderClient cp) {
+ mContentProviderClient = cp;
+ }
+
+ public ContentProviderClient getContentProviderClient() {
+ return mContentProviderClient;
+ }
+
+
public OCFile getFileByPath(String path) {
Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
OCFile file = null;
file = createFileInstance(c);
}
c.close();
- if (file == null && OCFile.PATH_SEPARATOR.equals(path)) {
+ if (file == null && OCFile.ROOT_PATH.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;
- }
-
- @Override
public OCFile getFileById(long id) {
Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
OCFile file = null;
return file;
}
- @Override
public boolean fileExists(long id) {
return fileExists(ProviderTableMeta._ID, String.valueOf(id));
}
- @Override
public boolean fileExists(String path) {
return fileExists(ProviderTableMeta.FILE_PATH, path);
}
- @Override
+
+ public Vector<OCFile> getFolderContent(OCFile f) {
+ if (f != null && f.isFolder() && f.getFileId() != -1) {
+ return getFolderContent(f.getFileId());
+
+ } else {
+ return new Vector<OCFile>();
+ }
+ }
+
+
+ public Vector<OCFile> getFolderImages(OCFile folder) {
+ Vector<OCFile> ret = new Vector<OCFile>();
+ if (folder != null) {
+ // TODO better implementation, filtering in the access to database (if possible) instead of here
+ Vector<OCFile> tmp = getFolderContent(folder);
+ OCFile current = null;
+ for (int i=0; i<tmp.size(); i++) {
+ current = tmp.get(i);
+ if (current.isImage()) {
+ ret.add(current);
+ }
+ }
+ }
+ return ret;
+ }
+
+
public boolean saveFile(OCFile file) {
boolean overriden = false;
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
- if (file.getParentId() != 0)
+ //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
- if (!file.isDirectory())
+ if (!file.isFolder())
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
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);
+ cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
boolean sameRemotePath = fileExists(file.getRemotePath());
- boolean changesSizeOfAncestors = false;
if (sameRemotePath ||
fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
} else {
oldFile = getFileById(file.getFileId());
}
- changesSizeOfAncestors = (oldFile.getFileLength() != file.getFileLength());
overriden = true;
if (getContentResolver() != null) {
new String[] { String.valueOf(file.getFileId()) });
} else {
try {
- getContentProvider().update(ProviderTableMeta.CONTENT_URI,
+ getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
cv, ProviderTableMeta._ID + "=?",
new String[] { String.valueOf(file.getFileId()) });
} catch (RemoteException e) {
}
}
} else {
- changesSizeOfAncestors = true;
Uri result_uri = null;
if (getContentResolver() != null) {
result_uri = getContentResolver().insert(
ProviderTableMeta.CONTENT_URI_FILE, cv);
} else {
try {
- result_uri = getContentProvider().insert(
+ result_uri = getContentProviderClient().insert(
ProviderTableMeta.CONTENT_URI_FILE, cv);
} catch (RemoteException e) {
Log_OC.e(TAG,
}
}
- if (file.isDirectory()) {
- calculateFolderSize(file.getFileId());
- if (file.needsUpdatingWhileSaving()) {
- for (OCFile f : getDirectoryContent(file))
- saveFile(f);
- }
- }
-
- if (changesSizeOfAncestors || file.isDirectory()) {
- updateSizesToTheRoot(file.getParentId());
+ if (file.isFolder()) {
+ updateFolderSize(file.getFileId());
+ } else {
+ updateFolderSize(file.getParentId());
}
return overriden;
}
- @Override
- public void saveFiles(List<OCFile> files) {
+ /**
+ * Inserts or updates the list of files contained in a given folder.
+ *
+ * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
+ * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
+ *
+ * @param folder
+ * @param files
+ * @param removeNotUpdated
+ */
+ public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
+
+ Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
- Iterator<OCFile> filesIt = files.iterator();
- ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
- OCFile file = null;
+ ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
- // prepare operations to perform
- while (filesIt.hasNext()) {
- file = filesIt.next();
+ // prepare operations to insert or update files to save in the given folder
+ for (OCFile file : updatedFiles) {
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_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
- if (file.getParentId() != 0)
- cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
+ //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
+ cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
- if (!file.isDirectory())
+ if (!file.isFolder()) {
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+ }
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
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);
+ cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
- if (fileExists(file.getRemotePath())) {
- OCFile oldFile = getFileByPath(file.getRemotePath());
- file.setFileId(oldFile.getFileId());
-
- if (file.isDirectory()) {
- cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
- file.setFileLength(oldFile.getFileLength());
- }
-
- 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());
- else {
- cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
- file.setFileLength(oldFile.getFileLength());
- }
-
+ boolean existsByPath = fileExists(file.getRemotePath());
+ if (existsByPath || fileExists(file.getFileId())) {
+ // updating an existing file
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
withValues(cv).
withSelection( ProviderTableMeta._ID + "=?",
.build());
} else {
+ // adding a new file
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
}
}
+
+ // prepare operations to remove files in the given folder
+ String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+ String [] whereArgs = null;
+ for (OCFile file : filesToRemove) {
+ if (file.getParentId() == folder.getFileId()) {
+ whereArgs = new String[]{mAccount.name, file.getRemotePath()};
+ //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
+ if (file.isFolder()) {
+ operations.add(ContentProviderOperation
+ .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
+ .build());
+ // TODO remove local folder
+ } else {
+ operations.add(ContentProviderOperation
+ .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
+ .build());
+ if (file.isDown()) {
+ new File(file.getStoragePath()).delete();
+ // TODO move the deletion of local contents after success of deletions
+ }
+ }
+ }
+ }
+
+ // update metadata of folder
+ ContentValues cv = new ContentValues();
+ cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
+ cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
+ cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
+ cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0); // FileContentProvider calculates the right size
+ cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
+ cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
+ cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
+ cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
+ cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
+ cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
+ cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
+ cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
+ cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
+ operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+ withValues(cv).
+ withSelection( ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(folder.getFileId()) })
+ .build());
// apply operations in batch
ContentProviderResult[] results = null;
+ Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
try {
if (getContentResolver() != null) {
results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
} else {
- results = getContentProvider().applyBatch(operations);
+ results = getContentProviderClient().applyBatch(operations);
}
} catch (OperationApplicationException e) {
- Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
+ Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
} catch (RemoteException e) {
- Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
+ Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
}
// update new id in file objects for insertions
if (results != null) {
long newId;
+ Iterator<OCFile> filesIt = updatedFiles.iterator();
+ OCFile file = null;
for (int i=0; i<results.length; i++) {
+ if (filesIt.hasNext()) {
+ file = filesIt.next();
+ } else {
+ file = null;
+ }
if (results[i].uri != null) {
newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
- files.get(i).setFileId(newId);
- //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
+ //updatedFiles.get(i).setFileId(newId);
+ if (file != null) {
+ file.setFileId(newId);
+ }
}
}
}
+
+ updateFolderSize(folder.getFileId());
+
+ }
- for (OCFile aFile : files) {
- if (aFile.isDirectory() && aFile.needsUpdatingWhileSaving())
- saveFiles(getDirectoryContent(aFile));
- }
+ /**
+ *
+ * @param id
+ */
+ private void updateFolderSize(long id) {
+ if (id > FileDataStorageManager.ROOT_PARENT_ID) {
+ Log_OC.d(TAG, "Updating size of " + id);
+ if (getContentResolver() != null) {
+ getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, null,
+ ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(id) });
+ } else {
+ try {
+ getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, null,
+ ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(id) });
+
+ } catch (RemoteException e) {
+ Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
+ }
+ }
+ } else {
+ Log_OC.e(TAG, "not updating size for folder " + id);
+ }
}
+
- public void setAccount(Account account) {
- mAccount = account;
+ public void removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
+ if (file != null) {
+ if (file.isFolder()) {
+ removeFolder(file, removeDBData, removeLocalCopy);
+
+ } else {
+ if (removeDBData) {
+ //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
+ Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
+ String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+ String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
+ if (getContentProviderClient() != null) {
+ try {
+ getContentProviderClient().delete(file_uri, where, whereArgs);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ } else {
+ getContentResolver().delete(file_uri, where, whereArgs);
+ }
+ updateFolderSize(file.getParentId());
+ }
+ if (removeLocalCopy && file.isDown()) {
+ boolean success = new File(file.getStoragePath()).delete();
+ if (!removeDBData && success) {
+ // maybe unnecessary, but should be checked TODO remove if unnecessary
+ file.setStoragePath(null);
+ saveFile(file);
+ }
+ }
+ }
+ }
}
+
- public Account getAccount() {
- return mAccount;
+ public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
+ if (folder != null && folder.isFolder()) {
+ if (removeDBData && folder.getFileId() != -1) {
+ removeFolderInDb(folder);
+ }
+ if (removeLocalContent) {
+ File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
+ removeLocalFolder(localFolder);
+ }
+ }
}
- public void setContentResolver(ContentResolver cr) {
- mContentResolver = cr;
+ private void removeFolderInDb(OCFile folder) {
+ Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId()); // URI for recursive deletion
+ String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+ String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
+ if (getContentProviderClient() != null) {
+ try {
+ getContentProviderClient().delete(folder_uri, where, whereArgs);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ } else {
+ getContentResolver().delete(folder_uri, where, whereArgs);
+ }
+ updateFolderSize(folder.getParentId());
}
- public ContentResolver getContentResolver() {
- return mContentResolver;
+ private void removeLocalFolder(File folder) {
+ if (folder.exists()) {
+ File[] files = folder.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ removeLocalFolder(file);
+ } else {
+ file.delete();
+ }
+ }
+ }
+ folder.delete();
+ }
}
- public void setContentProvider(ContentProviderClient cp) {
- mContentProvider = cp;
- }
+ /**
+ * Updates database for a folder that was moved to a different location.
+ *
+ * TODO explore better (faster) implementations
+ * TODO throw exceptions up !
+ */
+ public void moveFolder(OCFile folder, String newPath) {
+ // TODO check newPath
- public ContentProviderClient getContentProvider() {
- return mContentProvider;
- }
-
- @Override
- public Vector<OCFile> getDirectoryContent(OCFile f) {
- if (f != null && f.isDirectory() && f.getFileId() != -1) {
- return getDirectoryContent(f.getFileId());
+ if (folder != null && folder.isFolder() && folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())) {
+ /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
+ Cursor c = null;
+ if (getContentProviderClient() != null) {
+ try {
+ c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI,
+ null,
+ ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
+ new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
+ } catch (RemoteException e) {
+ Log_OC.e(TAG, e.getMessage());
+ }
+ } else {
+ c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
+ null,
+ ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
+ new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
+ }
+
+ /// 2. prepare a batch of update operations to change all the descendants
+ ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
+ int lengthOfOldPath = folder.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(MainApp.getAuthority(), operations);
+
+ } else {
+ getContentProviderClient().applyBatch(operations);
+ }
+
+ } catch (OperationApplicationException e) {
+ Log_OC.e(TAG, "Fail to update descendants of " + folder.getFileId() + " in database", e);
+
+ } catch (RemoteException e) {
+ Log_OC.e(TAG, "Fail to update desendants of " + folder.getFileId() + " in database", e);
+ }
- } else {
- return new Vector<OCFile>();
}
}
- private Vector<OCFile> getDirectoryContent(long parentId) {
+
+ private Vector<OCFile> getFolderContent(long parentId) {
Vector<OCFile> ret = new Vector<OCFile>();
String.valueOf(parentId));
Cursor c = null;
- if (getContentProvider() != null) {
+ if (getContentProviderClient() != null) {
try {
- c = getContentProvider().query(req_uri, null,
+ c = getContentProviderClient().query(req_uri, null,
ProviderTableMeta.FILE_PARENT + "=?" ,
new String[] { String.valueOf(parentId)}, null);
} catch (RemoteException e) {
}
+ private OCFile createRootDir() {
+ OCFile file = new OCFile(OCFile.ROOT_PATH);
+ file.setMimetype("DIR");
+ file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
+ saveFile(file);
+ return file;
+ }
private boolean fileExists(String cmp_key, String value) {
Cursor c;
new String[] { value, mAccount.name }, null);
} else {
try {
- c = getContentProvider().query(
+ c = getContentProviderClient().query(
ProviderTableMeta.CONTENT_URI,
null,
cmp_key + "=? AND "
new String[] { value, mAccount.name }, null);
} else {
try {
- c = getContentProvider().query(
+ c = getContentProviderClient().query(
ProviderTableMeta.CONTENT_URI,
null,
key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
.getColumnIndex(ProviderTableMeta.FILE_PARENT)));
file.setMimetype(c.getString(c
.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
- if (!file.isDirectory()) {
+ if (!file.isFolder()) {
file.setStoragePath(c.getString(c
.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
if (file.getStoragePath() == null) {
getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
file.setKeepInSync(c.getInt(
c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
+ file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
+
}
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});
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- } else {
- getContentResolver().delete(file_uri,
- 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();
- }
- }
-
- if (file.getFileLength() > 0) {
- updateSizesToTheRoot(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<OCFile> children = getDirectoryContent(dir);
- if (children.size() > 0) {
- OCFile child = null;
- for (int i=0; i<children.size(); i++) {
- child = children.get(i);
- if (child.isDirectory()) {
- removeDirectory(child, removeDBData, removeLocalContent);
- } else {
- if (removeDBData) {
- removeFile(child, removeLocalContent);
- } else if (removeLocalContent) {
- if (child.isDown()) {
- new File(child.getStoragePath()).delete();
- }
- }
- }
- }
- }
- if (removeDBData) {
- removeFile(dir, true);
- }
-
- if (dir.getFileLength() > 0) {
- updateSizesToTheRoot(dir.getParentId());
- }
- }
- }
-
-
- /**
- * Updates database for a folder that was moved to a different location.
- *
- * TODO explore better (faster) implementations
- * TODO throw exceptions up !
- */
- @Override
- public void moveDirectory(OCFile dir, String newPath) {
- // TODO check newPath
-
- if (dir != null && dir.isDirectory() && dir.fileExists() && !dir.getFileName().equals(OCFile.PATH_SEPARATOR)) {
- /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
- Cursor c = null;
- if (getContentProvider() != null) {
- try {
- c = getContentProvider().query(ProviderTableMeta.CONTENT_URI,
- null,
- ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
- new String[] { mAccount.name, dir.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
- } catch (RemoteException e) {
- Log_OC.e(TAG, e.getMessage());
- }
- } else {
- c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
- null,
- ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
- new String[] { mAccount.name, dir.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
- }
-
- /// 2. prepare a batch of update operations to change all the descendants
- ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(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(MainApp.getAuthority(), 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<OCFile> getDirectoryImages(OCFile directory) {
- Vector<OCFile> ret = new Vector<OCFile>();
- if (directory != null) {
- // TODO better implementation, filtering in the access to database (if possible) instead of here
- Vector<OCFile> tmp = getDirectoryContent(directory);
- OCFile current = null;
- for (int i=0; i<tmp.size(); i++) {
- current = tmp.get(i);
- if (current.isImage()) {
- ret.add(current);
- }
- }
- }
- return ret;
- }
-
- /**
- * Calculate and save the folderSize on DB
- * @param id
- */
- @Override
- public void calculateFolderSize(long id) {
- long folderSize = 0;
-
- Vector<OCFile> files = getDirectoryContent(id);
-
- for (OCFile f: files)
- {
- folderSize = folderSize + f.getFileLength();
- }
-
- updateSize(id, folderSize);
- }
-
- /**
- * Update the size value of an OCFile in DB
- */
- private int updateSize(long id, long size) {
- ContentValues cv = new ContentValues();
- cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size);
- int result = -1;
- if (getContentResolver() != null) {
- result = getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
- new String[] { String.valueOf(id) });
- } else {
- try {
- result = getContentProvider().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
- new String[] { String.valueOf(id) });
- } catch (RemoteException e) {
- Log_OC.e(TAG,"Fail to update size column into database " + e.getMessage());
- }
- }
- return result;
- }
-
- /**
- * Update the size of a subtree of folder from a file to the root
- * @param parentId: parent of the file
- */
- private void updateSizesToTheRoot(long parentId) {
-
- OCFile file;
-
- while (parentId != 0) {
-
- // Update the size of the parent
- calculateFolderSize(parentId);
-
- // search the next parent
- file = getFileById(parentId);
- parentId = file.getParentId();
-
- }
-
- }
-
}
import com.owncloud.android.Log_OC;
+
import android.os.Parcel;
import android.os.Parcelable;
import android.webkit.MimeTypeMap;
};
public static final String PATH_SEPARATOR = "/";
+ public static final String ROOT_PATH = PATH_SEPARATOR;
private static final String TAG = OCFile.class.getSimpleName();
private String mEtag;
+
/**
* Create new {@link OCFile} with given path.
*
mKeepInSync = source.readInt() == 1;
mLastSyncDateForProperties = source.readLong();
mLastSyncDateForData = source.readLong();
+ mEtag = source.readString();
}
@Override
dest.writeInt(mKeepInSync ? 1 : 0);
dest.writeLong(mLastSyncDateForProperties);
dest.writeLong(mLastSyncDateForData);
+ dest.writeString(mEtag);
}
/**
}
/**
- * Use this to find out if this file is a Directory
+ * Use this to find out if this file is a folder.
*
- * @return true if it is a directory
+ * @return true if it is a folder
*/
- public boolean isDirectory() {
+ public boolean isFolder() {
return mMimeType != null && mMimeType.equals("DIR");
}
*/
public String getFileName() {
File f = new File(getRemotePath());
- return f.getName().length() == 0 ? PATH_SEPARATOR : f.getName();
+ return f.getName().length() == 0 ? ROOT_PATH : f.getName();
}
/**
*/
public void setFileName(String name) {
Log_OC.d(TAG, "OCFile name changin from " + mRemotePath);
- if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(PATH_SEPARATOR)) {
+ if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(ROOT_PATH)) {
String parent = (new File(getRemotePath())).getParent();
parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR;
mRemotePath = parent + name;
- if (isDirectory()) {
+ if (isFolder()) {
mRemotePath += PATH_SEPARATOR;
}
Log_OC.d(TAG, "OCFile name changed to " + mRemotePath);
* not a directory
*/
public void addFile(OCFile file) throws IllegalStateException {
- if (isDirectory()) {
+ if (isFolder()) {
file.mParentId = mId;
mNeedsUpdating = true;
return;
mLastSyncDateForData = 0;
mKeepInSync = false;
mNeedsUpdating = false;
+ mEtag = null;
}
/**
@Override
public int compareTo(OCFile another) {
- if (isDirectory() && another.isDirectory()) {
+ if (isFolder() && another.isFolder()) {
return getRemotePath().toLowerCase().compareTo(another.getRemotePath().toLowerCase());
- } else if (isDirectory()) {
+ } else if (isFolder()) {
return -1;
- } else if (another.isDirectory()) {
+ } else if (another.isFolder()) {
return 1;
}
return getRemotePath().toLowerCase().compareTo(another.getRemotePath().toLowerCase());
@Override
public String toString() {
- String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, keepInSinc=%s]";
- asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mKeepInSync));
+ String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, keepInSinc=%s etag=%s]";
+ asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mKeepInSync), mEtag);
return asString;
}
return mEtag;
}
+ public void setEtag(String etag) {
+ this.mEtag = etag;
+ }
+
public long getLocalModificationTimestamp() {
if (mLocalPath != null && mLocalPath.length() > 0) {
File f = new File(mLocalPath);
import com.owncloud.android.ui.activity.ConflictsResolveActivity;
+
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
storageManager,
mOCAccount,
true,
- true,
mContext);
RemoteOperationResult result = sfo.execute(mOCAccount, mContext);
if (result.getCode() == ResultCode.SYNC_CONFLICT) {
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.DownloadFileOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
+import eu.alefzero.webdav.OnDatatransferProgressListener;
+
+
import android.accounts.Account;
import android.accounts.AccountsException;
import android.app.Notification;
import android.os.Process;
import android.widget.RemoteViews;
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.MainApp;
-import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
public class FileDownloader extends Service implements OnDatatransferProgressListener {
if (account == null || file == null) return false;
String targetKey = buildRemoteName(account, file);
synchronized (mPendingDownloads) {
- if (file.isDirectory()) {
+ if (file.isFolder()) {
// this can be slow if there are many downloads :(
Iterator<String> it = mPendingDownloads.keySet().iterator();
boolean found = false;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.db.DbHandler;
+import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.ChunkedUploadFileOperation;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.ExistenceCheckOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.ui.activity.FailedUploadActivity;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.activity.InstantUploadActivity;
+import com.owncloud.android.ui.preview.PreviewImageActivity;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.utils.OwnCloudVersion;
+
import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavEntry;
import eu.alefzero.webdav.WebdavUtils;
-import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.webkit.MimeTypeMap;
import android.widget.RemoteViews;
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.MainApp;
-import com.owncloud.android.R;
-import com.owncloud.android.db.DbHandler;
-import com.owncloud.android.ui.activity.FailedUploadActivity;
-import com.owncloud.android.ui.activity.FileActivity;
-import com.owncloud.android.ui.activity.FileDisplayActivity;
-import com.owncloud.android.ui.activity.InstantUploadActivity;
-import com.owncloud.android.ui.preview.PreviewImageActivity;
-import com.owncloud.android.ui.preview.PreviewImageFragment;
import eu.alefzero.webdav.WebdavClient;
return false;
String targetKey = buildRemoteName(account, file);
synchronized (mPendingUploads) {
- if (file.isDirectory()) {
+ if (file.isFolder()) {
// this can be slow if there are many uploads :(
Iterator<String> it = mPendingUploads.keySet().iterator();
boolean found = false;
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
import com.owncloud.android.Log_OC;
- import com.owncloud.android.datamodel.DataStorageManager;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
+
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
protected String mRemotePath;
protected boolean mCreateFullPath;
- protected DataStorageManager mStorageManager;
+ protected FileDataStorageManager mStorageManager;
/**
* Constructor
* @param createFullPath 'True' means that all the ancestor folders should be created if don't exist yet.
* @param storageManager Reference to the local database corresponding to the account where the file is contained.
*/
- public CreateFolderOperation(String remotePath, boolean createFullPath, DataStorageManager storageManager) {
+ public CreateFolderOperation(String remotePath, boolean createFullPath, FileDataStorageManager storageManager) {
mRemotePath = remotePath;
mCreateFullPath = createFullPath;
mStorageManager = storageManager;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountsException;
mCallerActivity = callerActivity;
mClient = null; // the client instance will be created from mAccount and mContext in the runnerThread to create below
- if (listener == null) {
- throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
- }
mListener = listener;
- if (listenerHandler == null) {
- throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
- }
mListenerHandler = listenerHandler;
Thread runnerThread = new Thread(this);
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
import com.owncloud.android.Log_OC;
- import com.owncloud.android.datamodel.DataStorageManager;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
+
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
OCFile mFileToRemove;
boolean mDeleteLocalCopy;
- DataStorageManager mDataStorageManager;
+ FileDataStorageManager mDataStorageManager;
/**
* @param deleteLocalCopy When 'true', and a local copy of the file exists, it is also removed.
* @param storageManager Reference to the local database corresponding to the account where the file is contained.
*/
- public RemoveFileOperation(OCFile fileToRemove, boolean deleteLocalCopy, DataStorageManager storageManager) {
+ public RemoveFileOperation(OCFile fileToRemove, boolean deleteLocalCopy, FileDataStorageManager storageManager) {
mFileToRemove = fileToRemove;
mDeleteLocalCopy = deleteLocalCopy;
mDataStorageManager = storageManager;
delete = new DeleteMethod(client.getBaseUri() + WebdavUtils.encodePath(mFileToRemove.getRemotePath()));
int status = client.executeMethod(delete, REMOVE_READ_TIMEOUT, REMOVE_CONNECTION_TIMEOUT);
if (delete.succeeded() || status == HttpStatus.SC_NOT_FOUND) {
- if (mFileToRemove.isDirectory()) {
- mDataStorageManager.removeDirectory(mFileToRemove, true, mDeleteLocalCopy);
- } else {
- mDataStorageManager.removeFile(mFileToRemove, mDeleteLocalCopy);
- }
+ mDataStorageManager.removeFile(mFileToRemove, true, mDeleteLocalCopy);
}
delete.getResponseBodyAsString(); // exhaust the response, although not interesting
result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders());
import java.io.IOException;
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
-//import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
-
-import android.accounts.Account;
import com.owncloud.android.Log_OC;
- import com.owncloud.android.datamodel.DataStorageManager;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.utils.FileStorageUtils;
+//import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
+
+import android.accounts.Account;
+
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
private Account mAccount;
private String mNewName;
private String mNewRemotePath;
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
/**
* @param newName New name to set as the name of file.
* @param storageManager Reference to the local database corresponding to the account where the file is contained.
*/
- public RenameFileOperation(OCFile file, Account account, String newName, DataStorageManager storageManager) {
+ public RenameFileOperation(OCFile file, Account account, String newName, FileDataStorageManager storageManager) {
mFile = file;
mAccount = account;
mNewName = newName;
String parent = (new File(mFile.getRemotePath())).getParent();
parent = (parent.endsWith(OCFile.PATH_SEPARATOR)) ? parent : parent + OCFile.PATH_SEPARATOR;
mNewRemotePath = parent + mNewName;
- if (mFile.isDirectory()) {
+ if (mFile.isFolder()) {
mNewRemotePath += OCFile.PATH_SEPARATOR;
}
int status = client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
if (move.succeeded()) {
- if (mFile.isDirectory()) {
+ if (mFile.isFolder()) {
saveLocalDirectory();
} else {
private void saveLocalDirectory() {
- mStorageManager.moveDirectory(mFile, mNewRemotePath);
+ mStorageManager.moveFolder(mFile, mNewRemotePath);
String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);
File localDir = new File(localPath);
if (localDir.exists()) {
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
-import android.accounts.Account;
-import android.content.Context;
-import android.content.Intent;
-
import com.owncloud.android.Log_OC;
- import com.owncloud.android.datamodel.DataStorageManager;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import android.accounts.Account;
+import android.content.Context;
+import android.content.Intent;
+
+
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavEntry;
import eu.alefzero.webdav.WebdavUtils;
private OCFile mLocalFile;
private OCFile mServerFile;
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
private Account mAccount;
private boolean mSyncFileContents;
- private boolean mLocalChangeAlreadyKnown;
private Context mContext;
private boolean mTransferWasRequested = false;
public SynchronizeFileOperation(
OCFile localFile,
OCFile serverFile, // make this null to let the operation checks the server; added to reuse info from SynchronizeFolderOperation
- DataStorageManager storageManager,
+ FileDataStorageManager storageManager,
Account account,
boolean syncFileContents,
- boolean localChangeAlreadyKnown,
Context context) {
mLocalFile = localFile;
mStorageManager = storageManager;
mAccount = account;
mSyncFileContents = syncFileContents;
- mLocalChangeAlreadyKnown = localChangeAlreadyKnown;
mContext = context;
}
/// check changes in server and local file
boolean serverChanged = false;
+ /* time for eTag is coming, but not yet
if (mServerFile.getEtag() != null) {
serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag())); // TODO could this be dangerous when the user upgrades the server from non-tagged to tagged?
- } else {
+ } else { */
// server without etags
serverChanged = (mServerFile.getModificationTimestamp() > mLocalFile.getModificationTimestampAtLastSyncForData());
- }
- boolean localChanged = (mLocalChangeAlreadyKnown || mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData());
+ //}
+ boolean localChanged = (mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData());
// TODO this will be always true after the app is upgraded to database version 2; will result in unnecessary uploads
/// decide action to perform depending upon changes
+ //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) {
if (localChanged && serverChanged) {
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
file.setFileLength(we.contentLength());
file.setMimetype(we.contentType());
file.setModificationTimestamp(we.modifiedTimestamp());
+ file.setEtag(we.etag());
+
return file;
}
package com.owncloud.android.providers;
+ import java.util.ArrayList;
import java.util.HashMap;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+
import android.content.ContentProvider;
+ import android.content.ContentProviderOperation;
+ import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+ import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
* The ContentProvider for the ownCloud App.
*
* @author Bartek Przybylski
+ * @author David A. Velasco
*
*/
public class FileContentProvider extends ContentProvider {
ProviderTableMeta.FILE_KEEP_IN_SYNC);
mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
ProviderTableMeta.FILE_ACCOUNT_OWNER);
+ mProjectionMap.put(ProviderTableMeta.FILE_ETAG,
+ ProviderTableMeta.FILE_ETAG);
}
private static final int SINGLE_FILE = 1;
private static final int DIRECTORY = 2;
private static final int ROOT_DIRECTORY = 3;
-
- private UriMatcher mUriMatcher;
- // static {
- // mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, null, ROOT_DIRECTORY);
- // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/", SINGLE_FILE);
- // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/#", SINGLE_FILE);
- // mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
- // }
+ private UriMatcher mUriMatcher;
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
+ //Log_OC.d(TAG, "Deleting " + uri + " at provider " + this);
+ int count = 0;
SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ count = delete(db, uri, where, whereArgs);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+
+ private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
int count = 0;
switch (mUriMatcher.match(uri)) {
case SINGLE_FILE:
+ /*Cursor c = query(db, uri, null, where, whereArgs, null);
+ String remotePath = "(unexisting)";
+ if (c != null && c.moveToFirst()) {
+ remotePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH));
+ }
+ Log_OC.d(TAG, "Removing FILE " + remotePath);
+ */
count = db.delete(ProviderTableMeta.DB_NAME,
ProviderTableMeta._ID
+ "="
+ uri.getPathSegments().get(1)
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ")" : ""), whereArgs);
+ /* just for log
+ if (c!=null) {
+ c.close();
+ }
+ */
+ break;
+ case DIRECTORY:
+ // deletion of folder is recursive
+ /*
+ Uri folderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, Long.parseLong(uri.getPathSegments().get(1)));
+ Cursor folder = query(db, folderUri, null, null, null, null);
+ String folderName = "(unknown)";
+ if (folder != null && folder.moveToFirst()) {
+ folderName = folder.getString(folder.getColumnIndex(ProviderTableMeta.FILE_PATH));
+ }
+ */
+ Cursor children = query(uri, null, null, null, null);
+ if (children != null && children.moveToFirst()) {
+ long childId;
+ boolean isDir;
+ //String remotePath;
+ while (!children.isAfterLast()) {
+ childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID));
+ isDir = "DIR".equals(children.getString(children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
+ //remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH));
+ if (isDir) {
+ count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), null, null);
+ } else {
+ count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), null, null);
+ }
+ children.moveToNext();
+ }
+ children.close();
+ } /*else {
+ Log_OC.d(TAG, "No child to remove in DIRECTORY " + folderName);
+ }
+ Log_OC.d(TAG, "Removing DIRECTORY " + folderName + " (or maybe not) ");
+ */
+ count += db.delete(ProviderTableMeta.DB_NAME,
+ ProviderTableMeta._ID
+ + "="
+ + uri.getPathSegments().get(1)
+ + (!TextUtils.isEmpty(where) ? " AND (" + where
+ + ")" : ""), whereArgs);
+ /* Just for log
+ if (folder != null) {
+ folder.close();
+ }*/
break;
case ROOT_DIRECTORY:
+ //Log_OC.d(TAG, "Removing ROOT!");
count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
break;
default:
+ //Log_OC.e(TAG, "Unknown uri " + uri);
throw new IllegalArgumentException("Unknown uri: " + uri.toString());
}
- getContext().getContentResolver().notifyChange(uri, null);
return count;
}
+
@Override
public String getType(Uri uri) {
@Override
public Uri insert(Uri uri, ContentValues values) {
+ //Log_OC.d(TAG, "Inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
+ Uri newUri = null;
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ newUri = insert(db, uri, values);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ getContext().getContentResolver().notifyChange(newUri, null);
+ return newUri;
+ }
+
+ private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) {
if (mUriMatcher.match(uri) != SINGLE_FILE &&
- mUriMatcher.match(uri) != ROOT_DIRECTORY) {
-
+ mUriMatcher.match(uri) != ROOT_DIRECTORY) {
+ //Log_OC.e(TAG, "Inserting invalid URI: " + uri);
throw new IllegalArgumentException("Unknown uri id: " + uri);
}
- SQLiteDatabase db = mDbHelper.getWritableDatabase();
- long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
- if (rowId > 0) {
- Uri insertedFileUri = ContentUris.withAppendedId(
- ProviderTableMeta.CONTENT_URI_FILE, rowId);
- getContext().getContentResolver().notifyChange(insertedFileUri,
- null);
+ String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH);
+ String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER);
+ String[] projection = new String[] {ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, ProviderTableMeta.FILE_ACCOUNT_OWNER };
+ String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
+ String[] whereArgs = new String[] {remotePath, accountName};
+ Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null);
+ if (doubleCheck == null || !doubleCheck.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
+ long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
+ if (rowId > 0) {
+ Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
+ //Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
+ return insertedFileUri;
+ } else {
+ //Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
+ throw new SQLException("ERROR " + uri);
+ }
+ } else {
+ // file is already inserted; race condition, let's avoid a duplicated entry
+ Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)));
+ doubleCheck.close();
return insertedFileUri;
}
- throw new SQLException("ERROR " + uri);
}
+
@Override
public boolean onCreate() {
mDbHelper = new DataBaseHelper(getContext());
mUriMatcher.addURI(authority, null, ROOT_DIRECTORY);
mUriMatcher.addURI(authority, "file/", SINGLE_FILE);
mUriMatcher.addURI(authority, "file/#", SINGLE_FILE);
+ mUriMatcher.addURI(authority, "dir/", DIRECTORY);
mUriMatcher.addURI(authority, "dir/#", DIRECTORY);
return true;
}
+
@Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+ Cursor result = null;
+ SQLiteDatabase db = mDbHelper.getReadableDatabase();
+ db.beginTransaction();
+ try {
+ result = query(db, uri, projection, selection, selectionArgs, sortOrder);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ return result;
+ }
+
+ private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
sqlQuery.setTables(ProviderTableMeta.DB_NAME);
case ROOT_DIRECTORY:
break;
case DIRECTORY:
+ String folderId = uri.getPathSegments().get(1);
sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "="
- + uri.getPathSegments().get(1));
+ + folderId);
break;
case SINGLE_FILE:
if (uri.getPathSegments().size() > 1) {
order = sortOrder;
}
- SQLiteDatabase db = mDbHelper.getReadableDatabase();
// DB case_sensitive
db.execSQL("PRAGMA case_sensitive_like = true");
- Cursor c = sqlQuery.query(db, projection, selection, selectionArgs,
- null, null, order);
-
+ Cursor c = sqlQuery.query(db, projection, selection, selectionArgs, null, null, order);
c.setNotificationUri(getContext().getContentResolver(), uri);
-
return c;
}
@Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- return mDbHelper.getWritableDatabase().update(
- ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+
+ //Log_OC.d(TAG, "Updating " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
+ int count = 0;
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ count = update(db, uri, values, selection, selectionArgs);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+
+ private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ switch (mUriMatcher.match(uri)) {
+ case DIRECTORY:
+ return updateFolderSize(db, selectionArgs[0]);
+ default:
+ return db.update(ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
+ }
+ }
+
+
+ private int updateFolderSize(SQLiteDatabase db, String folderId) {
+ int count = 0;
+ String [] whereArgs = new String[] { folderId };
+
+ // read current size saved for the folder
+ long folderSize = 0;
+ long folderParentId = -1;
+ Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId);
+ String[] folderProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH, ProviderTableMeta.FILE_PARENT};
+ String folderWhere = ProviderTableMeta._ID + "=?";
+ Cursor folderCursor = query(db, selectFolderUri, folderProjection, folderWhere, whereArgs, null);
+ if (folderCursor != null && folderCursor.moveToFirst()) {
+ folderSize = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));;
+ folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));;
+ }
+ folderCursor.close();
+
+ // read and sum sizes of children
+ long childrenSize = 0;
+ Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId);
+ String[] childrenProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH, ProviderTableMeta.FILE_PARENT};
+ String childrenWhere = ProviderTableMeta.FILE_PARENT + "=?";
+ Cursor childrenCursor = query(db, selectChildrenUri, childrenProjection, childrenWhere, whereArgs, null);
+ if (childrenCursor != null && childrenCursor.moveToFirst()) {
+ while (!childrenCursor.isAfterLast()) {
+ childrenSize += childrenCursor.getLong(childrenCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));
+ childrenCursor.moveToNext();
+ }
+ }
+ childrenCursor.close();
+
+ // update if needed
+ if (folderSize != childrenSize) {
+ Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize);
+ ContentValues cv = new ContentValues();
+ cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize);
+ count = db.update(ProviderTableMeta.DB_NAME, cv, folderWhere, whereArgs);
+
+ // propagate update until root
+ if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) {
+ Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId);
+ updateFolderSize(db, String.valueOf(folderParentId));
+ } else {
+ Log_OC.d("FileContentProvider", "NOT propagating to " + folderParentId);
+ }
+ } else {
+ Log_OC.d("FileContentProvider", "NOT updating, sizes are " + folderSize + " and " + childrenSize);
+ }
+ return count;
+ }
+
+
+ @Override
+ public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
+ Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" );
+ ContentProviderResult[] results = new ContentProviderResult[operations.size()];
+ int i=0;
+
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ db.beginTransaction(); // it's supposed that transactions can be nested
+ try {
+ for (ContentProviderOperation operation : operations) {
+ results[i] = operation.apply(this, results, i);
+ i++;
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ Log_OC.d("FileContentProvider", "applied batch in provider " + this);
+ return results;
}
+
class DataBaseHelper extends SQLiteOpenHelper {
public DataBaseHelper(Context context) {
+ ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
+ ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
+ ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
- + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER );"
+ + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, "
+ + ProviderTableMeta.FILE_ETAG + " TEXT );"
);
}
}
if (!upgraded)
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
+
+ if (oldVersion < 5 && newVersion >= 5) {
+ Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade");
+ db.beginTransaction();
+ try {
+ db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+ " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " +
+ " DEFAULT NULL");
+
+ upgraded = true;
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+ if (!upgraded)
+ Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
}
-
}
}
package com.owncloud.android.syncadapter;\r
\r
import java.io.IOException;\r
- import java.util.Date;\r
\r
import org.apache.http.HttpRequest;\r
import org.apache.http.HttpResponse;\r
import org.apache.http.client.ClientProtocolException;\r
- import org.apache.http.conn.ConnectionKeepAliveStrategy;\r
- import org.apache.http.protocol.HttpContext;\r
\r
import com.owncloud.android.authentication.AccountUtils;\r
import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;\r
- import com.owncloud.android.datamodel.DataStorageManager;\r
+ import com.owncloud.android.datamodel.FileDataStorageManager;\r
import com.owncloud.android.network.OwnCloudClientUtils;\r
\r
+\r
import android.accounts.Account;\r
import android.accounts.AccountManager;\r
import android.accounts.AuthenticatorException;\r
import eu.alefzero.webdav.WebdavClient;\r
\r
/**\r
- * Base SyncAdapter for OwnCloud Designed to be subclassed for the concrete\r
- * SyncAdapter, like ConcatsSync, CalendarSync, FileSync etc..\r
+ * Base synchronization adapter for ownCloud designed to be subclassed for different\r
+ * resource types, like FileSync, ConcatsSync, CalendarSync, etc..\r
* \r
- * @author sassman\r
+ * Implements the standard {@link AbstractThreadedSyncAdapter}.\r
* \r
+ * @author sassman\r
+ * @author David A. Velasco\r
*/\r
public abstract class AbstractOwnCloudSyncAdapter extends\r
AbstractThreadedSyncAdapter {\r
private AccountManager accountManager;\r
private Account account;\r
private ContentProviderClient contentProvider;\r
- private Date lastUpdated;\r
- private DataStorageManager mStoreManager;\r
+ private FileDataStorageManager mStoreManager;\r
\r
private WebdavClient mClient = null;\r
\r
this.contentProvider = contentProvider;\r
}\r
\r
- public Date getLastUpdated() {\r
- return lastUpdated;\r
- }\r
- \r
- public void setLastUpdated(Date lastUpdated) {\r
- this.lastUpdated = lastUpdated;\r
- }\r
- \r
- public void setStorageManager(DataStorageManager storage_manager) {\r
+ public void setStorageManager(FileDataStorageManager storage_manager) {\r
mStoreManager = storage_manager;\r
}\r
\r
- public DataStorageManager getStorageManager() {\r
+ public FileDataStorageManager getStorageManager() {\r
return mStoreManager;\r
}\r
\r
- protected ConnectionKeepAliveStrategy getKeepAliveStrategy() {\r
- return new ConnectionKeepAliveStrategy() {\r
- public long getKeepAliveDuration(HttpResponse response,\r
- HttpContext context) {\r
- // Change keep alive straategy basing on response: ie\r
- // forbidden/not found/etc\r
- // should have keep alive 0\r
- // default return: 5s\r
- int statusCode = response.getStatusLine().getStatusCode();\r
- \r
- // HTTP 400, 500 Errors as well as HTTP 118 - Connection timed\r
- // out\r
- if ((statusCode >= 400 && statusCode <= 418)\r
- || (statusCode >= 421 && statusCode <= 426)\r
- || (statusCode >= 500 && statusCode <= 510)\r
- || statusCode == 118) {\r
- return 0;\r
- }\r
- \r
- return 5 * 1000;\r
- }\r
- };\r
- }\r
- \r
- protected HttpResponse fireRawRequest(HttpRequest query)\r
- throws ClientProtocolException, OperationCanceledException,\r
- AuthenticatorException, IOException {\r
- /*\r
- * BasicHttpContext httpContext = new BasicHttpContext(); BasicScheme\r
- * basicAuth = new BasicScheme();\r
- * httpContext.setAttribute("preemptive-auth", basicAuth);\r
- * \r
- * HttpResponse response = getClient().execute(mHost, query,\r
- * httpContext);\r
- */\r
- return null;\r
- }\r
- \r
protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {\r
AccountUtils.constructFullURLForAccount(getContext(), account);\r
mClient = OwnCloudClientUtils.createOwnCloudClient(account, getContext());\r
protected WebdavClient getClient() {\r
return mClient;\r
}\r
+ \r
+ \r
+ /* method called by ContactSyncAdapter, that is never used */\r
+ protected HttpResponse fireRawRequest(HttpRequest query)\r
+ throws ClientProtocolException, OperationCanceledException,\r
+ AuthenticatorException, IOException {\r
+ return null;\r
+ }\r
+ \r
}
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AuthenticatorActivity;
- import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
+
import android.accounts.Account;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+ import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Bundle;
/**
- * SyncAdapter implementation for syncing sample SyncAdapter contacts to the
- * platform ContactOperations provider.
+ * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing
+ * ownCloud files.
+ *
+ * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)}.
*
* @author Bartek Przybylski
* @author David A. Velasco
*/
public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
- private final static String TAG = "FileSyncAdapter";
+ private final static String TAG = FileSyncAdapter.class.getSimpleName();
- /**
- * Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation
- */
+ /** Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation */
private static final int MAX_FAILED_RESULTS = 3;
+
+ /** Time stamp for the current synchronization process, used to distinguish fresh data */
private long mCurrentSyncTime;
+
+ /** Flag made 'true' when a request to cancel the synchronization is received */
private boolean mCancellation;
+
+ /** When 'true' the process was requested by the user through the user interface; when 'false', it was requested automatically by the system */
private boolean mIsManualSync;
- private int mFailedResultsCounter;
+
+ /** Counter for failed operations in the synchronization process */
+ private int mFailedResultsCounter;
+
+ /** Result of the last failed operation */
private RemoteOperationResult mLastFailedResult;
- private SyncResult mSyncResult;
+
+ /** Counter of conflicts found between local and remote files */
private int mConflictsFound;
+
+ /** Counter of failed operations in synchronization of kept-in-sync files */
private int mFailsInFavouritesFound;
+
+ /** Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and couldn't be copied automatically into it */
private Map<String, String> mForgottenLocalFiles;
+ /** {@link SyncResult} instance to return to the system when the synchronization finish */
+ private SyncResult mSyncResult;
+
+ /**
+ * Creates an {@link FileSyncAdapter}
+ *
+ * {@inheritDoc}
+ */
public FileSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
}
+
/**
* {@inheritDoc}
*/
mForgottenLocalFiles = new HashMap<String, String>();
mSyncResult = syncResult;
mSyncResult.fullSyncRequested = false;
- mSyncResult.delayUntil = 60*60*24; // sync after 24h
+ mSyncResult.delayUntil = 60*60*24; // avoid too many automatic synchronizations
this.setAccount(account);
this.setContentProvider(provider);
- this.setStorageManager(new FileDataStorageManager(account, getContentProvider()));
+ this.setStorageManager(new FileDataStorageManager(account, provider));
try {
this.initClientForCurrentAccount();
} catch (IOException e) {
- /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
+ /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again
mSyncResult.tooManyRetries = true;
notifyFailedSynchronization();
return;
} catch (AccountsException e) {
- /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
+ /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again
mSyncResult.tooManyRetries = true;
notifyFailedSynchronization();
return;
updateOCVersion();
mCurrentSyncTime = System.currentTimeMillis();
if (!mCancellation) {
- fetchData(OCFile.PATH_SEPARATOR, DataStorageManager.ROOT_PARENT_ID);
+ synchronizeFolder(getStorageManager().getFileByPath(OCFile.ROOT_PATH));
} else {
- Log_OC.d(TAG, "Leaving synchronization before any remote request due to cancellation was requested");
+ Log_OC.d(TAG, "Leaving synchronization before synchronizing the root folder because cancelation request");
}
/// notify the user about the failure of MANUAL synchronization
notifyFailedSynchronization();
-
}
if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) {
notifyFailsInFavourites();
}
if (mForgottenLocalFiles.size() > 0) {
notifyForgottenLocalFiles();
-
}
sendStickyBroadcast(false, null, mLastFailedResult); // message to signal the end to the UI
}
/**
* Called by system SyncManager when a synchronization is required to be cancelled.
*
- * Sets the mCancellation flag to 'true'. THe synchronization will be stopped when before a new folder is fetched. Data of the last folder
- * fetched will be still saved in the database. See onPerformSync implementation.
+ * Sets the mCancellation flag to 'true'. THe synchronization will be stopped later,
+ * before a new folder is fetched. Data of the last folder synchronized will be still
+ * locally saved.
+ *
+ * See {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)}
+ * and {@link #synchronizeFolder(String, long)}.
*/
@Override
public void onSyncCanceled() {
/**
- * Synchronize the properties of files and folders contained in a remote folder given by remotePath.
+ * Synchronizes the list of files contained in a folder identified with its remote path.
+ *
+ * Fetches the list and properties of the files contained in the given folder, including their
+ * properties, and updates the local database with them.
+ *
+ * Enters in the child folders to synchronize their contents also, following a recursive
+ * depth first strategy.
*
- * @param remotePath Remote path to the folder to synchronize.
- * @param parentId Database Id of the folder to synchronize.
+ * @param folder Folder to synchronize.
*/
- private void fetchData(String remotePath, long parentId) {
+ private void synchronizeFolder(OCFile folder) {
if (mFailedResultsCounter > MAX_FAILED_RESULTS || isFinisher(mLastFailedResult))
return;
- // perform folder synchronization
- SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation( remotePath,
+ /*
+ OCFile folder,
+ long currentSyncTime,
+ boolean updateFolderProperties,
+ boolean syncFullAccount,
+ DataStorageManager dataStorageManager,
+ Account account,
+ Context context ) {
+
+ }
+ */
+ // folder synchronization
+ SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation( folder,
mCurrentSyncTime,
- parentId,
+ true,
getStorageManager(),
getAccount(),
getContext()
// synchronized folder -> notice to UI - ALWAYS, although !result.isSuccess
- sendStickyBroadcast(true, remotePath, null);
+ sendStickyBroadcast(true, folder.getRemotePath(), null);
+ // check the result of synchronizing the folder
if (result.isSuccess() || result.getCode() == ResultCode.SYNC_CONFLICT) {
if (result.getCode() == ResultCode.SYNC_CONFLICT) {
if (synchFolderOp.getForgottenLocalFiles().size() > 0) {
mForgottenLocalFiles.putAll(synchFolderOp.getForgottenLocalFiles());
}
- // synchronize children folders
- List<OCFile> children = synchFolderOp.getChildren();
- fetchChildren(children); // beware of the 'hidden' recursion here!
-
- sendStickyBroadcast(true, remotePath, null);
+ if (result.isSuccess()) {
+ // synchronize children folders
+ List<OCFile> children = synchFolderOp.getChildren();
+ fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged()); // beware of the 'hidden' recursion here!
+ }
} else {
+ // in failures, the statistics for the global result are updated
if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
- // (result.isTemporalRedirection() && result.isIdPRedirection() &&
( result.isIdPRedirection() &&
MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
mSyncResult.stats.numAuthExceptions++;
}
/**
- * Synchronize data of folders in the list of received files
+ * Triggers the synchronization of any folder contained in the list of received files.
*
- * @param files Files to recursively fetch
+ * @param files Files to recursively synchronize.
*/
- private void fetchChildren(List<OCFile> files) {
+ private void fetchChildren(OCFile parent, List<OCFile> files, boolean parentEtagChanged) {
int i;
+ OCFile newFile = null;
+ String etag = null;
+ boolean syncDown = false;
for (i=0; i < files.size() && !mCancellation; i++) {
- OCFile newFile = files.get(i);
- if (newFile.isDirectory()) {
- fetchData(newFile.getRemotePath(), newFile.getFileId());
-
- // Update folder size on DB
- getStorageManager().calculateFolderSize(newFile.getFileId());
+ newFile = files.get(i);
+ if (newFile.isFolder()) {
+ /*
+ etag = newFile.getEtag();
+ syncDown = (parentEtagChanged || etag == null || etag.length() == 0);
+ if(syncDown) { */
+ synchronizeFolder(newFile);
+ // update the size of the parent folder again after recursive synchronization
+ //getStorageManager().updateFolderSize(parent.getFileId());
+ sendStickyBroadcast(true, parent.getRemotePath(), null); // notify again to refresh size in UI
+ //}
}
}
- if (mCancellation && i <files.size()) Log_OC.d(TAG, "Leaving synchronization before synchronizing " + files.get(i).getRemotePath() + " because cancelation request");
+ if (mCancellation && i <files.size()) Log_OC.d(TAG, "Leaving synchronization before synchronizing " + files.get(i).getRemotePath() + " due to cancelation request");
}
import android.accounts.Account;
import android.app.AlertDialog;
- import android.app.ProgressDialog;
import android.app.Dialog;
+ import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import com.owncloud.android.Log_OC;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
- import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
-import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
+ import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.operations.RemoveFileOperation;
import com.owncloud.android.operations.RenameFileOperation;
import com.owncloud.android.operations.SynchronizeFileOperation;
- import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+ import com.owncloud.android.operations.SynchronizeFolderOperation;
import com.owncloud.android.syncadapter.FileSyncService;
import com.owncloud.android.ui.dialog.EditNameDialog;
+ import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.ui.dialog.LoadingDialog;
import com.owncloud.android.ui.dialog.SslValidatorDialog;
- import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
import com.owncloud.android.ui.preview.PreviewVideoActivity;
+
/**
* Displays, what files the user has available in his ownCloud.
*
private ArrayAdapter<String> mDirectories;
/** Access point to the cached database for the current ownCloud {@link Account} */
- private DataStorageManager mStorageManager = null;
+ private FileDataStorageManager mStorageManager = null;
private SyncBroadcastReceiver mSyncBroadcastReceiver;
private UploadFinishReceiver mUploadFinishReceiver;
private View mRightFragmentContainer;
private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
+ private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS";
public static final int DIALOG_SHORT_WAIT = 0;
private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1;
private OCFile mWaitingToPreview;
private Handler mHandler;
+ private boolean mSyncInProgress = false;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
Log_OC.d(TAG, "onCreate() start");
/// Load of saved instance state
if(savedInstanceState != null) {
mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW);
-
+ mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS);
+
} else {
mWaitingToPreview = null;
- }
+ mSyncInProgress = false;
+ }
/// USER INTERFACE
// Action bar setup
mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
getSupportActionBar().setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation
- setSupportProgressBarIndeterminateVisibility(false); // always AFTER setContentView(...) ; to work around bug in its implementation
+ setSupportProgressBarIndeterminateVisibility(mSyncInProgress); // always AFTER setContentView(...) ; to work around bug in its implementation
}
if (file == null) {
// fall back to root folder
- file = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR); // never returns null
+ file = mStorageManager.getFileByPath(OCFile.ROOT_PATH); // never returns null
}
setFile(file);
- mDirectories.clear();
- OCFile fileIt = file;
- while(fileIt != null && fileIt.getFileName() != OCFile.PATH_SEPARATOR) {
- if (fileIt.isDirectory()) {
- mDirectories.add(fileIt.getFileName());
- }
- // get parent from path
- parentPath = fileIt.getRemotePath().substring(0, fileIt.getRemotePath().lastIndexOf(fileIt.getFileName()));
- fileIt = mStorageManager.getFileByPath(parentPath);
- }
- mDirectories.add(OCFile.PATH_SEPARATOR);
+ setNavigationListWithFolder(file);
if (!stateWasRecovered) {
Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
initFragmentsWithFile();
+ if (file.isFolder()) {
+ startSyncFolderOperation(file);
+ }
} else {
- updateFragmentsVisibility(!file.isDirectory());
- updateNavigationElementsInActionBar(file.isDirectory() ? null : file);
+ updateFragmentsVisibility(!file.isFolder());
+ updateNavigationElementsInActionBar(file.isFolder() ? null : file);
}
}
+ private void setNavigationListWithFolder(OCFile file) {
+ mDirectories.clear();
+ OCFile fileIt = file;
+ String parentPath;
+ while(fileIt != null && fileIt.getFileName() != OCFile.ROOT_PATH) {
+ if (fileIt.isFolder()) {
+ mDirectories.add(fileIt.getFileName());
+ }
+ //fileIt = mStorageManager.getFileById(fileIt.getParentId());
+ // get parent from path
+ parentPath = fileIt.getRemotePath().substring(0, fileIt.getRemotePath().lastIndexOf(fileIt.getFileName()));
+ fileIt = mStorageManager.getFileByPath(parentPath);
+ }
+ mDirectories.add(OCFile.PATH_SEPARATOR);
+ }
+
+
private void createMinFragments() {
OCFileListFragment listOfFiles = new OCFileListFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
private Fragment chooseInitialSecondFragment(OCFile file) {
Fragment secondFragment = null;
- if (file != null && !file.isDirectory()) {
+ if (file != null && !file.isFolder()) {
if (file.isDown() && PreviewMediaFragment.canBePreviewed(file)
&& file.getLastSyncDateForProperties() > 0 // temporal fix
) {
FileFragment second = getSecondFragment();
OCFile currentDir = getCurrentDir();
if((currentDir != null && currentDir.getParentId() != 0) ||
- (second != null && second.getFile() != null)) {
+ (second != null && second.getFile() != null)) {
onBackPressed();
+
}
break;
}
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
- int i = itemPosition;
- while (i-- != 0) {
- onBackPressed();
- }
- // the next operation triggers a new call to this method, but it's necessary to
- // ensure that the name exposed in the action bar is the current directory when the
- // user selected it in the navigation list
- if (itemPosition != 0)
+ if (itemPosition != 0) {
+ String targetPath = "";
+ for (int i=itemPosition; i < mDirectories.getCount() - 1; i++) {
+ targetPath = mDirectories.getItem(i) + OCFile.PATH_SEPARATOR + targetPath;
+ }
+ targetPath = OCFile.PATH_SEPARATOR + targetPath;
+ OCFile targetFolder = mStorageManager.getFileByPath(targetPath);
+ if (targetFolder != null) {
+ browseTo(targetFolder);
+ }
+
+ // the next operation triggers a new call to this method, but it's necessary to
+ // ensure that the name exposed in the action bar is the current directory when the
+ // user selected it in the navigation list
getSupportActionBar().setSelectedNavigationItem(0);
+ }
return true;
}
finish();
return;
}
- popDirname();
- listOfFiles.onBrowseUp();
+ int levelsUp = listOfFiles.onBrowseUp();
+ for (int i=0; i < levelsUp && mDirectories.getCount() > 1 ; i++) {
+ popDirname();
+ }
}
}
if (listOfFiles != null) { // should never be null, indeed
setFile(listOfFiles.getCurrentFile());
}
cleanSecondFragment();
+
}
@Override
Log_OC.e(TAG, "onSaveInstanceState() start");
super.onSaveInstanceState(outState);
outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
+ outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress);
+
Log_OC.d(TAG, "onSaveInstanceState() end");
}
/**
* Pushes a directory to the drop down list
* @param directory to push
- * @throws IllegalArgumentException If the {@link OCFile#isDirectory()} returns false.
+ * @throws IllegalArgumentException If the {@link OCFile#isFolder()} returns false.
*/
public void pushDirname(OCFile directory) {
- if(!directory.isDirectory()){
+ if(!directory.isFolder()){
throw new IllegalArgumentException("Only directories may be pushed!");
}
mDirectories.insert(directory.getFileName(), 0);
public void onReceive(Context context, Intent intent) {
boolean inProgress = intent.getBooleanExtra(FileSyncService.IN_PROGRESS, false);
String accountName = intent.getStringExtra(FileSyncService.ACCOUNT_NAME);
-
- Log_OC.d(TAG, "sync of account " + accountName + " is in_progress: " + inProgress);
+ RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
if (getAccount() != null && accountName.equals(getAccount().name)
&& mStorageManager != null
String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
- boolean fillBlankRoot = false;
- OCFile currentDir = getCurrentDir();
- if (currentDir == null) {
- currentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
- fillBlankRoot = (currentDir != null);
- }
+ OCFile currentFile = (getFile() == null) ? null : mStorageManager.getFileByPath(getFile().getRemotePath());
+ OCFile currentDir = (getCurrentDir() == null) ? null : mStorageManager.getFileByPath(getCurrentDir().getRemotePath());
- if ((synchFolderRemotePath != null && currentDir != null && (currentDir.getRemotePath().equals(synchFolderRemotePath)))
- || fillBlankRoot ) {
- if (!fillBlankRoot)
- currentDir = mStorageManager.getFileByPath(synchFolderRemotePath);
- OCFileListFragment fileListFragment = getListOfFilesFragment();
- if (fileListFragment != null) {
- fileListFragment.listDirectory(currentDir);
+ if (currentDir == null) {
+ // current folder was removed from the server
+ Toast.makeText( FileDisplayActivity.this,
+ String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)),
+ Toast.LENGTH_LONG)
+ .show();
+ browseToRoot();
+
+ } else {
+ if (currentFile == null && !getFile().isFolder()) {
+ // currently selected file was removed in the server, and now we know it
+ cleanSecondFragment();
+ currentFile = currentDir;
}
- if (getSecondFragment() == null)
- setFile(currentDir);
+
+ if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) {
+ OCFileListFragment fileListFragment = getListOfFilesFragment();
+ if (fileListFragment != null) {
+ fileListFragment.listDirectory(currentDir);
+ }
+ }
+ setFile(currentFile);
}
setSupportProgressBarIndeterminateVisibility(inProgress);
removeStickyBroadcast(intent);
+ mSyncInProgress = inProgress;
}
-
- RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
+
if (synchResult != null) {
if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) {
mLastSslUntrustedServerResult = synchResult;
}
}
}
-
+
private class UploadFinishReceiver extends BroadcastReceiver {
/**
* {@inheritDoc}
*/
@Override
- public DataStorageManager getStorageManager() {
+ public FileDataStorageManager getStorageManager() {
return mStorageManager;
}
+ public void browseToRoot() {
+ OCFileListFragment listOfFiles = getListOfFilesFragment();
+ if (listOfFiles != null) { // should never be null, indeed
+ while (mDirectories.getCount() > 1) {
+ popDirname();
+ }
+ OCFile root = mStorageManager.getFileByPath(OCFile.ROOT_PATH);
+ listOfFiles.listDirectory(root);
+ setFile(listOfFiles.getCurrentFile());
+ startSyncFolderOperation(root);
+ }
+ cleanSecondFragment();
+ }
+
+
+ public void browseTo(OCFile folder) {
+ if (folder == null || !folder.isFolder()) {
+ throw new IllegalArgumentException("Trying to browse to invalid folder " + folder);
+ }
+ OCFileListFragment listOfFiles = getListOfFilesFragment();
+ if (listOfFiles != null) {
+ setNavigationListWithFolder(folder);
+ listOfFiles.listDirectory(folder);
+ setFile(listOfFiles.getCurrentFile());
+ startSyncFolderOperation(folder);
+ } else {
+ Log_OC.e(TAG, "Unexpected null when accessing list fragment");
+ }
+ cleanSecondFragment();
+ }
+
+
/**
* {@inheritDoc}
*
public void onBrowsedDownTo(OCFile directory) {
pushDirname(directory);
cleanSecondFragment();
+
+ // Sync Folder
+ startSyncFolderOperation(directory);
+
}
/**
}
+ // private void updateDisplayHomeAtSync(){
+ // ActionBar actionBar = getSupportActionBar();
+ // OCFile currentDir = getCurrentDir();
+ // if (currentDir.getParentId() != DataStorageManager.ROOT_PARENT_ID) {
+ // actionBar.setHomeButtonEnabled(!mSyncInProgress);
+ // actionBar.setDisplayHomeAsUpEnabled(!mSyncInProgress);
+ // }
+ // else {
+ // actionBar.setHomeButtonEnabled(true);
+ // actionBar.setDisplayHomeAsUpEnabled(false);
+ // }
+ // }
+ //
/**
* {@inheritDoc}
*/
} else if (operation instanceof CreateFolderOperation) {
onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
- }
+
+ }
}
refeshListOfFilesFragment();
} else {
- //dismissDialog(DIALOG_SHORT_WAIT);
dismissLoadingDialog();
try {
Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG);
i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, getAccount());
startActivity(i);
- } else {
- Toast msg = Toast.makeText(this, R.string.sync_file_fail_msg, Toast.LENGTH_LONG);
- msg.show();
- }
+ }
} else {
if (operation.transferWasRequested()) {
private OCFile getCurrentDir() {
OCFile file = getFile();
if (file != null) {
- if (file.isDirectory()) {
+ if (file.isFolder()) {
return file;
} else if (mStorageManager != null) {
String parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName()));
}
return null;
}
+
+ public void startSyncFolderOperation(OCFile folder) {
+ long currentSyncTime = System.currentTimeMillis();
+
+ mSyncInProgress = true;
+
+ // perform folder synchronization
+ RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,
+ currentSyncTime,
+ false,
+ getStorageManager(),
+ getAccount(),
+ getApplicationContext()
+ );
+ synchFolderOp.execute(getAccount(), this, null, null, this);
+
+ setSupportProgressBarIndeterminateVisibility(true);
+ }
+
+ // public void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
+ // int childCount = viewGroup.getChildCount();
+ // for (int i = 0; i < childCount; i++) {
+ // View view = viewGroup.getChildAt(i);
+ // view.setEnabled(enabled);
+ // view.setClickable(!enabled);
+ // if (view instanceof ViewGroup) {
+ // enableDisableViewGroup((ViewGroup) view, enabled);
+ // }
+ // }
+ // }
}
import android.net.Uri;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
- import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import com.owncloud.android.R;
import com.owncloud.android.db.DbHandler;
+
/**
* An Activity that allows the user to change the application's settings.
*
* @author Bartek Przybylski
- *
+ * @author David A. Velasco
*/
- public class Preferences extends SherlockPreferenceActivity implements OnPreferenceChangeListener {
+ public class Preferences extends SherlockPreferenceActivity {
private static final String TAG = "OwnCloudPreferences";
private final int mNewSession = 47;
private final int mEditSession = 48;
private DbHandler mDbHandler;
private Vector<OwnCloudSession> mSessions;
- private ListPreference mTrackingUpdateInterval;
- private CheckBoxPreference mDeviceTracking;
private CheckBoxPreference pCode;
//private CheckBoxPreference pLogging;
//private Preference pLoggingHistory;
Intent intent;
switch (item.getItemId()) {
- //case R.id.addSessionItem:
- case 1:
- intent = new Intent(this, PreferencesNewSession.class);
- startActivityForResult(intent, mNewSession);
- break;
- case R.id.SessionContextEdit:
- intent = new Intent(this, PreferencesNewSession.class);
- intent.putExtra("sessionId", mSessions.get(mSelectedMenuItem)
- .getEntryId());
- intent.putExtra("sessionName", mSessions.get(mSelectedMenuItem)
- .getName());
- intent.putExtra("sessionURL", mSessions.get(mSelectedMenuItem)
- .getUrl());
- startActivityForResult(intent, mEditSession);
- break;
case android.R.id.home:
intent = new Intent(getBaseContext(), FileDisplayActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
super.onDestroy();
}
- @Override
- /**
- * Updates various summaries after updates. Also starts and stops
- * the
- */
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- // Update current account summary
- /*if (preference.equals(mAccountList)) {
- mAccountList.setSummary(newValue.toString());
- }
-
- // Update tracking interval summary
- else*/ if (preference.equals(mTrackingUpdateInterval)) {
- String trackingSummary = getResources().getString(
- R.string.prefs_trackmydevice_interval_summary);
- trackingSummary = String.format(trackingSummary,
- newValue.toString());
- mTrackingUpdateInterval.setSummary(trackingSummary);
- }
-
- // Start or stop tracking service
- else if (preference.equals(mDeviceTracking)) {
- Intent locationServiceIntent = new Intent();
- locationServiceIntent
- .setAction("com.owncloud.android.location.LocationLauncher");
- locationServiceIntent.putExtra("TRACKING_SETTING",
- (Boolean) newValue);
- sendBroadcast(locationServiceIntent);
- }
- return true;
- }
}
import android.widget.ListView;\r
import android.widget.TextView;\r
\r
+\r
+import java.util.Vector;\r
+\r
import com.owncloud.android.DisplayUtils;\r
import com.owncloud.android.R;\r
import com.owncloud.android.authentication.AccountUtils;\r
- import com.owncloud.android.datamodel.DataStorageManager;\r
+ import com.owncloud.android.datamodel.FileDataStorageManager;\r
import com.owncloud.android.datamodel.OCFile;\r
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
import com.owncloud.android.ui.activity.TransferServiceGetter;\r
\r
-import java.util.Vector;\r
-\r
\r
/**\r
* This Adapter populates a ListView with all files and folders in an ownCloud\r
private Context mContext;\r
private OCFile mFile = null;\r
private Vector<OCFile> mFiles = null;\r
- private DataStorageManager mStorageManager;\r
+ private FileDataStorageManager mStorageManager;\r
private Account mAccount;\r
private TransferServiceGetter mTransferServiceGetter;\r
- //total size of a directory (recursive)\r
- private Long totalSizeOfDirectoriesRecursive = null;\r
- private Long lastModifiedOfAllSubdirectories = null;\r
\r
public FileListListAdapter(Context context, TransferServiceGetter transferServiceGetter) {\r
mContext = context;\r
TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
\r
- if (!file.isDirectory()) {\r
+ if (!file.isFolder()) {\r
fileSizeV.setVisibility(View.VISIBLE);\r
fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
lastModV.setVisibility(View.VISIBLE);\r
* @param directory New file to adapt. Can be NULL, meaning "no content to adapt".\r
* @param updatedStorageManager Optional updated storage manager; used to replace mStorageManager if is different (and not NULL)\r
*/\r
- public void swapDirectory(OCFile directory, DataStorageManager updatedStorageManager) {\r
+ public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager) {\r
mFile = directory;\r
if (updatedStorageManager != null && updatedStorageManager != mStorageManager) {\r
mStorageManager = updatedStorageManager;\r
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
}\r
if (mStorageManager != null) {\r
- mFiles = mStorageManager.getDirectoryContent(mFile);\r
+ mFiles = mStorageManager.getFolderContent(mFile);\r
} else {\r
mFiles = null;\r
}\r
import com.owncloud.android.R;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.operations.RemoveFileOperation;
import com.owncloud.android.operations.RenameFileOperation;
import com.owncloud.android.operations.SynchronizeFileOperation;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.ConflictsResolveActivity;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.ui.preview.PreviewImageFragment;
+
import eu.alefzero.webdav.OnDatatransferProgressListener;
/**
private void renameFile() {
OCFile file = getFile();
String fileName = file.getFileName();
- int extensionStart = file.isDirectory() ? -1 : fileName.lastIndexOf(".");
+ int extensionStart = file.isFolder() ? -1 : fileName.lastIndexOf(".");
int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length();
EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this);
dialog.show(getFragmentManager(), "nameeditdialog");
}
} else {
- mLastRemoteOperation = new SynchronizeFileOperation(file, null, mStorageManager, mAccount, true, false, getActivity());
+ mLastRemoteOperation = new SynchronizeFileOperation(file, null, mStorageManager, mAccount, true, getActivity());
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
// update ui
i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount);
startActivity(i);
- } else {
- Toast msg = Toast.makeText(getActivity(), R.string.sync_file_fail_msg, Toast.LENGTH_LONG);
- msg.show();
- }
+ }
if (file.isDown()) {
setButtonsForDown();
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
- import com.owncloud.android.datamodel.DataStorageManager;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.FileHandler;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
+
import android.accounts.Account;
import android.app.Activity;
import android.os.Bundle;
/**
- * Call this, when the user presses the up button
+ * Call this, when the user presses the up button.
+ *
+ * Tries to move up the current folder one level. If the parent folder was removed from the database,
+ * it continues browsing up until finding an existing folders.
+ *
+ * return Count of folder levels browsed up.
*/
- public void onBrowseUp() {
+ public int onBrowseUp() {
OCFile parentDir = null;
+ int moveCount = 0;
if(mFile != null){
- DataStorageManager storageManager = mContainerActivity.getStorageManager();
- parentDir = storageManager.getFileById(mFile.getParentId());
- mFile = parentDir;
+ FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
+
+ String parentPath = null;
+ if (mFile.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) {
+ parentPath = new File(mFile.getRemotePath()).getParent();
+ parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
+ parentDir = storageManager.getFileByPath(parentPath);
+ moveCount++;
+ } else {
+ parentDir = storageManager.getFileByPath(OCFile.ROOT_PATH); // never returns null; keep the path in root folder
+ }
+ while (parentDir == null) {
+ parentPath = new File(parentPath).getParent();
+ parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
+ parentDir = storageManager.getFileByPath(parentPath);
+ moveCount++;
+ } // exit is granted because storageManager.getFileByPath("/") never returns null
+ mFile = parentDir;
}
- listDirectory(parentDir);
+
+ if (mFile != null) {
+ listDirectory(mFile);
+
+ mContainerActivity.startSyncFolderOperation(mFile);
+ } // else - should never happen now
+
+ return moveCount;
}
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
OCFile file = (OCFile) mAdapter.getItem(position);
if (file != null) {
- if (file.isDirectory()) {
+ if (file.isFolder()) {
// update state and view of this fragment
listDirectory(file);
// then, notify parent activity to let it update its state and view, and other fragments
List<Integer> toDisable = new ArrayList<Integer>();
MenuItem item = null;
- if (targetFile.isDirectory()) {
+ if (targetFile.isFolder()) {
// contextual menu for folders
toHide.add(R.id.action_open_file_with);
toHide.add(R.id.action_download_file);
switch (item.getItemId()) {
case R.id.action_rename_file: {
String fileName = mTargetFile.getFileName();
- int extensionStart = mTargetFile.isDirectory() ? -1 : fileName.lastIndexOf(".");
+ int extensionStart = mTargetFile.isFolder() ? -1 : fileName.lastIndexOf(".");
int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length();
EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this);
dialog.show(getFragmentManager(), EditNameDialog.TAG);
int messageStringId = R.string.confirmation_remove_alert;
int posBtnStringId = R.string.confirmation_remove_remote;
int neuBtnStringId = -1;
- if (mTargetFile.isDirectory()) {
+ if (mTargetFile.isFolder()) {
messageStringId = R.string.confirmation_remove_folder_alert;
posBtnStringId = R.string.confirmation_remove_remote_and_local;
neuBtnStringId = R.string.confirmation_remove_folder_local;
}
case R.id.action_sync_file: {
Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
- RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
+ RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, getSherlockActivity());
operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
((FileDisplayActivity) getSherlockActivity()).showLoadingDialog();
return true;
* @param directory File to be listed
*/
public void listDirectory(OCFile directory) {
- DataStorageManager storageManager = mContainerActivity.getStorageManager();
+ FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
if (storageManager != null) {
// Check input parameters for null
// If that's not a directory -> List its parent
- if(!directory.isDirectory()){
+ if(!directory.isFolder()){
Log_OC.w(TAG, "You see, that is not a directory -> " + directory.toString());
directory = storageManager.getFileById(directory.getParentId());
}
mList.setSelectionFromTop(0, 0);
}
mFile = directory;
-
}
}
public void startMediaPreview(OCFile file, int i, boolean b);
public void startImagePreview(OCFile file);
+
+ public void startSyncFolderOperation(OCFile folder);
/**
* Getter for the current DataStorageManager in the container activity
*/
- public DataStorageManager getStorageManager();
+ public FileDataStorageManager getStorageManager();
/**
@Override
public void onNeutral(String callerTag) {
- File f = null;
- if (mTargetFile.isDirectory()) {
- // TODO run in a secondary thread?
- mContainerActivity.getStorageManager().removeDirectory(mTargetFile, false, true);
-
- } else if (mTargetFile.isDown() && (f = new File(mTargetFile.getStoragePath())).exists()) {
- f.delete();
- mTargetFile.setStoragePath(null);
- mContainerActivity.getStorageManager().saveFile(mTargetFile);
- }
+ mContainerActivity.getStorageManager().removeFile(mTargetFile, false, true); // TODO perform in background task / new thread
listDirectory();
mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
}
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
- import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
-import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.dialog.LoadingDialog;
import com.owncloud.android.ui.fragment.FileFragment;
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.R;
/**
* Holds a swiping galley where image files contained in an ownCloud directory are shown
private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
private ViewPager mViewPager;
private PreviewImagePagerAdapter mPreviewImagePagerAdapter;
//OCFile parentFolder = mStorageManager.getFileById(getFile().getParentId());
if (parentFolder == null) {
// should not be necessary
- parentFolder = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
+ parentFolder = mStorageManager.getFileByPath(OCFile.ROOT_PATH);
}
mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), parentFolder, getAccount(), mStorageManager);
mViewPager = (ViewPager) findViewById(R.id.fragmentPager);
mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());
// Update file according to DB file, if it is possible
- if (file.getFileId() > DataStorageManager.ROOT_PARENT_ID)
+ if (file.getFileId() > FileDataStorageManager.ROOT_PARENT_ID)
file = mStorageManager.getFileById(file.getFileId());
if (file != null) {
import java.util.Set;
import java.util.Vector;
- import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.fragment.FileFragment;
+
import android.accounts.Account;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.view.ViewGroup;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.ui.fragment.FileFragment;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
/**
* Adapter class that provides Fragment instances
private Set<Object> mObsoleteFragments;
private Set<Integer> mObsoletePositions;
private Set<Integer> mDownloadErrors;
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
private Map<Integer, FileFragment> mCachedFragments;
* @param parentFolder Folder where images will be searched for.
* @param storageManager Bridge to database.
*/
- public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, DataStorageManager storageManager) {
+ public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, FileDataStorageManager storageManager) {
super(fragmentManager);
if (fragmentManager == null) {
mAccount = account;
mStorageManager = storageManager;
- mImageFiles = mStorageManager.getDirectoryImages(parentFolder);
+ mImageFiles = mStorageManager.getFolderImages(parentFolder);
mObsoleteFragments = new HashSet<Object>();
mObsoletePositions = new HashSet<Integer>();
mDownloadErrors = new HashSet<Integer>();
package com.owncloud.android.ui.preview;
- import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.media.MediaService;
+import com.owncloud.android.ui.activity.FileActivity;
+
import android.accounts.Account;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.widget.MediaController;
import android.widget.VideoView;
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.R;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.media.MediaService;
-import com.owncloud.android.ui.activity.FileActivity;
--
/**
* Activity implementing a basic video player.
*
private static final String TAG = PreviewVideoActivity.class.getSimpleName();
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
private int mSavedPlaybackPosition; // in the unit time handled by MediaPlayer.getCurrentPosition()
private boolean mAutoplay; // when 'true', the playback starts immediately with the activity
import com.owncloud.android.Log_OC;
import com.owncloud.android.MainApp;
-
import com.owncloud.android.network.BearerAuthScheme;
import com.owncloud.android.network.BearerCredentials;
+
+
import android.net.Uri;
public class WebdavClient extends HttpClient {
try {
method.setFollowRedirects(mFollowRedirects);
} catch (Exception e) {
- if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used");
+ //if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
customRedirectionNeeded = mFollowRedirects;
}
if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
import com.owncloud.android.Log_OC;
+
import android.net.Uri;
public class WebdavEntry {
- private String mName, mPath, mUri, mContentType;
+ private String mName, mPath, mUri, mContentType, mEtag;
private long mContentLength, mCreateTimestamp, mModifiedTimestamp;
public WebdavEntry(MultiStatusResponse ms, String splitElement) {
DavPropertySet propSet = ms.getProperties(status);
@SuppressWarnings("rawtypes")
DavProperty prop = propSet.get(DavPropertyName.DISPLAYNAME);
- if (prop != null)
+ if (prop != null) {
mName = (String) prop.getName().toString();
+ mName = mName.substring(1, mName.length()-1);
+ }
else {
String[] tmp = mPath.split("/");
if (tmp.length > 0)
.parseResponseDate((String) prop.getValue());
mCreateTimestamp = (d != null) ? d.getTime() : 0;
}
+
+ prop = propSet.get(DavPropertyName.GETETAG);
+ if (prop != null) {
+ mEtag = (String) prop.getValue();
+ mEtag = mEtag.substring(1, mEtag.length()-1);
+ }
} else {
Log_OC.e("WebdavEntry",
public long modifiedTimestamp() {
return mModifiedTimestamp;
}
+
+ public String etag() {
+ return mEtag;
+ }
private void resetData() {
mName = mUri = mContentType = null;