Added construction of SynchronizeFolderOperation to OperationService
[pub/Android/ownCloud.git] / src / com / owncloud / android / services / OperationsService.java
index 3c56dea..b97c424 100644 (file)
@@ -35,6 +35,7 @@ import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundExce
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
 import com.owncloud.android.lib.resources.shares.ShareType;
 import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation;
@@ -42,12 +43,13 @@ import com.owncloud.android.operations.common.SyncOperation;
 import com.owncloud.android.operations.CreateFolderOperation;
 import com.owncloud.android.operations.CreateShareOperation;
 import com.owncloud.android.operations.GetServerInfoOperation;
+import com.owncloud.android.operations.MoveFileOperation;
 import com.owncloud.android.operations.OAuth2GetAccessToken;
 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.Log_OC;
 
 import android.accounts.Account;
 import android.accounts.AccountsException;
@@ -71,7 +73,6 @@ public class OperationsService extends Service {
     
     public static final String EXTRA_ACCOUNT = "ACCOUNT";
     public static final String EXTRA_SERVER_URL = "SERVER_URL";
-    public static final String EXTRA_AUTH_TOKEN_TYPE = "AUTH_TOKEN_TYPE";
     public static final String EXTRA_OAUTH2_QUERY_PARAMETERS = "OAUTH2_QUERY_PARAMETERS";
     public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
     public static final String EXTRA_SEND_INTENT = "SEND_INTENT";
@@ -80,13 +81,13 @@ public class OperationsService extends Service {
     public static final String EXTRA_CREATE_FULL_PATH = "CREATE_FULL_PATH";
     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";
     
     // 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 EXTRA_PASSWORD = "PASSWORD";
     public static final String EXTRA_AUTH_TOKEN = "AUTH_TOKEN";
-    public static final String EXTRA_FOLLOW_REDIRECTS = "FOLLOW_REDIRECTS";
     public static final String EXTRA_COOKIE = "COOKIE";
     
     public static final String ACTION_CREATE_SHARE = "CREATE_SHARE";
@@ -99,10 +100,13 @@ 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_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>>();
 
@@ -116,17 +120,15 @@ public class OperationsService extends Service {
         public String mUsername = null;
         public String mPassword = null;
         public String mAuthToken = null;
-        public boolean mFollowRedirects = true;
         public String mCookie = null;
         
         public Target(Account account, Uri serverUrl, String username, String password, String authToken,
-                boolean followRedirects, String cookie) {
+                String cookie) {
             mAccount = account;
             mServerUrl = serverUrl;
             mUsername = username;
             mPassword = password;
             mAuthToken = authToken;
-            mFollowRedirects = followRedirects;
             mCookie = cookie;
         }
     }
@@ -159,17 +161,21 @@ public class OperationsService extends Service {
      * 
      * 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" );
+        if (ACTION_SYNC_FOLDER.equals(intent.getAction())) {
+            // WIP: for the moment, only SYNC_FOLDER is expected here; the rest of the operations are requested through
+            // the Binder
+            Pair<Target, RemoteOperation> itemToQueue = newOperation(intent);
+            if (itemToQueue != null) {
+                mPendingOperations.add(itemToQueue);
+            }
+        }
+        
         Message msg = mServiceHandler.obtainMessage();
         msg.arg1 = startId;
         mServiceHandler.sendMessage(msg);
-        //Log_OC.wtf(TAG, "onStartCommand end" );
         return START_NOT_STICKY;
     }
 
@@ -286,126 +292,26 @@ public class OperationsService extends Service {
 
 
         /**
-         * 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);
-                    boolean followRedirects = operationIntent.getBooleanExtra(EXTRA_FOLLOW_REDIRECTS, true);
-                    String cookie = operationIntent.getStringExtra(EXTRA_COOKIE);
-                    target = new Target(
-                            account, 
-                            (serverUrl == null) ? null : Uri.parse(serverUrl),
-                            username,
-                            password,
-                            authToken,
-                            followRedirects,
-                            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(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
-                        String authTokenType = 
-                                operationIntent.getStringExtra(EXTRA_AUTH_TOKEN_TYPE);
-                        operation = new GetServerInfoOperation(
-                                serverUrl, authTokenType, 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, true);
-                        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, account, 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());
-                    }
-                    
-                }
-                    
-            } 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) {
+                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);
@@ -451,6 +357,136 @@ public class OperationsService extends Service {
     
 
     /**
+     * Creates a new operation, as described by operationIntent.
+     * 
+     * @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(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);
+                    boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true);
+                    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;
+        }
+    }
+    
+
+    /**
      * Performs the next operation in the queue
      */
     private void nextOperation() {
@@ -480,16 +516,19 @@ public class OperationsService extends Service {
                                         getContentResolver());
                     } else {
                         OwnCloudCredentials credentials = null;
-                        if (mLastTarget.mUsername != null) {
+                        if (mLastTarget.mUsername != null && 
+                                mLastTarget.mUsername.length() > 0) {
                             credentials = OwnCloudCredentialsFactory.newBasicCredentials(
                                     mLastTarget.mUsername, 
                                     mLastTarget.mPassword);  // basic
                             
-                        } else if (mLastTarget.mAuthToken != null) {
+                        } else if (mLastTarget.mAuthToken != null && 
+                                mLastTarget.mAuthToken.length() > 0) {
                             credentials = OwnCloudCredentialsFactory.newBearerCredentials(
                                     mLastTarget.mAuthToken);  // bearer token
                             
-                        } else if (mLastTarget.mCookie != null) {
+                        } else if (mLastTarget.mCookie != null &&
+                                mLastTarget.mCookie.length() > 0) {
                             credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(
                                     mLastTarget.mCookie); // SAML SSO
                         }
@@ -497,7 +536,6 @@ public class OperationsService extends Service {
                                 mLastTarget.mServerUrl, credentials);
                         mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
                                 getClientFor(ocAccount, this);
-                        mOwnCloudClient.setFollowRedirects(mLastTarget.mFollowRedirects);
                         mStorageManager = null;
                     }
                 }