[FELIX-4532] ConcurrentModificationException in fileinstall

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1623838 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/WatcherScanner.java b/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/WatcherScanner.java
index 4f3bab1..11f02ed 100644
--- a/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/WatcherScanner.java
+++ b/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/WatcherScanner.java
@@ -24,6 +24,7 @@
 import java.nio.file.Path;
 import java.nio.file.PathMatcher;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
 import org.osgi.framework.BundleContext;
@@ -59,53 +60,50 @@
 
     public Set<File> scan(boolean reportImmediately) {
         watcher.processEvents();
-        if (changed.isEmpty()) {
-            return new HashSet<File>();
-        }
-        Set<File> files = new HashSet<File>();
-        Set<File> removed = new HashSet<File>();
-        if (reportImmediately) {
-            removed.addAll(storedChecksums.keySet());
-        }
-        for (File file : changed)
-        {
-            long lastChecksum = lastChecksums.get(file) != null ? (Long) lastChecksums.get(file) : 0;
-            long storedChecksum = storedChecksums.get(file) != null ? (Long) storedChecksums.get(file) : 0;
-            long newChecksum = checksum(file);
-            lastChecksums.put(file, newChecksum);
-            if (file.exists()) {
-                // Only handle file when it does not change anymore and it has changed since last reported
-                if ((newChecksum == lastChecksum || reportImmediately)) {
-                    if (newChecksum != storedChecksum) {
-                        storedChecksums.put(file, newChecksum);
-                        files.add(file);
-                    } else {
-                        changed.remove(file);
+        synchronized (changed) {
+            if (changed.isEmpty()) {
+                return new HashSet<File>();
+            }
+            Set<File> files = new HashSet<File>();
+            Set<File> removed = new HashSet<File>();
+            if (reportImmediately) {
+                removed.addAll(storedChecksums.keySet());
+            }
+            for (Iterator<File> iterator = changed.iterator(); iterator.hasNext(); ) {
+                File file = iterator.next();
+                long lastChecksum = lastChecksums.get(file) != null ? (Long) lastChecksums.get(file) : 0;
+                long storedChecksum = storedChecksums.get(file) != null ? (Long) storedChecksums.get(file) : 0;
+                long newChecksum = checksum(file);
+                lastChecksums.put(file, newChecksum);
+                if (file.exists()) {
+                    // Only handle file when it does not change anymore and it has changed since last reported
+                    if ((newChecksum == lastChecksum || reportImmediately)) {
+                        if (newChecksum != storedChecksum) {
+                            storedChecksums.put(file, newChecksum);
+                            files.add(file);
+                        } else {
+                            iterator.remove();
+                        }
+                        if (reportImmediately) {
+                            removed.remove(file);
+                        }
                     }
-                    if (reportImmediately) {
-                        removed.remove(file);
+                } else {
+                    if (!reportImmediately) {
+                        removed.add(file);
                     }
                 }
-            } else {
-                if (!reportImmediately) {
-                    removed.add(file);
-                }
             }
-        }
-        for (File file : removed)
-        {
-            // Make sure we'll handle a file that has been deleted
-            files.addAll(removed);
-            // Remove no longer used checksums
-            lastChecksums.remove(file);
-            storedChecksums.remove(file);
-        }
-        for (File file : files)
-        {
-            changed.remove(file);
-        }
+            for (File file : removed) {
+                // Make sure we'll handle a file that has been deleted
+                files.addAll(removed);
+                // Remove no longer used checksums
+                lastChecksums.remove(file);
+                storedChecksums.remove(file);
+            }
 
-        return files;
+            return files;
+        }
     }
 
     public void close() throws IOException {
@@ -123,7 +121,9 @@
                     return;
                 }
             }
-            changed.add(file);
+            synchronized (changed) {
+                changed.add(file);
+            }
         }
 
         @Override
@@ -135,7 +135,9 @@
                     return;
                 }
             }
-            changed.add(file);
+            synchronized (changed) {
+                changed.add(file);
+            }
         }
 
         @Override