blob: b324c99621c45e5884aa876269aa8ec8a59a7736 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jci2.listeners;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.jci2.monitor.FilesystemAlterationListener;
import org.apache.commons.jci2.monitor.FilesystemAlterationObserver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* AbstractFilesystemAlterationListener provides some convenience methods helping to
* implement a FilesystemAlterationListener.
* @author tcurdt
*/
public abstract class AbstractFilesystemAlterationListener implements FilesystemAlterationListener {
private final Log log = LogFactory.getLog(AbstractFilesystemAlterationListener.class);
private final Collection<File> createdFiles = new ArrayList<File>();
private final Collection<File> changedFiles = new ArrayList<File>();
private final Collection<File> deletedFiles = new ArrayList<File>();
private final Collection<File> createdDirectories = new ArrayList<File>();
private final Collection<File> changedDirectories = new ArrayList<File>();
private final Collection<File> deletedDirectories = new ArrayList<File>();
private final static class Signal {
public boolean triggered;
}
private final Signal eventSignal = new Signal();
private final Signal checkSignal = new Signal();
protected FilesystemAlterationObserver observer;
public void onDirectoryCreate( final File pDir ) {
createdDirectories.add(pDir);
}
public void onDirectoryChange( final File pDir ) {
changedDirectories.add(pDir);
}
public void onDirectoryDelete( final File pDir ) {
deletedDirectories.add(pDir);
}
public void onFileCreate( final File pFile) {
createdFiles.add(pFile);
}
public void onFileChange( final File pFile ) {
changedFiles.add(pFile);
}
public void onFileDelete( final File pFile ) {
deletedFiles.add(pFile);
}
public Collection<File> getChangedDirectories() {
return changedDirectories;
}
public Collection<File> getChangedFiles() {
return changedFiles;
}
public Collection<File> getCreatedDirectories() {
return createdDirectories;
}
public Collection<File> getCreatedFiles() {
return createdFiles;
}
public Collection<File> getDeletedDirectories() {
return deletedDirectories;
}
public Collection<File> getDeletedFiles() {
return deletedFiles;
}
protected void signals() {
if (createdFiles.size() > 0 || createdDirectories.size() > 0 ||
changedFiles.size() > 0 || changedDirectories.size() > 0 ||
deletedFiles.size() > 0 || deletedDirectories.size() > 0) {
log.debug("event signal");
synchronized(eventSignal) {
eventSignal.triggered = true;
eventSignal.notifyAll();
}
}
log.debug("check signal");
synchronized(checkSignal) {
checkSignal.triggered = true;
checkSignal.notifyAll();
}
}
public void onStart( final FilesystemAlterationObserver pObserver ) {
observer = pObserver;
createdFiles.clear();
changedFiles.clear();
deletedFiles.clear();
createdDirectories.clear();
changedDirectories.clear();
deletedDirectories.clear();
}
public void onStop( final FilesystemAlterationObserver pObserver ) {
signals();
observer = null;
}
public void waitForEvent() throws Exception {
synchronized(eventSignal) {
eventSignal.triggered = false;
}
log.debug("waiting for change");
if (!waitForSignal(eventSignal, 10)) {
throw new Exception("timeout");
}
}
/**
* we don't reset the signal so if there was a check it is
* already true and exit immediatly otherwise it will behave just
* like waitForCheck()
*
* @throws Exception in case of a timeout
*/
public void waitForFirstCheck() throws Exception {
log.debug("waiting for first check");
if (!waitForSignal(checkSignal, 10)) {
throw new Exception("timeout");
}
}
/**
* wait for the next filesystem check to happen
*
* @throws Exception in case of a timeout
*/
public void waitForCheck() throws Exception {
synchronized(checkSignal) {
checkSignal.triggered = false;
}
log.debug("waiting for check");
if (!waitForSignal(checkSignal, 10)) {
throw new Exception("timeout");
}
}
private boolean waitForSignal(final Signal pSignal, final int pSecondsTimeout) {
int i = 0;
while(true) {
synchronized(pSignal) {
if (!pSignal.triggered) {
try {
pSignal.wait(1000);
} catch (final InterruptedException e) {
}
if (++i > pSecondsTimeout) {
log.error("timeout after " + pSecondsTimeout + "s");
return false;
}
} else {
pSignal.triggered = false;
break;
}
}
}
return true;
}
}