]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/impl/DirectoryWatch.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / impl / DirectoryWatch.java
1 /*******************************************************************************\r
2  * Copyright (c) 2010- Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  * \r
9  * Contributors:\r
10  *    VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.accessor.impl;\r
13 \r
14 import java.io.File;\r
15 import java.io.FileFilter;\r
16 import java.util.ArrayList;\r
17 import java.util.HashSet;\r
18 import java.util.List;\r
19 import java.util.Set;\r
20 import java.util.Timer;\r
21 import java.util.TimerTask;\r
22 import java.util.concurrent.CopyOnWriteArrayList;\r
23 \r
24 /**\r
25  * DirectoryWatch monitors a directory for file additions / removals.\r
26  * <p>\r
27  * DirectoryWatch is used in the long wait for WatchService.   \r
28  *\r
29  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
30  */\r
31 public class DirectoryWatch {\r
32 \r
33         public static final long POLL_INTERVAL = 10000; // seconds\r
34         \r
35         Timer timer;\r
36         FileFilter filter;\r
37         File directory;\r
38         List<File> knownFiles;\r
39         CopyOnWriteArrayList<DirectoryListener> listeners = new CopyOnWriteArrayList<DirectoryListener>();\r
40 \r
41         TimerTask task = new TimerTask() { \r
42                 public void run() {\r
43                         poll();\r
44                 } \r
45         };\r
46         \r
47         public DirectoryWatch(File directory, FileFilter filter) {\r
48                 this.directory = directory;\r
49                 this.filter = filter;\r
50                 knownFiles = readFiles();\r
51                 timer = new Timer(directory.toString()+" watcher", true);\r
52                 timer.schedule(task, 1, POLL_INTERVAL);\r
53         }\r
54         \r
55         /**\r
56          * Close the timer. \r
57          * This method does one last poll.\r
58          */\r
59         public void close() {           \r
60                 timer.cancel();\r
61                 poll();\r
62         }\r
63         \r
64         public static class DirectoryEvent {\r
65                 public Set<File> filesAdded = new HashSet<File>();\r
66                 public Set<File> filesRemoved = new HashSet<File>();\r
67         }\r
68         \r
69         public interface DirectoryListener {\r
70                 void onWatchEvent(DirectoryEvent e);\r
71         }\r
72         \r
73         public void addListener(DirectoryListener listener) {\r
74                 listeners.add(listener);                \r
75         }\r
76         \r
77         public void removeListener(DirectoryListener listener) {                \r
78                 listeners.remove(listener);\r
79         }\r
80         \r
81         /**\r
82          * Get a snapshot of currently known files\r
83          * \r
84          * @return a snapshot of files\r
85          */\r
86         public List<File> files() {\r
87                 return knownFiles;\r
88         }\r
89         \r
90         /**\r
91          * Reload the directory\r
92          */\r
93         public void refresh() {\r
94                 poll();\r
95         }\r
96         \r
97         /**\r
98          * Add file to the known list without reading the disk. \r
99          * The modification is void after next timer refresh. \r
100          * \r
101          * @param f\r
102          */\r
103         public synchronized void add(File f) {\r
104                 ArrayList<File> newList = new ArrayList<File>( knownFiles );\r
105                 newList.add(f);\r
106                 knownFiles = newList;\r
107         }\r
108         \r
109         /**\r
110          * Remove file from the known list without reading the disk.\r
111          * The modification is void after next timer refresh. \r
112          * \r
113          * @param f\r
114          */\r
115         public synchronized void remove(File f) {\r
116                 ArrayList<File> newList = new ArrayList<File>( knownFiles );\r
117                 newList.remove(f);\r
118                 knownFiles = newList;           \r
119         }\r
120         \r
121         /**\r
122          * Read files\r
123          * @return a list of absolute files\r
124          */\r
125         private List<File> readFiles() {                \r
126                 File[] files = directory.listFiles(filter);\r
127                 List<File> newFiles = new ArrayList<File>( files.length );\r
128                 for (File f : files) {\r
129 //                      System.out.println(f);\r
130 //                      f = f.getAbsoluteFile();\r
131 //                      System.out.println(f);\r
132                         newFiles.add(f);                \r
133                 }\r
134                 return newFiles;\r
135         }\r
136         \r
137         /**\r
138          * Read files and spawn events\r
139          */\r
140         private synchronized void poll() {\r
141                 DirectoryEvent e = read();\r
142                 if (e.filesAdded.isEmpty() && e.filesRemoved.isEmpty()) return;\r
143                 // Spawn an event\r
144                 for (DirectoryListener l : listeners)\r
145                         l.onWatchEvent(e);\r
146         }\r
147         \r
148         private DirectoryEvent read() {\r
149                 List<File> oldFiles = knownFiles;\r
150                 List<File> newFiles = readFiles();\r
151                 knownFiles = newFiles;\r
152 \r
153                 DirectoryEvent result = new DirectoryEvent();\r
154                 result.filesAdded.addAll(newFiles);\r
155                 result.filesAdded.removeAll(oldFiles);\r
156 \r
157                 result.filesRemoved.addAll(oldFiles);\r
158                 result.filesRemoved.removeAll(newFiles);\r
159                 \r
160                 return result;\r
161         }\r
162         \r
163 }\r
164 \r