X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/dba9c3a64dec698d142eb6f1653d441db7e1573a..e2a7e9bbf90800dace008d3425fce495b2d515bc:/src/com/owncloud/android/files/OwnCloudFolderObserver.java diff --git a/src/com/owncloud/android/files/OwnCloudFolderObserver.java b/src/com/owncloud/android/files/OwnCloudFolderObserver.java index 2cb45519..db84448c 100644 --- a/src/com/owncloud/android/files/OwnCloudFolderObserver.java +++ b/src/com/owncloud/android/files/OwnCloudFolderObserver.java @@ -1,6 +1,25 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2014 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + package com.owncloud.android.files; import java.io.File; +import java.util.HashMap; +import java.util.Map; import android.accounts.Account; import android.content.Context; @@ -15,59 +34,144 @@ import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.ui.activity.ConflictsResolveActivity; import com.owncloud.android.utils.Log_OC; +/** + * Observer watching a folder to request the synchronization of kept-in-sync files + * inside it. + * + * Takes into account two possible update cases: + * - an editor directly updates the file; + * - an editor works on a temporal file, and later replaces the kept-in-sync file with the + * temporal. + * + * The second case requires to monitor the folder parent of the files, since a direct + * {@link FileObserver} on it will not receive more events after the file is deleted to + * be replaced later. + * + * @author David A. Velasco + */ public class OwnCloudFolderObserver extends FileObserver { - private static int MASK = (FileObserver.CREATE | FileObserver.MOVED_TO); + private static int UPDATE_MASK = ( + FileObserver.ATTRIB | FileObserver.MODIFY | + FileObserver.MOVED_TO | FileObserver.CLOSE_WRITE + ); + /* + private static int ALL_EVENTS_EVEN_THOSE_NOT_DOCUMENTED = 0x7fffffff; // NEVER use 0xffffffff + */ private static String TAG = OwnCloudFolderObserver.class.getSimpleName(); private String mPath; - private int mMask; - private Account mOCAccount; + private Account mAccount; private Context mContext; + private Map mObservedChildren; public OwnCloudFolderObserver(String path, Account account, Context context) { - super(path, FileObserver.ALL_EVENTS); + super(path, UPDATE_MASK); + if (path == null) throw new IllegalArgumentException("NULL path argument received"); if (account == null) throw new IllegalArgumentException("NULL account argument received"); if (context == null) throw new IllegalArgumentException("NULL context argument received"); + mPath = path; - mOCAccount = account; + mAccount = account; mContext = context; + mObservedChildren = new HashMap(); } + @Override public void onEvent(int event, String path) { - Log_OC.d(TAG, "Got file modified with event " + event + " and path " + mPath - + ((path != null) ? File.separator + path : "")); - if ((event & MASK) == 0) { - Log_OC.wtf(TAG, "Incorrect event " + event + " sent for file " + mPath - + ((path != null) ? File.separator + path : "") + " with registered for " + mMask - + " and original path " + mPath); - - } else { - if ((event & FileObserver.CREATE) != 0) { - // TODO Enable a flag + Log_OC.d(TAG, "Got event " + event + " on FOLDER " + mPath + " about " + + ((path != null) ? path : "")); + + boolean shouldSynchronize = false; + synchronized(mObservedChildren) { + if (path != null && path.length() > 0 && mObservedChildren.containsKey(path)) { + + if ((event & FileObserver.MODIFY) != 0) { + if (!mObservedChildren.get(path)) { + mObservedChildren.put(path, Boolean.valueOf(true)); + } + } + + /* + if ((event & FileObserver.ATTRIB) != 0) { + if (mObservedChildren.get(path) != true) { + mObservedChildren.put(path, Boolean.valueOf(true)); + } + } + */ + + /* + if ((event & FileObserver.MOVED_TO) != 0) { + if (mObservedChildren.get(path) != true) { + mObservedChildren.put(path, Boolean.valueOf(true)); + } + } + */ + + if ((event & FileObserver.CLOSE_WRITE) != 0) { + mObservedChildren.put(path, Boolean.valueOf(false)); + shouldSynchronize = true; + } } - if ((event & FileObserver.MOVED_TO) != 0) { - // TODO Start sync + } + if (shouldSynchronize) { + startSyncOperation(path); + } + + if ((event & OwnCloudFileObserver.IN_IGNORE) != 0 && + (path == null || path.length() == 0)) { + Log_OC.d(TAG, "Stopping the observance on " + mPath); + } + + } + + + public void startWatching(String localPath) { + synchronized (mObservedChildren) { + if (!mObservedChildren.containsKey(localPath)) { + mObservedChildren.put(localPath, Boolean.valueOf(false)); } } + + if (new File(mPath).exists()) { + startWatching(); + Log_OC.d(TAG, "Started watching parent folder " + mPath + "/"); + } + // else - the observance can't be started on a file not existing; } - private void startSyncOperation() { - // TODO Move to common file because it is being used in OCFileObserver - // too + public void stopWatching(String localPath) { + synchronized (mObservedChildren) { + mObservedChildren.remove(localPath); + if (mObservedChildren.isEmpty()) { + stopWatching(); + Log_OC.d(TAG, "Stopped watching parent folder " + mPath + "/"); + } + } + } - FileDataStorageManager storageManager = new FileDataStorageManager(mOCAccount, mContext.getContentResolver()); + public boolean isEmpty() { + synchronized (mObservedChildren) { + return mObservedChildren.isEmpty(); + } + } + + + private void startSyncOperation(String childName) { + FileDataStorageManager storageManager = + new FileDataStorageManager(mAccount, mContext.getContentResolver()); // a fresh object is needed; many things could have occurred to the file // since it was registered to observe again, assuming that local files // are linked to a remote file AT MOST, SOMETHING TO BE DONE; - OCFile file = storageManager.getFileByLocalPath(mPath); - SynchronizeFileOperation sfo = new SynchronizeFileOperation(file, null, mOCAccount, true, mContext); + OCFile file = storageManager.getFileByLocalPath(mPath + File.separator + childName); + SynchronizeFileOperation sfo = + new SynchronizeFileOperation(file, null, mAccount, true, mContext); RemoteOperationResult result = sfo.execute(storageManager, mContext); if (result.getCode() == ResultCode.SYNC_CONFLICT) { // ISSUE 5: if the user is not running the app (this is a service!), @@ -75,9 +179,12 @@ public class OwnCloudFolderObserver extends FileObserver { Intent i = new Intent(mContext, ConflictsResolveActivity.class); i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file); - i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mOCAccount); + i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount); mContext.startActivity(i); } + // TODO save other errors in some point where the user can inspect them later; + // or maybe just toast them; + // or nothing, very strange fails } }