X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/21ec36e39ff79217886a55045611598295c08322..refs/heads/master:/src/com/owncloud/android/services/OperationsService.java diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java index 7667e90a..b8658c95 100644 --- a/src/com/owncloud/android/services/OperationsService.java +++ b/src/com/owncloud/android/services/OperationsService.java @@ -19,11 +19,21 @@ package com.owncloud.android.services; -import java.io.IOException; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentMap; +import android.accounts.Account; +import android.accounts.AccountsException; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; +import android.app.Service; +import android.content.Intent; +import android.net.Uri; +import android.os.Binder; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.util.Pair; import com.owncloud.android.MainApp; import com.owncloud.android.R; @@ -42,9 +52,10 @@ import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation; -import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.operations.CopyFileOperation; import com.owncloud.android.operations.CreateFolderOperation; -import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.operations.CreateShareViaLinkOperation; +import com.owncloud.android.operations.CreateShareWithShareeOperation; import com.owncloud.android.operations.GetServerInfoOperation; import com.owncloud.android.operations.MoveFileOperation; import com.owncloud.android.operations.OAuth2GetAccessToken; @@ -52,29 +63,21 @@ 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.operations.UnshareOperation; +import com.owncloud.android.operations.UpdateShareViaLinkOperation; +import com.owncloud.android.operations.common.SyncOperation; -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AccountsException; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; -import android.app.Service; -import android.content.Intent; -import android.net.Uri; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.util.Pair; +import java.io.IOException; +import java.util.Calendar; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; public class OperationsService extends Service { - + private static final String TAG = OperationsService.class.getSimpleName(); - + public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_SERVER_URL = "SERVER_URL"; public static final String EXTRA_OAUTH2_QUERY_PARAMETERS = "OAUTH2_QUERY_PARAMETERS"; @@ -87,12 +90,19 @@ public class OperationsService extends Service { 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"; - public static final String EXTRA_PASSWORD_SHARE = "PASSWORD_SHARE"; + public static final String EXTRA_SHARE_PASSWORD = "SHARE_PASSWORD"; + public static final String EXTRA_SHARE_TYPE = "SHARE_TYPE"; + public static final String EXTRA_SHARE_WITH = "SHARE_WITH"; + public static final String EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS = "SHARE_EXPIRATION_YEAR"; + public static final String EXTRA_SHARE_EXPIRATION_MONTH_OF_YEAR = "SHARE_EXPIRATION_MONTH_OF_YEAR"; + public static final String EXTRA_SHARE_EXPIRATION_DAY_OF_MONTH = "SHARE_EXPIRATION_DAY_OF_MONTH"; public static final String EXTRA_COOKIE = "COOKIE"; - - public static final String ACTION_CREATE_SHARE = "CREATE_SHARE"; + + public static final String ACTION_CREATE_SHARE_VIA_LINK = "CREATE_SHARE_VIA_LINK"; + public static final String ACTION_CREATE_SHARE_WITH_SHAREE = "CREATE_SHARE_WITH_SHAREE"; public static final String ACTION_UNSHARE = "UNSHARE"; + public static final String ACTION_UPDATE_SHARE = "UPDATE_SHARE"; public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO"; public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN"; public static final String ACTION_GET_USER_NAME = "GET_USER_NAME"; @@ -100,24 +110,25 @@ public class OperationsService extends Service { 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_SYNC_FOLDER = "SYNC_FOLDER"; public static final String ACTION_MOVE_FILE = "MOVE_FILE"; - + public static final String ACTION_COPY_FILE = "COPY_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 ConcurrentMap> - mUndispatchedFinishedOperations = + private ConcurrentMap> + mUndispatchedFinishedOperations = new ConcurrentHashMap>(); - + private static class Target { public Uri mServerUrl = null; public Account mAccount = null; public String mCookie = null; - + public Target(Account account, Uri serverUrl, String cookie) { mAccount = account; mServerUrl = serverUrl; @@ -151,11 +162,11 @@ public class OperationsService extends Service { mSyncFolderHandler = new SyncFolderHandler(thread.getLooper(), this); } - + /** * Entry point to add a new operation to the queue of operations. - * - * New operations are added calling to startService(), resulting in a call to this method. + *

+ * 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. */ @Override @@ -200,8 +211,8 @@ public class OperationsService extends Service { // Saving cookies try { OwnCloudClientManagerFactory.getDefaultSingleton(). - saveAllClients(this, MainApp.getAccountType()); - + saveAllClients(this, MainApp.getAccountType()); + // TODO - get rid of these exceptions } catch (AccountNotFoundException e) { e.printStackTrace(); @@ -212,7 +223,7 @@ public class OperationsService extends Service { } catch (IOException e) { e.printStackTrace(); } - + mUndispatchedFinishedOperations.clear(); mOperationsBinder = null; @@ -227,16 +238,15 @@ public class OperationsService extends Service { } /** - * Provides a binder object that clients can use to perform actions on the queue of operations, - * except the addition of new operations. + * 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 mOperationsBinder; } - + /** * Called when ALL the bound clients were unbound. */ @@ -248,20 +258,20 @@ public class OperationsService extends Service { /** - * Binder to let client components to perform actions on the queue of operations. - * - * It provides by itself the available operations. + * Binder to let client components to perform actions on the queue of operations. + *

+ * It provides by itself the available operations. */ public class OperationsServiceBinder extends Binder /* implements OnRemoteOperationListener */ { - - /** + + /** * Map of listeners that will be reported about the end of operations from a * {@link OperationsServiceBinder} instance */ - private ConcurrentMap mBoundListeners = + private final ConcurrentMap mBoundListeners = new ConcurrentHashMap(); - - private ServiceHandler mServiceHandler = null; + + private ServiceHandler mServiceHandler = null; public OperationsServiceBinder(ServiceHandler serviceHandler) { mServiceHandler = serviceHandler; @@ -280,15 +290,15 @@ public class OperationsService extends Service { public void clearListeners() { - + mBoundListeners.clear(); } - + /** * Adds a listener interested in being reported about the end of operations. - * - * @param listener Object to notify about the end of operations. + * + * @param listener Object to notify about the end of operations. * @param callbackHandler {@link Handler} to access the listener without * breaking Android threading protection. */ @@ -298,15 +308,15 @@ public class OperationsService extends Service { mBoundListeners.put(listener, callbackHandler); } } - - + + /** * Removes a listener from the list of objects interested in the being reported about * the end of operations. * * @param listener Object to notify about progress of transfer. */ - public void removeOperationListener (OnRemoteOperationListener listener) { + public void removeOperationListener(OnRemoteOperationListener listener) { synchronized (mBoundListeners) { mBoundListeners.remove(listener); } @@ -314,8 +324,8 @@ public class OperationsService extends Service { /** - * TODO - IMPORTANT: update implementation when more operations are moved into the service - * + * TODO - IMPORTANT: update implementation when more operations are moved into the service + * * @return 'True' when an operation that enforces the user to wait for completion is * in process. */ @@ -343,8 +353,8 @@ public class OperationsService extends Service { return Long.MAX_VALUE; } } - - + + public boolean dispatchResultIfFinished(int operationId, OnRemoteOperationListener listener) { Pair undispatched = @@ -378,8 +388,8 @@ public class OperationsService extends Service { /** - * Operations worker. Performs the pending operations in the order they were requested. - * + * Operations 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 ServiceHandler extends Handler { @@ -388,8 +398,8 @@ public class OperationsService extends Service { OperationsService mService; - - + + private ConcurrentLinkedQueue> mPendingOperations = new ConcurrentLinkedQueue>(); private RemoteOperation mCurrentOperation = null; @@ -412,7 +422,7 @@ public class OperationsService extends Service { Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } - + /** * Performs the next operation in the queue @@ -457,7 +467,8 @@ public class OperationsService extends Service { // TODO refactor to run GetUserName as AsyncTask in the context of // AuthenticatorActivity credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials( - mLastTarget.mCookie); // SAML SSO + null, // unknown + mLastTarget.mCookie); // SAML SSO } OwnCloudAccount ocAccount = new OwnCloudAccount( mLastTarget.mServerUrl, credentials); @@ -474,7 +485,7 @@ public class OperationsService extends Service { } 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", @@ -514,9 +525,9 @@ public class OperationsService extends Service { } - + } - + /** * Creates a new operation, as described by operationIntent. @@ -534,7 +545,7 @@ public class OperationsService extends Service { 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); @@ -546,28 +557,66 @@ public class OperationsService extends Service { ); String action = operationIntent.getAction(); - if (action.equals(ACTION_CREATE_SHARE)) { // Create Share + if (action.equals(ACTION_CREATE_SHARE_VIA_LINK)) { // Create public share via link String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - String password = operationIntent.getStringExtra(EXTRA_PASSWORD_SHARE); + String password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD); Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT); if (remotePath.length() > 0) { - operation = new CreateShareOperation(OperationsService.this, remotePath, - ShareType.PUBLIC_LINK, - "", false, password, 1, sendIntent); + operation = new CreateShareViaLinkOperation( + remotePath, + password, + sendIntent + ); } - + + } else if (ACTION_UPDATE_SHARE.equals(action)) { + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + if (remotePath.length() > 0) { + operation = new UpdateShareViaLinkOperation(remotePath); + + String password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD); + ((UpdateShareViaLinkOperation)operation).setPassword(password); + + long expirationDate = operationIntent.getLongExtra( + EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS, + 0 + ); + ((UpdateShareViaLinkOperation)operation).setExpirationDate( + expirationDate + ); + } + + } else if (action.equals(ACTION_CREATE_SHARE_WITH_SHAREE)) { + // Create private share with user or group + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String shareeName = operationIntent.getStringExtra(EXTRA_SHARE_WITH); + ShareType shareType = (ShareType) operationIntent.getSerializableExtra(EXTRA_SHARE_TYPE); + if (remotePath.length() > 0) { + operation = new CreateShareWithShareeOperation( + remotePath, + shareeName, + shareType + ); + } + } else if (action.equals(ACTION_UNSHARE)) { // Unshare file String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + ShareType shareType = (ShareType) operationIntent. + getSerializableExtra(EXTRA_SHARE_TYPE); + String shareWith = operationIntent.getStringExtra(EXTRA_SHARE_WITH); if (remotePath.length() > 0) { - operation = new UnshareLinkOperation( - remotePath, - OperationsService.this); + operation = new UnshareOperation( + remotePath, + shareType, + shareWith, + 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 = @@ -577,7 +626,7 @@ public class OperationsService extends Service { getString(R.string.oauth2_redirect_uri), getString(R.string.oauth2_grant_type), oauth2QueryParameters); - + } else if (action.equals(ACTION_GET_USER_NAME)) { // Get User Name operation = new GetRemoteUserNameOperation(); @@ -601,7 +650,7 @@ public class OperationsService extends Service { 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); @@ -612,7 +661,7 @@ public class OperationsService extends Service { ); } else if (action.equals(ACTION_SYNC_FOLDER)) { - // Sync file + // Sync folder (all its descendant files are sync'ed) String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); operation = new SynchronizeFolderOperation( this, // TODO remove this dependency from construction time @@ -620,14 +669,19 @@ public class OperationsService extends Service { 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); + operation = new MoveFileOperation(remotePath, newParentPath, account); + + } else if (action.equals(ACTION_COPY_FILE)) { + // Copy file/folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH); + operation = new CopyFileOperation(remotePath, newParentPath, account); } - } } catch (IllegalArgumentException e) { @@ -641,11 +695,11 @@ public class OperationsService extends Service { return null; } } - + /** * Sends a broadcast when a new operation is added to the queue. - * + * * Local broadcasts are only delivered to activities in the same process, but can't be * done sticky :\ * @@ -655,43 +709,43 @@ public class OperationsService extends Service { private void sendBroadcastNewOperation(Target target, RemoteOperation operation) { Intent intent = new Intent(ACTION_OPERATION_ADDED); if (target.mAccount != null) { - intent.putExtra(EXTRA_ACCOUNT, target.mAccount); + intent.putExtra(EXTRA_ACCOUNT, target.mAccount); } else { - intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); + intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); } //LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); //lbm.sendBroadcast(intent); sendStickyBroadcast(intent); } - + // TODO - maybe add a notification for real start of operations - + /** * Sends a LOCAL broadcast when an operations finishes in order to the interested activities c * an update their view * * Local broadcasts are only delivered to activities in the same process. - * - * @param target Account or URL pointing to an OC server. - * @param operation Finished operation. - * @param result Result of the operation. + * + * @param target Account or URL pointing to an OC server. + * @param operation Finished operation. + * @param result Result of the operation. */ private void sendBroadcastOperationFinished(Target target, RemoteOperation operation, RemoteOperationResult result) { Intent intent = new Intent(ACTION_OPERATION_FINISHED); intent.putExtra(EXTRA_RESULT, result); if (target.mAccount != null) { - intent.putExtra(EXTRA_ACCOUNT, target.mAccount); + intent.putExtra(EXTRA_ACCOUNT, target.mAccount); } else { - intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); + intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); } //LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); //lbm.sendBroadcast(intent); sendStickyBroadcast(intent); } - + /** * Notifies the currently subscribed listeners about the end of an operation. * @@ -718,10 +772,9 @@ public class OperationsService extends Service { } } if (count == 0) { - //mOperationResults.put(operation.hashCode(), result); - Pair undispatched = + Pair undispatched = new Pair(operation, result); - mUndispatchedFinishedOperations.put(operation.hashCode(), undispatched); + mUndispatchedFinishedOperations.put(((Runnable) operation).hashCode(), undispatched); } Log_OC.d(TAG, "Called " + count + " listeners"); }