import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.operations.RemoveFileOperation;
import com.owncloud.android.operations.RenameFileOperation;
import com.owncloud.android.operations.SynchronizeFileOperation;
+import com.owncloud.android.operations.SynchronizeFolderOperation;
import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.utils.FileStorageUtils;
import android.accounts.Account;
import android.accounts.AccountsException;
public static final String EXTRA_SYNC_FILE_CONTENTS = "SYNC_FILE_CONTENTS";
public static final String EXTRA_RESULT = "RESULT";
public static final String EXTRA_NEW_PARENT_PATH = "NEW_PARENT_PATH";
-
+ public static final String EXTRA_FILE = "FILE";
+
// TODO review if ALL OF THEM are necessary
public static final String EXTRA_SUCCESS_IF_ABSENT = "SUCCESS_IF_ABSENT";
public static final String EXTRA_USERNAME = "USERNAME";
public static final String ACTION_REMOVE = "REMOVE";
public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER";
public static final String ACTION_SYNC_FILE = "SYNC_FILE";
+ public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER"; // for the moment, just to download
+ public static final String ACTION_CANCEL_SYNC_FOLDER = "CANCEL_SYNC_FOLDER"; // for the moment, just to download
public static final String ACTION_MOVE_FILE = "MOVE_FILE";
public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED";
public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + ".OPERATION_FINISHED";
- private ConcurrentLinkedQueue<Pair<Target, RemoteOperation>> mPendingOperations =
- new ConcurrentLinkedQueue<Pair<Target, RemoteOperation>>();
private ConcurrentMap<Integer, Pair<RemoteOperation, RemoteOperationResult>>
mUndispatchedFinishedOperations =
}
}
- private Looper mServiceLooper;
- private ServiceHandler mServiceHandler;
- private OperationsServiceBinder mBinder;
- private OwnCloudClient mOwnCloudClient = null;
- private Target mLastTarget = null;
- private FileDataStorageManager mStorageManager;
- private RemoteOperation mCurrentOperation = null;
+ private ServiceHandler mOperationsHandler;
+ private OperationsServiceBinder mOperationsBinder;
+ private SyncFolderHandler mSyncFolderHandler;
/**
* Service initialization
@Override
public void onCreate() {
super.onCreate();
- HandlerThread thread = new HandlerThread("Operations service thread", Process.THREAD_PRIORITY_BACKGROUND);
+ /// First worker thread for most of operations
+ HandlerThread thread = new HandlerThread("Operations thread", Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+ mOperationsHandler = new ServiceHandler(thread.getLooper(), this);
+ mOperationsBinder = new OperationsServiceBinder(mOperationsHandler);
+
+ /// Separated worker thread for download of folders (WIP)
+ thread = new HandlerThread("Syncfolder thread", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
- mServiceLooper = thread.getLooper();
- mServiceHandler = new ServiceHandler(mServiceLooper, this);
- mBinder = new OperationsServiceBinder();
+ mSyncFolderHandler = new SyncFolderHandler(thread.getLooper(), this);
}
*
* New operations are added calling to startService(), resulting in a call to this method.
* This ensures the service will keep on working although the caller activity goes away.
- *
- * IMPORTANT: the only operations performed here right now is {@link GetSharedFilesOperation}. The class
- * is taking advantage of it due to time constraints.
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- //Log_OC.wtf(TAG, "onStartCommand init" );
- Message msg = mServiceHandler.obtainMessage();
- msg.arg1 = startId;
- mServiceHandler.sendMessage(msg);
- //Log_OC.wtf(TAG, "onStartCommand end" );
+ // WIP: for the moment, only SYNC_FOLDER and CANCEL_SYNC_FOLDER is expected here;
+ // the rest of the operations are requested through the Binder
+ if (ACTION_SYNC_FOLDER.equals(intent.getAction())) {
+ if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_REMOTE_PATH)) {
+ Log_OC.e(TAG, "Not enough information provided in intent");
+ return START_NOT_STICKY;
+ }
+ Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
+ String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
+
+ Pair<Account, String> itemSyncKey = new Pair<Account , String>(account, remotePath);
+
+ Pair<Target, RemoteOperation> itemToQueue = newOperation(intent);
+ if (itemToQueue != null) {
+ mSyncFolderHandler.add(account, remotePath, (SynchronizeFolderOperation)itemToQueue.second);
+ sendBroadcastNewSyncFolder(account, remotePath);
+ Message msg = mSyncFolderHandler.obtainMessage();
+ msg.arg1 = startId;
+ msg.obj = itemSyncKey;
+ mSyncFolderHandler.sendMessage(msg);
+ }
+ } else if (ACTION_CANCEL_SYNC_FOLDER.equals(intent.getAction())) {
+ if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_FILE)) {
+ Log_OC.e(TAG, "Not enough information provided in intent");
+ return START_NOT_STICKY;
+ }
+ Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
+ OCFile file = intent.getParcelableExtra(EXTRA_FILE);
+
+ // Cancel operation
+ mSyncFolderHandler.cancel(account,file);
+ } else {
+ Message msg = mOperationsHandler.obtainMessage();
+ msg.arg1 = startId;
+ mOperationsHandler.sendMessage(msg);
+ }
+
return START_NOT_STICKY;
}
+ /**
+ * TODO remove this method when "folder synchronization" replaces "folder download"; this is a fast and ugly
+ * patch.
+ */
+ private void sendBroadcastNewSyncFolder(Account account, String remotePath) {
+ Intent added = new Intent(FileDownloader.getDownloadAddedMessage());
+ added.putExtra(FileDownloader.ACCOUNT_NAME, account.name);
+ added.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath);
+ added.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name) + remotePath);
+ sendStickyBroadcast(added);
+ }
+
+
@Override
public void onDestroy() {
//Log_OC.wtf(TAG, "onDestroy init" );
super.onDestroy();
}
-
/**
* Provides a binder object that clients can use to perform actions on the queue of operations,
* except the addition of new operations.
@Override
public IBinder onBind(Intent intent) {
//Log_OC.wtf(TAG, "onBind" );
- return mBinder;
+ return mOperationsBinder;
}
*/
@Override
public boolean onUnbind(Intent intent) {
- ((OperationsServiceBinder)mBinder).clearListeners();
+ ((OperationsServiceBinder)mOperationsBinder).clearListeners();
return false; // not accepting rebinding (default behaviour)
}
-
+
/**
* Binder to let client components to perform actions on the queue of operations.
*
private ConcurrentMap<OnRemoteOperationListener, Handler> mBoundListeners =
new ConcurrentHashMap<OnRemoteOperationListener, Handler>();
+ private ServiceHandler mServiceHandler = null;
+
+
+ public OperationsServiceBinder(ServiceHandler serviceHandler) {
+ mServiceHandler = serviceHandler;
+ }
+
+
/**
* Cancels an operation
*
* @return 'True' when an operation that enforces the user to wait for completion is in process.
*/
public boolean isPerformingBlockingOperation() {
- return (!mPendingOperations.isEmpty());
+ return (!mServiceHandler.mPendingOperations.isEmpty());
}
/**
- * Creates and adds to the queue a new operation, as described by operationIntent
+ * Creates and adds to the queue a new operation, as described by operationIntent.
+ *
+ * Calls startService to make the operation is processed by the ServiceHandler.
*
* @param operationIntent Intent describing a new operation to queue and execute.
* @return Identifier of the operation created, or null if failed.
*/
- public long newOperation(Intent operationIntent) {
- RemoteOperation operation = null;
- Target target = null;
- try {
- if (!operationIntent.hasExtra(EXTRA_ACCOUNT) &&
- !operationIntent.hasExtra(EXTRA_SERVER_URL)) {
- Log_OC.e(TAG, "Not enough information provided in intent");
-
- } else {
- Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT);
- String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL);
- String username = operationIntent.getStringExtra(EXTRA_USERNAME);
- String password = operationIntent.getStringExtra(EXTRA_PASSWORD);
- String authToken = operationIntent.getStringExtra(EXTRA_AUTH_TOKEN);
- String cookie = operationIntent.getStringExtra(EXTRA_COOKIE);
- target = new Target(
- account,
- (serverUrl == null) ? null : Uri.parse(serverUrl),
- username,
- password,
- authToken,
- cookie
- );
-
- String action = operationIntent.getAction();
- if (action.equals(ACTION_CREATE_SHARE)) { // Create Share
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT);
- if (remotePath.length() > 0) {
- operation = new CreateShareOperation(OperationsService.this, remotePath, ShareType.PUBLIC_LINK,
- "", false, "", 1, sendIntent);
- }
-
- } else if (action.equals(ACTION_UNSHARE)) { // Unshare file
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- if (remotePath.length() > 0) {
- operation = new UnshareLinkOperation(
- remotePath,
- OperationsService.this);
- }
-
- } else if (action.equals(ACTION_GET_SERVER_INFO)) {
- // check OC server and get basic information from it
- operation = new GetServerInfoOperation(serverUrl, OperationsService.this);
-
- } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) {
- /// GET ACCESS TOKEN to the OAuth server
- String oauth2QueryParameters =
- operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS);
- operation = new OAuth2GetAccessToken(
- getString(R.string.oauth2_client_id),
- getString(R.string.oauth2_redirect_uri),
- getString(R.string.oauth2_grant_type),
- oauth2QueryParameters);
-
- } else if (action.equals(ACTION_EXISTENCE_CHECK)) {
- // Existence Check
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- boolean successIfAbsent = operationIntent.getBooleanExtra(EXTRA_SUCCESS_IF_ABSENT, false);
- operation = new ExistenceCheckRemoteOperation(remotePath, OperationsService.this, successIfAbsent);
-
- } else if (action.equals(ACTION_GET_USER_NAME)) {
- // Get User Name
- operation = new GetRemoteUserNameOperation();
-
- } else if (action.equals(ACTION_RENAME)) {
- // Rename file or folder
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- String newName = operationIntent.getStringExtra(EXTRA_NEWNAME);
- operation = new RenameFileOperation(remotePath, newName);
-
- } else if (action.equals(ACTION_REMOVE)) {
- // Remove file or folder
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, false);
- operation = new RemoveFileOperation(remotePath, onlyLocalCopy);
-
- } else if (action.equals(ACTION_CREATE_FOLDER)) {
- // Create Folder
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, true);
- operation = new CreateFolderOperation(remotePath, createFullPath);
-
- } else if (action.equals(ACTION_SYNC_FILE)) {
- // Sync file
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true);
- operation = new SynchronizeFileOperation(remotePath, account, syncFileContents, getApplicationContext());
- } else if (action.equals(ACTION_MOVE_FILE)) {
- // Move file/folder
- String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
- String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH);
- operation = new MoveFileOperation(remotePath,newParentPath,account);
- }
-
- }
-
- } catch (IllegalArgumentException e) {
- Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
- operation = null;
- }
-
- if (operation != null) {
- mPendingOperations.add(new Pair<Target , RemoteOperation>(target, operation));
+ public long queueNewOperation(Intent operationIntent) {
+ Pair<Target, RemoteOperation> itemToQueue = newOperation(operationIntent);
+ if (itemToQueue != null) {
+ mServiceHandler.mPendingOperations.add(itemToQueue);
startService(new Intent(OperationsService.this, OperationsService.class));
- //Log_OC.wtf(TAG, "New operation added, opId: " + operation.hashCode());
- // better id than hash? ; should be good enough by the time being
- return operation.hashCode();
+ return itemToQueue.second.hashCode();
} else {
- //Log_OC.wtf(TAG, "New operation failed, returned Long.MAX_VALUE");
return Long.MAX_VALUE;
}
}
-
+
+
public boolean dispatchResultIfFinished(int operationId, OnRemoteOperationListener listener) {
Pair<RemoteOperation, RemoteOperationResult> undispatched =
mUndispatchedFinishedOperations.remove(operationId);
return true;
//Log_OC.wtf(TAG, "Sending callback later");
} else {
- if (!mPendingOperations.isEmpty()) {
+ if (!mServiceHandler.mPendingOperations.isEmpty()) {
return true;
} else {
return false;
//Log_OC.wtf(TAG, "Not finished yet");
}
}
+
+
+ /**
+ * Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting to download.
+ *
+ * If 'file' is a directory, returns 'true' if some of its descendant files is downloading or waiting to download.
+ *
+ * @param account ownCloud account where the remote file is stored.
+ * @param file A file that could be affected
+ */
+ public boolean isSynchronizing(Account account, String remotePath) {
+ return mSyncFolderHandler.isSynchronizing(account, remotePath);
+ }
}
-
-
+
+
+ /**
+ * SyncFolder worker. Performs the pending operations in the order they were requested.
+ *
+ * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}.
+ */
+ private static class SyncFolderHandler extends Handler {
+
+ // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak
+
+ OperationsService mService;
+
+ private ConcurrentMap<String,SynchronizeFolderOperation> mPendingOperations =
+ new ConcurrentHashMap<String,SynchronizeFolderOperation>();
+ private OwnCloudClient mOwnCloudClient = null;
+ private FileDataStorageManager mStorageManager;
+ private SynchronizeFolderOperation mCurrentSyncOperation;
+
+
+ public SyncFolderHandler(Looper looper, OperationsService service) {
+ super(looper);
+ if (service == null) {
+ throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");
+ }
+ mService = service;
+ }
+
+
+ public boolean isSynchronizing(Account account, String remotePath) {
+ if (account == null || remotePath == null) return false;
+ String targetKey = buildRemoteName(account, remotePath);
+ synchronized (mPendingOperations) {
+ return (mPendingOperations.containsKey(targetKey));
+ }
+ }
+
+
+ @Override
+ public void handleMessage(Message msg) {
+ Pair<Account, String> itemSyncKey = (Pair<Account, String>) msg.obj;
+ doOperation(itemSyncKey.first, itemSyncKey.second);
+ mService.stopSelf(msg.arg1);
+ }
+
+
+ /**
+ * Performs the next operation in the queue
+ */
+ private void doOperation(Account account, String remotePath) {
+
+ String syncKey = buildRemoteName(account,remotePath);
+
+ synchronized(mPendingOperations) {
+ mCurrentSyncOperation = mPendingOperations.get(syncKey);
+ }
+
+ if (mCurrentSyncOperation != null) {
+ RemoteOperationResult result = null;
+
+ try {
+
+ OwnCloudAccount ocAccount = new OwnCloudAccount(account, mService);
+ mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+ getClientFor(ocAccount, mService);
+ mStorageManager = new FileDataStorageManager(
+ account,
+ mService.getContentResolver()
+ );
+
+ result = mCurrentSyncOperation.execute(mOwnCloudClient, mStorageManager);
+
+ } catch (AccountsException e) {
+ Log_OC.e(TAG, "Error while trying to get autorization", e);
+ } catch (IOException e) {
+ Log_OC.e(TAG, "Error while trying to get autorization", e);
+ } finally {
+ synchronized(mPendingOperations) {
+ mPendingOperations.remove(syncKey);
+ }
+
+ mService.dispatchResultToOperationListeners(null, mCurrentSyncOperation, result);
+ }
+ }
+ }
+
+ public void add(Account account, String remotePath, SynchronizeFolderOperation syncFolderOperation){
+ String syncKey = buildRemoteName(account,remotePath);
+ mPendingOperations.putIfAbsent(syncKey,syncFolderOperation);
+ }
+
+
+ /**
+ * Cancels a pending or current sync operation.
+ *
+ * @param account Owncloud account where the remote file is stored.
+ * @param file File
+ */
+ public void cancel(Account account, OCFile file) {
+ SynchronizeFolderOperation syncOperation = null;
+ synchronized (mPendingOperations) {
+ syncOperation = mPendingOperations.remove(buildRemoteName(account, file.getRemotePath()));
+ }
+ if (syncOperation != null) {
+ syncOperation.cancel();
+ }
+
+ /// cancellation of download needs to be done separately in any case; a SynchronizeFolderOperation
+ // may finish much sooner than the real download of the files in the folder
+ Intent intent = new Intent(mService, FileDownloader.class);
+ intent.setAction(FileDownloader.ACTION_CANCEL_FILE_DOWNLOAD);
+ intent.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
+ intent.putExtra(FileDownloader.EXTRA_FILE, file);
+ mService.startService(intent);
+ }
+
+ /**
+ * Builds a key from the account and file to download
+ *
+ * @param account Account where the file to download is stored
+ * @param path File path
+ */
+ private String buildRemoteName(Account account, String path) {
+ return account.name + path;
+ }
+ }
+
+
/**
* Operations worker. Performs the pending operations in the order they were requested.
*
*/
private static class ServiceHandler extends Handler {
// don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak
+
+
OperationsService mService;
+
+
+ private ConcurrentLinkedQueue<Pair<Target, RemoteOperation>> mPendingOperations =
+ new ConcurrentLinkedQueue<Pair<Target, RemoteOperation>>();
+ private RemoteOperation mCurrentOperation = null;
+ private Target mLastTarget = null;
+ private OwnCloudClient mOwnCloudClient = null;
+ private FileDataStorageManager mStorageManager;
+
+
public ServiceHandler(Looper looper, OperationsService service) {
super(looper);
if (service == null) {
@Override
public void handleMessage(Message msg) {
- mService.nextOperation();
+ nextOperation();
mService.stopSelf(msg.arg1);
}
- }
-
-
- /**
- * Performs the next operation in the queue
- */
- private void nextOperation() {
- //Log_OC.wtf(TAG, "nextOperation init" );
- Pair<Target, RemoteOperation> next = null;
- synchronized(mPendingOperations) {
- next = mPendingOperations.peek();
- }
-
- if (next != null) {
+ /**
+ * Performs the next operation in the queue
+ */
+ private void nextOperation() {
- mCurrentOperation = next.second;
- RemoteOperationResult result = null;
- try {
- /// prepare client object to send the request to the ownCloud server
- if (mLastTarget == null || !mLastTarget.equals(next.first)) {
- mLastTarget = next.first;
- if (mLastTarget.mAccount != null) {
- OwnCloudAccount ocAccount = new OwnCloudAccount(mLastTarget.mAccount, this);
- mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
- getClientFor(ocAccount, this);
- mStorageManager =
- new FileDataStorageManager(
- mLastTarget.mAccount,
- getContentResolver());
- } else {
- OwnCloudCredentials credentials = null;
- if (mLastTarget.mUsername != null &&
- mLastTarget.mUsername.length() > 0) {
- credentials = OwnCloudCredentialsFactory.newBasicCredentials(
- mLastTarget.mUsername,
- mLastTarget.mPassword); // basic
-
- } else if (mLastTarget.mAuthToken != null &&
- mLastTarget.mAuthToken.length() > 0) {
- credentials = OwnCloudCredentialsFactory.newBearerCredentials(
- mLastTarget.mAuthToken); // bearer token
-
- } else if (mLastTarget.mCookie != null &&
- mLastTarget.mCookie.length() > 0) {
- credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(
- mLastTarget.mCookie); // SAML SSO
+ //Log_OC.wtf(TAG, "nextOperation init" );
+
+ Pair<Target, RemoteOperation> next = null;
+ synchronized(mPendingOperations) {
+ next = mPendingOperations.peek();
+ }
+
+ if (next != null) {
+
+ mCurrentOperation = next.second;
+ RemoteOperationResult result = null;
+ try {
+ /// prepare client object to send the request to the ownCloud server
+ if (mLastTarget == null || !mLastTarget.equals(next.first)) {
+ mLastTarget = next.first;
+ if (mLastTarget.mAccount != null) {
+ OwnCloudAccount ocAccount = new OwnCloudAccount(mLastTarget.mAccount, mService);
+ mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+ getClientFor(ocAccount, mService);
+ mStorageManager = new FileDataStorageManager(
+ mLastTarget.mAccount,
+ mService.getContentResolver()
+ );
+ } else {
+ OwnCloudCredentials credentials = null;
+ if (mLastTarget.mUsername != null &&
+ mLastTarget.mUsername.length() > 0) {
+ credentials = OwnCloudCredentialsFactory.newBasicCredentials(
+ mLastTarget.mUsername,
+ mLastTarget.mPassword); // basic
+
+ } else if (mLastTarget.mAuthToken != null &&
+ mLastTarget.mAuthToken.length() > 0) {
+ credentials = OwnCloudCredentialsFactory.newBearerCredentials(
+ mLastTarget.mAuthToken); // bearer token
+
+ } else if (mLastTarget.mCookie != null &&
+ mLastTarget.mCookie.length() > 0) {
+ credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(
+ mLastTarget.mCookie); // SAML SSO
+ }
+ OwnCloudAccount ocAccount = new OwnCloudAccount(
+ mLastTarget.mServerUrl, credentials);
+ mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+ getClientFor(ocAccount, mService);
+ mStorageManager = null;
}
- OwnCloudAccount ocAccount = new OwnCloudAccount(
- mLastTarget.mServerUrl, credentials);
- mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
- getClientFor(ocAccount, this);
- mStorageManager = null;
}
- }
- /// perform the operation
- if (mCurrentOperation instanceof SyncOperation) {
- result = ((SyncOperation)mCurrentOperation).execute(mOwnCloudClient, mStorageManager);
- } else {
- result = mCurrentOperation.execute(mOwnCloudClient);
- }
+ /// perform the operation
+ if (mCurrentOperation instanceof SyncOperation) {
+ result = ((SyncOperation)mCurrentOperation).execute(mOwnCloudClient, mStorageManager);
+ } else {
+ result = mCurrentOperation.execute(mOwnCloudClient);
+ }
+
+ } catch (AccountsException e) {
+ if (mLastTarget.mAccount == null) {
+ Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e);
+ } else {
+ Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e);
+ }
+ result = new RemoteOperationResult(e);
+
+ } catch (IOException e) {
+ if (mLastTarget.mAccount == null) {
+ Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e);
+ } else {
+ Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e);
+ }
+ result = new RemoteOperationResult(e);
+ } catch (Exception e) {
+ if (mLastTarget.mAccount == null) {
+ Log_OC.e(TAG, "Unexpected error for a NULL account", e);
+ } else {
+ Log_OC.e(TAG, "Unexpected error for " + mLastTarget.mAccount.name, e);
+ }
+ result = new RemoteOperationResult(e);
- } catch (AccountsException e) {
- if (mLastTarget.mAccount == null) {
- Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e);
- } else {
- Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e);
+ } finally {
+ synchronized(mPendingOperations) {
+ mPendingOperations.poll();
+ }
}
- result = new RemoteOperationResult(e);
- } catch (IOException e) {
- if (mLastTarget.mAccount == null) {
- Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e);
- } else {
- Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e);
- }
- result = new RemoteOperationResult(e);
- } catch (Exception e) {
- if (mLastTarget.mAccount == null) {
- Log_OC.e(TAG, "Unexpected error for a NULL account", e);
- } else {
- Log_OC.e(TAG, "Unexpected error for " + mLastTarget.mAccount.name, e);
- }
- result = new RemoteOperationResult(e);
-
- } finally {
- synchronized(mPendingOperations) {
- mPendingOperations.poll();
- }
+ //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result);
+ mService.dispatchResultToOperationListeners(mLastTarget, mCurrentOperation, result);
}
-
- //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result);
- dispatchResultToOperationListeners(mLastTarget, mCurrentOperation, result);
}
+
+
+
}
- operation = new CreateShareOperation(remotePath, ShareType.PUBLIC_LINK,
+
+
+ /**
+ * Creates a new operation, as described by operationIntent.
+ *
+ * TODO - move to ServiceHandler (probably)
+ *
+ * @param operationIntent Intent describing a new operation to queue and execute.
+ * @return Pair with the new operation object and the information about its target server.
+ */
+ private Pair<Target , RemoteOperation> newOperation(Intent operationIntent) {
+ RemoteOperation operation = null;
+ Target target = null;
+ try {
+ if (!operationIntent.hasExtra(EXTRA_ACCOUNT) &&
+ !operationIntent.hasExtra(EXTRA_SERVER_URL)) {
+ Log_OC.e(TAG, "Not enough information provided in intent");
+
+ } else {
+ Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT);
+ String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL);
+ String username = operationIntent.getStringExtra(EXTRA_USERNAME);
+ String password = operationIntent.getStringExtra(EXTRA_PASSWORD);
+ String authToken = operationIntent.getStringExtra(EXTRA_AUTH_TOKEN);
+ String cookie = operationIntent.getStringExtra(EXTRA_COOKIE);
+ target = new Target(
+ account,
+ (serverUrl == null) ? null : Uri.parse(serverUrl),
+ username,
+ password,
+ authToken,
+ cookie
+ );
+
+ String action = operationIntent.getAction();
+ if (action.equals(ACTION_CREATE_SHARE)) { // Create Share
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT);
+ if (remotePath.length() > 0) {
++ operation = new CreateShareOperation(OperationsService.this, remotePath, ShareType.PUBLIC_LINK,
+ "", false, "", 1, sendIntent);
+ }
+
+ } else if (action.equals(ACTION_UNSHARE)) { // Unshare file
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ if (remotePath.length() > 0) {
+ operation = new UnshareLinkOperation(
+ remotePath,
+ OperationsService.this);
+ }
+
+ } else if (action.equals(ACTION_GET_SERVER_INFO)) {
+ // check OC server and get basic information from it
+ operation = new GetServerInfoOperation(serverUrl, OperationsService.this);
+
+ } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) {
+ /// GET ACCESS TOKEN to the OAuth server
+ String oauth2QueryParameters =
+ operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS);
+ operation = new OAuth2GetAccessToken(
+ getString(R.string.oauth2_client_id),
+ getString(R.string.oauth2_redirect_uri),
+ getString(R.string.oauth2_grant_type),
+ oauth2QueryParameters);
+
+ } else if (action.equals(ACTION_EXISTENCE_CHECK)) {
+ // Existence Check
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ boolean successIfAbsent = operationIntent.getBooleanExtra(EXTRA_SUCCESS_IF_ABSENT, false);
+ operation = new ExistenceCheckRemoteOperation(remotePath, OperationsService.this, successIfAbsent);
+
+ } else if (action.equals(ACTION_GET_USER_NAME)) {
+ // Get User Name
+ operation = new GetRemoteUserNameOperation();
+
+ } else if (action.equals(ACTION_RENAME)) {
+ // Rename file or folder
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ String newName = operationIntent.getStringExtra(EXTRA_NEWNAME);
+ operation = new RenameFileOperation(remotePath, newName);
+
+ } else if (action.equals(ACTION_REMOVE)) {
+ // Remove file or folder
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, false);
+ operation = new RemoveFileOperation(remotePath, onlyLocalCopy);
+
+ } else if (action.equals(ACTION_CREATE_FOLDER)) {
+ // Create Folder
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, true);
+ operation = new CreateFolderOperation(remotePath, createFullPath);
+
+ } else if (action.equals(ACTION_SYNC_FILE)) {
+ // Sync file
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true);
+ operation = new SynchronizeFileOperation(
+ remotePath, account, syncFileContents, getApplicationContext()
+ );
+
+ } else if (action.equals(ACTION_SYNC_FOLDER)) {
+ // Sync file
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ operation = new SynchronizeFolderOperation(
+ this, // TODO remove this dependency from construction time
+ remotePath,
+ account,
+ System.currentTimeMillis() // TODO remove this dependency from construction time
+ );
+
+ } else if (action.equals(ACTION_MOVE_FILE)) {
+ // Move file/folder
+ String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+ String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH);
+ operation = new MoveFileOperation(remotePath,newParentPath,account);
+ }
+
+ }
+
+ } catch (IllegalArgumentException e) {
+ Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
+ operation = null;
+ }
+ if (operation != null) {
+ return new Pair<Target , RemoteOperation>(target, operation);
+ } else {
+ return null;
+ }
+ }
+
/**
* Sends a broadcast when a new operation is added to the queue.
/**
* Notifies the currently subscribed listeners about the end of an operation.
- *
+ *
* @param target Account or URL pointing to an OC server.
* @param operation Finished operation.
* @param result Result of the operation.
private void dispatchResultToOperationListeners(
Target target, final RemoteOperation operation, final RemoteOperationResult result) {
int count = 0;
- Iterator<OnRemoteOperationListener> listeners = mBinder.mBoundListeners.keySet().iterator();
+ Iterator<OnRemoteOperationListener> listeners = mOperationsBinder.mBoundListeners.keySet().iterator();
while (listeners.hasNext()) {
final OnRemoteOperationListener listener = listeners.next();
- final Handler handler = mBinder.mBoundListeners.get(listener);
+ final Handler handler = mOperationsBinder.mBoundListeners.get(listener);
if (handler != null) {
handler.post(new Runnable() {
@Override
}
Log_OC.d(TAG, "Called " + count + " listeners");
}
-
-
}