You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by lh...@apache.org on 2009/02/14 01:04:34 UTC

svn commit: r744307 - in /servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor: FileMonitor.java FileMonitorActivator.java Scanner.java

Author: lhein
Date: Sat Feb 14 00:04:33 2009
New Revision: 744307

URL: http://svn.apache.org/viewvc?rev=744307&view=rev
Log:
fixed SMX4KNL-190

Modified:
    servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitor.java
    servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitorActivator.java
    servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/Scanner.java

Modified: servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitor.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitor.java?rev=744307&r1=744306&r2=744307&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitor.java (original)
+++ servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitor.java Sat Feb 14 00:04:33 2009
@@ -25,51 +25,56 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import java.util.Enumeration;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleListener;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.BundleEvent;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.prefs.Preferences;
+import org.osgi.service.prefs.PreferencesService;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
- * Watches a deploy directory for files that are added, updated or removed then processing them.
- * Currently we support OSGi bundles, OSGi configuration files and expanded directories of OSGi bundles.
- *
+ * Watches a deploy directory for files that are added, updated or removed then
+ * processing them. Currently we support OSGi bundles, OSGi configuration files
+ * and expanded directories of OSGi bundles.
+ * 
  * @version $Revision: 1.1 $
  */
 public class FileMonitor {
-	
+
     public final static String CONFIG_DIR = "org.apache.servicemix.filemonitor.configDir";
     public final static String DEPLOY_DIR = "org.apache.servicemix.filemonitor.monitorDir";
     public final static String GENERATED_JAR_DIR = "org.apache.servicemix.filemonitor.generatedJarDir";
     public final static String SCAN_INTERVAL = "org.apache.servicemix.filemonitor.scanInterval";
+    public final static String PREFERENCE_KEY = "FileMonitor";
 
     protected static final String ALIAS_KEY = "_alias_factory_pid";
 
@@ -90,6 +95,7 @@
     private ServiceListener deployerListener;
     private BundleListener bundleListener;
     private Executor executor;
+    private String pid;
 
     public FileMonitor() {
         String base = System.getProperty("servicemix.base", ".");
@@ -99,10 +105,11 @@
     }
 
     @SuppressWarnings("unchecked")
-    public FileMonitor(FileMonitorActivator activator, Dictionary properties) {
+    public FileMonitor(FileMonitorActivator activator, Dictionary properties, String pid) {
         this();
-        
+
         this.activator = activator;
+        this.pid = pid;
 
         File value = getFileValue(properties, CONFIG_DIR);
         if (value != null) {
@@ -137,14 +144,16 @@
         dirs.add(deployDir);
         scanner.setScanDirs(dirs);
         scanner.setScanInterval(scanInterval);
-
+        // load the scan results for this monitor
+        loadScannerState();
         scanner.addListener(new Scanner.BulkListener() {
             public void filesChanged(List<String> filenames) throws Exception {
                 onFilesChanged(filenames);
             }
         });
 
-        LOGGER.info("Starting to monitor the deploy directory: " + deployDir + " every " + scanInterval + " millis");
+        LOGGER.info("Starting to monitor the deploy directory: " + deployDir + " every " + scanInterval
+                    + " millis");
         if (configDir != null) {
             LOGGER.info("Config directory is at: " + configDir);
         }
@@ -158,11 +167,14 @@
     }
 
     public void stop() {
+        // first stop the scanner
         scanner.stop();
+        // load the scan results for this monitor
+        saveScannerState();
     }
 
     // Properties
-    //-------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
 
     public BundleContext getContext() {
         return activator.getContext();
@@ -209,7 +221,7 @@
     }
 
     // Implementation methods
-    //-------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
 
     protected synchronized void onFilesChanged(Collection<String> filenames) {
         bundlesToStart.clear();
@@ -225,8 +237,7 @@
                 if (isValidConfigFile(file)) {
                     if (file.exists()) {
                         updateConfiguration(file);
-                    }
-                    else {
+                    } else {
                         deleteConfiguration(file);
                     }
                     continue;
@@ -264,26 +275,24 @@
                     }
                     file = f;
                 } else {
-                	String transformedFile = artifactToBundle.get(filename);
-                	if (transformedFile != null) {
-                		file = new File(transformedFile);
-                		if (file.exists()) {
-                			file.delete();
-                		}
-                	}
+                    String transformedFile = artifactToBundle.get(filename);
+                    if (transformedFile != null) {
+                        file = new File(transformedFile);
+                        if (file.exists()) {
+                            file.delete();
+                        }
+                    }
                 }
 
                 // Handle final bundles
                 if (isValidArtifactFile(file)) {
                     if (file.exists()) {
                         deployBundle(file);
-                    }
-                    else {
+                    } else {
                         undeployBundle(file);
                     }
                 }
-            }
-            catch (Exception e) {
+            } catch (Exception e) {
                 LOGGER.warn("Failed to process: " + file + ". Reason: " + e, e);
             }
         }
@@ -320,33 +329,35 @@
 
     private File transformArtifact(File file) throws Exception {
         // Check registered deployers
-        ServiceReference[] srvRefs = getContext().getAllServiceReferences(DeploymentListener.class.getName(), null);
-		if(srvRefs != null) {
-		    for(ServiceReference sr : srvRefs) {
-		    	try {
-		    		DeploymentListener deploymentListener = (DeploymentListener) getContext().getService(sr);
-		    		if (deploymentListener.canHandle(file)) {
-		    			File transformedFile = deploymentListener.handle(file, getGenerateDir());
-		    			artifactToBundle.put(file.getAbsolutePath(), transformedFile.getAbsolutePath());
-		    			return transformedFile;
-		    		}
-		    	} finally {
-		    		getContext().ungetService(sr);
-		    	}
-		    }
-		}
+        ServiceReference[] srvRefs = getContext().getAllServiceReferences(DeploymentListener.class.getName(),
+                                                                          null);
+        if (srvRefs != null) {
+            for (ServiceReference sr : srvRefs) {
+                try {
+                    DeploymentListener deploymentListener = (DeploymentListener)getContext().getService(sr);
+                    if (deploymentListener.canHandle(file)) {
+                        File transformedFile = deploymentListener.handle(file, getGenerateDir());
+                        artifactToBundle.put(file.getAbsolutePath(), transformedFile.getAbsolutePath());
+                        return transformedFile;
+                    }
+                } finally {
+                    getContext().ungetService(sr);
+                }
+            }
+        }
         JarFile jar = null;
         try {
             // Handle OSGi bundles with the default deployer
             if (file.getName().endsWith("txt") || file.getName().endsWith("xml")
-            		|| file.getName().endsWith("properties")) {
-            	// that's file type which is not supported as bundle and avoid exception in the log
+                || file.getName().endsWith("properties")) {
+                // that's file type which is not supported as bundle and avoid
+                // exception in the log
                 return null;
             }
             jar = new JarFile(file);
             Manifest m = jar.getManifest();
-            if (m.getMainAttributes().getValue(new Attributes.Name("Bundle-SymbolicName")) != null &&
-                m.getMainAttributes().getValue(new Attributes.Name("Bundle-Version")) != null) {
+            if (m.getMainAttributes().getValue(new Attributes.Name("Bundle-SymbolicName")) != null
+                && m.getMainAttributes().getValue(new Attributes.Name("Bundle-Version")) != null) {
                 return file;
             }
         } catch (Exception e) {
@@ -357,7 +368,7 @@
             }
         }
         return null;
-	}
+    }
 
     protected void deployBundle(File file) throws IOException, BundleException {
         LOGGER.info("Deploying: " + file.getCanonicalPath());
@@ -368,15 +379,13 @@
             Bundle bundle = getBundleForJarFile(file);
             if (bundle != null) {
                 bundlesToUpdate.add(bundle);
-            }
-            else {
+            } else {
                 bundle = getContext().installBundle(file.getCanonicalFile().toURI().toString(), in);
                 if (!isBundleFragment(bundle)) {
                     bundlesToStart.add(bundle);
                 }
             }
-        }
-        finally {
+        } finally {
             closeQuietly(in);
         }
     }
