You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2012/10/01 18:39:36 UTC

svn commit: r1392430 - in /karaf/trunk/features/core/src: main/java/org/apache/karaf/features/internal/ test/java/org/apache/karaf/features/internal/

Author: cschneider
Date: Mon Oct  1 16:39:35 2012
New Revision: 1392430

URL: http://svn.apache.org/viewvc?rev=1392430&view=rev
Log:
KARAF-608 Implemented staged  boot

Added:
    karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/BootFeaturesInstallerTest.java   (with props)
Modified:
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BootFeaturesInstaller.java
    karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java
    karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/TestBase.java

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BootFeaturesInstaller.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BootFeaturesInstaller.java?rev=1392430&r1=1392429&r2=1392430&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BootFeaturesInstaller.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BootFeaturesInstaller.java Mon Oct  1 16:39:35 2012
@@ -16,11 +16,14 @@
  */
 package org.apache.karaf.features.internal;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
-import java.util.LinkedHashSet;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
@@ -64,52 +67,78 @@ public class BootFeaturesInstaller {
     }
     
 	void installBootFeatures() {
-		Set<Feature> features = determineFeaturesToInstall();
+	    List<Feature> installedFeatures = Arrays.asList(featuresService.listInstalledFeatures());
+		List<Set<String>> stagedFeatureNames = parseBootFeatures(boot);
+        List<Set<Feature>> stagedFeatures = toFeatureSetList(stagedFeatureNames);
+
         try {
-            featuresService.installFeatures(features, EnumSet.of(Option.NoCleanIfFailure, Option.ContinueBatchOnFailure));
+            for (Set<Feature> features : stagedFeatures) {
+                features.removeAll(installedFeatures);
+                featuresService.installFeatures(features, EnumSet.of(Option.NoCleanIfFailure, Option.ContinueBatchOnFailure));                
+            }
         } catch (Exception e) {
             LOGGER.error("Error installing boot features", e);
         }
 	}
 	
