+
+
+    /**
+     * 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) {
+
+                try {
+
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(account, mService);
+                    mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, mService);
+                    mStorageManager = new FileDataStorageManager(
+                            account,
+                            mService.getContentResolver()
+                    );
+
+                    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);
+                    }
+                }
+            }
+        }
+
+        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;
+        }
+    }
+
+