@@ -387,8 +396,7 @@
 
         if (bundle == null) {
             LOGGER.warn("Could not find Bundle for file: " + file.getCanonicalPath());
-        }
-        else {
+        } else {
             bundle.stop();
             bundle.uninstall();
         }
@@ -412,7 +420,7 @@
         return (p1 != null && p1.equalsIgnoreCase(p2));
     }
 
-    protected static String normalizeFilePath( String path ) {
+    protected static String normalizeFilePath(String path) {
         if (path != null) {
             path = path.replaceFirst("file:/*", "");
             path = path.replaceAll("[\\\\/]+", "/");
@@ -427,8 +435,7 @@
                 LOGGER.warn("No ConfigurationAdmin so cannot deploy configurations");
                 loggedConfigAdminWarning = true;
             }
-        }
-        else {
+        } else {
             Properties properties = new Properties();
             InputStream in = new FileInputStream(file);
             try {
@@ -447,8 +454,7 @@
                     config.setBundleLocation(null);
                 }
                 config.update(hashtable);
-            }
-            finally {
+            } finally {
                 closeQuietly(in);
             }
         }
@@ -456,9 +462,9 @@
 
     protected void interpolation(Properties properties) {
         for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
-            String key = (String) e.nextElement();
+            String key = (String)e.nextElement();
             String val = properties.getProperty(key);
-            Matcher matcher = Pattern.compile( "\\$\\{([^}]+)\\}" ).matcher(val);
+            Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
             while (matcher.find()) {
                 String rep = System.getProperty(matcher.group(1));
                 if (rep != null) {
@@ -476,18 +482,19 @@
         config.delete();
     }
 
-    protected Configuration getConfiguration(String pid, String factoryPid) throws IOException, InvalidSyntaxException {
+    protected Configuration getConfiguration(String pid, String factoryPid) throws IOException,
+        InvalidSyntaxException {
         ConfigurationAdmin configurationAdmin = activator.getConfigurationAdmin();
         if (factoryPid != null) {
-            Configuration[] configs = configurationAdmin.listConfigurations("(|(" + ALIAS_KEY + "=" + pid + ")(.alias_factory_pid=" + factoryPid + "))");
+            Configuration[] configs = configurationAdmin.listConfigurations("(|(" + ALIAS_KEY + "=" + pid
+                                                                            + ")(.alias_factory_pid="
+                                                                            + factoryPid + "))");
             if (configs == null || configs.length == 0) {
                 return configurationAdmin.createFactoryConfiguration(pid, null);
-            }
-            else {
+            } else {
                 return configs[0];
             }
-        }
-        else {
+        } else {
             return configurationAdmin.getConfiguration(pid, null);
         }
     }
@@ -499,10 +506,9 @@
         if (n > 0) {
             String factoryPid = pid.substring(n + 1);
             pid = pid.substring(0, n);
-            return new String[]{pid, factoryPid};
-        }
-        else {
-            return new String[]{pid, null};
+            return new String[] {pid, factoryPid};
+        } else {
+            return new String[] {pid, null};
         }
     }
 
@@ -510,9 +516,8 @@
         ServiceTracker packageAdminTracker = activator.getPackageAdminTracker();
         if (packageAdminTracker != null) {
             try {
-                return (PackageAdmin) packageAdminTracker.waitForService(5000L);
-            }
-            catch (InterruptedException e) {
+                return (PackageAdmin)packageAdminTracker.waitForService(5000L);
+            } catch (InterruptedException e) {
                 // ignore
             }
         }
@@ -532,8 +537,7 @@
             try {
                 bundle.update();
                 LOGGER.info("Updated: " + bundle);
-            }
-            catch (BundleException e) {
+            } catch (BundleException e) {
                 LOGGER.warn("Failed to update bundle: " + bundle + ". Reason: " + e, e);
             }
         }
@@ -542,8 +546,7 @@
             try {
                 bundle.start();
                 LOGGER.info("Started: " + bundle);
-            }
-            catch (BundleException e) {
+            } catch (BundleException e) {
                 LOGGER.warn("Failed to start bundle: " + bundle + ". Reason: " + e, e);
                 rescheduleStart(bundle);
             }
@@ -586,8 +589,7 @@
                     bundle.start();
                     LOGGER.info("Pending bundle started: " + bundle);
                     success = true;
-                }
-                catch (BundleException e) {
+                } catch (BundleException e) {
                     LOGGER.info("Pending bundle not started: " + bundle);
                     pendingStartBundles.add(bundle);
                 }
