1package eu.siacs.conversations.utils;
2
3
4import android.os.FileObserver;
5
6import java.io.File;
7import java.util.ArrayList;
8import java.util.List;
9import java.util.Stack;
10
11/**
12 * Copyright (C) 2012 Bartek Przybylski
13 * Copyright (C) 2015 ownCloud Inc.
14 * Copyright (C) 2016 Daniel Gultsch
15 */
16
17public abstract class ConversationsFileObserver {
18
19 private final String path;
20 private final List<SingleFileObserver> mObservers = new ArrayList<>();
21
22 public ConversationsFileObserver(String path) {
23 this.path = path;
24 }
25
26 public synchronized void startWatching() {
27 Stack<String> stack = new Stack<>();
28 stack.push(path);
29
30 while (!stack.empty()) {
31 String parent = stack.pop();
32 mObservers.add(new SingleFileObserver(parent, FileObserver.DELETE| FileObserver.MOVED_FROM));
33 final File path = new File(parent);
34 final File[] files = path.listFiles();
35 if (files == null) {
36 continue;
37 }
38 for(File file : files) {
39 if (file.isDirectory() && file.getName().charAt(0) != '.') {
40 final String currentPath = file.getAbsolutePath();
41 if (depth(file) <= 8 && !stack.contains(currentPath) && !observing(currentPath)) {
42 stack.push(currentPath);
43 }
44 }
45 }
46 }
47 for(FileObserver observer : mObservers) {
48 observer.startWatching();
49 }
50 }
51
52 private static int depth(File file) {
53 int depth = 0;
54 while((file = file.getParentFile()) != null) {
55 depth++;
56 }
57 return depth;
58 }
59
60 private boolean observing(String path) {
61 for(SingleFileObserver observer : mObservers) {
62 if(path.equals(observer.path)) {
63 return true;
64 }
65 }
66 return false;
67 }
68
69 public synchronized void stopWatching() {
70 for(FileObserver observer : mObservers) {
71 observer.stopWatching();
72 }
73 mObservers.clear();
74 }
75
76 abstract public void onEvent(int event, String path);
77
78 public void restartWatching() {
79 stopWatching();
80 startWatching();
81 }
82
83 private class SingleFileObserver extends FileObserver {
84 private final String path;
85
86 public SingleFileObserver(String path, int mask) {
87 super(path, mask);
88 this.path = path;
89 }
90
91 @Override
92 public void onEvent(int event, String filename) {
93 ConversationsFileObserver.this.onEvent(event, path+'/'+filename);
94 }
95
96 }
97}