Author: gertv
Date: Thu Aug 9 15:15:55 2012
New Revision: 1371248
URL: http://svn.apache.org/viewvc?rev=1371248&view=rev
Log:
KARAF-1600: Avoid duplicate feature and bundle resolution when installing
cascading features
Added:
karaf/branches/karaf-2.3.x/features/core/src/test/resources/org/apache/karaf/features/internal/
karaf/branches/karaf-2.3.x/features/core/src/test/resources/org/apache/karaf/features/internal/repo2.xml
Modified:
karaf/branches/karaf-2.3.x/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
karaf/branches/karaf-2.3.x/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java
Modified:
karaf/branches/karaf-2.3.x/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
URL:
http://svn.apache.org/viewvc/karaf/branches/karaf-2.3.x/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java?rev=1371248&r1=1371247&r2=1371248&view=diff
==============================================================================
---
karaf/branches/karaf-2.3.x/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
(original)
+++
karaf/branches/karaf-2.3.x/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
Thu Aug 9 15:15:55 2012
@@ -518,7 +518,11 @@ public class FeaturesServiceImpl impleme
throw new Exception("No feature named '" + dependency.getName()
+ "' with version '" + dependency.getVersion() + "'
available");
}
- doInstallFeature(state, fi, verbose);
+ if (state.features.containsKey(fi)) {
+ LOGGER.debug("Feature {} with version {} is already being
installed", feature.getName(), feature.getVersion());
+ } else {
+ doInstallFeature(state, fi, verbose);
+ }
}
for (String config : feature.getConfigurations().keySet()) {
Dictionary<String, String> props = new Hashtable<String,
String>(feature.getConfigurations().get(config));
@@ -590,11 +594,11 @@ public class FeaturesServiceImpl impleme
protected Set<Bundle> findBundlesToRefresh(InstallationState state) {
Set<Bundle> bundles = new HashSet<Bundle>();
bundles.addAll(findBundlesWithOptionalPackagesToRefresh(state));
- bundles.addAll(findBundlesWithFramentsToRefresh(state));
+ bundles.addAll(findBundlesWithFragmentsToRefresh(state));
return bundles;
}
- protected Set<Bundle> findBundlesWithFramentsToRefresh(InstallationState
state) {
+ protected Set<Bundle> findBundlesWithFragmentsToRefresh(InstallationState
state) {
Set<Bundle> bundles = new HashSet<Bundle>();
Set<Bundle> oldBundles = new HashSet<Bundle>(state.bundles);
oldBundles.removeAll(state.installed);
Modified:
karaf/branches/karaf-2.3.x/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java
URL:
http://svn.apache.org/viewvc/karaf/branches/karaf-2.3.x/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java?rev=1371248&r1=1371247&r2=1371248&view=diff
==============================================================================
---
karaf/branches/karaf-2.3.x/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java
(original)
+++
karaf/branches/karaf-2.3.x/features/core/src/test/java/org/apache/karaf/features/internal/FeaturesServiceImplTest.java
Thu Aug 9 15:15:55 2012
@@ -24,16 +24,22 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.List;
+import java.util.LinkedList;
import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import org.apache.felix.utils.manifest.Clause;
+import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.Feature;
import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkListener;
/**
@@ -173,6 +179,56 @@ public class FeaturesServiceImplTest ext
}
}
+ /**
+ * This test ensures that every feature get installed only once, even if
it appears multiple times in the list
+ * of transitive feature dependencies (KARAF-1600)
+ */
+ public void testNoDuplicateFeaturesInstallation() throws Exception {
+ final List<Feature> installed = new LinkedList<Feature>();
+
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl() {
+ // override methods which refers to bundle context to avoid
mocking everything
+ @Override
+ protected boolean loadState() {
+ return true;
+ }
+
+ @Override
+ protected void saveState() {
+
+ }
+
+ @Override
+ protected void doInstallFeature(InstallationState state, Feature
feature, boolean verbose) throws Exception {
+ installed.add(feature);
+
+ super.doInstallFeature(state, feature, verbose);
+ }
+
+ @Override
+ protected Bundle installBundleIfNeeded(InstallationState state,
BundleInfo bundleInfo, boolean verbose) throws IOException, BundleException {
+ // let's return a mock bundle and bundle id to keep the
features service happy
+ Bundle bundle = createNiceMock(Bundle.class);
+ expect(bundle.getBundleId()).andReturn(10l).anyTimes();
+ replay(bundle);
+ return bundle;
+ }
+ };
+ impl.addRepository(getClass().getResource("repo2.xml").toURI());
+
+ try {
+ impl.installFeature("all");
+
+ // copying the features to a set to filter out the duplicates
+ Set<Feature> noduplicates = new HashSet<Feature>();
+ noduplicates.addAll(installed);
+
+ assertEquals("Every feature should only have been installed once",
installed.size(), noduplicates.size());
+ } catch (Exception e) {
+ fail(String.format("Service should not throw any exceptions: %s",
e));
+ }
+ }
+
public void testGetOptionalImportsOnly() {
FeaturesServiceImpl service = new FeaturesServiceImpl();
Added:
karaf/branches/karaf-2.3.x/features/core/src/test/resources/org/apache/karaf/features/internal/repo2.xml
URL:
http://svn.apache.org/viewvc/karaf/branches/karaf-2.3.x/features/core/src/test/resources/org/apache/karaf/features/internal/repo2.xml?rev=1371248&view=auto
==============================================================================
---
karaf/branches/karaf-2.3.x/features/core/src/test/resources/org/apache/karaf/features/internal/repo2.xml
(added)
+++
karaf/branches/karaf-2.3.x/features/core/src/test/resources/org/apache/karaf/features/internal/repo2.xml
Thu Aug 9 15:15:55 2012
@@ -0,0 +1,41 @@
+<!--
+
+ 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.
+-->
+<features name="repo2">
+ <feature name="common">
+ <bundle>b1</bundle>
+ </feature>
+ <feature name="f1">
+ <feature>common</feature>
+ <bundle>b2</bundle>
+ </feature>
+ <feature name="f2">
+ <feature>common</feature>
+ <feature>f1</feature>
+ <bundle>b3</bundle>
+ </feature>
+ <feature name="f3">
+ <feature>f1</feature>
+ <feature>f2</feature>
+ <bundle>b4</bundle>
+ </feature>
+ <feature name="all">
+ <feature>f1</feature>
+ <feature>f2</feature>
+ <feature>f3</feature>
+ </feature>
+</features>