You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2010/10/21 15:42:25 UTC
svn commit: r1025996 - in /karaf/trunk: assembly/src/main/filtered-resources/
features/core/src/main/java/org/apache/karaf/features/internal/
features/core/src/test/java/org/apache/karaf/features/
Author: gnodet
Date: Thu Oct 21 13:42:25 2010
New Revision: 1025996
URL: http://svn.apache.org/viewvc?rev=1025996&view=rev
Log:
[KARAF-251] Allow the use of version ranges on dependant features
Modified:
karaf/trunk/assembly/src/main/filtered-resources/features.xml
karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
karaf/trunk/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
Modified: karaf/trunk/assembly/src/main/filtered-resources/features.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/assembly/src/main/filtered-resources/features.xml?rev=1025996&r1=1025995&r2=1025996&view=diff
==============================================================================
--- karaf/trunk/assembly/src/main/filtered-resources/features.xml (original)
+++ karaf/trunk/assembly/src/main/filtered-resources/features.xml Thu Oct 21 13:42:25 2010
@@ -17,8 +17,16 @@
limitations under the License.
-->
<features name="karaf-${project.version}">
+ <feature name="spring" version="${spring2.version}">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/${aopalliance.bundle.version}</bundle>
+ <bundle>mvn:org.springframework/spring-core/${spring2.version}</bundle>
+ <bundle>mvn:org.springframework/spring-beans/${spring2.version}</bundle>
+ <bundle>mvn:org.springframework/spring-aop/${spring2.version}</bundle>
+ <bundle>mvn:org.springframework/spring-context/${spring2.version}</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/${spring2.version}</bundle>
+ </feature>
<feature name="spring" version="${spring.version}">
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/${aopalliance.bundle.version}</bundle>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/${aopalliance.bundle.version}</bundle>
<bundle>mvn:org.springframework/spring-core/${spring.version}</bundle>
<bundle>mvn:org.springframework/spring-asm/${spring.version}</bundle>
<bundle>mvn:org.springframework/spring-expression/${spring.version}</bundle>
@@ -28,7 +36,7 @@
<bundle>mvn:org.springframework/spring-context-support/${spring.version}</bundle>
</feature>
<feature name="spring-dm" version="${spring.osgi.version}">
- <feature version="${spring.version}">spring</feature>
+ <feature version="[2.5.6,4)">spring</feature>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/${cglib.bundle.version}</bundle>
<bundle>mvn:org.springframework.osgi/spring-osgi-io/${spring.osgi.version}</bundle>
<bundle>mvn:org.springframework.osgi/spring-osgi-core/${spring.osgi.version}</bundle>
@@ -91,8 +99,8 @@
sshRealm=karaf
hostKey=${karaf.base}/etc/host.key
</config>
- <bundle>mvn:org.apache.mina/mina-core/${mina.version}</bundle>
- <bundle>mvn:org.apache.sshd/sshd-core/${sshd.version}</bundle>
+ <bundle dependency='true'>mvn:org.apache.mina/mina-core/${mina.version}</bundle>
+ <bundle dependency='true'>mvn:org.apache.sshd/sshd-core/${sshd.version}</bundle>
<bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/${project.version}</bundle>
</feature>
<feature name="management" version="${project.version}">
@@ -100,10 +108,10 @@
<bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/${aries.jmx.version}</bundle>
<bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/${aries.jmx.version}</bundle>
</feature>
- <feature name="jasypt-encryption" version="${project.version}">
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-codec/${commons-codec.bundle.version}</bundle>
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-lang/${commons-lang.bundle.version}</bundle>
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/${jasypt.bundle.version}</bundle>
+ <feature name="jasypt-encryption" version="${project.version}" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-codec/${commons-codec.bundle.version}</bundle>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-lang/${commons-lang.bundle.version}</bundle>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/${jasypt.bundle.version}</bundle>
<bundle>mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.jasypt/${project.version}</bundle>
</feature>
</features>
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=1025996&r1=1025995&r2=1025996&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 Thu Oct 21 13:42:25 2010
@@ -33,6 +33,7 @@ import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.felix.utils.version.VersionTable;
import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeatureEvent;
@@ -378,12 +379,37 @@ public class FeaturesServiceImpl impleme
protected void doInstallFeature(InstallationState state, Feature feature) throws Exception {
for (Feature dependency : feature.getDependencies()) {
- Feature f = getFeature(dependency.getName(), dependency.getVersion());
- if (f == null) {
+ VersionRange range = FeatureImpl.DEFAULT_VERSION.equals(dependency.getVersion())
+ ? VersionRange.ANY_VERSION : new VersionRange(dependency.getVersion(), true, true);
+ Feature fi = null;
+ for (Feature f : installed.keySet()) {
+ if (f.getName().equals(dependency.getName())) {
+ Version v = VersionTable.getVersion(f.getVersion());
+ if (range.contains(v)) {
+ if (fi == null || VersionTable.getVersion(fi.getVersion()).compareTo(v) < 0) {
+ fi = f;
+ }
+ }
+ }
+ }
+ if (fi == null) {
+ Map<String, Feature> avail = getFeatures().get(dependency.getName());
+ if (avail != null) {
+ for (Feature f : avail.values()) {
+ Version v = VersionTable.getVersion(f.getVersion());
+ if (range.contains(v)) {
+ if (fi == null || VersionTable.getVersion(fi.getVersion()).compareTo(v) < 0) {
+ fi = f;
+ }
+ }
+ }
+ }
+ }
+ if (fi == null) {
throw new Exception("No feature named '" + dependency.getName()
+ "' with version '" + dependency.getVersion() + "' available");
}
- doInstallFeature(state, f);
+ doInstallFeature(state, fi);
}
for (String config : feature.getConfigurations().keySet()) {
Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config));
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=1025996&r1=1025995&r2=1025996&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 Thu Oct 21 13:42:25 2010
@@ -43,6 +43,7 @@ import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.service.log.LogService;
import org.osgi.service.packageadmin.PackageAdmin;
+import org.slf4j.Logger;
import static org.easymock.EasyMock.*;
@@ -338,9 +339,9 @@ public class FeaturesServiceTest extends
}
- // Tests install of a Repository that includes a feature
- // with a feature dependency
- // The dependant feature is in the same repository
+ // Tests install of a Repository that includes a feature
+ // with a feature dependency
+ // The dependant feature is in the same repository
// Tests uninstall of features
public void testInstallFeatureWithDependantFeatures() throws Exception {
@@ -362,7 +363,7 @@ public class FeaturesServiceTest extends
URI uri = tmp.toURI();
BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- Bundle installedBundle = EasyMock.createMock(Bundle.class);
+ Bundle installedBundle = EasyMock.createMock(Bundle.class);
// Installs feature f1 with dependency on f2
// so will install f2 first
@@ -375,7 +376,7 @@ public class FeaturesServiceTest extends
expect(bundleContext.getBundle(12345L)).andReturn(installedBundle);
expect(installedBundle.getHeaders()).andReturn(new Hashtable());
installedBundle.start();
-
+
// Then installs f1
expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
expect(bundleContext.installBundle(isA(String.class),
@@ -386,7 +387,7 @@ public class FeaturesServiceTest extends
expect(bundleContext.getBundle(1234L)).andReturn(installedBundle);
expect(installedBundle.getHeaders()).andReturn(new Hashtable()).anyTimes();
installedBundle.start();
-
+
// uninstalls first feature name = f1, version = 0.1
expect(bundleContext.getBundle(1234)).andReturn(installedBundle);
installedBundle.uninstall();
@@ -401,14 +402,201 @@ public class FeaturesServiceTest extends
FeaturesServiceImpl svc = new FeaturesServiceImpl();
svc.setBundleContext(bundleContext);
- svc.addRepository(uri);
+ svc.addRepository(uri);
svc.installFeature("f1", "0.1");
-
+
// Uninstall repository
svc.uninstallFeature("f1", "0.1");
svc.uninstallFeature("f2", "0.1");
-
+
+ }
+
+ // Tests install of a Repository that includes a feature with a feature dependency
+ public void testInstallFeatureWithDependantFeaturesAndVersionWithoutPreinstall() throws Exception {
+
+ String name = getJarUrl(Bundle.class);
+
+ File tmp = File.createTempFile("smx", ".feature");
+ PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+ pw.println("<features>");
+ pw.println(" <feature name=\"f1\" version=\"0.1\">");
+ pw.println(" <feature version=\"0.1\">f2</feature>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.1\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.2\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println("</features>");
+ pw.close();
+
+ URI uri = tmp.toURI();
+
+ BundleContext bundleContext = prepareBundleContextForInstallUninstall();
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl();
+ svc.setBundleContext(bundleContext);
+ svc.addRepository(uri);
+
+ svc.installFeature("f1", "0.1");
+
+ // Uninstall repository
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.1");
+ }
+
+ // Tests install of a Repository that includes a feature with a feature dependency
+ public void testInstallFeatureWithDependantFeaturesAndNoVersionWithoutPreinstall() throws Exception {
+
+ String name = getJarUrl(Bundle.class);
+
+ File tmp = File.createTempFile("smx", ".feature");
+ PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+ pw.println("<features>");
+ pw.println(" <feature name=\"f1\" version=\"0.1\">");
+ pw.println(" <feature>f2</feature>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.1\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.2\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println("</features>");
+ pw.close();
+
+ URI uri = tmp.toURI();
+
+ BundleContext bundleContext = prepareBundleContextForInstallUninstall();
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl();
+ svc.setBundleContext(bundleContext);
+ svc.addRepository(uri);
+
+ svc.installFeature("f1", "0.1");
+
+ // Uninstall repository
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.2");
+ }
+
+ public void testInstallFeatureWithDependantFeaturesAndRangeWithoutPreinstall() throws Exception {
+
+ String name = getJarUrl(Bundle.class);
+
+ File tmp = File.createTempFile("smx", ".feature");
+ PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+ pw.println("<features>");
+ pw.println(" <feature name=\"f1\" version=\"0.1\">");
+ pw.println(" <feature version=\"[0.1,0.3)\">f2</feature>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.1\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.2\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println("</features>");
+ pw.close();
+
+ URI uri = tmp.toURI();
+
+ BundleContext bundleContext = prepareBundleContextForInstallUninstall();
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl();
+ svc.setBundleContext(bundleContext);
+ svc.addRepository(uri);
+
+ svc.installFeature("f1", "0.1");
+
+ // Uninstall repository
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.2");
+ }
+
+ public void testInstallFeatureWithDependantFeaturesAndRangeWithPreinstall() throws Exception {
+
+ String name = getJarUrl(Bundle.class);
+
+ File tmp = File.createTempFile("smx", ".feature");
+ PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+ pw.println("<features>");
+ pw.println(" <feature name=\"f1\" version=\"0.1\">");
+ pw.println(" <feature version=\"[0.1,0.3)\">f2</feature>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.1\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println(" <feature name=\"f2\" version=\"0.2\">");
+ pw.println(" <bundle>" + name + "</bundle>");
+ pw.println(" </feature>");
+ pw.println("</features>");
+ pw.close();
+
+ URI uri = tmp.toURI();
+
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ Bundle installedBundle = EasyMock.createMock(Bundle.class);
+
+ // Installs feature f1 with dependency on f2
+ expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
+ expect(bundleContext.installBundle(isA(String.class),
+ isA(InputStream.class))).andReturn(installedBundle);
+ expect(installedBundle.getBundleId()).andReturn(12345L).anyTimes();
+ expect(bundleContext.getBundle(12345L)).andReturn(installedBundle).anyTimes();
+ expect(installedBundle.getHeaders()).andReturn(new Hashtable()).anyTimes();
+ installedBundle.start();
+
+ expect(bundleContext.getBundles()).andReturn(new Bundle[] { installedBundle });
+ expect(installedBundle.getSymbolicName()).andReturn(name).anyTimes();
+ expect(bundleContext.installBundle(isA(String.class),
+ isA(InputStream.class))).andReturn(installedBundle);
+ installedBundle.start();
+
+ // uninstalls first feature name = f2, version = 0.1
+ installedBundle.uninstall();
+
+ expect(bundleContext.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+
+ replay(bundleContext, installedBundle);
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl();
+ svc.setBundleContext(bundleContext);
+ svc.addRepository(uri);
+
+ svc.installFeature("f2", "0.1");
+ svc.installFeature("f1", "0.1");
+
+ // Uninstall repository
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.1");
+ }
+
+ private BundleContext prepareBundleContextForInstallUninstall() throws Exception {
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ Bundle installedBundle = EasyMock.createMock(Bundle.class);
+
+ // Installs feature f1 with dependency on f2
+ expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
+ expect(bundleContext.installBundle(isA(String.class),
+ isA(InputStream.class))).andReturn(installedBundle);
+ expect(installedBundle.getBundleId()).andReturn(12345L);
+ expect(installedBundle.getBundleId()).andReturn(12345L);
+ expect(installedBundle.getBundleId()).andReturn(12345L);
+ expect(bundleContext.getBundle(12345L)).andReturn(installedBundle);
+ expect(installedBundle.getHeaders()).andReturn(new Hashtable());
+ installedBundle.start();
+
+ // uninstalls first feature name = f2, version = 0.1
+ expect(bundleContext.getBundle(12345)).andReturn(installedBundle);
+ installedBundle.uninstall();
+
+ expect(bundleContext.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+
+ replay(bundleContext, installedBundle);
+ return bundleContext;
}
public void testInstallBatchFeatureWithContinueOnFailureNoClean() throws Exception {