You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by ff...@apache.org on 2013/07/12 10:30:13 UTC

svn commit: r1502470 - in /karaf/trunk: assemblies/features/framework/src/main/filtered-resources/resources/etc/ features/core/src/main/java/org/apache/karaf/features/internal/ features/core/src/main/resources/OSGI-INF/blueprint/ features/core/src/test...

Author: ffang
Date: Fri Jul 12 08:30:12 2013
New Revision: 1502470

URL: http://svn.apache.org/r1502470
Log:
[KARAF-2312]Uninstalling a feature should respect bundle start levels

Modified:
    karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.features.cfg
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
    karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    karaf/trunk/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java

Modified: karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.features.cfg
URL: http://svn.apache.org/viewvc/karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.features.cfg?rev=1502470&r1=1502469&r2=1502470&view=diff
==============================================================================
--- karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.features.cfg (original)
+++ karaf/trunk/assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.features.cfg Fri Jul 12 08:30:12 2013
@@ -26,6 +26,13 @@
 #
 #respectStartLvlDuringFeatureStartup=true
 
+
+#
+# Defines if the startlvl should be respected during feature uninstall. The default value is true.
+# If true, means stop bundles respecting the descend order of start level in a certain feature.
+#
+#respectStartLvlDuringFeatureUninstall=true
+
 #
 # Comma separated list of features repositories to register by default
 #
@@ -39,4 +46,4 @@ featuresBoot=config
 #
 # Defines if the boot features are started in asynchronous mode (in a dedicated thread)
 #
-featuresBootAsynchronous=false
\ No newline at end of file
+featuresBootAsynchronous=false

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java?rev=1502470&r1=1502469&r2=1502470&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java Fri Jul 12 08:30:12 2013
@@ -411,8 +411,21 @@ public class BundleManager {
 				// Ignore
 			}
 		}
+		refreshPackages(null);
 	}
 
+        public void uninstall(List<Bundle> bundles) {
+                for (Bundle b : bundles) {
+                        try {
+                                b.uninstall();
+                        } catch (Exception e2) {
+                                // Ignore
+                        }
+                }
+                refreshPackages(null);
+        }
+
+
 	public void uninstallById(Set<Long> bundles) throws BundleException,
 			InterruptedException {
 		for (long bundleId : bundles) {
@@ -486,6 +499,10 @@ public class BundleManager {
 		}
 	}
 
+	public BundleContext getBundleContext() {
+	    return this.bundleContext;
+	}
+	
 	public static class BundleInstallerResult {
 		Bundle bundle;
 		boolean isNew;

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java?rev=1502470&r1=1502469&r2=1502470&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java Fri Jul 12 08:30:12 2013
@@ -82,8 +82,10 @@ public class FeaturesServiceImpl impleme
 
     private final BundleManager bundleManager;
     private final FeatureConfigInstaller configManager;
+    
 
     private boolean respectStartLvlDuringFeatureStartup;
+    private boolean respectStartLvlDuringFeatureUninstall;
     private long resolverTimeout = 5000;
     private Set<URI> uris;
     private Map<URI, Repository> repositories = new HashMap<URI, Repository>();
@@ -368,6 +370,7 @@ public class FeaturesServiceImpl impleme
      * @throws Exception in case of install failure.
      */
     public void installFeatures(Set<Feature> features, EnumSet<Option> options) throws Exception {
+
         final InstallationState state = new InstallationState();
         final InstallationState failure = new InstallationState();
         boolean verbose = options.contains(FeaturesService.Option.Verbose);
@@ -661,7 +664,25 @@ public class FeaturesServiceImpl impleme
         for (Set<Long> b : installed.values()) {
             bundles.removeAll(b);
         }
-        bundleManager.uninstallById(bundles);
+   
+        List<Bundle> bundlesDescendSortedByStartLvl = new ArrayList<Bundle>();
+        for (long bundleId : bundles) {
+            Bundle b = bundleManager.getBundleContext().getBundle(bundleId);
+            if (b != null) {
+                bundlesDescendSortedByStartLvl.add(b);
+            }
+        }
+        
+        if (isRespectStartLvlDuringFeatureUninstall()) {
+            Collections.sort(bundlesDescendSortedByStartLvl, new Comparator<Bundle>() {
+                @Override
+                public int compare(Bundle bundle, Bundle bundle1) {
+                    return bundle1.adapt(BundleStartLevel.class).getStartLevel() -
+                        bundle.adapt(BundleStartLevel.class).getStartLevel();
+                }
+            });
+        }
+        bundleManager.uninstall(bundlesDescendSortedByStartLvl);
         callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureUninstalled, false));
         saveState();
     }
