View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jci.monitor;
19  
20  import java.io.File;
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  /**
29   * It's a runnable that spawns of a monitoring thread triggering the
30   * the observers and managing the their listeners.
31   * 
32   * @author tcurdt
33   */
34  public final class FilesystemAlterationMonitor implements Runnable {
35  
36      private final Log log = LogFactory.getLog(FilesystemAlterationMonitor.class);
37  
38      private final Object observersLock = new Object();
39      private Map<File, FilesystemAlterationObserver> observers = Collections.unmodifiableMap(new HashMap<File, FilesystemAlterationObserver>());
40      
41      /** delay between calls to {@link FilesystemAlterationObserver#checkAndNotify()}, default 3000 ms */
42      private volatile long delay = 3000; // volatile because shared with daemon thread
43      private Thread thread = null;
44  
45      private volatile boolean running = true;
46          
47      public FilesystemAlterationMonitor() {
48      }
49  
50  
51      public void start() {
52          thread = new Thread(this);
53          thread.setName("Filesystem Alteration Monitor");
54          thread.setDaemon(true);
55          thread.start();
56      }
57  
58  
59      public void stop() {
60          running = false;
61  
62          if (thread != null) {
63              try {
64                  thread.join(delay);
65              } catch (InterruptedException e) {
66              }
67          }
68      }
69  
70  
71      /**
72       * Set the delay between calls to the observers.
73       *  
74       * @param pDelay the delay in milliseconds (default if not set 3000 ms)
75       */
76      public void setInterval( final long pDelay ) {
77          delay = pDelay;
78      }
79  
80  
81      public void addListener( final File pRoot, final FilesystemAlterationListener pListener ) {
82  
83          FilesystemAlterationObserver observer;
84  
85          synchronized (observersLock) {
86              observer = observers.get(pRoot);
87  
88              if (observer == null) {
89                  final Map<File, FilesystemAlterationObserver> newObservers = new HashMap<File, FilesystemAlterationObserver>(observers);
90                  observer = new FilesystemAlterationObserverImpl(pRoot);
91                  newObservers.put(pRoot, observer);
92                  observers = Collections.unmodifiableMap(newObservers);
93              }
94          }
95  
96          observer.addListener(pListener);
97      }
98     
99      public void removeListener( final FilesystemAlterationListener pListener ) {
100         synchronized (observersLock) {
101             for (FilesystemAlterationObserver observer : observers.values()) {
102                 observer.removeListener(pListener);
103                 // FIXME: remove observer if there are no listeners?
104             }
105         }
106     }
107 
108     public FilesystemAlterationListener[] getListenersFor( final File pRoot  ) {
109         final FilesystemAlterationObserver observer = observers.get(pRoot);
110 
111         if (observer == null) {
112             return new FilesystemAlterationListener[0];
113         }
114 
115         return observer.getListeners();
116     }
117 
118 
119     public void run() {
120         log.debug("fam running");
121         
122         while (running) {
123 
124             for (FilesystemAlterationObserver observer : observers.values()) {
125                 observer.checkAndNotify();
126             }
127 
128             try {
129                 Thread.sleep(delay);
130             } catch (final InterruptedException e) {
131             }
132         }
133         
134         log.debug("fam exiting");
135     }
136 
137 }