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 }