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