Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
src/main/java/org/fcrepo/federation/bagit/BagItWatchService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package org.fcrepo.federation.bagit; | ||
|
||
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.FileNotFoundException; | ||
import java.io.FileReader; | ||
import java.io.IOException; | ||
import java.io.LineNumberReader; | ||
import java.nio.file.FileSystems; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.WatchKey; | ||
import java.nio.file.WatchService; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.google.common.base.Function; | ||
|
||
public class BagItWatchService implements WatchService { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(BagItWatchService.class); | ||
|
||
static final Pattern MANIFEST = Pattern.compile("^manifest-([^\\.]+).txt$"); | ||
static final Pattern TAG_MANIFEST = Pattern.compile("^tagmanifest-([^\\.]+).txt$"); | ||
|
||
static GetFilesFromManifest getFilesFromManifest = new GetFilesFromManifest(); | ||
|
||
WatchService delegate; | ||
|
||
Collection<Path> tagFiles = new ArrayList<Path>(); | ||
|
||
Collection<Path> manifests = new ArrayList<Path>(); | ||
|
||
BagItWatchService() throws IOException { | ||
delegate = FileSystems.getDefault().newWatchService(); | ||
} | ||
|
||
public BagItWatchService(File bagItDir) throws IOException { | ||
this(); | ||
for (File file: bagItDir.listFiles()) { | ||
if (isManifest(file)) { | ||
monitorManifest(file); | ||
} else if (isTagManifest(file)) { | ||
for (File listedFile: getFilesFromManifest.apply(file)) monitorTagFile(listedFile); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
delegate.close(); | ||
} | ||
|
||
@Override | ||
public WatchKey poll() { | ||
return delegate.poll(); | ||
} | ||
|
||
@Override | ||
public WatchKey poll(long timeout, TimeUnit unit) | ||
throws InterruptedException { | ||
return delegate.poll(timeout, unit); | ||
} | ||
|
||
@Override | ||
public WatchKey take() throws InterruptedException { | ||
return delegate.take(); | ||
} | ||
|
||
public void monitorTagFile(File input) throws IOException { | ||
Path path = Paths.get(input.toURI()); | ||
if (!tagFiles.contains(path)) tagFiles.add(path); | ||
path.register(this, ENTRY_MODIFY); | ||
} | ||
|
||
public void monitorManifest(File input) throws IOException { | ||
Path path = Paths.get(input.toURI()); | ||
if (!manifests.contains(path)) manifests.add(path); | ||
path.register(this, ENTRY_MODIFY); | ||
} | ||
|
||
boolean isManifest(String fileName) { | ||
Matcher m = MANIFEST.matcher(fileName); | ||
if (m.find()) { | ||
String csa = m.group(1); | ||
try { | ||
MessageDigest.getInstance(csa); | ||
return true; | ||
} catch (NoSuchAlgorithmException e) { | ||
logger.warn("Ignoring potential manifest file {} because {} is not a supported checksum algorithm.", fileName, csa); | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
boolean isManifest(File file) { | ||
if (file.isFile() && file.canRead() && !file.isHidden()) { | ||
return(isManifest(file.getName())); | ||
} else return false; | ||
} | ||
|
||
boolean isManifest(Path path) { | ||
return isManifest(path.toFile()); | ||
} | ||
|
||
boolean isTagManifest(String fileName) { | ||
Matcher m = TAG_MANIFEST.matcher(fileName); | ||
if (m.find()) { | ||
String csa = m.group(1); | ||
try { | ||
MessageDigest.getInstance(csa); | ||
return true; | ||
} catch (NoSuchAlgorithmException e) { | ||
logger.warn("Ignoring potential tag-manifest file {} because {} is not a supported checksum algorithm.", fileName, csa); | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
boolean isTagManifest(File file) { | ||
if (file.isFile() && file.canRead() && !file.isHidden()) { | ||
return isTagManifest(file.getName()); | ||
} else return false; | ||
} | ||
|
||
boolean isTagManifest(Path path) { | ||
return isManifest(path.toFile()); | ||
} | ||
|
||
static class GetFilesFromManifest implements Function<File, Collection<File>> { | ||
|
||
@Override | ||
public Collection<File> apply(File input) { | ||
try { | ||
ArrayList<File> result = new ArrayList<File>(); | ||
LineNumberReader lnr = new LineNumberReader(new FileReader(input)); | ||
String line = null; | ||
while((line = lnr.readLine()) != null) { | ||
File file = new File(input.getParentFile(), line); | ||
result.add(file); | ||
} | ||
return result; | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
return null; | ||
} | ||
} | ||
|
||
} | ||
|
||
} |
48 changes: 48 additions & 0 deletions
48
src/main/java/org/fcrepo/federation/bagit/ManifestMonitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.fcrepo.federation.bagit; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.nio.file.WatchEvent; | ||
import java.nio.file.WatchKey; | ||
import java.util.List; | ||
|
||
public class ManifestMonitor implements Runnable { | ||
|
||
private BagItConnector connector; | ||
|
||
private BagItWatchService watchService; | ||
|
||
private boolean run; | ||
|
||
public ManifestMonitor(BagItConnector connector) throws IOException { | ||
this.connector = connector; | ||
this.watchService = new BagItWatchService(connector.getBagItDirectory()); | ||
} | ||
|
||
@Override | ||
public void run() { | ||
while(!Thread.interrupted()) { | ||
WatchKey key = watchService.poll(); | ||
List<WatchEvent<?>> events = key.pollEvents(); | ||
boolean manifest = false; | ||
boolean tagManifest = false; | ||
Path path; | ||
for (WatchEvent<?> event: events) { | ||
Path context = (Path)event.context(); | ||
if (watchService.isManifest(context)) { | ||
manifest = true; | ||
path= context; | ||
} else if (watchService.isTagManifest(context)) { | ||
tagManifest = true; | ||
path= context; | ||
} | ||
} | ||
if (manifest) { | ||
//connector.manifestChanged(path.toFile()); | ||
} else if (tagManifest) { | ||
//connector.tagFileChanged(path.toFile()); | ||
} | ||
} | ||
} | ||
|
||
} |
50 changes: 50 additions & 0 deletions
50
src/test/java/org/fcrepo/federation/bagit/BagItWatchServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.fcrepo.federation.bagit; | ||
|
||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertTrue; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.when; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
|
||
import org.junit.Test; | ||
|
||
public class BagItWatchServiceTest { | ||
|
||
@Test | ||
public void testIsManifest() throws IOException { | ||
File input = mock(File.class); | ||
when(input.isFile()).thenReturn(true); | ||
when(input.canRead()).thenReturn(true); | ||
|
||
BagItWatchService test = new BagItWatchService(); | ||
String fname = "not-a-manifest.txt"; | ||
when(input.getName()).thenReturn(fname); | ||
assertFalse("\"" + fname + "\" should not be a valid manifest file", test.isManifest(input)); | ||
fname = "manifest-md5.txt"; | ||
when(input.getName()).thenReturn(fname); | ||
assertTrue("\"" + fname + "\" should be a valid manifest file", test.isManifest(input)); | ||
fname = "manifest-foobar.txt"; | ||
when(input.getName()).thenReturn(fname); | ||
assertFalse("Unexpected checksum algorithm \"foobar\" returned valid manifest", test.isManifest(input)); | ||
} | ||
|
||
@Test | ||
public void testIsTagManifest() throws IOException { | ||
File input = mock(File.class); | ||
when(input.isFile()).thenReturn(true); | ||
when(input.canRead()).thenReturn(true); | ||
|
||
BagItWatchService test = new BagItWatchService(); | ||
String fname = "not-a-manifest.txt"; | ||
when(input.getName()).thenReturn(fname); | ||
assertFalse("\"" + fname + "\" should not be a valid manifest file", test.isTagManifest(input)); | ||
fname = "tagmanifest-md5.txt"; | ||
when(input.getName()).thenReturn(fname); | ||
assertTrue("\"" + fname + "\" should be a valid manifest file", test.isTagManifest(input)); | ||
fname = "tagmanifest-foobar.txt"; | ||
when(input.getName()).thenReturn(fname); | ||
assertFalse("Unexpected checksum algorithm \"foobar\" returned valid manifest", test.isTagManifest(input)); | ||
} | ||
} |