@@ -612,8 +614,8 @@
     }
 
     /**
-     * Returns the root directory of the expanded OSGi bundle if the file is part of an expanded OSGi bundle
-     * or null if it is not
+     * Returns the root directory of the expanded OSGi bundle if the file is
+     * part of an expanded OSGi bundle or null if it is not
      */
     protected File getExpandedBundleRootDirectory(File file) throws IOException {
         File parent = file.getParentFile();
@@ -633,21 +635,22 @@
     }
 
     /**
-     * Returns true if the given directory is a valid child directory within the {@link #deployDir}
+     * Returns true if the given directory is a valid child directory within the
+     * {@link #deployDir}
      */
     protected boolean isValidBundleSourceDirectory(File dir) throws IOException {
         if (dir != null) {
             String parentPath = dir.getCanonicalPath();
             String rootPath = deployDir.getCanonicalPath();
             return !parentPath.equals(rootPath) && parentPath.startsWith(rootPath);
-        }
-        else {
+        } else {
             return false;
         }
     }
 
     /**
-     * Returns true if the given directory is a valid child file within the {@link #deployDir} or a child of {@link #generateDir}
+     * Returns true if the given directory is a valid child file within the
+     * {@link #deployDir} or a child of {@link #generateDir}
      */
     protected boolean isValidArtifactFile(File file) throws IOException {
         if (file != null) {
@@ -655,22 +658,21 @@
             String deployPath = deployDir.getCanonicalPath();
             String generatePath = generateDir.getCanonicalPath();
             return filePath.equals(deployPath) || filePath.startsWith(generatePath);
-        }
-        else {
+        } else {
             return false;
         }
     }
 
     /**
-     * Returns true if the given directory is a valid child file within the {@link #configDir}
+     * Returns true if the given directory is a valid child file within the
+     * {@link #configDir}
      */
     protected boolean isValidConfigFile(File file) throws IOException {
         if (file != null && file.getName().endsWith(".cfg")) {
             String filePath = file.getParentFile().getCanonicalPath();
             String configPath = configDir.getCanonicalPath();
             return filePath.equals(configPath);
-        }
-        else {
+        } else {
             return false;
         }
     }
