diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecorator.java b/datamover/source/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecorator.java index 624416c4969916ff8e27dd1f75537036fb00e2af..3d7eb1077fcf97ec5570b72c0857f1caa456d5e1 100644 --- a/datamover/source/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecorator.java +++ b/datamover/source/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecorator.java @@ -20,7 +20,7 @@ import java.io.File; import java.io.FileFilter; import ch.systemsx.cisd.common.utilities.FileUtilities; -import ch.systemsx.cisd.datamover.DirectoryScanningTimerTask.IPathHandler; +import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IPathHandler; /** * A class that decorates an {@link IPathHandler} with a selective cleansing task. The files that should be removed in diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/DirectoryScanningTimerTask.java b/datamover/source/java/ch/systemsx/cisd/datamover/DirectoryScanningTimerTask.java deleted file mode 100644 index f3cb5d14b8baa40c6b450191aabc33f052ff6cbe..0000000000000000000000000000000000000000 --- a/datamover/source/java/ch/systemsx/cisd/datamover/DirectoryScanningTimerTask.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2007 ETH Zuerich, CISD - * - * Licensed 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 ch.systemsx.cisd.datamover; - -import java.io.File; -import java.io.FileFilter; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; -import java.util.TimerTask; - -import org.apache.log4j.Logger; - -import ch.systemsx.cisd.common.logging.LogCategory; -import ch.systemsx.cisd.common.logging.LogFactory; -import ch.systemsx.cisd.common.utilities.CollectionIO; -import ch.systemsx.cisd.common.utilities.FileUtilities; -import ch.systemsx.cisd.common.utilities.IFromStringConverter; - -/** - * A {@link TimerTask} that scans a source directory for entries that are accepted by some {@link FileFilter} and - * handles the accepted entries by some {@link IPathHandler}. It maintains a list of faulty paths that failed to be - * handled OK in the past. Clearing the list will make the class to retry handling the paths. - * <p> - * The class should be constructed in the start-up phase and as part of the system's self-test in order to reveal - * problems with incorrect paths timely. - * - * @author Bernd Rinn - */ -public final class DirectoryScanningTimerTask extends TimerTask -{ - - public static final String FAULTY_PATH_FILENAME = ".faulty_paths"; - - private static final Logger operationLog = - LogFactory.getLogger(LogCategory.OPERATION, DirectoryScanningTimerTask.class); - - private static final Logger notificationLog = - LogFactory.getLogger(LogCategory.NOTIFY, DirectoryScanningTimerTask.class); - - private static final IFromStringConverter<File> FILE_CONVERTER = new IFromStringConverter<File>() - { - public File fromString(String value) - { - return new File(value); - } - }; - - private final IPathHandler handler; - - private final File sourceDirectory; - - private boolean errorReadingDirectory; - - private final FileFilter filter; - - private final Set<File> faultyPaths; - - private final File faultyPathsFile; - - private long faultyPathsLastChanged; - - /** - * A handler for paths. The paths are supposed to go away when they have been handled successfully. - */ - public interface IPathHandler - { - /** - * Handles the <var>path</var>. - * - * @return <code>true</code> if the <var>path</var> has been handled correctly and <code>false</code> - * otherwise. - */ - public boolean handle(File path); - } - - /** - * Creates a <var>DirectoryScanningTimerTask</var>. - * - * @param sourceDirectory The directory to scan for entries. - * @param filter The file filter that picks the entries to handle. - * @param handler The handler that is used for treating the matching paths. - */ - public DirectoryScanningTimerTask(File sourceDirectory, FileFilter filter, IPathHandler handler) - { - assert sourceDirectory != null; - assert filter != null; - assert handler != null; - assert FileUtilities.checkDirectoryFullyAccessible(sourceDirectory, "source") == null : FileUtilities - .checkDirectoryFullyAccessible(sourceDirectory, "source"); - - this.sourceDirectory = sourceDirectory; - this.filter = filter; - this.handler = handler; - this.faultyPaths = new HashSet<File>(); - this.faultyPathsFile = new File(sourceDirectory, FAULTY_PATH_FILENAME); - faultyPathsFile.delete(); - } - - /** - * Handles all entries in {@link #sourceDirectory} that are picked by the {@link #filter} by some {@link #handler}. - */ - @Override - public void run() - { - if (operationLog.isTraceEnabled()) - { - operationLog.trace("Start scanning directory."); - } - checkForFaultyPathsFileChanged(); - final File[] paths = listFiles(); - if (paths == null) // Means: error reading directory listing - { - return; - } - // Sort in order of "oldest first" in order to move older items before newer items. This becomes important when - // doing online quality control of measurements. - Arrays.sort(paths, new Comparator<File>() - { - public int compare(File o1, File o2) - { - return (int) (o1.lastModified() - o2.lastModified()); - } - }); - for (File path : paths) - { - if (faultyPathsFile.equals(path)) // Never touch the faultyPathsFile. - { - continue; - } - if (path.getName().startsWith(".is_finished_")) // Ignore any .is_finished files as created in remote mode. - { - continue; - } - handle(path); - } - if (operationLog.isTraceEnabled()) - { - operationLog.trace("Finished scanning directory."); - } - } - - private void checkForFaultyPathsFileChanged() - { - if (faultyPathsFile.exists()) - { - if (faultyPathsFile.lastModified() > faultyPathsLastChanged) // Handles manual manipulation. - { - faultyPaths.clear(); - CollectionIO.readCollection(faultyPathsFile, faultyPaths, FILE_CONVERTER); - faultyPathsLastChanged = faultyPathsFile.lastModified(); - if (operationLog.isInfoEnabled()) - { - operationLog.info(String.format("Reread faulty paths file (%s), new set contains %d entries", - faultyPathsFile.getPath(), faultyPaths.size())); - } - } - } else - // Handles manual removal. - { - faultyPaths.clear(); - } - } - - private File[] listFiles() - { - File[] paths = null; - RuntimeException ex = null; - try - { - paths = sourceDirectory.listFiles(filter); - } catch (RuntimeException e) - { - ex = e; - } - if (paths == null) - { - if (errorReadingDirectory == false) - { - logFailureInDirectoryListing(ex); - errorReadingDirectory = true; // Avoid mailbox flooding. - } - } else - { - errorReadingDirectory = false; - } - return paths; - } - - private void logFailureInDirectoryListing(RuntimeException ex) - { - if (ex == null) - { - if (sourceDirectory.isFile()) - { - notificationLog.error(String - .format("Failed to get listing of directory '%s' (path is file instead of directory).", - sourceDirectory)); - } else - { - notificationLog.error(String.format("Failed to get listing of directory '%s' (path not found).", - sourceDirectory)); - } - } else - { - notificationLog.error(String.format("Failed to get listing of directory '%s'.", sourceDirectory), ex); - } - } - - private void handle(File path) - { - if (faultyPaths.contains(path)) - { // Guard: skip faulty paths. - return; - } - - final boolean handledOK = handler.handle(path); - if (path.exists()) - { - if (handledOK) - { - operationLog.warn(String.format("Handler %s reports path '%s' be handled OK, but path still exists.", - handler.getClass().getSimpleName(), path)); - } - faultyPaths.add(path); - CollectionIO.writeIterable(faultyPathsFile, faultyPaths); - faultyPathsLastChanged = faultyPathsFile.lastModified(); - } - } - -} diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/IntraFSPathMover.java b/datamover/source/java/ch/systemsx/cisd/datamover/IntraFSPathMover.java deleted file mode 100644 index c8ccdab6c79b24ee18cf4e2af71a49d9f58a9e1d..0000000000000000000000000000000000000000 --- a/datamover/source/java/ch/systemsx/cisd/datamover/IntraFSPathMover.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2007 ETH Zuerich, CISD - * - * Licensed 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 ch.systemsx.cisd.datamover; - -import java.io.File; - -import org.apache.log4j.Logger; - -import ch.systemsx.cisd.common.logging.LogCategory; -import ch.systemsx.cisd.common.logging.LogFactory; -import ch.systemsx.cisd.common.utilities.FileUtilities; - -/** - * A {@link DirectoryScanningTimerTask.IPathHandler} that moves paths out of the way within one file system by calling - * {@link File#renameTo(File)}.. - * - * @author Bernd Rinn - */ -public class IntraFSPathMover implements DirectoryScanningTimerTask.IPathHandler -{ - - private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, IntraFSPathMover.class); - - private static final Logger notificationLog = LogFactory.getLogger(LogCategory.NOTIFY, IntraFSPathMover.class); - - private final File destinationDirectory; - - /** - * Creates a <var>PathMover</var>. - * - * @param destinationDirectory The directory to move paths to. - */ - public IntraFSPathMover(File destinationDirectory) - { - assert destinationDirectory != null; - assert FileUtilities.checkDirectoryFullyAccessible(destinationDirectory, "destination") == null : FileUtilities - .checkDirectoryFullyAccessible(destinationDirectory, "destination"); - - this.destinationDirectory = destinationDirectory; - } - - public boolean handle(File path) - { - assert path != null; - assert destinationDirectory != null; - - if (operationLog.isInfoEnabled()) - { - operationLog - .info(String.format("Moving path '%s' to '%s'", path.getPath(), destinationDirectory.getPath())); - } - boolean movedOK = path.renameTo(new File(destinationDirectory, path.getName())); - if (movedOK == false) - { - notificationLog.error(String.format("Moving path '%s' to directory '%s' failed.", path, - destinationDirectory)); - } - return movedOK; - } - -} diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/Main.java b/datamover/source/java/ch/systemsx/cisd/datamover/Main.java index 520398fa88cd78c6eedcba69a7f0e4bfb1bfb5d9..66526cefcca0d1238d97ee2ff57bdefcdd511c2d 100644 --- a/datamover/source/java/ch/systemsx/cisd/datamover/Main.java +++ b/datamover/source/java/ch/systemsx/cisd/datamover/Main.java @@ -17,41 +17,36 @@ package ch.systemsx.cisd.datamover; import java.io.File; -import java.io.FileFilter; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Timer; import org.apache.log4j.Logger; +import ch.systemsx.cisd.common.Constants; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.exceptions.HighLevelException; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.utilities.BuildAndEnvironmentInfo; +import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask; +import ch.systemsx.cisd.common.utilities.IntraFSPathMover; +import ch.systemsx.cisd.common.utilities.NamePrefixFileFilter; import ch.systemsx.cisd.common.utilities.OSUtilities; import ch.systemsx.cisd.common.utilities.RegexFileFilter; +import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IPathHandler; import ch.systemsx.cisd.common.utilities.RegexFileFilter.PathType; -import ch.systemsx.cisd.datamover.DirectoryScanningTimerTask.IPathHandler; import ch.systemsx.cisd.datamover.rsync.RsyncCopier; import ch.systemsx.cisd.datamover.xcopy.XcopyCopier; /** - * The main class of the raw data mover. + * The main class of the datamover. * * @author Bernd Rinn */ public class Main { - private static final FileFilter ALWAYS_TRUE_FILTER = new FileFilter() - { - public boolean accept(File pathname) - { - return true; - } - }; - private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, Main.class); private static final Logger notificationLog = LogFactory.getLogger(LogCategory.NOTIFY, Main.class); @@ -60,7 +55,7 @@ public class Main { public void uncaughtException(Thread t, Throwable e) { - notificationLog.error("An exception has occurred.", e); + notificationLog.error("An exception has occurred [thread: '" + t.getName() + "'].", e); } }; @@ -72,7 +67,7 @@ public class Main private static void printInitialLogMessage(final Parameters parameters) { - operationLog.info("Data mover is starting up."); + operationLog.info("datamover is starting up."); for (String line : BuildAndEnvironmentInfo.INSTANCE.getEnvironmentInfo()) { operationLog.info(line); @@ -90,7 +85,8 @@ public class Main } else if (OSUtilities.isWindows()) { return new XcopyCopier(OSUtilities.findExecutable("xcopy"), requiresDeletionBeforeCreation); - } else { + } else + { throw new ConfigurationFailureException("Unable to find a copy engine."); } } @@ -192,7 +188,8 @@ public class Main final IPathHandler remoteMover = new RemotePathMover(remoteDataDirectory, remoteHost, monitor, operations, parameters); final DirectoryScanningTimerTask remoteMovingTask = - new DirectoryScanningTimerTask(localTemporaryDirectory, ALWAYS_TRUE_FILTER, remoteMover); + new DirectoryScanningTimerTask(localTemporaryDirectory, + new NamePrefixFileFilter(Constants.IS_FINISHED_PREFIX, false), remoteMover); final RegexFileFilter cleansingFilter = new RegexFileFilter(); if (parameters.getCleansingRegex() != null) { @@ -224,7 +221,7 @@ public class Main final Parameters parameters = new Parameters(args); printInitialLogMessage(parameters); startupServer(parameters); - operationLog.info("Data mover ready and waiting for data."); + operationLog.info("datamover ready and waiting for data."); } } diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/RemotePathMover.java b/datamover/source/java/ch/systemsx/cisd/datamover/RemotePathMover.java index 3a34def44fc9d4fa6c12f046b96e3479ce7f77b0..d08cbde57ea76b116216653a8a2c1b45d525f7f1 100644 --- a/datamover/source/java/ch/systemsx/cisd/datamover/RemotePathMover.java +++ b/datamover/source/java/ch/systemsx/cisd/datamover/RemotePathMover.java @@ -20,10 +20,13 @@ import java.io.File; import java.io.IOException; import org.apache.log4j.Logger; + +import ch.systemsx.cisd.common.Constants; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.StatusFlag; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask; import ch.systemsx.cisd.common.utilities.FileUtilities; /** @@ -191,7 +194,7 @@ public final class RemotePathMover implements DirectoryScanningTimerTask.IPathHa private boolean markAsFinishedLocal(File path) { - final File markFile = new File(destinationDirectory, ".is_finished_" + path.getName()); + final File markFile = new File(destinationDirectory, Constants.IS_FINISHED_PREFIX + path.getName()); try { markFile.createNewFile(); @@ -210,7 +213,7 @@ public final class RemotePathMover implements DirectoryScanningTimerTask.IPathHa private boolean markAsFinishedRemote(File path) { - final File markFile = new File(path.getParent(), ".is_finished_" + path.getName()); + final File markFile = new File(path.getParent(), Constants.IS_FINISHED_PREFIX + path.getName()); try { markFile.createNewFile(); diff --git a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecoratorTest.java b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecoratorTest.java index 39ad89ffdb91a2ca5b46e1fdea2ac1d8d18644e1..38f53b85b3a7c7712830a51477dae06e404e4e2e 100644 --- a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecoratorTest.java +++ b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CleansingPathHandlerDecoratorTest.java @@ -26,8 +26,8 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.utilities.FileUtilities; +import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IPathHandler; -import ch.systemsx.cisd.datamover.DirectoryScanningTimerTask.IPathHandler; /** * Test cases for the {@link CleansingPathHandlerDecorator}. diff --git a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CopyActivityMonitorTest.java b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CopyActivityMonitorTest.java index 88b32adb2492903d99a62275743b412f3d153b39..9d12d92040fe59d1414be1983e69c0056dc025a2 100644 --- a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CopyActivityMonitorTest.java +++ b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/CopyActivityMonitorTest.java @@ -29,6 +29,7 @@ import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.logging.LogMonitoringAppender; import ch.systemsx.cisd.common.utilities.ITerminable; +import ch.systemsx.cisd.common.utilities.StoringUncaughtExceptionHandler; /** * Test cases for the {@link CopyActivityMonitor} class. diff --git a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/DirectoryScanningTimerTaskTest.java b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/DirectoryScanningTimerTaskTest.java deleted file mode 100644 index f0c46e18fa7ca21fe7c9880002174db73bf0dbb1..0000000000000000000000000000000000000000 --- a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/DirectoryScanningTimerTaskTest.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2007 ETH Zuerich, CISD - * - * Licensed 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 ch.systemsx.cisd.datamover; - -import static org.testng.AssertJUnit.assertEquals; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import ch.systemsx.cisd.common.logging.LogCategory; -import ch.systemsx.cisd.common.logging.LogInitializer; -import ch.systemsx.cisd.common.logging.LogMonitoringAppender; -import ch.systemsx.cisd.common.utilities.CollectionIO; -import ch.systemsx.cisd.common.utilities.FileUtilities; -import ch.systemsx.cisd.datamover.DirectoryScanningTimerTask.IPathHandler; - -/** - * Test cases for the {@link DirectoryScanningTimerTask}. - * - * @author Bernd Rinn - */ -public class DirectoryScanningTimerTaskTest -{ - - private static final File unitTestRootDirectory = new File("targets" + File.separator + "unit-test-wd"); - - private static final File workingDirectory = new File(unitTestRootDirectory, "DirectoryScanningTimerTaskTest"); - - private final StoringUncaughtExceptionHandler exceptionHandler = new StoringUncaughtExceptionHandler(); - - private final static FileFilter ALWAYS_FALSE_FILE_FILTER = new FileFilter() - { - public boolean accept(File pathname) - { - return false; - } - }; - - private final static FileFilter ALWAYS_TRUE_FILE_FILTER = new FileFilter() - { - public boolean accept(File pathname) - { - return true; - } - }; - - private final static String EXCEPTION_THROWING_FILE_FILTER_MESSAGE = "Exception throwing file filter does its job."; - - private final static FileFilter EXCEPTION_THROWING_FILE_FILTER = new FileFilter() - { - public boolean accept(File pathname) - { - throw new RuntimeException(EXCEPTION_THROWING_FILE_FILTER_MESSAGE); - } - }; - - private final MockPathHandler mockPathHandler = new MockPathHandler(); - - /** - * A mock implementation that stores the handled paths. - */ - public static class MockPathHandler implements IPathHandler - { - - final List<File> handledPaths = new ArrayList<File>(); - - public void clear() - { - handledPaths.clear(); - } - - public boolean handle(File path) - { - handledPaths.add(path); - path.delete(); - return true; - } - - } - - @BeforeClass - public void init() - { - LogInitializer.init(); - unitTestRootDirectory.mkdirs(); - assert unitTestRootDirectory.isDirectory(); - Thread.setDefaultUncaughtExceptionHandler(exceptionHandler); - } - - @BeforeMethod - public void setUp() - { - FileUtilities.deleteRecursively(workingDirectory); - workingDirectory.mkdirs(); - workingDirectory.deleteOnExit(); - mockPathHandler.clear(); - } - - @AfterMethod - public void checkException() - { - exceptionHandler.checkAndRethrowException(); - } - - @Test(expectedExceptions = - { AssertionError.class }) - public void testFailedConstructionNonExistent() - { - final File nonExistentFile = new File(unitTestRootDirectory, "non-existent"); - nonExistentFile.delete(); - new DirectoryScanningTimerTask(nonExistentFile, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - } - - @Test(expectedExceptions = - { AssertionError.class }) - public void testFailedConstructionFileInsteadOfDirectory() throws IOException - { - final File file = new File(unitTestRootDirectory, "existent_file"); - file.delete(); - file.deleteOnExit(); - file.createNewFile(); - new DirectoryScanningTimerTask(file, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - } - - @Test(groups = - { "requires_unix" }, expectedExceptions = - { AssertionError.class }) - public void testFailedConstructionReadOnly() throws IOException, InterruptedException - { - final File readOnlyDirectory = new File(unitTestRootDirectory, "read_only_directory"); - readOnlyDirectory.delete(); - readOnlyDirectory.mkdir(); - readOnlyDirectory.deleteOnExit(); - if (readOnlyDirectory.setReadOnly() == false) - { - // Can't use assert here since we expect an AssertationError - throw new IllegalStateException(); - } - - try - { - // Here we should get an AssertationError - new DirectoryScanningTimerTask(readOnlyDirectory, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - } finally - { - // Unfortunately, with JDK 5 there is no portable way to set a file or directory read/write, once - // it has been set read-only, thus this test 'requires_unix' for the time being. - Runtime.getRuntime().exec(String.format("/bin/chmod u+w %s", readOnlyDirectory.getPath())).waitFor(); - if (readOnlyDirectory.canWrite() == false) - { - // Can't use assert here since we expect an AssertationError - throw new IllegalStateException(); - } - } - } - - @Test - public void testFaultyPathsDeletion() - { - final File faultyPaths = new File(workingDirectory, DirectoryScanningTimerTask.FAULTY_PATH_FILENAME); - CollectionIO.writeIterable(faultyPaths, Collections.singleton("some_path")); - new DirectoryScanningTimerTask(workingDirectory, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - assert faultyPaths.length() == 0; - } - - @Test - public void testProcessOK() throws IOException - { - final File someFile = new File(workingDirectory, "some_file"); - someFile.createNewFile(); - someFile.deleteOnExit(); - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(workingDirectory, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - assertEquals(0, mockPathHandler.handledPaths.size()); - scanner.run(); - assertEquals(1, mockPathHandler.handledPaths.size()); - assertEquals(someFile, mockPathHandler.handledPaths.get(0)); - } - - @Test - public void testFileFilterUsed() throws IOException - { - final File someFile = new File(workingDirectory, "some_file"); - someFile.createNewFile(); - someFile.deleteOnExit(); - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(workingDirectory, ALWAYS_FALSE_FILE_FILTER, mockPathHandler); - assertEquals(0, mockPathHandler.handledPaths.size()); - scanner.run(); - assertEquals(0, mockPathHandler.handledPaths.size()); - } - - @Test - public void testManipulateFaultyPaths() throws IOException - { - final File faultyPaths = new File(workingDirectory, DirectoryScanningTimerTask.FAULTY_PATH_FILENAME); - final File someFile = new File(workingDirectory, "some_file"); - someFile.createNewFile(); - someFile.deleteOnExit(); - assert someFile.exists(); - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(workingDirectory, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - CollectionIO.writeIterable(faultyPaths, Collections.singleton(someFile)); - scanner.run(); - assertEquals(0, mockPathHandler.handledPaths.size()); - } - - @Test - public void testFaultyPaths() throws IOException - { - final File faultyPaths = new File(workingDirectory, DirectoryScanningTimerTask.FAULTY_PATH_FILENAME); - final File someFile = new File(workingDirectory, "some_file"); - final MockPathHandler myPathHandler = new MockPathHandler() - { - boolean firstTime = true; - - @Override - public boolean handle(File path) - { - if (firstTime) - { - firstTime = false; - return false; - } - return super.handle(path); - } - }; - someFile.createNewFile(); - assert someFile.exists(); - someFile.deleteOnExit(); - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(workingDirectory, ALWAYS_TRUE_FILE_FILTER, myPathHandler); - - // See whether faulty_paths settings works. - scanner.run(); - assertEquals(0, mockPathHandler.handledPaths.size()); - List<String> faulty = CollectionIO.readList(faultyPaths); - assertEquals(1, faulty.size()); - assertEquals(someFile.getPath(), faulty.get(0)); - // See whether fault_paths resetting works. - assert faultyPaths.delete(); - myPathHandler.clear(); // Isn't necessary, just for expressing intention. - // See whether faulty_paths settings works. - scanner.run(); - assertEquals(1, myPathHandler.handledPaths.size()); - assertEquals(someFile, myPathHandler.handledPaths.get(0)); - } - - @Test - public void testPathOrder() throws IOException - { - final File dir = new File(workingDirectory, "testPathOrder"); - final File f1 = new File(dir, "1"); - final File f2 = new File(dir, "2"); - final File f3 = new File(dir, "3"); - final File f4 = new File(dir, "4"); - final long now = System.currentTimeMillis(); - dir.mkdir(); - dir.deleteOnExit(); - f1.createNewFile(); - f1.deleteOnExit(); - f2.createNewFile(); - f2.deleteOnExit(); - f3.createNewFile(); - f3.deleteOnExit(); - f4.createNewFile(); - f4.deleteOnExit(); - // Order should be: 2, 4, 3, 1 - f2.setLastModified(now - 10000); - f4.setLastModified(now - 5000); - f3.setLastModified(now - 1000); - f1.setLastModified(now); - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(dir, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - scanner.run(); - assertEquals(f2, mockPathHandler.handledPaths.get(0)); - assertEquals(f4, mockPathHandler.handledPaths.get(1)); - assertEquals(f3, mockPathHandler.handledPaths.get(2)); - assertEquals(f1, mockPathHandler.handledPaths.get(3)); - assertEquals(4, mockPathHandler.handledPaths.size()); - } - - @Test - public void testMissingDirectory() - { - final File dir = new File(workingDirectory, "testMissingDirectory"); - dir.mkdir(); - LogMonitoringAppender appender = - LogMonitoringAppender.addAppender(LogCategory.NOTIFY, "Failed to get listing of directory"); - // The directory needs to exist when the scanner is created, otherwise the self-test will fail. - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(dir, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - dir.delete(); - assert dir.exists() == false; - scanner.run(); - assert appender.hasLogHappened(); - LogMonitoringAppender.removeAppender(appender); - } - - @Test - public void testDirectoryIsFile() throws IOException - { - final File dir = new File(workingDirectory, "testMissingDirectory"); - dir.mkdir(); - LogMonitoringAppender appender = - LogMonitoringAppender.addAppender(LogCategory.NOTIFY, "Failed to get listing of directory"); - // The directory needs to exist when the scanner is created, otherwise the self-test will fail. - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(dir, ALWAYS_TRUE_FILE_FILTER, mockPathHandler); - dir.delete(); - dir.createNewFile(); - dir.deleteOnExit(); - assert dir.isFile(); - scanner.run(); - assert appender.hasLogHappened(); - dir.delete(); - LogMonitoringAppender.removeAppender(appender); - } - - @Test - public void testFailingFileFilter() throws IOException - { - final File dir = new File(workingDirectory, "testMissingDirectory"); - dir.mkdir(); - dir.deleteOnExit(); - final File file = new File(dir, "some.file"); - file.createNewFile(); - file.deleteOnExit(); - LogMonitoringAppender appender1 = - LogMonitoringAppender.addAppender(LogCategory.NOTIFY, "Failed to get listing of directory"); - LogMonitoringAppender appender2 = - LogMonitoringAppender.addAppender(LogCategory.NOTIFY, EXCEPTION_THROWING_FILE_FILTER_MESSAGE); - // The directory needs to exist when the scanner is created, otherwise the self-test will fail. - final DirectoryScanningTimerTask scanner = - new DirectoryScanningTimerTask(dir, EXCEPTION_THROWING_FILE_FILTER, mockPathHandler); - scanner.run(); - assert appender1.hasLogHappened(); - assert appender2.hasLogHappened(); - file.delete(); - dir.delete(); - LogMonitoringAppender.removeAppender(appender1); - LogMonitoringAppender.removeAppender(appender2); - } - -} diff --git a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/StoringUncaughtExceptionHandler.java b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/StoringUncaughtExceptionHandler.java deleted file mode 100644 index 12d05082396c48b579a7d0366dde3360acd3c82b..0000000000000000000000000000000000000000 --- a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/StoringUncaughtExceptionHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2007 ETH Zuerich, CISD - * - * Licensed 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 ch.systemsx.cisd.datamover; - -import java.lang.Thread.UncaughtExceptionHandler; - -/** - * An exception handler that stores the first occurring exception for later investigation. Needs to be activated by - * - * <pre> - * StoringUncaughtExceptionHandler exceptionHandler = new StoringUncaughtExceptionHandler(); - * Thread.setDefaultUncaughtExceptionHandler(exceptionHandler); - * </pre> - * - * @author Bernd Rinn - */ -public class StoringUncaughtExceptionHandler implements UncaughtExceptionHandler -{ - - private Throwable throwable; - - private String threadName; - - public void uncaughtException(Thread t, Throwable e) - { - if (throwable == null) // Only store the first throwable - { - throwable = e; - threadName = t.getName(); - } - } - - /** Resets the handler. Any stored exception will be lost. */ - public void reset() - { - throwable = null; - threadName = null; - } - - /** - * @return <code>true</code> if an exception or error has occurred, <code>false</code> otherwise. - */ - public boolean hasExceptionOccurred() - { - return (throwable != null); - } - - /** - * @return The throwable, if any has been occurred, or <code>null</code> otherwise. - */ - public Throwable getThrowable() - { - return throwable; - } - - /** - * @return The name of the thread where the exception or error has occurred, or <code>null</code>, if no - * exception or error has occurred. - */ - public String getThreadName() - { - return threadName; - } - - /** - * Checks whether an exception or error has occurred and, if yes, throws a new {@link RuntimeException} with the - * caught exception as cause in the current thread. - */ - public void checkAndRethrowException() - { - if (hasExceptionOccurred()) - { - throw new RuntimeException(String.format("An exception occurred in thread %s.", getThreadName()), - getThrowable()); - } - } - -} \ No newline at end of file diff --git a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/rsync/RsyncCopierTest.java b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/rsync/RsyncCopierTest.java index dddfaeb4034bf9ba5e75624456e8cc7c673de595..1d423b7209731c5467da8fd2e19c5110744f0411 100644 --- a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/rsync/RsyncCopierTest.java +++ b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/rsync/RsyncCopierTest.java @@ -30,7 +30,7 @@ import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.StatusFlag; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.utilities.CollectionIO; -import ch.systemsx.cisd.datamover.StoringUncaughtExceptionHandler; +import ch.systemsx.cisd.common.utilities.StoringUncaughtExceptionHandler; /** * Test cases for the {@link RsyncCopier} class.