001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.jci.listeners;
019
020 import java.io.File;
021 import java.util.ArrayList;
022 import java.util.Collection;
023
024 import org.apache.commons.jci.monitor.FilesystemAlterationListener;
025 import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
026 import org.apache.commons.logging.Log;
027 import org.apache.commons.logging.LogFactory;
028
029 /**
030 * AbstractFilesystemAlterationListener provides some convenience methods helping to
031 * implement a FilesystemAlterationListener.
032 * @author tcurdt
033 */
034 public abstract class AbstractFilesystemAlterationListener implements FilesystemAlterationListener {
035
036 private final Log log = LogFactory.getLog(AbstractFilesystemAlterationListener.class);
037
038 private final Collection<File> createdFiles = new ArrayList<File>();
039 private final Collection<File> changedFiles = new ArrayList<File>();
040 private final Collection<File> deletedFiles = new ArrayList<File>();
041 private final Collection<File> createdDirectories = new ArrayList<File>();
042 private final Collection<File> changedDirectories = new ArrayList<File>();
043 private final Collection<File> deletedDirectories = new ArrayList<File>();
044
045
046 private final static class Signal {
047 public boolean triggered;
048 }
049
050 private final Signal eventSignal = new Signal();
051 private final Signal checkSignal = new Signal();
052
053 protected FilesystemAlterationObserver observer;
054
055 public void onDirectoryCreate( final File pDir ) {
056 createdDirectories.add(pDir);
057 }
058 public void onDirectoryChange( final File pDir ) {
059 changedDirectories.add(pDir);
060 }
061 public void onDirectoryDelete( final File pDir ) {
062 deletedDirectories.add(pDir);
063 }
064
065 public void onFileCreate( final File pFile) {
066 createdFiles.add(pFile);
067 }
068 public void onFileChange( final File pFile ) {
069 changedFiles.add(pFile);
070 }
071 public void onFileDelete( final File pFile ) {
072 deletedFiles.add(pFile);
073 }
074
075
076 public Collection<File> getChangedDirectories() {
077 return changedDirectories;
078 }
079
080 public Collection<File> getChangedFiles() {
081 return changedFiles;
082 }
083
084 public Collection<File> getCreatedDirectories() {
085 return createdDirectories;
086 }
087
088 public Collection<File> getCreatedFiles() {
089 return createdFiles;
090 }
091
092 public Collection<File> getDeletedDirectories() {
093 return deletedDirectories;
094 }
095
096 public Collection<File> getDeletedFiles() {
097 return deletedFiles;
098 }
099
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 }