-    private Set<Feature> determineFeaturesToInstall() {
-    	List<Feature> installedFeatures = Arrays.asList(featuresService.listInstalledFeatures());
-        String[] list = boot.split(",");
-        Set<Feature> features = new LinkedHashSet<Feature>();
-        for (String f : list) {
-            f = f.trim();
-            if (f.length() > 0) {
-                String featureVersion = null;
-
-                // first we split the parts of the feature string to gain access to the version info
-                // if specified
-                String[] parts = f.split(";");
-                String featureName = parts[0];
-                for (String part : parts) {
-                    // if the part starts with "version=" it contains the version info
-                    if (part.startsWith(VERSION_PREFIX)) {
-                        featureVersion = part.substring(VERSION_PREFIX.length());
-                    }
-                }
-
-                if (featureVersion == null) {
-                    // no version specified - use default version
-                    featureVersion = org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
-                }
-
+	private List<Set<Feature>> toFeatureSetList(List<Set<String>> stagedFeatures) {
+	    ArrayList<Set<Feature>> result = new ArrayList<Set<Feature>>();
+	    for (Set<String> features : stagedFeatures) {
+	        HashSet<Feature> featureSet = new HashSet<Feature>();
+            for (String featureName : features) {
                 try {
-                    // try to grab specific feature version
-                    Feature feature = featuresService.getFeature(featureName, featureVersion);
-                    if (feature != null && !installedFeatures.contains(feature)) {
-                        features.add(feature);
+                    Feature feature = getFeature(featureName);
+                    if (feature == null) {
+                        LOGGER.error("Error Boot feature " + featureName + " not found");
                     } else {
-                        LOGGER.error("Error installing boot feature " + f + ": feature not found");
+                        featureSet.add(feature);
                     }
                 } catch (Exception e) {
-                    LOGGER.error("Error installing boot feature " + f, e);
+                    LOGGER.error("Error getting feature for feature string " + featureName, e);
                 }
             }
+            result.add(featureSet);
         }
-		return features;
+        return result;
 	}
+	
+	/**
+	 * 
+	 * @param featureSt either feature name or <featurename>;version=<version>
+	 * @return feature matching the feature string
+	 * @throws Exception
+	 */
+    private Feature getFeature(String featureSt) throws Exception {
+        String[] parts = featureSt.trim().split(";");
+        String featureName = parts[0];
+        String featureVersion = null;
+        for (String part : parts) {
+            // if the part starts with "version=" it contains the version info
+            if (part.startsWith(VERSION_PREFIX)) {
+                featureVersion = part.substring(VERSION_PREFIX.length());
+            }
+        }
+        if (featureVersion == null) {
+            // no version specified - use default version
+            featureVersion = org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
+        }
+        return featuresService.getFeature(featureName, featureVersion);
+    }
+    
+    protected List<Set<String>> parseBootFeatures(String bootFeatures) {
+        Pattern pattern = Pattern.compile("(\\((.+))\\),|.+");
+        Matcher matcher = pattern.matcher(bootFeatures);
+        List<Set<String>> result = new ArrayList<Set<String>>();
+        while (matcher.find()) {
+            String group = matcher.group(2) != null ? matcher.group(2) : matcher.group();
+            result.add(parseFeatureList(group));
+        }
+        return result;
+    }
+
+    private Set<String> parseFeatureList(String group) {
+        HashSet<String> features = new HashSet<String>(Arrays.asList(group.trim().split("\\s*,\\s*")));
+        return features;
+    }
+
 }

Added: karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/BootFeaturesInstallerTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/BootFeaturesInstallerTest.java?rev=1392430&view=auto
==============================================================================
--- karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/BootFeaturesInstallerTest.java (added)
+++ karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/BootFeaturesInstallerTest.java Mon Oct  1 16:39:35 2012
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features.internal;
+
+import static java.util.Arrays.asList;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.util.EnumSet;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService.Option;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BootFeaturesInstallerTest extends TestBase {
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testParser() {
+        BootFeaturesInstaller installer = new BootFeaturesInstaller(null, "");
+        Assert.assertEquals(asList(setOf("test1", "test2"),setOf("test3")), installer.parseBootFeatures("(test1, test2), test3"));
+        Assert.assertEquals(asList(setOf("test1", "test2", "test3")), installer.parseBootFeatures("test1, test2, test3"));
+    }
+    
+    /**
+     * This test checks KARAF-388 which allows you to specify version of boot feature.
+     * @throws Exception 
+     */
+    @Test
+    public void testStartDoesNotFailWithNonExistentVersion() throws Exception  {
+        FeaturesServiceImpl impl = EasyMock.createMock(FeaturesServiceImpl.class);
+        expect(impl.listInstalledFeatures()).andReturn(new Feature[]{});
+        EasyMock.expectLastCall();
+        Feature sshFeature = feature("ssh", "1.0.0");
+        expect(impl.getFeature("ssh", "1.0.0")).andReturn(sshFeature);
+        expect(impl.getFeature("transaction", "1.2")).andReturn(null);
+        
+        // Only the ssh feature should get installed
+        impl.installFeatures(setOf(sshFeature), EnumSet.of(Option.NoCleanIfFailure, Option.ContinueBatchOnFailure));
+        EasyMock.expectLastCall();
+        
+        replay(impl);
+        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(impl , "transaction;version=1.2,ssh;version=1.0.0");
+        bootFeatures.installBootFeatures();
+        EasyMock.verify(impl);        
+    }
+    
+    @Test
+    public void testStagedBoot() throws Exception  {
+        FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
+        Feature sshFeature = feature("ssh", "1.0.0");
+        Feature transactionFeature = feature("transaction", "2.0.0");
+        expect(impl.listInstalledFeatures()).andStubReturn(new Feature[]{});
+        expect(impl.getFeature("transaction", "0.0.0")).andStubReturn(transactionFeature);
+        expect(impl.getFeature("ssh", "0.0.0")).andStubReturn(sshFeature);
+
+        impl.installFeatures(setOf(transactionFeature), EnumSet.of(Option.NoCleanIfFailure, Option.ContinueBatchOnFailure));
+        EasyMock.expectLastCall();
+        impl.installFeatures(setOf(sshFeature), EnumSet.of(Option.NoCleanIfFailure, Option.ContinueBatchOnFailure));
+        EasyMock.expectLastCall();
+        
+        replay(impl);
+        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(impl , "(transaction), ssh");
+        bootFeatures.installBootFeatures();
+        EasyMock.verify(impl);        
+    }
+}

Propchange: karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/BootFeaturesInstallerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java?rev=1392430&r1=1392429&r2=1392430&view=diff
==============================================================================
--- karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java (original)
+++ karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java Mon Oct  1 16:39:35 2012
@@ -19,17 +19,13 @@ package org.apache.karaf.features.intern
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -121,52 +117,7 @@ public class FeaturesServiceImplTest ext
         }
     }
 
-    /**
-     * This test checks KARAF-388 which allows you to specify version of boot feature.
-     */
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testStartDoesNotFailWithNonExistentVersion()  {
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        expect(bundleManager.createAndRegisterEventAdminListener()).andReturn(null);
-        bundleManager.refreshBundles(EasyMock.anyObject(Set.class), EasyMock.anyObject(Set.class), EasyMock.anyObject(EnumSet.class));
-        EasyMock.expectLastCall().anyTimes();
-
-        final Map<String, Map<String, Feature>> features = features(
-                feature("transaction", "1.0.0"),
-                feature("transaction", "2.0.0"),
-                feature("ssh", "1.0.0")
-        );
-
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(bundleManager, null) {
-            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
-                return features;
-            };
 
-            // override methods which refers to bundle context to avoid mocking everything
-            @Override
-            protected boolean loadState() {
-                return true;
-            }
-            @Override
-            protected void saveState() {
-            }
-        };
-       
-        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(impl, "transaction;version=1.2,ssh;version=1.0.0");
-        replay(bundleManager);
-        try {
-            Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0]));
-            impl.start();
-            bootFeatures.installBootFeatures();
-            assertFalse("Feature transaction 1.0.0 should not be installed", impl.isInstalled(impl.getFeature("transaction", "1.0.0")));
-            assertFalse("Feature transaction 2.0.0 should not be installed", impl.isInstalled(impl.getFeature("transaction", "2.0.0")));
-            assertTrue("Feature ssh should be installed", impl.isInstalled(impl.getFeature("ssh", "1.0.0")));
-        } catch (Exception e) {
-            fail(String.format("Service should not throw start-up exception but log the error instead: %s", e));
-        }
-        
-    }
     
     /**
      * This test ensures that every feature get installed only once, even if it appears multiple times in the list

Modified: karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/TestBase.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/TestBase.java?rev=1392430&r1=1392429&r2=1392430&view=diff
==============================================================================
--- karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/TestBase.java (original)
+++ karaf/trunk/features/core/src/test/java/org/apache/karaf/features/internal/TestBase.java Mon Oct  1 16:39:35 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.karaf.features.internal;
 
+import static java.util.Arrays.asList;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 
@@ -90,6 +91,14 @@ public class TestBase {
     public Set<Long> setOf(Long ... elements) {
         return new HashSet<Long>(Arrays.asList(elements));
     }
+    
+    public Set<String> setOf(String ... elements) {
+        return new HashSet<String>(asList(elements));
+    }
+    
+    public Set<Feature> setOf(Feature ... elements) {
+        return new HashSet<Feature>(Arrays.asList(elements));
+    }
 
     @SuppressWarnings("unchecked")
     public void ignoreRefreshes(BundleManager bundleManager) {