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