KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > util > monitor > DirectoryScanner


1 /*
2  * Copyright (C) The Loom Group. All rights reserved.
3  *
4  * This software is published under the terms of the Loom
5  * Software License version 1.1, a copy of which has been included
6  * with this distribution in the LICENSE.txt file.
7  */

8 package org.codehaus.loom.components.util.monitor;
9
10 import java.io.File JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.Map JavaDoc;
15 import java.util.Set JavaDoc;
16
17 /**
18  * Utility class that scans for changes in a directory.
19  * If changes are detected it will notify its
20  * <code>DirectoryChangeListener</code>.
21  *
22  * @author Johan Sjoberg
23  * @author Peter Donald
24  * @version $Revision: 1.5 $ $Date: 2004/12/04 10:45:31 $
25  */

26 public class DirectoryScanner implements Runnable JavaDoc
27 {
28     /** The monitor thread */
29     private final Thread JavaDoc m_monitorThread = new Thread JavaDoc( this );
30
31     /** Flag indicating if we are running or not */
32     private volatile boolean m_keepRunning = false;
33
34     /** Poll frequency */
35     private long m_frequency = 1000L * 5L;
36
37     /** Priority of the monitor thread */
38     private int m_priority = Thread.NORM_PRIORITY;
39
40     /** Class listening for changes in the directory */
41     private DirectoryChangeListener m_directoryChangeListener;
42
43     /** Last modification time */
44     private long m_lastModified;
45
46     /** The directory to monitor */
47     private File JavaDoc m_directory;
48
49     /** Files in the monitored directory */
50     private Set JavaDoc m_files;
51
52     /** File modification times */
53     private Map JavaDoc m_times;
54
55     /**
56      * Set the directory to be scanned.
57      *
58      * @param path The directory's path
59      * @throws IllegalArgumentException if the directory doesn't exist.
60      */

61     public void setDirectory( final String JavaDoc path )
62     {
63         m_directory = new File JavaDoc( path );
64         if( !m_directory.isDirectory() )
65         {
66             final String JavaDoc message =
67               "Argument [" + path + "] doesn't seem to be a directory.";
68             throw new IllegalArgumentException JavaDoc( message );
69         }
70         m_files = new HashSet JavaDoc();
71         m_times = new HashMap JavaDoc();
72         final File JavaDoc[] files = m_directory.listFiles();
73         for( int i = 0; i < files.length; i++ )
74         {
75             final File JavaDoc file = files[i];
76             m_files.add( file );
77             m_times.put( file, new Long JavaDoc( file.lastModified() ) );
78         }
79         m_lastModified = System.currentTimeMillis();
80     }
81
82     /**
83      * Set the <code>DirectoryChangeListener</code> to
84      * notify about changes in the directory.
85      *
86      * @param directoryChangeListener The listener
87      */

88     public void setDirectoryChangeListener( final DirectoryChangeListener directoryChangeListener )
89     {
90         m_directoryChangeListener = directoryChangeListener;
91     }
92
93     /**
94      * Set scan frequency for the background thread.
95      *
96      * @param frequency The scan frequency in milliseconds
97      */

98     public void setFrequency( final long frequency )
99     {
100         m_frequency = frequency;
101     }
102
103     /**
104      * Start the background thread
105      */

106     public void start() throws Exception JavaDoc
107     {
108         m_keepRunning = true;
109         m_monitorThread.setDaemon( true );
110         m_monitorThread.setPriority( m_priority );
111         m_monitorThread.start();
112     }
113
114     /**
115      * Stop the background thread
116      */

117     public void stop() throws Exception JavaDoc
118     {
119         m_keepRunning = false;
120         m_monitorThread.interrupt();
121         m_monitorThread.join();
122     }
123
124     /**
125      * Kick the scanner thread in motion.
126      */

127     public final void run()
128     {
129         try
130         {
131             while( m_keepRunning )
132             {
133                 Thread.sleep( m_frequency );
134                 testModifiedAfter( System.currentTimeMillis() );
135             }
136         }
137         catch( InterruptedException JavaDoc e )
138         {
139             Thread.interrupted();
140         }
141     }
142
143     /**
144      * Test if the directory has been modified after a given time
145      *
146      * @param time The time to use when polling for changes.
147      */

148     public void testModifiedAfter( final long time )
149     {
150         if( m_lastModified > time )
151         {
152             return;
153         }
154
155         final File JavaDoc[] files = m_directory.listFiles();
156
157         // This will be true if there is an IOException,
158
// or if the directory dissapears. Both reasons
159
// to not remove appslications :) -- PR
160
if( null == files )
161         {
162             m_directoryChangeListener.unableToListContents();
163         }
164         else
165         {
166             final HashSet JavaDoc existingFiles = new HashSet JavaDoc();
167             final HashSet JavaDoc modifiedFiles = new HashSet JavaDoc();
168             final HashSet JavaDoc addedFiles = new HashSet JavaDoc();
169             final int fileCount = files.length;
170
171             for( int i = 0; i < files.length; i++ )
172             {
173                 final File JavaDoc file = files[i];
174                 final long newModTime = file.lastModified();
175                 if( m_files.contains( file ) )
176                 {
177                     existingFiles.add( file );
178                     final Long JavaDoc oldModTime = (Long JavaDoc)m_times.get( file );
179                     if( oldModTime.longValue() != newModTime )
180                     {
181                         modifiedFiles.add( file );
182                     }
183                 }
184                 else
185                 {
186                     addedFiles.add( file );
187                 }
188                 m_times.put( file, new Long JavaDoc( newModTime ) );
189             }
190
191             final int lastCount = m_files.size();
192             final int addedCount = addedFiles.size();
193             final int modifiedCount = modifiedFiles.size();
194
195             // If no new files have been added and none
196
// deleted then there is nothing to do.
197
if( fileCount == lastCount && 0 == addedCount && 0 == modifiedCount )
198             {
199                 return;
200             }
201
202             final HashSet JavaDoc deletedFiles = new HashSet JavaDoc();
203
204             // If only new files were added and none were changed
205
// then we don't have to scan for deleted files.
206
if( fileCount != lastCount + addedCount )
207             {
208                 final Iterator JavaDoc iterator = m_files.iterator();
209                 while( iterator.hasNext() )
210                 {
211                     final File JavaDoc file = (File JavaDoc)iterator.next();
212                     if( !existingFiles.contains( file ) )
213                     {
214                         deletedFiles.add( file );
215                         m_times.remove( file );
216                     }
217                 }
218             }
219
220             final int deletedCount = deletedFiles.size();
221
222             if( 0 != addedCount )
223             {
224                 m_directoryChangeListener.directoryChange(
225                   DirectoryChangeListener.ADDITION, addedFiles );
226             }
227             if( 0 != deletedCount )
228             {
229                 m_directoryChangeListener.directoryChange(
230                   DirectoryChangeListener.REMOVAL, deletedFiles );
231             }
232             if( 0 != modifiedCount )
233             {
234                 m_directoryChangeListener.directoryChange(
235                   DirectoryChangeListener.MODIFICATION, modifiedFiles );
236             }
237
238             existingFiles.addAll( addedFiles );
239             m_files = existingFiles;
240         }
241     }
242 }
243
Popular Tags