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.listeners;
19  
20  import java.io.File;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  
24  import org.apache.commons.jci.monitor.FilesystemAlterationListener;
25  import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  /**
30   * AbstractFilesystemAlterationListener provides some convenience methods helping to
31   * implement a FilesystemAlterationListener.
32   * @author tcurdt
33   */
34  public abstract class AbstractFilesystemAlterationListener implements FilesystemAlterationListener {
35  
36      private final Log log = LogFactory.getLog(AbstractFilesystemAlterationListener.class);
37  
38      private final Collection<File> createdFiles = new ArrayList<File>();
39      private final Collection<File> changedFiles = new ArrayList<File>();
40      private final Collection<File> deletedFiles = new ArrayList<File>();
41      private final Collection<File> createdDirectories = new ArrayList<File>();
42      private final Collection<File> changedDirectories = new ArrayList<File>();
43      private final Collection<File> deletedDirectories = new ArrayList<File>();
44  
45      
46      private final static class Signal {
47          public boolean triggered;
48      }
49  
50      private final Signal eventSignal = new Signal();
51      private final Signal checkSignal = new Signal();
52      
53      protected FilesystemAlterationObserver observer;
54  
55      public void onDirectoryCreate( final File pDir ) {
56          createdDirectories.add(pDir);
57      }
58      public void onDirectoryChange( final File pDir ) {
59          changedDirectories.add(pDir);
60      }
61      public void onDirectoryDelete( final File pDir ) {
62          deletedDirectories.add(pDir);
63      }
64  
65      public void onFileCreate( final File pFile) {
66          createdFiles.add(pFile);
67      }
68      public void onFileChange( final File pFile ) {
69          changedFiles.add(pFile);
70      }
71      public void onFileDelete( final File pFile ) {
72          deletedFiles.add(pFile);
73      }
74  
75  
76      public Collection<File> getChangedDirectories() {
77          return changedDirectories;
78      }
79  
80      public Collection<File> getChangedFiles() {
81          return changedFiles;
82      }
83  
84      public Collection<File> getCreatedDirectories() {
85          return createdDirectories;
86      }
87  
88      public Collection<File> getCreatedFiles() {
89          return createdFiles;
90      }
91  
92      public Collection<File> getDeletedDirectories() {
93          return deletedDirectories;
94      }
95  
96      public Collection<File> getDeletedFiles() {
97          return deletedFiles;
98      }
99  
100     protected void signals() {
101         if (createdFiles.size() > 0 || createdDirectories.size() > 0 ||
102             changedFiles.size() > 0 || changedDirectories.size() > 0 ||
103             deletedFiles.size() > 0 || deletedDirectories.size() > 0) {
104 
105             log.debug("event signal");
106 
107             synchronized(eventSignal) {
108                 eventSignal.triggered = true;
109                 eventSignal.notifyAll();
110             }
111         }
112 
113         log.debug("check signal");
114 
115         synchronized(checkSignal) {
116             checkSignal.triggered = true;
117             checkSignal.notifyAll();
118         }
119     }
120 
121     public void onStart( final FilesystemAlterationObserver pObserver ) {
122         observer = pObserver;
123 
124         createdFiles.clear();
125         changedFiles.clear();
126         deletedFiles.clear();
127         createdDirectories.clear();
128         changedDirectories.clear();
129         deletedDirectories.clear();
130     }
131 
132     public void onStop( final FilesystemAlterationObserver pObserver ) {
133         signals();
134         observer = null;
135     }
136         
137     public void waitForEvent() throws Exception {
138         synchronized(eventSignal) {
139             eventSignal.triggered = false;
140         }
141         log.debug("waiting for change");
142         if (!waitForSignal(eventSignal, 10)) {
143             throw new Exception("timeout");
144         }
145     }
146     
147     /**
148      * we don't reset the signal so if there was a check it is
149      * already true and exit immediatly otherwise it will behave just
150      * like waitForCheck()
151      * 
152      * @throws Exception in case of a timeout
153      */
154     public void waitForFirstCheck() throws Exception {
155         log.debug("waiting for first check");
156         if (!waitForSignal(checkSignal, 10)) {
157             throw new Exception("timeout");
158         }        
159     }
160 
161     /**
162      * wait for the next filesystem check to happen
163      * 
164      * @throws Exception in case of a timeout
165      */
166     public void waitForCheck() throws Exception {
167         synchronized(checkSignal) {
168             checkSignal.triggered = false;
169         }
170         log.debug("waiting for check");
171         if (!waitForSignal(checkSignal, 10)) {
172             throw new Exception("timeout");
173         }
174     }
175     
176     private boolean waitForSignal(final Signal pSignal, final int pSecondsTimeout) {
177         int i = 0;
178         while(true) {
179             synchronized(pSignal) {
180                 if (!pSignal.triggered) {
181                     try {
182                         pSignal.wait(1000);
183                     } catch (InterruptedException e) {
184                     }
185 
186                     if (++i > pSecondsTimeout) {
187                         log.error("timeout after " + pSecondsTimeout + "s");
188                         return false;
189                     }
190                     
191                 } else {
192                     pSignal.triggered = false;
193                     break;
194                 }
195             }
196         }        
197         return true;
198     }
199 
200 }