FELIX-1716: Fileinstall does not properly handle bundles uninstalled through the OSGi API
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@825165 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java b/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
index 26aab3c..c838ad4 100644
--- a/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
+++ b/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
@@ -43,7 +43,9 @@
import org.apache.felix.fileinstall.ArtifactUrlTransformer;
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.service.packageadmin.PackageAdmin;
@@ -70,7 +72,7 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class DirectoryWatcher extends Thread
+public class DirectoryWatcher extends Thread implements BundleListener
{
public final static String FILENAME = "felix.fileinstall.filename";
public final static String POLL = "felix.fileinstall.poll";
@@ -116,6 +118,7 @@
startBundles = getBoolean(properties, START_NEW_BUNDLES, true); // by default, we start bundles.
filter = (String) properties.get(FILTER);
noInitialDelay = getBoolean(properties, NO_INITIAL_DELAY, false);
+ this.context.addBundleListener(this);
FilenameFilter flt;
if (filter != null && filter.length() > 0)
@@ -199,6 +202,24 @@
}
}
+ public void bundleChanged(BundleEvent bundleEvent)
+ {
+ if (bundleEvent.getType() == BundleEvent.UNINSTALLED)
+ {
+ for (Iterator it = currentManagedArtifacts.entrySet().iterator(); it.hasNext();)
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ Artifact artifact = (Artifact) entry.getValue();
+ if (artifact.getBundleId() == bundleEvent.getBundle().getBundleId())
+ {
+ log("Bundle " + bundleEvent.getBundle().getBundleId() + " has been uninstalled", null);
+ currentManagedArtifacts.remove(entry.getKey());
+ break;
+ }
+ }
+ }
+ }
+
private void process(Set files)
{
List/*<ArtifactListener>*/ listeners = FileInstall.getListeners();
@@ -554,6 +575,7 @@
public void close()
{
+ this.context.removeBundleListener(this);
interrupt();
try
{
diff --git a/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java b/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
index 486c9ac..a17fcae 100644
--- a/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
+++ b/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
@@ -28,9 +28,8 @@
import org.easymock.MockControl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
import org.osgi.service.packageadmin.PackageAdmin;
-import org.apache.felix.fileinstall.internal.DirectoryWatcher;
-import org.apache.felix.fileinstall.internal.FileInstall;
/**
@@ -64,6 +63,7 @@
public void testGetLongWithNonExistentProperty()
{
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
assertEquals( "getLong gives the default value for non-existing properties", 100, dw.getLong( props, TEST, 100 ) );
@@ -73,6 +73,8 @@
public void testGetLongWithExistentProperty()
{
props.put( TEST, "33" );
+
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
assertEquals( "getLong retrieves the right property value", 33, dw.getLong( props, TEST, 100 ) );
@@ -83,6 +85,7 @@
{
props.put( TEST, "incorrect" );
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContext.getServiceReference( "org.osgi.service.log.LogService" );
mockBundleContextControl.setReturnValue( null );
mockBundleContextControl.replay();
@@ -93,6 +96,7 @@
public void testGetBooleanWithNonExistentProperty()
{
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
assertEquals( "getBoolean gives the default value for non-existing properties", true, dw.getBoolean( props, TEST, true ) );
@@ -102,6 +106,8 @@
public void testGetBooleanWithExistentProperty()
{
props.put( TEST, "true" );
+
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
assertEquals( "getBoolean retrieves the right property value", true, dw.getBoolean( props, TEST, false ) );
@@ -112,6 +118,7 @@
{
props.put( TEST, "incorrect" );
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContext.getServiceReference( "org.osgi.service.log.LogService" );
mockBundleContextControl.setReturnValue( null );
mockBundleContextControl.replay();
@@ -122,6 +129,7 @@
public void testGetFileWithNonExistentProperty()
{
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
assertEquals( "getFile gives the default value for non-existing properties", new File("tmp"), dw.getFile( props, TEST, new File("tmp") ) );
@@ -131,6 +139,8 @@
public void testGetFileWithExistentProperty()
{
props.put( TEST, "test" );
+
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
assertEquals( "getBoolean retrieves the right property value", new File("test"), dw.getFile( props, TEST, new File("tmp") ) );
@@ -145,6 +155,8 @@
props.put( DirectoryWatcher.DIR, new File( "src/test/resources" ).getAbsolutePath() );
props.put( DirectoryWatcher.TMPDIR, new File( "src/test/resources" ).getAbsolutePath() );
props.put( DirectoryWatcher.FILTER, ".*\\.cfg" );
+
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
@@ -162,6 +174,8 @@
public void testDefaultParametersAreSetAfterEmptyInitialization()
{
props.put( DirectoryWatcher.DIR, new File( "src/test/resources" ).getAbsolutePath() );
+
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContextControl.replay();
dw = new DirectoryWatcher( props, mockBundleContext );
@@ -178,6 +192,7 @@
public void testIsFragment() throws Exception
{
+ mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
mockBundleContext.createFilter( "" );
mockBundleContextControl.setMatcher( MockControl.ALWAYS_MATCHER );
mockBundleContextControl.setReturnValue( null );