From 0888c280e9ede273e0d1f3dfd77cd5130f7185d1 Mon Sep 17 00:00:00 2001
From: Andreas Pieber <anpieber@gmail.com>
Date: Sun, 20 Feb 2011 05:03:41 +0100
Subject: [PATCH] [KARAF-473] FeatureService#getFeatures handles version ranges

---
 .../features/internal/FeaturesServiceImpl.java     |   55 ++++++++++++++++---
 .../apache/karaf/features/FeaturesServiceTest.java |   49 +++++++++++++++++
 2 files changed, 95 insertions(+), 9 deletions(-)

diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
index a7b416d..a809c35 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
@@ -16,12 +16,37 @@
  */
 package org.apache.karaf.features.internal;
 
-import java.io.*;
+import static java.lang.String.format;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
@@ -800,13 +825,25 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
             return null;
         } else {
             Feature feature = versions.get(version);
-            if (feature == null && FeatureImpl.DEFAULT_VERSION.equals(version)) {
-                Version latest = new Version(cleanupVersion(version));
-                for (String available : versions.keySet()) {
-                    Version availableVersion = new Version(cleanupVersion(available));
-                    if (availableVersion.compareTo(latest) > 0) {
-                        feature = versions.get(available);
-                        latest = availableVersion;
+            if (feature == null) {
+                if (FeatureImpl.DEFAULT_VERSION.equals(version)) {
+                    Version latest = new Version(cleanupVersion(version));
+                    for (String available : versions.keySet()) {
+                        Version availableVersion = new Version(cleanupVersion(available));
+                        if (availableVersion.compareTo(latest) > 0) {
+                            feature = versions.get(available);
+                            latest = availableVersion;
+                        }
+                    }
+                } else {
+                    Version latest = new Version(cleanupVersion(FeatureImpl.DEFAULT_VERSION));
+                    VersionRange versionRange = new VersionRange(version, true, true);
+                    for (String available : versions.keySet()) {
+                        Version availableVersion = new Version(cleanupVersion(available));
+                        if (availableVersion.compareTo(latest) > 0 && versionRange.contains(availableVersion)) {
+                            feature = versions.get(available);
+                            latest = availableVersion;
+                        }
                     }
                 }
             }
diff --git a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
index 984df87..4395989 100644
--- a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
@@ -16,6 +16,14 @@
  */
 package org.apache.karaf.features;
 
+import static org.easymock.EasyMock.aryEq;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -35,6 +43,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.jar.JarInputStream;
 
 import junit.framework.TestCase;
+
 import org.apache.karaf.features.internal.FeatureImpl;
 import org.apache.karaf.features.internal.FeaturesServiceImpl;
 import org.easymock.EasyMock;
@@ -573,6 +582,46 @@ public class FeaturesServiceTest extends TestCase {
         svc.uninstallFeature("f2", "0.1");
     }
 
+    public void testGetFeaturesShouldHandleDifferentVersionPatterns() throws Exception {
+
+        String name = getJarUrl(Bundle.class);
+
+        File tmp = File.createTempFile("smx", ".feature");
+        PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+        pw.println("<features xmlns=\"http://karaf.apache.org/xmlns/features/v1.0.0\">");
+        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();
+
+        FeaturesServiceImpl svc = new FeaturesServiceImpl();
+        svc.addRepository(uri);
+
+        Feature feature = svc.getFeature("f2", "[0.1,0.3)");
+        assertEquals("f2", feature.getName());
+        assertEquals("0.2", feature.getVersion());
+
+        Feature feature2 = svc.getFeature("f2", "0.0.0");
+        assertEquals("f2", feature2.getName());
+        assertEquals("0.2", feature2.getVersion());
+
+        Feature feature3 = svc.getFeature("f2", "0.2");
+        assertEquals("f2", feature3.getName());
+        assertEquals("0.2", feature3.getVersion());
+
+        Feature feature4 = svc.getFeature("f2", "0.3");
+        assertNull(feature4);
+    }
+
     private BundleContext prepareBundleContextForInstallUninstall() throws Exception {
         BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
         Bundle installedBundle = EasyMock.createMock(Bundle.class);
-- 
1.7.4.1

