<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="app_name">ownCloud</string>
<string name="main_password">Password:</string>
<string name="main_login">Username:</string>
<string name="main_button_login">Login</string>
<string name="actionbar_see_details">Details</string>
<string name="prefs_category_general">General</string>
+ <string name="prefs_category_more">More</string>
<string name="prefs_add_session">Add new session</string>
<string name="prefs_create_img_thumbnails">Create image thumbnails</string>
<string name="prefs_select_oc_account">Select an account</string>
<string name="prefs_log_title_history">Logging History</string>
<string name="prefs_log_summary_history">This shows the recorded logs</string>
<string name="prefs_log_delete_history_button">Delete History</string>
+ <string name="prefs_help">Help</string>
+ <string name="prefs_recommend">Recommend to a friend</string>
+ <string name="prefs_feedback">Feedback</string>
+ <string name="prefs_imprint">Imprint</string>
+ <string name="recommend_subject">"Try %1$s on your smartphone!"</string>
+ <string name="recommend_text">"I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s"</string>
+
<string name="auth_check_server">Check Server</string>
<string name="auth_account_name">Account name</string>
<string name="auth_host_url">Server address</string>
<string name="sync_foreign_files_forgotten_ticker">Some local files were forgotten</string>
<string name="sync_foreign_files_forgotten_content">%1$d files out of the %2$s directory could not be copied into</string>
<string name="sync_foreign_files_forgotten_explanation">As of version 1.3.16, files uploaded from this device are copied into the local %1$s folder to prevent data loss when a single file is synced with multiple accounts.\n\nDue to this change, all files uploaded in previous versions of this app were copied into the %2$s folder. However, an error prevented the completion of this operation during account synchronization. You may either leave the file(s) as is and remove the link to %3$s, or move the file(s) into the %1$s directory and retain the link to %4$s.\n\nListed below are the local file(s), and the the remote file(s) in %5$s they were linked to.</string>
+ <string name="sync_current_folder_was_removed">Folder %1$s does not exist anymore</string>
<string name="foreign_files_move">"Move all"</string>
<string name="foreign_files_success">"All files were moved"</string>
<string name="foreign_files_fail">"Some files could not be moved"</string>
<string name="auth_connecting_auth_server">Connecting to authentication server…</string>
<string name="auth_follow_auth_server">Follow instructions above to get authenticated</string>
<string name="auth_unsupported_auth_method">The server does not support this authentication method</string>
+ <string name="auth_unsupported_multiaccount">%1$s does not support multiple accounts</string>
<string name="crashlog_message">Application terminated unexpectedly. Would you like to submit a crash report?</string>
<string name="crashlog_send_report">Send report</string>
import android.widget.Toast;
import com.owncloud.android.authentication.AccountAuthenticator;
-import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
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;
mParents.add("");
if (prepareStreamsToUpload()) {
mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
- Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE);
+ Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
if (accounts.length == 0) {
Log_OC.i(TAG, "No ownCloud account is available");
showDialog(DIALOG_NO_ACCOUNT);
// Settings.ADD_ACCOUNT_SETTINGS
// and Settings.EXTRA_AUTHORITIES
Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
- intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTHORITY });
+ intent.putExtra("authorities", new String[] { MainApp.getAuthTokenType() });
startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
} else {
// since in API7 there is no direct call for
});
return builder.create();
case DIALOG_MULTIPLE_ACCOUNT:
- CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE).length];
+ CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
for (int i = 0; i < ac.length; ++i) {
- ac[i] = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[i].name;
+ ac[i] = mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name;
}
builder.setTitle(R.string.common_choose_account);
builder.setItems(ac, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- mAccount = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[which];
+ mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
populateDirectoryList();
}
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");
if (resultCode == RESULT_CANCELED) {
finish();
}
- Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.AUTH_TOKEN_TYPE);
+ Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAuthTokenType());
if (accounts.length == 0) {
showDialog(DIALOG_NO_ACCOUNT);
} else {
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;
+ import com.owncloud.android.MainApp;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
import com.owncloud.android.utils.FileStorageUtils;
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
-
- /* CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
- *
- * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
- */
- /*
- OCFile oldFile = null;
- if (existsByPath) {
- // grant same id
- oldFile = getFileByPath(file.getRemotePath());
- file.setFileId(oldFile.getFileId());
- } else {
- oldFile = getFileById(file.getFileId());
- }
-
- if (file.isFolder()) {
- // folders keep size information, since it's calculated
- file.setFileLength(oldFile.getFileLength());
- cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
-
- } else if (file.getStoragePath() == null && oldFile.getStoragePath() != null) {
- // regular files keep access to local contents, although it's lost in the new OCFile
- file.setStoragePath(oldFile.getStoragePath());
- cv.put(ProviderTableMeta.FILE_STORAGE_PATH, oldFile.getStoragePath());
- }
- */
-
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(ProviderMeta.AUTHORITY_FILES, operations);
+ 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(ProviderMeta.AUTHORITY_FILES, operations);
++ 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 = getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
- 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 != FileDataStorageManager.ROOT_PARENT_ID) {
- while (parentId != 0) {
--
-- // Update the size of the parent
- updateFolderSize(parentId);
- calculateFolderSize(parentId);
--
-- // search the next parent
-- file = getFileById(parentId);
-- parentId = file.getParentId();
--
-- }
-
-- }
- */
--
}
*/\r
package com.owncloud.android.db;\r
\r
+ import com.owncloud.android.MainApp;\r
+ \r
import android.net.Uri;\r
import android.provider.BaseColumns;\r
\r
*/\r
public class ProviderMeta {\r
\r
- public static final String AUTHORITY_FILES = "org.owncloud";\r
- public static final String DB_FILE = "owncloud.db";\r
+ /* These constants are now in MainApp\r
+ public static final String AUTHORITY_FILES = "org.owncloud";\r
+ public static final String DB_FILE = "owncloud.db";\r
+ */\r
public static final String DB_NAME = "filelist";\r
- public static final int DB_VERSION = 4;\r
+ public static final int DB_VERSION = 5;\r
\r
private ProviderMeta() {\r
}\r
static public class ProviderTableMeta implements BaseColumns {\r
public static final String DB_NAME = "filelist";\r
public static final Uri CONTENT_URI = Uri.parse("content://"\r
- + AUTHORITY_FILES + "/");\r
+ + MainApp.getAuthority() + "/");\r
public static final Uri CONTENT_URI_FILE = Uri.parse("content://"\r
- + AUTHORITY_FILES + "/file");\r
+ + MainApp.getAuthority() + "/file");\r
public static final Uri CONTENT_URI_DIR = Uri.parse("content://"\r
- + AUTHORITY_FILES + "/dir");\r
+ + MainApp.getAuthority() + "/dir");\r
\r
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.owncloud.file";\r
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.owncloud.file";\r
public static final String FILE_LAST_SYNC_DATE = "last_sync_date"; // _for_properties, but let's keep it as it is\r
public static final String FILE_LAST_SYNC_DATE_FOR_DATA = "last_sync_date_for_data";\r
public static final String FILE_KEEP_IN_SYNC = "keep_in_sync";\r
+ public static final String FILE_ETAG = "etag";\r
\r
public static final String DEFAULT_SORT_ORDER = FILE_NAME\r
+ " collate nocase asc";\r
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
- 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 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 static final String EXTRA_ACCOUNT = "ACCOUNT";
public static final String EXTRA_FILE = "FILE";
- public static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";
- public static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";
+ private static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";
+ private static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";
public static final String EXTRA_DOWNLOAD_RESULT = "RESULT";
public static final String EXTRA_FILE_PATH = "FILE_PATH";
public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
private int mLastPercent;
+ public String getDownloadAddedMessage() {
+ return getClass().getName().toString() + DOWNLOAD_ADDED_MESSAGE;
+ }
+
+ public String getDownloadFinishMessage() {
+ return getClass().getName().toString() + DOWNLOAD_FINISH_MESSAGE;
+ }
+
/**
* Builds a key for mPendingDownloads from the account and file to download
*
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;
boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
// (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection()
(downloadResult.isIdPRedirection()
- && AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mDownloadClient.getAuthTokenType())));
+ && MainApp.getAuthTokenTypeSamlSessionCookie().equals(mDownloadClient.getAuthTokenType())));
if (needsToUpdateCredentials) {
// let the user update credentials with one click
Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
* @param downloadResult Result of the download operation
*/
private void sendBroadcastDownloadFinished(DownloadFileOperation download, RemoteOperationResult downloadResult) {
- Intent end = new Intent(DOWNLOAD_FINISH_MESSAGE);
+ Intent end = new Intent(getDownloadFinishMessage());
end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());
end.putExtra(ACCOUNT_NAME, download.getAccount().name);
end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
* @param download Added download operation
*/
private void sendBroadcastNewDownload(DownloadFileOperation download) {
- Intent added = new Intent(DOWNLOAD_ADDED_MESSAGE);
+ Intent added = new Intent(getDownloadAddedMessage());
added.putExtra(ACCOUNT_NAME, download.getAccount().name);
added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
added.putExtra(EXTRA_FILE_PATH, download.getSavePath());
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;
public class FileUploader extends Service implements OnDatatransferProgressListener {
- public static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
+ private static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
public static final String EXTRA_UPLOAD_RESULT = "RESULT";
public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
public static final String EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH";
private int mLastPercent;
private RemoteViews mDefaultNotificationContentView;
+
+ public String getUploadFinishMessage() {
+ return getClass().getName().toString() + UPLOAD_FINISH_MESSAGE;
+ }
+
/**
* Builds a key for mPendingUploads from the account and file to upload
*
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;
boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
//(uploadResult.isTemporalRedirection() && uploadResult.isIdPRedirection() &&
(uploadResult.isIdPRedirection() &&
- AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mUploadClient.getAuthTokenType())));
+ MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
if (needsToUpdateCredentials) {
// let the user update credentials with one click
Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
* @param uploadResult Result of the upload operation
*/
private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) {
- Intent end = new Intent(UPLOAD_FINISH_MESSAGE);
+ Intent end = new Intent(getUploadFinishMessage());
end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
// path, after
// possible
import org.apache.commons.httpclient.Credentials;
import com.owncloud.android.Log_OC;
- import com.owncloud.android.authentication.AccountAuthenticator;
+ import com.owncloud.android.MainApp;
import com.owncloud.android.network.BearerCredentials;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
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);
boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials);
boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null);
if (bearerAuthorization) {
- am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
+ am.invalidateAuthToken(MainApp.getAccountType(), ((BearerCredentials)cred).getAccessToken());
} else if (samlBasedSsoAuthorization ) {
- am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ssoSessionCookie);
+ am.invalidateAuthToken(MainApp.getAccountType(), ssoSessionCookie);
} else {
am.clearPassword(mAccount);
}
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 static final UriMatcher mUriMatcher;
-
- 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);
-// }
- public static final String METHOD_UPDATE_FOLDER_SIZE = "updateFolderSize";
++ 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);
- mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
- }
-
@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);
+ 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);
}
- throw new SQLException("ERROR " + uri);
}
+
@Override
public boolean onCreate() {
mDbHelper = new DataBaseHelper(getContext());
+
+ String authority = getContext().getResources().getString(R.string.authority);
+ mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ 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.net.UnknownHostException;\r
- //import java.util.Date;\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
-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
import android.accounts.Account;\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 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
- * 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
+ \r
+ \r
+ /* method called by ContactSyncAdapter, that is never used */\r
+ protected HttpResponse fireRawRequest(HttpRequest query)\r
+ throws ClientProtocolException, OperationCanceledException,\r
+ AuthenticatorException, IOException {\r
- /* methods never used below */\r
- /*\r
- public Date getLastUpdated() {\r
- return lastUpdated;\r
- }\r
- \r
- public void setLastUpdated(Date lastUpdated) {\r
- this.lastUpdated = lastUpdated;\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
+ return null;\r
+ }\r
+\r
}
import org.apache.jackrabbit.webdav.DavException;
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.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.operations.RemoteOperationResult;
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() &&
- AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType()))) {
+ MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
mSyncResult.stats.numAuthExceptions++;
} else if (result.getException() instanceof DavException) {
}
/**
- * 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");
}
* @param dirRemotePath Remote path of a folder that was just synchronized (with or without success)
*/
private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) {
- Intent i = new Intent(FileSyncService.SYNC_MESSAGE);
+ FileSyncService fileSyncService = new FileSyncService();
+
+ Intent i = new Intent(fileSyncService.getSyncMessage());
i.putExtra(FileSyncService.IN_PROGRESS, inProgress);
i.putExtra(FileSyncService.ACCOUNT_NAME, getAccount().name);
if (dirRemotePath != null) {
( mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
// (mLastFailedResult.isTemporalRedirection() && mLastFailedResult.isIdPRedirection() &&
( mLastFailedResult.isIdPRedirection() &&
- AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType()))
+ MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
)
);
// TODO put something smart in the contentIntent below for all the possible errors
import android.os.IBinder;\r
\r
/**\r
- * Background service for syncing files to our local Database\r
+ * Background service for synchronizing remote files with their local state.\r
* \r
- * @author Bartek Przybylski\r
+ * Serves as a connector to an instance of {@link FileSyncAdapter}, as required by standard Android APIs. \r
* \r
+ * @author Bartek Przybylski\r
+ * @author David A. Velasco\r
*/\r
public class FileSyncService extends Service {\r
+ \r
public static final String SYNC_MESSAGE = "ACCOUNT_SYNC";\r
public static final String SYNC_FOLDER_REMOTE_PATH = "SYNC_FOLDER_REMOTE_PATH";\r
public static final String IN_PROGRESS = "SYNC_IN_PROGRESS";\r
public static final String ACCOUNT_NAME = "ACCOUNT_NAME";\r
public static final String SYNC_RESULT = "SYNC_RESULT";\r
\r
+ public String getSyncMessage(){\r
+ return getClass().getName().toString() + SYNC_MESSAGE;\r
+ }\r
/*\r
* {@inheritDoc}\r
*/\r
public IBinder onBind(Intent intent) {\r
return new FileSyncAdapter(getApplicationContext(), true).getSyncAdapterBinder();\r
}\r
+ \r
}\r
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.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
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.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.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.fragment.OCFileListFragment;
import com.owncloud.android.ui.preview.PreviewImageActivity;
--import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
import com.owncloud.android.ui.preview.PreviewVideoActivity;
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;
+ private String mDownloadAddedMessage;
+ private String mDownloadFinishMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account is valid
mHandler = new Handler();
+
+ FileDownloader downloader = new FileDownloader();
+ mDownloadAddedMessage = downloader.getDownloadAddedMessage();
+ mDownloadFinishMessage= downloader.getDownloadFinishMessage();
/// bindings to transference services
mUploadConnection = new ListServiceConnection();
/// 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
+
+
Log_OC.d(TAG, "onCreate() end");
}
}
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
) {
// the user browsed to other file ; forget the automatic preview
mWaitingToPreview = null;
- } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
+ } else if (downloadEvent.equals(mDownloadAddedMessage)) {
// grant that the right panel updates the progress bar
detailsFragment.listenForTransferProgress();
detailsFragment.updateFileDetails(true, false);
- } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+ } else if (downloadEvent.equals(mDownloadFinishMessage)) {
// update the right panel
boolean detailsFragmentChanged = false;
if (waitedPreview) {
FileFragment second = getSecondFragment();
OCFile currentDir = getCurrentDir();
if((currentDir != null && currentDir.getParentId() != 0) ||
- (second != null && second.getFile() != null)) {
+ (second != null && second.getFile() != null)) {
onBackPressed();
+
}
break;
}
}
private void startSynchronization() {
- ContentResolver.cancelSync(null, AccountAuthenticator.AUTHORITY); // cancel the current synchronizations of any ownCloud account
+ ContentResolver.cancelSync(null, MainApp.getAuthTokenType()); // cancel the current synchronizations of any ownCloud account
Bundle bundle = new Bundle();
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(
getAccount(),
- AccountAuthenticator.AUTHORITY, bundle);
+ MainApp.getAuthTokenType(), bundle);
}
@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");
}
super.onResume();
Log_OC.e(TAG, "onResume() start");
+ FileUploader fileUploader = new FileUploader();
+ FileSyncService fileSyncService = new FileSyncService();
+
// Listen for sync messages
- IntentFilter syncIntentFilter = new IntentFilter(FileSyncService.SYNC_MESSAGE);
+ IntentFilter syncIntentFilter = new IntentFilter(fileSyncService.getSyncMessage());
mSyncBroadcastReceiver = new SyncBroadcastReceiver();
registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
// Listen for upload messages
- IntentFilter uploadIntentFilter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+ IntentFilter uploadIntentFilter = new IntentFilter(fileUploader.getUploadFinishMessage());
mUploadFinishReceiver = new UploadFinishReceiver();
registerReceiver(mUploadFinishReceiver, uploadIntentFilter);
// Listen for download messages
- IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
- downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+ IntentFilter downloadIntentFilter = new IntentFilter(mDownloadAddedMessage);
+ downloadIntentFilter.addAction(mDownloadFinishMessage);
mDownloadFinishReceiver = new DownloadFinishReceiver();
registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
/**
* 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);
+// }
+// }
+// }
}
public void onResume() {
super.onResume();
mUploadFinishReceiver = new UploadFinishReceiver();
- IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+ FileUploader fileUploader = new FileUploader();
+ IntentFilter filter = new IntentFilter(fileUploader.getUploadFinishMessage());
getActivity().registerReceiver(mUploadFinishReceiver, filter);
}
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.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
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;
private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
- private DataStorageManager mStorageManager;
+ private FileDataStorageManager mStorageManager;
private ViewPager mViewPager;
private PreviewImagePagerAdapter mPreviewImagePagerAdapter;
private boolean mFullScreen;
-
+ private String mDownloadAddedMessage;
+ private String mDownloadFinishMessage;
+
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
} else {
mRequestWaitingForBinder = false;
}
+
+ FileDownloader downloader = new FileDownloader();
+ mDownloadAddedMessage = downloader.getDownloadAddedMessage();
+ mDownloadFinishMessage= downloader.getDownloadFinishMessage();
}
private void initViewPager() {
//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);
super.onResume();
//Log.e(TAG, "ACTIVITY, ONRESUME");
mDownloadFinishReceiver = new DownloadFinishReceiver();
- IntentFilter filter = new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
- filter.addAction(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
+
+ IntentFilter filter = new IntentFilter(mDownloadFinishMessage);
+ filter.addAction(mDownloadAddedMessage);
registerReceiver(mDownloadFinishReceiver, filter);
}
boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
//boolean isOffscreen = Math.abs((mViewPager.getCurrentItem() - position)) <= mViewPager.getOffscreenPageLimit();
- if (position >= 0 && intent.getAction().equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+ if (position >= 0 && intent.getAction().equals(mDownloadFinishMessage)) {
if (downloadWasFine) {
mPreviewImagePagerAdapter.updateFile(position, file);
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 org.apache.http.params.CoreProtocolPNames;
import com.owncloud.android.Log_OC;
+ import com.owncloud.android.MainApp;
- import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.network.BearerAuthScheme;
import com.owncloud.android.network.BearerCredentials;
getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
mFollowRedirects = true;
mSsoSessionCookie = null;
- mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD;
+ mAuthTokenType = MainApp.getAuthTokenTypePass();
}
public void setBearerCredentials(String accessToken) {
mCredentials = new BearerCredentials(accessToken);
getState().setCredentials(AuthScope.ANY, mCredentials);
mSsoSessionCookie = null;
- mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN;
+ mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();
}
public void setBasicCredentials(String username, String password) {
mCredentials = new UsernamePasswordCredentials(username, password);
getState().setCredentials(AuthScope.ANY, mCredentials);
mSsoSessionCookie = null;
- mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD;
+ mAuthTokenType = MainApp.getAuthTokenTypePass();
}
public void setSsoSessionCookie(String accessToken) {
getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
mSsoSessionCookie = accessToken;
mCredentials = null;
- mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE;
+ mAuthTokenType = MainApp.getAuthTokenTypeSamlSessionCookie();
}
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) {