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);
+ }
+ }
}