@@ -691,9 +693,8 @@
     protected File getFileValue(Dictionary properties, String key) {
         Object value = properties.get(key);
         if (value instanceof File) {
-            return (File) value;
-        }
-        else if (value != null) {
+            return (File)value;
+        } else if (value != null) {
             return new File(value.toString());
         }
         return null;
@@ -703,9 +704,8 @@
     protected Long getLongValue(Dictionary properties, String key) {
         Object value = properties.get(key);
         if (value instanceof Long) {
-            return (Long) value;
-        }
-        else if (value != null) {
+            return (Long)value;
+        } else if (value != null) {
             return Long.parseLong(value.toString());
         }
         return null;
@@ -714,10 +714,48 @@
     protected void closeQuietly(Closeable in) {
         try {
             in.close();
-        }
-        catch (IOException e) {
+        } catch (IOException e) {
             LOGGER.warn("Failed to close stream. " + e, e);
         }
     }
 
+    protected PreferencesService getPreferenceService() {
+        if (activator.getPreferenceServiceTracker() != null) {
+            try {
+                return (PreferencesService)activator.getPreferenceServiceTracker().waitForService(5000L);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+        return null;
+    }
+
+    protected void saveScannerState() {
+        try {
+            Map<String, Long> results = scanner.getLastScanResults();
+            Preferences prefs = getPreferenceService().getUserPreferences(PREFERENCE_KEY).node(pid);
+            Iterator<String> it = results.keySet().iterator();
+            while (it.hasNext()) {
+                String key = it.next();
+                Long value = results.get(key);
+                prefs.putLong(key, value);
+            }
+            prefs.flush();
+        } catch (Exception e) {
+            LOGGER.error("Error persisting FileMonitor state", e);
+        }
+    }
+
+    protected void loadScannerState() {
+        try {
+            Preferences prefs = getPreferenceService().getUserPreferences(PREFERENCE_KEY).node(pid);
+            Map<String, Long> lastResult = new HashMap<String, Long>();
+            for (String key : prefs.keys()) {
+                lastResult.put(key, prefs.getLong(key, -1));
+            }
+            scanner.setLastScanResults(lastResult);
+        } catch (Exception e) {
+            LOGGER.error("Error loading FileMonitor state", e);
+        }
+    }
 }

Modified: servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitorActivator.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitorActivator.java?rev=744307&r1=744306&r2=744307&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitorActivator.java (original)
+++ servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/FileMonitorActivator.java Sat Feb 14 00:04:33 2009
@@ -23,6 +23,8 @@
 import java.util.Hashtable;
 import java.util.Map;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -30,21 +32,26 @@
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedServiceFactory;
 import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.prefs.PreferencesService;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
- * Inspired by <a href="http://www.aqute.biz/Code/FileInstall">FileInstall</a> by Peter Kriens.
+ * Inspired by <a href="http://www.aqute.biz/Code/FileInstall">FileInstall</a>
+ * by Peter Kriens.
  * 
  * @version $Revision: 1.1 $
  */
 public class FileMonitorActivator implements BundleActivator, ManagedServiceFactory {
+    private static final Log LOGGER = LogFactory.getLog(FileMonitorActivator.class);
+
     private BundleContext context;
     private ServiceTracker packageAdminTracker;
     private ServiceTracker configurationAdminTracker;
+    private ServiceTracker preferenceServiceTracker;
     private Map<String, FileMonitor> fileMonitors = new HashMap<String, FileMonitor>();
 
     // BundleActivator interface
-    //-------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
     public void start(BundleContext context) throws Exception {
         this.context = context;
 
@@ -58,13 +65,12 @@
         configurationAdminTracker = new ServiceTracker(context, ConfigurationAdmin.class.getName(), null);
         configurationAdminTracker.open();
 
+        preferenceServiceTracker = new ServiceTracker(context, PreferencesService.class.getName(), null);
+        preferenceServiceTracker.open();
+
         Hashtable initialProperties = new Hashtable();
-        setPropertiesFromContext(initialProperties,
-                FileMonitor.CONFIG_DIR,
-                FileMonitor.DEPLOY_DIR,
-                FileMonitor.GENERATED_JAR_DIR,
-                FileMonitor.SCAN_INTERVAL
-        );
+        setPropertiesFromContext(initialProperties, FileMonitor.CONFIG_DIR, FileMonitor.DEPLOY_DIR,
+                                 FileMonitor.GENERATED_JAR_DIR, FileMonitor.SCAN_INTERVAL);
         updated("initialPid", initialProperties);
     }
 
@@ -72,27 +78,28 @@
         Collection<FileMonitor> fileMonitors = this.fileMonitors.values();
         for (FileMonitor monitor : fileMonitors) {
             try {
+                // stop the monitor
                 monitor.stop();
-            }
-            catch (Exception e) {
+            } catch (Exception e) {
                 // Ignore
             }
         }
         this.fileMonitors.clear();
 
+        preferenceServiceTracker.close();
         configurationAdminTracker.close();
         packageAdminTracker.close();
     }
 
     // ManagedServiceFactory interface
-    //-------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
     public String getName() {
         return "org.apache.servicemix.kernel.filemonitor.FileMonitor";
     }
 
     public void updated(String pid, Dictionary properties) throws ConfigurationException {
         deleted(pid);
-        FileMonitor monitor = new FileMonitor(this, properties);
+        FileMonitor monitor = new FileMonitor(this, properties, pid);
         fileMonitors.put(pid, monitor);
         monitor.start();
     }
@@ -105,7 +112,7 @@
     }
 
     // Properties
-    //-------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
     public BundleContext getContext() {
         return context;
     }
@@ -119,11 +126,15 @@
     }
 
     public ConfigurationAdmin getConfigurationAdmin() {
-        return (ConfigurationAdmin) getConfigurationAdminTracker().getService();
+        return (ConfigurationAdmin)getConfigurationAdminTracker().getService();
+    }
+
+    public ServiceTracker getPreferenceServiceTracker() {
+        return preferenceServiceTracker;
     }
 
     // Implementation methods
-    //-------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
     protected void setPropertiesFromContext(Hashtable properties, String... keys) {
         for (String key : keys) {
             Object value = context.getProperty(key);

Modified: servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/Scanner.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/Scanner.java?rev=744307&r1=744306&r2=744307&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/Scanner.java (original)
+++ servicemix/smx4/kernel/trunk/filemonitor/src/main/java/org/apache/servicemix/kernel/filemonitor/Scanner.java Sat Feb 14 00:04:33 2009
@@ -17,7 +17,16 @@
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -25,19 +34,19 @@
 /**
  * Scanner
  * <p/>
- * Utility for scanning a directory for added, removed and changed
- * files and reporting these events via registered Listeners.
+ * Utility for scanning a directory for added, removed and changed files and
+ * reporting these events via registered Listeners.
  * <p/>
  * From the <a href="http://jetty.codehaus.org/">Jetty Util project</a>
- *
+ * 
  * @version $Revision: 1.1 $
  */
 public class Scanner {
-    
+
     private static Log logger = LogFactory.getLog(Scanner.class);
     private long _scanInterval;
     private List<Listener> _listeners = Collections.synchronizedList(new ArrayList<Listener>());
-    private Map<String, Long> _prevScan = Collections.emptyMap();
+    private Map<String, Long> _prevScan = new HashMap<String, Long>();
     private FilenameFilter _filter;
     private List<File> _scanDirs;
     private volatile boolean _running = false;
@@ -73,7 +82,7 @@
 
     /**
      * Get the scan interval
-     *
+     * 
      * @return interval between scans in millis
      */
     public long getScanInterval() {
@@ -82,7 +91,7 @@
 
     /**
      * Set the scan interval
-     *
+     * 
      * @param scanInterval pause between scans in millis
      */
     public synchronized void setScanInterval(long scanInterval) {
@@ -101,7 +110,7 @@
 
     /**
      * Set the location of the directory to scan.
-     *
+     * 
      * @param dir
      * @deprecated use setScanDirs(List dirs) instead
      */
@@ -112,12 +121,12 @@
 
     /**
      * Get the location of the directory to scan
-     *
+     * 
      * @return
      * @deprecated use getScanDirs() instead
      */
     public File getScanDir() {
-        return (_scanDirs == null ? null : (File) _scanDirs.get(0));
+        return (_scanDirs == null ? null : (File)_scanDirs.get(0));
     }
 
     public void setScanDirs(List<File> dirs) {
@@ -129,9 +138,9 @@
     }
 
     /**
-     * Apply a filter to files found in the scan directory.
-     * Only files matching the filter will be reported as added/changed/removed.
-     *
+     * Apply a filter to files found in the scan directory. Only files matching
+     * the filter will be reported as added/changed/removed.
+     * 
      * @param filter
      */
     public void setFilenameFilter(FilenameFilter filter) {
@@ -140,7 +149,7 @@
 
     /**
      * Get any filter applied to files in the scan dir.
-     *
+     * 
      * @return
      */
     public FilenameFilter getFilenameFilter() {
@@ -148,11 +157,10 @@
     }
 
     /**
-     * Whether or not an initial scan will report all files as being
-     * added.
-     *
+     * Whether or not an initial scan will report all files as being added.
+     * 
      * @param reportExisting if true, all files found on initial scan will be
-     *                       reported as being added, otherwise not
+     *            reported as being added, otherwise not
      */
     public void setReportExistingFilesOnStartup(boolean reportExisting) {
         this._reportExisting = reportExisting;
@@ -160,7 +168,7 @@
 
     /**
      * Add an added/removed/changed listener
-     *
+     * 
      * @param listener
      */
     public synchronized void addListener(Listener listener) {
@@ -173,7 +181,7 @@
 
     /**
      * Remove a registered listener
-     *
+     * 
      * @param listener the Listener to be removed
      */
     public synchronized void removeListener(Listener listener) {
@@ -196,9 +204,8 @@
         if (_reportExisting) {
             // if files exist at startup, report them
             scan();
-        }
-        else {
-            //just register the list of existing files and only report changes
+        } else {
+            // just register the list of existing files and only report changes
             _prevScan = scanFiles();
         }
 
@@ -257,7 +264,7 @@
 
     /**
      * Recursively scan all files in the designated directories.
-     *
+     * 
      * @return Map of name of file to last modified time
      */
     public Map<String, Long> scanFiles() {
@@ -268,7 +275,7 @@
         HashMap<String, Long> scanInfo = new HashMap<String, Long>();
         Iterator<File> itor = _scanDirs.iterator();
         while (itor.hasNext()) {
-            File dir = (File) itor.next();
+            File dir = (File)itor.next();
 
             if ((dir != null) && (dir.exists())) {
                 scanFile(dir, scanInfo);
@@ -280,9 +287,9 @@
 
     /**
      * Report the adds/changes/removes to the registered listeners
-     *
+     * 
      * @param currentScan the info from the most recent pass
-     * @param oldScan     info from the previous pass
+     * @param oldScan info from the previous pass
      */
     public void reportDifferences(Map<String, Long> currentScan, Map<String, Long> oldScan) {
         List<String> bulkChanges = new ArrayList<String>();
@@ -295,14 +302,12 @@
                 logger.debug("File added: " + entry.getKey());
                 reportAddition(entry.getKey());
                 bulkChanges.add(entry.getKey());
-            }
-            else if (!oldScan.get(entry.getKey()).equals(entry.getValue())) {
+            } else if (!oldScan.get(entry.getKey()).equals(entry.getValue())) {
                 logger.debug("File changed: " + entry.getKey());
                 reportChange(entry.getKey());
                 oldScanKeys.remove(entry.getKey());
                 bulkChanges.add(entry.getKey());
-            }
-            else {
+            } else {
                 oldScanKeys.remove(entry.getKey());
             }
         }
@@ -324,10 +329,10 @@
     }
 
     /**
-     * Get last modified time on a single file or recurse if
-     * the file is a directory.
-     *
-     * @param f           file or directory
+     * Get last modified time on a single file or recurse if the file is a
+     * directory.
+     * 
+     * @param f file or directory
      * @param scanInfoMap map of filenames to last modified times
      */
     private void scanFile(File f, Map<String, Long> scanInfoMap) {
@@ -337,27 +342,26 @@
             }
 
             if (f.isFile()) {
-                if ((_filter == null) || ((_filter != null) && _filter.accept(f.getParentFile(), f.getName()))) {
+                if ((_filter == null)
+                    || ((_filter != null) && _filter.accept(f.getParentFile(), f.getName()))) {
                     String name = f.getCanonicalPath();
                     long lastModified = f.lastModified();
                     scanInfoMap.put(name, new Long(lastModified));
                 }
-            }
-            else if (f.isDirectory()) {
+            } else if (f.isDirectory()) {
                 File[] files = f.listFiles();
                 for (int i = 0; i < files.length; i++) {
                     scanFile(files[i], scanInfoMap);
                 }
             }
-        }
-        catch (IOException e) {
+        } catch (IOException e) {
             logger.warn("Error scanning watched files", e);
         }
     }
 
     /**
      * Report a file addition to the registered FileAddedListeners
-     *
+     * 
      * @param filename
      */
     private void reportAddition(String filename) {
@@ -366,13 +370,11 @@
             try {
                 Listener l = itor.next();
                 if (l instanceof DiscreteListener) {
-                    ((DiscreteListener) l).fileAdded(filename);
+                    ((DiscreteListener)l).fileAdded(filename);
                 }
-            }
-            catch (Exception e) {
+            } catch (Exception e) {
                 logger.warn(e);
-            }
-            catch (Error e) {
+            } catch (Error e) {
                 logger.warn(e);
             }
         }
@@ -380,7 +382,7 @@
 
     /**
      * Report a file removal to the FileRemovedListeners
-     *
+     * 
      * @param filename
      */
     private void reportRemoval(String filename) {
@@ -389,13 +391,11 @@
             try {
                 Listener l = itor.next();
                 if (l instanceof DiscreteListener) {
-                    ((DiscreteListener) l).fileRemoved(filename);
+                    ((DiscreteListener)l).fileRemoved(filename);
                 }
-            }
-            catch (Exception e) {
+            } catch (Exception e) {
                 logger.warn(e);
-            }
-            catch (Error e) {
+            } catch (Error e) {
                 logger.warn(e);
             }
         }
@@ -403,7 +403,7 @@
 
     /**
      * Report a file change to the FileChangedListeners
-     *
+     * 
      * @param filename
      */
     private void reportChange(String filename) {
@@ -412,13 +412,11 @@
             try {
                 Listener l = itor.next();
                 if (l instanceof DiscreteListener) {
-                    ((DiscreteListener) l).fileChanged(filename);
+                    ((DiscreteListener)l).fileChanged(filename);
                 }
-            }
-            catch (Exception e) {
+            } catch (Exception e) {
                 logger.warn(e);
-            }
-            catch (Error e) {
+            } catch (Error e) {
                 logger.warn(e);
             }
         }
@@ -430,16 +428,28 @@
             try {
                 Listener l = itor.next();
                 if (l instanceof BulkListener) {
-                    ((BulkListener) l).filesChanged(filenames);
+                    ((BulkListener)l).filesChanged(filenames);
                 }
-            }
-            catch (Exception e) {
+            } catch (Exception e) {
                 logger.warn(e);
-            }
-            catch (Error e) {
+            } catch (Error e) {
                 logger.warn(e);
             }
         }
     }
-    
+
+    protected Map<String, Long> getLastScanResults() {
+        Map<String, Long> result = new HashMap<String, Long>();
+        synchronized (_prevScan) {
+            result.putAll(_prevScan);
+        }
+        return result;
+    }
+
+    protected void setLastScanResults(Map<String, Long> results) {
+        synchronized (_prevScan) {
+            _prevScan.clear();
+            _prevScan.putAll(results);
+        }
+    }
 }