@@ -1071,4 +1092,11 @@ public class FeaturesServiceImpl impleme
        return satisfied;
     }
 
+    public boolean isRespectStartLvlDuringFeatureUninstall() {
+        return respectStartLvlDuringFeatureUninstall;
+    }
+
+    public void setRespectStartLvlDuringFeatureUninstall(boolean respectStartLvlDuringFeatureUninstall) {
+        this.respectStartLvlDuringFeatureUninstall = respectStartLvlDuringFeatureUninstall;
+    }
 }

Modified: karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1502470&r1=1502469&r2=1502470&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml (original)
+++ karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml Fri Jul 12 08:30:12 2013
@@ -35,6 +35,7 @@ http://aries.apache.org/blueprint/xmlns/
             <ext:property name="featuresBoot" value=""/>
             <ext:property name="resolverTimeout" value="5000"/>
             <ext:property name="respectStartLvlDuringFeatureStartup" value="true"/>
+            <ext:property name="respectStartLvlDuringFeatureUninstall" value="true"/>
             <ext:property name="featuresBootAsynchronous" value="false"/>
         </ext:default-properties>
         <ext:location>file:$(karaf.base)/etc/org.apache.karaf.features.cfg</ext:location>
@@ -52,6 +53,7 @@ http://aries.apache.org/blueprint/xmlns/
     	<argument ref="configInstaller" />
         <property name="urls" value="$[featuresRepositories]" />
         <property name="respectStartLvlDuringFeatureStartup" value="$[respectStartLvlDuringFeatureStartup]" />
+        <property name="respectStartLvlDuringFeatureUninstall" value="$[respectStartLvlDuringFeatureUninstall]" />
         <property name="resolverTimeout" value="$[resolverTimeout]" />
     </bean>
     

Modified: karaf/trunk/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java?rev=1502470&r1=1502469&r2=1502470&view=diff
==============================================================================
--- karaf/trunk/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java (original)
+++ karaf/trunk/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java Fri Jul 12 08:30:12 2013
@@ -33,6 +33,7 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -48,6 +49,7 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 
 public class FeaturesServiceTest extends TestBase {
@@ -135,14 +137,15 @@ public class FeaturesServiceTest extends
         Bundle bundlef101 = createDummyBundle(12345L, "bundle-0.1", headers());
 
         BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
         expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile).anyTimes();
         expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, true));
         expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, false));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
         ignoreRefreshes(bundleManager);
-        bundleManager.uninstallById(Collections.EMPTY_SET);        
-        EasyMock.expectLastCall();
-        bundleManager.uninstallById(setOf(12345L));
-        EasyMock.expectLastCall();
+        bundleManager.uninstall(Collections.EMPTY_LIST);        
+        EasyMock.expectLastCall().times(2);
+        
         
         replay(bundleManager);
         FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
@@ -192,45 +195,50 @@ public class FeaturesServiceTest extends
     // with a feature dependency
     // The dependant feature is in the same repository
     // Tests uninstall of features
+    @SuppressWarnings("unchecked")
     @Test
     public void testInstallFeatureWithDependantFeatures() throws Exception {
         URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><feature version='0.1'>f2</feature><bundle>bundle-f1-0.1</bundle></feature>"
-                + "  <feature name='f2' version='0.1'><bundle>bundle-f2-0.1</bundle></feature>"
-                + "</features>");
+                                 + "  <feature name='f1' version='0.1'><feature version='0.1'>f2</feature><bundle>bundle-f1-0.1</bundle></feature>"
+                                 + "  <feature name='f2' version='0.1'><bundle>bundle-f2-0.1</bundle></feature>"
+                                 + "</features>");
 
         BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
         Bundle bundlef101 = createDummyBundle(12345L, "bundle-f1-0.1", headers());
         Bundle bundlef201 = createDummyBundle(54321L, "bundle-f2-0.1", headers());
