All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.pastdev.jsch.nio.file.UnixSshPathWatchKey Maven / Gradle / Ivy
package com.pastdev.jsch.nio.file;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.attribute.PosixFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UnixSshPathWatchKey implements WatchKey, Runnable {
private static Logger logger = LoggerFactory.getLogger( UnixSshPathWatchKey.class );
private Map> addMap;
private boolean cancelled;
private Map> deleteMap;
UnixSshPath dir;
Map entries;
private boolean initialized;
private Set> kindsToWatch;
private Map> modifyMap;
private long pollingInterval;
private TimeUnit pollingIntervalTimeUnit;
private State state;
private UnixSshFileSystemWatchService watchService;
private ReentrantLock mapLock = new ReentrantLock();
private ReentrantLock stateLock = new ReentrantLock();
ReentrantLock pollerLock = new ReentrantLock();
private Condition initializationComplete = pollerLock.newCondition();
private Condition runImmediately = pollerLock.newCondition();
public UnixSshPathWatchKey( UnixSshFileSystemWatchService watchService, UnixSshPath dir, Kind>[] kinds, long pollingInterval, TimeUnit pollingIntervalTimeUnit ) {
this.watchService = watchService;
this.dir = dir;
this.kindsToWatch = new HashSet<>();
this.kindsToWatch.addAll( Arrays.asList( kinds ) );
this.pollingInterval = pollingInterval;
this.pollingIntervalTimeUnit = pollingIntervalTimeUnit;
this.cancelled = false;
this.initialized = false;
this.addMap = new HashMap<>();
this.deleteMap = new HashMap<>();
this.modifyMap = new HashMap<>();
this.state = State.READY;
}
void addCreateEvent( UnixSshPath path ) {
if ( kindsToWatch.contains( StandardWatchEventKinds.ENTRY_CREATE ) ) {
try {
mapLock.lock();
logger.trace( "added: {}", path );
if ( !addMap.containsKey( path ) ) {
addMap.put( path, new UnixSshPathWatchEvent( StandardWatchEventKinds.ENTRY_CREATE, path ) );
}
}
finally {
mapLock.unlock();
}
signal();
}
}
void addDeleteEvent( UnixSshPath path ) {
if ( kindsToWatch.contains( StandardWatchEventKinds.ENTRY_DELETE ) ) {
try {
mapLock.lock();
logger.trace( "deleted: {}", path );
if ( !deleteMap.containsKey( path ) ) {
deleteMap.put( path, new UnixSshPathWatchEvent( StandardWatchEventKinds.ENTRY_DELETE, path ) );
}
}
finally {
mapLock.unlock();
}
signal();
}
}
void addModifyEvent( UnixSshPath path ) {
if ( kindsToWatch.contains( StandardWatchEventKinds.ENTRY_MODIFY ) ) {
try {
mapLock.lock();
logger.trace( "modified: {}", path );
if ( modifyMap.containsKey( path ) ) {
modifyMap.get( path ).increment();
}
else {
UnixSshPathWatchEvent event = new UnixSshPathWatchEvent( StandardWatchEventKinds.ENTRY_MODIFY, path );
modifyMap.put( path, event );
}
}
finally {
mapLock.unlock();
}
signal();
}
}
@Override
public void cancel() {
watchService.unregister( this );
cancelled = true;
}
@Override
public boolean isValid() {
return (!cancelled) && (!watchService.closed());
}
private static boolean modified( PosixFileAttributes attributes, PosixFileAttributes otherAttributes ) {
if ( attributes.size() != otherAttributes.size() ) {
return true;
}
if ( attributes.lastModifiedTime() != otherAttributes.lastModifiedTime() ) {
return true;
}
return false;
}
@Override
public List> pollEvents() {
try {
mapLock.lock();
List> currentEvents = new ArrayList<>();
currentEvents.addAll( addMap.values() );
currentEvents.addAll( deleteMap.values() );
currentEvents.addAll( modifyMap.values() );
addMap.clear();
deleteMap.clear();
modifyMap.clear();
return Collections.unmodifiableList( currentEvents );
}
finally {
mapLock.unlock();
}
}
@Override
public boolean reset() {
if ( !isValid() ) {
return false;
}
try {
mapLock.lock();
if ( addMap.size() > 0 || deleteMap.size() > 0 || modifyMap.size() > 0 ) {
signal();
return true;
}
}
finally {
mapLock.unlock();
}
try {
stateLock.lock();
state = State.READY;
}
finally {
stateLock.unlock();
}
return true;
}
@Override
public void run() {
boolean first = true;
try {
while ( true ) {
if ( !isValid() ) {
break;
}
try {
logger.trace( "polling {}", dir );
Map entries =
dir.getFileSystem().provider().statDirectory( dir );
logger.trace( "got response {}", dir );
if ( first ) {
first = false;
this.entries = entries;
try {
pollerLock.lock();
logger.trace( "initialization complete got lock" );
initialized = true;
initializationComplete.signalAll();
logger.debug( "poller is initialized" );
}
finally {
pollerLock.unlock();
}
}
else {
for ( UnixSshPath entryPath : entries.keySet() ) {
if ( this.entries.containsKey( entryPath ) ) {
if ( modified( entries.get( entryPath ), this.entries.remove( entryPath ) ) ) {
addModifyEvent( entryPath );
}
}
else {
addCreateEvent( entryPath );
}
}
for ( UnixSshPath entryPath : this.entries.keySet() ) {
addDeleteEvent( entryPath );
}
this.entries = entries;
}
}
catch ( IOException e ) {
logger.error( "checking {} failed: {}", dir, e );
logger.debug( "checking directory failed: ", e );
}
try {
pollerLock.lock();
logger.trace( "poller entering await {} {}", pollingInterval, pollingIntervalTimeUnit );
runImmediately.await( pollingInterval, pollingIntervalTimeUnit );
}
finally {
pollerLock.unlock();
}
}
}
catch ( ClosedWatchServiceException e ) {
logger.debug( "watch service was closed, so exit" );
}
catch ( InterruptedException e ) {
// time to close out
logger.debug( "interrupt caught, closing down poller" );
}
logger.info( "poller stopped for {}", dir );
}
void runImmediately() {
try {
pollerLock.lock();
runImmediately.signal();
}
finally {
pollerLock.unlock();
}
}
private void signal() {
try {
stateLock.lock();
logger.trace( "signaling" );
if ( state != State.SIGNALLED ) {
state = State.SIGNALLED;
logger.trace( "enqueueing {}", this );
watchService.enqueue( this );
}
}
finally {
stateLock.unlock();
}
}
boolean waitForInitialization( long time, TimeUnit timeUnit ) {
logger.debug( "waiting {} {} for initialization", time, timeUnit );
try {
pollerLock.lock();
logger.debug( "wait for initialization obtained lock" );
if ( initialized ) {
return true;
}
initializationComplete.await( time, timeUnit );
logger.debug( "initialization complete" );
return true;
}
catch ( InterruptedException e ) {
return false;
}
finally {
pollerLock.unlock();
}
}
@Override
public UnixSshPath watchable() {
return dir;
}
private enum State {
READY, SIGNALLED
}
}