b777a97c642a67fdb7cd02ad116cfea4429008d8
[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 package org.wamblee.io;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20
21 import java.io.File;
22 import java.io.FileFilter;
23
24 import java.util.Date;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Map;
28 import java.util.Set;
29
30
31 /**
32  * Monitors a directory for changes.
33  *
34  * @author Erik Brakkee
35  */
36 public class DirectoryMonitor {
37     /**
38      * DOCUMENT ME!
39      */
40     private static final Log LOG = LogFactory.getLog(DirectoryMonitor.class);
41
42     /**
43      * DOCUMENT ME!
44      */
45     private File directory;
46
47     /**
48      * DOCUMENT ME!
49      */
50     private FileFilter filter;
51
52     /**
53      * DOCUMENT ME!
54      */
55     private Listener listener;
56
57     /**
58      * DOCUMENT ME!
59      */
60     private Map<File, Date> contents;
61
62 /**
63      * Creates a new DirectoryMonitor object.
64      *
65      * @param aDirectory DOCUMENT ME!
66      * @param aFilefilter DOCUMENT ME!
67      * @param aListener DOCUMENT ME!
68      */
69     public DirectoryMonitor(File aDirectory, FileFilter aFilefilter,
70         Listener aListener) {
71         directory = aDirectory;
72
73         if (!directory.isDirectory()) {
74             throw new IllegalArgumentException("Directory '" + directory
75                 + "' does not exist");
76         }
77
78         filter       = aFilefilter;
79         listener     = aListener;
80         contents     = new HashMap<File, Date>();
81     }
82
83     /**
84      * Polls the directory for changes and notifies the listener of any
85      * changes. In case of any exceptions thrown by the listener while
86      * handling the changes, the next call to this method will invoked the
87      * listeners again for the same changes.
88      */
89     public void poll() {
90         LOG.debug("Polling " + directory);
91
92         Map<File, Date> newContents  = new HashMap<File, Date>();
93         File[]          files        = directory.listFiles(filter);
94
95         // Check deleted files. 
96         Set<File>       deletedFiles = new HashSet<File>(contents.keySet());
97
98         for (File file : files) {
99             if (file.isFile()) {
100                 if (contents.containsKey(file)) {
101                     deletedFiles.remove(file);
102                 }
103             }
104         }
105
106         for (File file : deletedFiles) {
107             listener.fileDeleted(file);
108         }
109
110         for (File file : files) {
111             if (file.isFile()) {
112                 if (contents.containsKey(file)) {
113                     Date oldDate = contents.get(file);
114
115                     if (file.lastModified() != oldDate.getTime()) {
116                         listener.fileChanged(file);
117                     } else {
118                         // No change.
119                     }
120
121                     newContents.put(file, new Date(file.lastModified()));
122                 } else {
123                     listener.fileCreated(file);
124                     newContents.put(file, new Date(file.lastModified()));
125                 }
126             }
127         }
128
129         contents = newContents;
130     }
131
132     public static interface Listener {
133         void fileChanged(File aFile);
134
135         void fileCreated(File aFile);
136
137         void fileDeleted(File aFile);
138     }
139 }