Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 277bb13c authored by Vincent Bourgmayer's avatar Vincent Bourgmayer
Browse files

Add FileObserver classes

- Add "FileObservers" Package
- Add RecursiveFileObserver into FileObservers package. (Narinder's code)
- Add FileEventListener interface into FileObservers package. (Narinder's code)
- refactor some details in RecursiveFileObserver from Narinder's latest source code:
    - replace 'watch(File file)' method by private final static FileFilter
    - Remove a synchronized bloc that where duplicated
- Add a "FileObserver" class in models Package based on Narinder's work.
parent 09a63c5a
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
/*
 * Copyright © Narinder Rana (/e/ foundation).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */

package foundation.e.drive.FileObservers;

import java.io.File;

/**
 * @author Narinder Rana
 */
public interface FileEventListener  {
    void onEvent(int event, File file);
}
+168 −0
Original line number Diff line number Diff line
/*
 * Copyright © Narinder Rana (/e/ foundation).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */

package foundation.e.drive.FileObservers;

import android.content.Context;
import android.os.FileObserver;

import java.io.File;
import java.io.FileFilter;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;

import foundation.e.drive.database.DbHelper;
import foundation.e.drive.models.SyncedFolder;

/**
 * @author Narinder Rana
 * @author Vincent Bourgmayer
 */
public class RecursiveFileObserver extends FileObserver {
    private final HashMap<String, FileObserver> mObservers = new HashMap<>();
    private final static FileFilter watchableDirectoriesFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isDirectory() && !file.getName().equals(".") && !file.getName().equals("..");
        }
    };


    private final Context applicationContext;
    private String mPath;
    private int mMask;
    private FileEventListener mListener;

    public RecursiveFileObserver(Context applicationContext, String path, FileEventListener listener) {
        this(applicationContext, path, ALL_EVENTS, listener);

    }

    public RecursiveFileObserver(Context applicationContext, String path, int mask, FileEventListener listener) {
        super(path, mask);
        mPath = path;
        mMask = mask | FileObserver.CREATE | FileObserver.DELETE_SELF;
        mListener = listener;
        this.applicationContext=applicationContext;
    }


    @Override
    public void onEvent(int event, String path) {
        File file;
        if (path == null) {
            file = new File(mPath);
        } else {
            file = new File(mPath, path);
        }
        notify(event, file);
    }

    private void notify(int event, File file) {
        if (mListener != null) {
            mListener.onEvent(event & FileObserver.ALL_EVENTS, file);
        }
    }

    @Override
    public void startWatching() {
        Stack<String> stack = new Stack<>();

        List<SyncedFolder> mSyncedFolders = DbHelper.getAllSyncedFolders(applicationContext);
        if(!mSyncedFolders.isEmpty()){
            for(SyncedFolder syncedFolder:mSyncedFolders){
                stack.push(syncedFolder.getLocalFolder());
                stack.push(syncedFolder.getRemoteFolder());
            }
        }

        // Recursively watch all child directories
        while (!stack.empty()) {
            String parent = stack.pop();
            startWatching(parent);

            File path = new File(parent);
            File[] files = path.listFiles(watchableDirectoriesFilter);
            if (files != null) {
                for (File file : files) {
                    stack.push(file.getAbsolutePath());
                }
            }
        }
    }

    /**
     * Start watching a single file
     * @param path
     */
    private void startWatching(String path) {
        synchronized (mObservers) {
            FileObserver observer = mObservers.remove(path);
            if (observer != null) {
                observer.stopWatching();
            }
            observer = new SingleFileObserver(path, mMask);
            observer.startWatching();
            mObservers.put(path, observer);
        }
    }

    @Override
    public void stopWatching() {
        for (FileObserver observer : mObservers.values()) {
            observer.stopWatching();
        }
        mObservers.clear();
    }

    /**
     * Stop watching a single file
     * @param path
     */
    private void stopWatching(String path) {
        synchronized (mObservers) {
            FileObserver observer = mObservers.remove(path);
            if (observer != null) {
                observer.stopWatching();
            }
        }
    }

    private class SingleFileObserver extends FileObserver {
        private String filePath;

        public SingleFileObserver(String path, int mask) {
            super(path, mask);
            filePath = path;
        }

        @Override
        public void onEvent(int event, String path) {
            File file;
            if (path == null) {
                file = new File(filePath);
            } else {
                file = new File(filePath, path);
            }

            switch (event & FileObserver.ALL_EVENTS) {
                case DELETE_SELF:
                    RecursiveFileObserver.this.stopWatching(filePath);
                    break;
                case CREATE:
                    if (watchableDirectoriesFilter.accept(file)) {
                        RecursiveFileObserver.this.startWatching(file.getAbsolutePath());
                    }
                    break;
            }

            RecursiveFileObserver.this.notify(event, file);
        }
    }
}
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright © Narinder Rana (/e/ foundation).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */

package foundation.e.drive.models;

import java.io.File;
import java.io.Serializable;
import java.util.List;

/**
 * @author Narinder Rana
 */
public class FileObserver implements Serializable {

    private List<File> files;
    public FileObserver(List<File> files) {
        this.files = files;

    }

    public List<File> getFiles() {
        return files;
    }

    public void setFiles(List<File> files) {
        this.files = files;
    }
}