-        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
-        expect(bundleManager.installBundleIfNeeded("bundle-f1-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, true));
-        expect(bundleManager.installBundleIfNeeded("bundle-f2-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef201, true));
+        expect(bundleManager.getDataFile(EasyMock.<String> anyObject())).andReturn(dataFile).anyTimes();
+        expect(bundleManager.installBundleIfNeeded("bundle-f1-0.1", 0, null))
+            .andReturn(new BundleInstallerResult(bundlef101, true));
+        expect(bundleManager.installBundleIfNeeded("bundle-f2-0.1", 0, null))
+            .andReturn(new BundleInstallerResult(bundlef201, true));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext).anyTimes();
+        expect(bundleContext.getBundle(12345)).andReturn(bundlef101).anyTimes();
         ignoreRefreshes(bundleManager);
-        bundleManager.uninstallById(setOf(12345L));        
-        EasyMock.expectLastCall();
-        bundleManager.uninstallById(setOf(54321L));
-        EasyMock.expectLastCall();
-        
+        bundleManager.uninstall(Collections.EMPTY_LIST);
+       
+        EasyMock.expectLastCall().anyTimes();
         replay(bundleManager);
+        
         FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
         svc.addRepository(uri);
         svc.installFeature("f1", "0.1");
         svc.uninstallFeature("f1", "0.1");
-        svc.uninstallFeature("f2", "0.1");
         verify(bundleManager);
+
     }
-    
+
     @SuppressWarnings("unchecked")
     private BundleManager prepareBundleManagerForInstallUninstall(String bundleUri, String bundlename) throws Exception {
         BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
         Bundle installedBundle = createDummyBundle(12345L, bundlename, headers());
         expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
         expect(bundleManager.installBundleIfNeeded(bundleUri, 0, null)).andReturn(new BundleInstallerResult(installedBundle, true));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
         ignoreRefreshes(bundleManager);
-        bundleManager.uninstallById(Collections.EMPTY_SET);        
-        EasyMock.expectLastCall();
-        bundleManager.uninstallById(setOf(12345L));
-        EasyMock.expectLastCall();
+        bundleManager.uninstall(Collections.EMPTY_LIST);
+        EasyMock.expectLastCall().times(2);
         return bundleManager;
     }
 
@@ -282,14 +290,15 @@ public class FeaturesServiceTest extends
                 + "</features>");
 
         BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
         Bundle bundleVer02 = createDummyBundle(54321L, "bundleVer02", headers());
         expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
         expect(bundleManager.installBundleIfNeeded("bundle-0.2", 0, null)).andReturn(new BundleInstallerResult(bundleVer02, true));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
         ignoreRefreshes(bundleManager);
-        bundleManager.uninstallById(Collections.EMPTY_SET);        
-        EasyMock.expectLastCall();
-        bundleManager.uninstallById(setOf(54321L));
-        EasyMock.expectLastCall();
+        bundleManager.uninstall(Collections.EMPTY_LIST);        
+        EasyMock.expectLastCall().times(2);
+        
 
         replay(bundleManager);
         FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
@@ -313,15 +322,16 @@ public class FeaturesServiceTest extends
                 + "</features>", bundleVer01Uri, bundleVer02Uri);
         
         BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
         Bundle bundleVer01 = createDummyBundle(12345L, "bundleVer01", headers());
         expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
         expect(bundleManager.installBundleIfNeeded(bundleVer01Uri, 0, null)).andReturn(new BundleInstallerResult(bundleVer01, true));
         expect(bundleManager.installBundleIfNeeded(bundleVer01Uri, 0, null)).andReturn(new BundleInstallerResult(bundleVer01, false));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
         ignoreRefreshes(bundleManager);
-        bundleManager.uninstallById(Collections.EMPTY_SET);        
-        EasyMock.expectLastCall();
-        bundleManager.uninstallById(setOf(12345L));
-        EasyMock.expectLastCall();
+        bundleManager.uninstall(Collections.EMPTY_LIST);        
+        
+        EasyMock.expectLastCall().times(2);
 
         replay(bundleManager);
         FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);