-  private ContentResolver mContentResolver;
-  private ContentProviderClient mContentProvider;
-  private Account mAccount;
-  
-  private static String TAG = "FileDataStorageManager";
-  
-  public FileDataStorageManager(Account account, ContentResolver cr) {
-    mContentProvider = null;
-    mContentResolver = cr;
-    mAccount = account;
-  }
-  
-  public FileDataStorageManager(Account account, ContentProviderClient cp) {
-    mContentProvider = cp;
-    mContentResolver = null;
-    mAccount = account;
-  }
-  
-  @Override
-  public OCFile getFileByPath(String path) {
-    Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
-    if (c.moveToFirst())
-      return createFileInstance(c);
-    return null;
-  }
-
-  @Override
-  public OCFile getFileById(long id) {
-    Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
-    if (c.moveToFirst())
-      return createFileInstance(c);
-    return null;
-  }
-
-  @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 boolean saveFile(OCFile file) {
-    boolean overriden = false;
-    ContentValues cv = new ContentValues();
-    cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
-    cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
-    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_PATH, file.getPath());
-    cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
-    cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
-
-    if (fileExists(file.getPath())) {
-      file.setFileId(getFileByPath(file.getPath()).getFileId());
-      overriden = true;
-      if (getContentResolver() != null) {
-        getContentResolver().update(ProviderTableMeta.CONTENT_URI,
-                                    cv,
-                                    ProviderTableMeta._ID + "=?",
-                                    new String[] {String.valueOf(file.getFileId())});
-      } else {
-        try {
-          getContentProvider().update(ProviderTableMeta.CONTENT_URI,
-                                      cv,
-                                      ProviderTableMeta._ID + "=?",
-                                      new String[] {String.valueOf(file.getFileId())});
-        } catch (RemoteException e) {
-          Log.e(TAG, "Fail to insert insert file to database " + e.getMessage());
+    private ContentResolver mContentResolver;
+    private ContentProviderClient mContentProvider;
+    private Account mAccount;
+
+    private static String TAG = "FileDataStorageManager";
+
+    public FileDataStorageManager(Account account, ContentResolver cr) {
+        mContentProvider = null;
+        mContentResolver = cr;
+        mAccount = account;
+    }
+
+    public FileDataStorageManager(Account account, ContentProviderClient cp) {
+        mContentProvider = cp;
+        mContentResolver = null;
+        mAccount = account;
+    }
+
+    @Override
+    public OCFile getFileByPath(String path) {
+        Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
+        OCFile file = null;
+        if (c.moveToFirst()) {
+            file = createFileInstance(c);
+        }
+        c.close();
+        return file;
+    }
+
+    @Override
+    public OCFile getFileById(long id) {
+        Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
+        OCFile file = null;
+        if (c.moveToFirst()) {
+            file = createFileInstance(c);
+        }
+        c.close();
+        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 boolean saveFile(OCFile file) {
+        boolean overriden = false;
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
+        cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
+        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_PATH, file.getRemotePath());
+        if (!file.isDirectory())
+            cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+        cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
+        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate());
+        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+
+        if (fileExists(file.getRemotePath())) {
+            OCFile oldFile = getFileByPath(file.getRemotePath());
+            if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
+                file.setStoragePath(oldFile.getStoragePath());
+            if (!file.isDirectory());
+                cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+            file.setFileId(oldFile.getFileId());
+
+            overriden = true;
+            if (getContentResolver() != null) {
+                getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
+                        ProviderTableMeta._ID + "=?",
+                        new String[] { String.valueOf(file.getFileId()) });
+            } else {
+                try {
+                    getContentProvider().update(ProviderTableMeta.CONTENT_URI,
+                            cv, ProviderTableMeta._ID + "=?",
+                            new String[] { String.valueOf(file.getFileId()) });
+                } catch (RemoteException e) {
+                    Log.e(TAG,
+                            "Fail to insert insert file to database "
+                                    + e.getMessage());
+                }
+            }
+        } else {
+            Uri result_uri = null;
+            if (getContentResolver() != null) {
+                result_uri = getContentResolver().insert(
+                        ProviderTableMeta.CONTENT_URI_FILE, cv);
+            } else {
+                try {
+                    result_uri = getContentProvider().insert(
+                            ProviderTableMeta.CONTENT_URI_FILE, cv);
+                } catch (RemoteException e) {
+                    Log.e(TAG,
+                            "Fail to insert insert file to database "
+                                    + e.getMessage());
+                }
+            }
+            if (result_uri != null) {
+                long new_id = Long.parseLong(result_uri.getPathSegments()
+                        .get(1));
+                file.setFileId(new_id);
+            }
+        }
+
+        if (file.isDirectory() && file.needsUpdatingWhileSaving())
+            for (OCFile f : getDirectoryContent(file))
+                saveFile(f);
+
+        return overriden;
+    }
+
+
+    @Override
+    public void saveFiles(List<OCFile> files) {
+        
+        Iterator<OCFile> filesIt = files.iterator();
+        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
+        OCFile file = null;
+
+        // prepare operations to perform
+        while (filesIt.hasNext()) {
+            file = filesIt.next();
+            ContentValues cv = new ContentValues();
+            cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
+            cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
+            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_PATH, file.getRemotePath());
+            if (!file.isDirectory())
+                cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+            cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
+            cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate());
+            cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+
+            if (fileExists(file.getRemotePath())) {
+                OCFile tmpfile = getFileByPath(file.getRemotePath());
+                file.setStoragePath(tmpfile.getStoragePath());
+                if (!file.isDirectory());
+                    cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+                file.setFileId(tmpfile.getFileId());
+
+                operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+                        withValues(cv).
+                        withSelection(  ProviderTableMeta._ID + "=?", 
+                                        new String[] { String.valueOf(file.getFileId()) })
+                        .build());
+                
+            } else {
+                operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
+            }