0f84183c1b4478cdb32aad51dcc49b4145eeebc8
[utils] / support / general / src / main / java / org / wamblee / io / DirectoryMonitor.java
1 /*
2  * Copyright 2006 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.wamblee.io;
18
19 import java.io.File;
20 import java.io.FileFilter;
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32 /**
33  * Monitors a directory for changes.
34  * 
35  * @author Erik Brakkee
36  */
37 public class DirectoryMonitor {
38
39         private static final Log LOG = LogFactory.getLog(DirectoryMonitor.class);
40
41         public static interface Listener {
42                 
43                 void fileChanged(File aFile);
44
45                 void fileCreated(File aFile);
46
47                 void fileDeleted(File aFile);
48         };
49
50         private File _directory;
51         private FileFilter _filter;
52         private Listener _listener;
53         private Map<File, Date> _contents;
54
55         public DirectoryMonitor(File aDirectory, FileFilter aFilefilter,
56                         Listener aListener) {
57                 _directory = aDirectory;
58                 if (!_directory.isDirectory()) {
59                         throw new IllegalArgumentException("Directory '" + _directory
60                                         + "' does not exist");
61                 }
62                 _filter = aFilefilter;
63                 _listener = aListener;
64                 _contents = new HashMap<File, Date>();
65         }
66
67         /**
68          * Polls the directory for changes and notifies the listener of any changes. 
69          * In case of any exceptions thrown by the listener while handling the changes, 
70          * the next call to this method will invoked the listeners again for the same changes. 
71          */
72         public void poll() {
73                 LOG.debug("Polling " + _directory);
74                 Map<File, Date> newContents = new HashMap<File, Date>();
75                 File[] files = _directory.listFiles(_filter);
76
77                 // Check deleted files. 
78                 Set<File> deletedFiles = new HashSet<File>(_contents.keySet());
79                 for (File file : files) {
80                         if (file.isFile()) {
81                                 if (_contents.containsKey(file)) {
82                                         deletedFiles.remove(file);
83                                 }
84                         }
85                 }
86                 for (File file : deletedFiles) {
87                         _listener.fileDeleted(file);
88                 }
89                 
90                 for (File file : files) {
91                         if (file.isFile()) {
92                                 if (_contents.containsKey(file)) {
93                                         Date oldDate = _contents.get(file);
94                                         if (file.lastModified() != oldDate.getTime()) {
95                                                 _listener.fileChanged(file);
96                                         } else {
97                                                 // No change.
98                                         }
99                                         newContents.put(file, new Date(file.lastModified()));
100                                 } else {
101                                         _listener.fileCreated(file);
102                                         newContents.put(file, new Date(file.lastModified()));
103                                 }
104                         }
105                 }
106                 
107                 _contents = newContents;
108         }
109
110 }