From 7b76b14d5c3207636be5c51c017c7c704f5458a0 Mon Sep 17 00:00:00 2001
From: brinn <brinn>
Date: Tue, 15 Jul 2008 08:07:43 +0000
Subject: [PATCH] fix: - better error handling when store item filters throw
 exceptions - unit test

SVN: 7236
---
 .../utilities/DirectoryScannedStore.java      | 32 +++++++++++++++----
 .../utilities/DirectoryScanningTimerTask.java | 27 ++++++++++------
 .../DirectoryScanningTimerTaskTest.java       |  2 +-
 3 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScannedStore.java b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScannedStore.java
index e87c0ebfad9..b178df0ee9a 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScannedStore.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScannedStore.java
@@ -20,7 +20,10 @@ import java.io.FileFilter;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
+
 import ch.systemsx.cisd.common.logging.ISimpleLogger;
+import ch.systemsx.cisd.common.logging.LogLevel;
 import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStore;
 
 /**
@@ -69,17 +72,34 @@ public final class DirectoryScannedStore implements IScannedStore
         }
     }
 
-    public StoreItem[] filterReadyToProcess(StoreItem[] items)
+    public StoreItem[] filterReadyToProcess(StoreItem[] items, ISimpleLogger loggerOrNull)
     {
-        final List<StoreItem> result = new ArrayList<StoreItem>(items.length);
-        for (StoreItem item : items)
+        StoreItem currentItem = null;
+        try
         {
-            if (filter.accept(new File(directory, item.getName())))
+            final List<StoreItem> result = new ArrayList<StoreItem>(items.length);
+            for (StoreItem item : items)
             {
-                result.add(item);
+                currentItem = item;
+                if (filter.accept(new File(directory, item.getName())))
+                {
+                    result.add(item);
+                }
             }
+            return result.toArray(new StoreItem[result.size()]);
+        } catch (final RuntimeException ex)
+        {
+            if (loggerOrNull != null)
+            {
+                loggerOrNull.log(LogLevel.ERROR, String.format(
+                        "Failed to filter store items for processing: "
+                                + "filter '%s' threw exception %s (message: \"%s\") on item '%s'",
+                        StringUtils.defaultIfEmpty(filter.getClass().getSimpleName(), "UNKNOWN"),
+                        ex.getClass().getSimpleName(), StringUtils.defaultIfEmpty(ex.getMessage(),
+                                "-"), currentItem));
+            }
+            return null;
         }
-        return result.toArray(new StoreItem[result.size()]);
     }
 
     //
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java
index 4c1fe7f0af4..e10f0ff37f6 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java
@@ -69,7 +69,7 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ITime
     private final ConditionalNotificationLogger notificationLogger;
 
     private final Map<StoreItem, String> errorLog;
-    
+
     private boolean didSomeWork;
 
     private String threadNameOrNull;
@@ -182,8 +182,7 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ITime
 
     private final StoreItem[] listStoreItems()
     {
-        final StoreItem[] storeItems =
-                sourceDirectory.tryListSorted(notificationLogger);
+        final StoreItem[] storeItems = sourceDirectory.tryListSorted(notificationLogger);
         if (storeItems != null)
         {
             notificationLogger.reset(String.format("Directory '%s' is available again.",
@@ -224,7 +223,12 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ITime
                 numberOfItemsProcessedInLastRound = 0;
                 final StoreItem[] allStoreItems = listStoreItems();
                 cleanseErrorLog(allStoreItems);
-                final StoreItem[] storeItems = sourceDirectory.filterReadyToProcess(allStoreItems);
+                final StoreItem[] storeItems =
+                        sourceDirectory.filterReadyToProcess(allStoreItems, notificationLogger);
+                if (storeItems == null)
+                {
+                    break;
+                }
                 final int numberOfItems = storeItems.length;
                 directoryScanningHandler.beforeHandle();
                 for (int i = 0; i < numberOfItems; i++)
@@ -304,9 +308,13 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ITime
         }
     }
 
-    private void cleanseErrorLog(StoreItem[] allStoreItems)
+    private void cleanseErrorLog(StoreItem[] allStoreItemsOrNull)
     {
-        final Set<StoreItem> itemSet = new HashSet<StoreItem>(Arrays.asList(allStoreItems));
+        if (allStoreItemsOrNull == null)
+        {
+            return;
+        }
+        final Set<StoreItem> itemSet = new HashSet<StoreItem>(Arrays.asList(allStoreItemsOrNull));
         for (StoreItem errorItem : errorLog.keySet())
         {
             if (itemSet.contains(errorItem) == false)
@@ -315,7 +323,7 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ITime
             }
         }
     }
-    
+
     private String getDefaultErrorMessage(final StoreItem storeItem)
     {
         return String.format("Error processing item '%s'.", storeItem);
@@ -364,9 +372,10 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ITime
         /**
          * Performs a filtering on the items.
          * 
-         * @returns Only those <var>items</var> which are ready to be processed right now.
+         * @returns Only those <var>items</var> which are ready to be processed right now, or
+         *          <code>null</code>, if the filtering step produced an exception.
          */
-        StoreItem[] filterReadyToProcess(final StoreItem[] items);
+        StoreItem[] filterReadyToProcess(final StoreItem[] items, ISimpleLogger loggerOrNull);
 
         /**
          * Returns <code>true</code>, if the <var>item</var> either still exists or is in an
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java
index 60b8dabecbb..358749b0cbf 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java
@@ -301,7 +301,7 @@ public class DirectoryScanningTimerTaskTest
         createNewFile(file);
         final LogMonitoringAppender appender1 =
                 LogMonitoringAppender.addAppender(LogCategory.NOTIFY,
-                        "Failed to get listing of directory");
+                        "Failed to filter store items for processing:");
         final LogMonitoringAppender appender2 =
                 LogMonitoringAppender.addAppender(LogCategory.NOTIFY,
                         EXCEPTION_THROWING_FILE_FILTER_MESSAGE);
-- 
GitLab