Repository: karaf
Updated Branches:
  refs/heads/karaf-4.0.x 8b73927c6 -> 177072e2e


[KARAF-129] Add upgrade option to Feature install command


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/177072e2
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/177072e2
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/177072e2

Branch: refs/heads/karaf-4.0.x
Commit: 177072e2ed7c360333177dd4c015d9cbae7d763e
Parents: 8b73927
Author: Vladimir Konkov <[email protected]>
Authored: Thu Jan 21 17:38:22 2016 +0300
Committer: Jean-Baptiste Onofré <[email protected]>
Committed: Wed Feb 17 16:52:49 2016 +0100

----------------------------------------------------------------------
 .../features/command/InstallFeatureCommand.java |  4 +++
 .../apache/karaf/features/FeaturesService.java  |  3 +-
 .../internal/service/FeaturesServiceImpl.java   | 37 +++++++++++++++-----
 .../org/apache/karaf/itests/FeatureTest.java    | 12 +++++++
 4 files changed, 46 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/177072e2/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
----------------------------------------------------------------------
diff --git 
a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
 
b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
index 571a713..8983009 100644
--- 
a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
+++ 
b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
@@ -52,6 +52,9 @@ public class InstallFeatureCommand extends 
FeaturesCommandSupport {
     @Option(name = "-t", aliases = "--simulate", description = "Perform a 
simulation only", required = false, multiValued = false)
     boolean simulate;
 
+    @Option(name = "-u", aliases = "--upgrade", description = "Perform an 
upgrade of feature if previous version are installed or install it", required = 
false, multiValued = false)
+    boolean upgrade;
+
     @Option(name = "--store", description = "Store the resolution into the 
given file and result for offline analysis")
     String outputFile;
 
@@ -64,6 +67,7 @@ public class InstallFeatureCommand extends 
FeaturesCommandSupport {
         addOption(FeaturesService.Option.NoAutoRefreshBundles, noRefresh);
         addOption(FeaturesService.Option.NoAutoManageBundles, noManage);
         addOption(FeaturesService.Option.Verbose, verbose);
+        addOption(FeaturesService.Option.Upgrade, upgrade);
         admin.setResolutionOutputFile(outputFile);
         admin.installFeatures(new HashSet<String>(features), region, options);
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/177072e2/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
----------------------------------------------------------------------
diff --git 
a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java 
b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
index 87e2f4a..a9aab6b 100644
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
@@ -56,7 +56,8 @@ public interface FeaturesService {
         NoAutoStartBundles,
         NoAutoManageBundles,
         Simulate,
-        Verbose
+        Verbose,
+        Upgrade
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/karaf/blob/177072e2/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
 
b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 75d7c0f..e5bb14e 100644
--- 
a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ 
b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -107,6 +107,7 @@ import static 
org.apache.karaf.features.internal.util.MapUtils.remove;
 public class FeaturesServiceImpl implements FeaturesService, 
Deployer.DeployCallback {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(FeaturesServiceImpl.class);
+    private static final String FEATURE_OSGI_REQUIREMENT_PREFIX = "feature:";
 
     /**
      * Our bundle.
@@ -734,7 +735,7 @@ public class FeaturesServiceImpl implements 
FeaturesService, Deployer.DeployCall
 
     @Override
     public boolean isRequired(Feature f) {
-        String id = "feature:" + f.getName() + "/" + new 
VersionRange(f.getVersion(), true);
+        String id = FEATURE_OSGI_REQUIREMENT_PREFIX + f.getName() + "/" + new 
VersionRange(f.getVersion(), true);
         synchronized (lock) {
             Set<String> features = state.requirements.get(ROOT_REGION);
             return features != null && features.contains(id);
@@ -822,7 +823,13 @@ public class FeaturesServiceImpl implements 
FeaturesService, Deployer.DeployCall
         if (region == null || region.isEmpty()) {
             region = ROOT_REGION;
         }
+        Set<String> fl = required.get(region);
+        if (fl == null) {
+            fl = new HashSet<>();
+            required.put(region, fl);
+        }
         List<String> featuresToAdd = new ArrayList<>();
+        List<String> featuresToRemove = new ArrayList<>();
         for (String feature : features) {
             feature = normalize(feature);
             String name = feature.substring(0, feature.indexOf("/"));
@@ -849,16 +856,28 @@ public class FeaturesServiceImpl implements 
FeaturesService, Deployer.DeployCall
             if (!matched && !options.contains(Option.NoFailOnFeatureNotFound)) 
{
                 throw new IllegalArgumentException("No matching features for " 
+ feature);
             }
+            if (options.contains(Option.Upgrade)) {
+                for (String existentFeatureReq : fl) {
+                    //remove requirement prefix feature:
+                    String existentFeature = 
existentFeatureReq.substring(FEATURE_OSGI_REQUIREMENT_PREFIX.length());
+                    if (existentFeature.startsWith(name + "/")
+                            && !featuresToAdd.contains(existentFeature)) {
+                        featuresToRemove.add(existentFeature);
+                        //do not break cycle to remove all old versions of 
feature
+                    }
+                }
+            }
+        }
+        if (!featuresToRemove.isEmpty()) {
+            print("Removing features: " + join(featuresToRemove), 
options.contains(Option.Verbose));
+            for (String featureReq : featuresToRemove) {
+                fl.remove(FEATURE_OSGI_REQUIREMENT_PREFIX + featureReq);
+            }
         }
         featuresToAdd = new ArrayList<>(new LinkedHashSet<>(featuresToAdd));
         print("Adding features: " + join(featuresToAdd), 
options.contains(Option.Verbose));
-        Set<String> fl = required.get(region);
-        if (fl == null) {
-            fl = new HashSet<>();
-            required.put(region, fl);
-        }
         for (String feature : featuresToAdd) {
-            fl.add("feature:" + feature);
+            fl.add(FEATURE_OSGI_REQUIREMENT_PREFIX + feature);
         }
         Map<String, Map<String, FeatureState>> stateChanges = 
Collections.emptyMap();
         doProvisionInThread(required, stateChanges, state, options);
@@ -881,7 +900,7 @@ public class FeaturesServiceImpl implements 
FeaturesService, Deployer.DeployCall
             feature = normalize(feature);
             if (feature.endsWith("/0.0.0")) {
                 // Match only on name
-                String nameSep = "feature:" + feature.substring(0, 
feature.indexOf("/") + 1);
+                String nameSep = FEATURE_OSGI_REQUIREMENT_PREFIX + 
feature.substring(0, feature.indexOf("/") + 1);
                 for (String f : fl) {
                     Pattern pattern = Pattern.compile(nameSep.substring(0, 
nameSep.length() - 1));
                     Matcher matcher = pattern.matcher(f);
@@ -1316,7 +1335,7 @@ public class FeaturesServiceImpl implements 
FeaturesService, Deployer.DeployCall
     }
     
     private Pattern getFeaturePattern(String name, String version) {
-        String req = "feature:" + name + "/" + new VersionRange(version, true);
+        String req = FEATURE_OSGI_REQUIREMENT_PREFIX + name + "/" + new 
VersionRange(version, true);
         req = req.replace("[", "\\[");
         req = req.replace("(", "\\(");
         req = req.replace("]", "\\]");

http://git-wip-us.apache.org/repos/asf/karaf/blob/177072e2/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java 
b/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
index b6b3e99..862cc2d 100644
--- a/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
+++ b/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
@@ -66,6 +66,18 @@ public class FeatureTest extends KarafTestSupport {
     }
 
     @Test
+    public void installWithUpgradeCommand() throws Exception {
+        final String featureToUpgrade = "transaction-api";
+        final String oldVersion = "1.1.0";
+        final String newVersion = "1.2.0";
+        System.out.println(executeCommand("feature:install -v -r " + 
featureToUpgrade + "/" + oldVersion, new RolePrincipal("admin")));
+        assertFeatureInstalled(featureToUpgrade, oldVersion);
+        System.out.println(executeCommand("feature:install -r --upgrade " + 
featureToUpgrade + "/" + newVersion, new RolePrincipal("admin")));
+        assertFeatureNotInstalled(featureToUpgrade, oldVersion);
+        assertFeatureInstalled(featureToUpgrade, newVersion);
+    }
+
+    @Test
     public void installUninstallViaMBean() throws Exception {
         MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
         ObjectName name = new 
ObjectName("org.apache.karaf:type=feature,name=root");

Reply via email to