Author: kwin Date: Thu Feb 16 10:43:39 2017 New Revision: 1783196 URL: http://svn.apache.org/viewvc?rev=1783196&view=rev Log: SLING-6392 support entity id changes for the same url (by uninstalling stale resources)
Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/BundleInstallUpgradeDowngradeTest.java sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/MockInstallableResource.java sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java?rev=1783196&r1=1783195&r2=1783196&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java Thu Feb 16 10:43:39 2017 @@ -31,6 +31,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -224,8 +225,20 @@ public class PersistentResourceList { t = new EntityResourceList(input.getEntityId(), this.listener); this.data.put(input.getEntityId(), t); } - t.addOrUpdate(input); + + // find stale resources (other entity ids with the same URL) + Collection<RegisteredResource> staleResources = getResourcesWithUrl(input.getURL(), input.getEntityId()); + for (RegisteredResource staleResource : staleResources) { + // get according group + EntityResourceList group = this.data.get(staleResource.getEntityId()); + if (group == null) { + logger.error("Could not get group of stale resource {}", staleResource); + } else { + group.remove(input.getURL()); + logger.warn("Removing stale resource {}, overwritten by {}", staleResource, input); + } + } } else { // check if there is an old resource and remove it first if ( this.untransformedResources.contains(input) ) { @@ -241,6 +254,7 @@ public class PersistentResourceList { public List<RegisteredResource> getUntransformedResources() { return this.untransformedResources; } + /** * Remove a resource by url. @@ -283,6 +297,27 @@ public class PersistentResourceList { } /** + * + * @param url the url of the resource to look for + * @param entityIdToSkip all resources having this entity id should in no case be returned + * @return the list of all registered resources with the given url, not having the entityId which should be skipped. + */ + private Collection<RegisteredResource> getResourcesWithUrl(String url, String entityIdToSkip) { + Collection<RegisteredResource> foundResources = new LinkedList<>(); + for(final EntityResourceList group : this.data.values()) { + if (group.getResourceId().equals(entityIdToSkip)) { + continue; + } + for (RegisteredResource resource : group.listResources()) { + if (resource.getURL().equals(url)) { + foundResources.add(resource); + } + } + } + return foundResources; + } + + /** * Compact the internal state and remove empty groups. * @return <code>true</code> if another cycle should be started. */ Modified: sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/BundleInstallUpgradeDowngradeTest.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/BundleInstallUpgradeDowngradeTest.java?rev=1783196&r1=1783195&r2=1783196&view=diff ============================================================================== --- sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/BundleInstallUpgradeDowngradeTest.java (original) +++ sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/BundleInstallUpgradeDowngradeTest.java Thu Feb 16 10:43:39 2017 @@ -19,6 +19,8 @@ package org.apache.sling.installer.it; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import org.apache.sling.installer.api.InstallableResource; +import org.apache.sling.installer.it.OsgiInstallerTestBase.BundleEvent; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -207,4 +209,44 @@ public class BundleInstallUpgradeDowngra } } + + /** + * This test class assures that whenever a new bundle is + * provided with the same url as an already installed bundle, + * the already installed bundle is uninstalled and the new one installed. + * @see <a href="https://issues.apache.org/jira/browse/SLING-6392">SLING-6392</a> + */ + @Test + public void testReplaceBundleWithSameUrlButDifferentSymbolicName() throws Exception { + final String symbolicName = "osgi-installer-testbundle"; + final String symbolicName2 = "osgi-installer-testA"; + final String installableResourceId = "stable-id"; + + assertNull("Test bundle must not be present before test", findBundle(symbolicName)); + assertNull("Test A bundle must not be present before test", findBundle(symbolicName2)); + { + //assertNull("Test bundle must be absent before installing", findBundle(symbolicName)); + final Object listener = this.startObservingBundleEvents(); + installer.updateResources(URL_SCHEME, getInstallableResource( + getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.0.jar"), installableResourceId, "1", InstallableResource.DEFAULT_PRIORITY), null); + this.waitForBundleEvents(symbolicName + " must be installed", listener, + new BundleEvent(symbolicName, "1.0", org.osgi.framework.BundleEvent.INSTALLED), + new BundleEvent(symbolicName, "1.0", org.osgi.framework.BundleEvent.STARTED)); + assertBundle("After installing", symbolicName, "1.0", Bundle.ACTIVE); + } + + // now modify the bundle (having the same url but a different symbolic name and different digest) + { + final Object listener = this.startObservingBundleEvents(); + installer.updateResources(URL_SCHEME, getInstallableResource( + getTestBundle(BUNDLE_BASE_NAME + "-testA-1.0.jar"), installableResourceId, "2", InstallableResource.DEFAULT_PRIORITY), null); + this.waitForBundleEvents(symbolicName2 + " must be installed and " + symbolicName + " uninstalled", listener, + new BundleEvent(symbolicName, "1.0", org.osgi.framework.BundleEvent.STOPPED), + new BundleEvent(symbolicName, "1.0", org.osgi.framework.BundleEvent.UNINSTALLED), + new BundleEvent(symbolicName2, "1.0", org.osgi.framework.BundleEvent.INSTALLED), + new BundleEvent(symbolicName2, "1.0", org.osgi.framework.BundleEvent.STARTED)); + assertBundle("After installing a different bundle with same id " + installableResourceId, symbolicName2, "1.0", Bundle.ACTIVE); + assertNull("Test bundle must not be present after removing it", findBundle(symbolicName)); + } + } } \ No newline at end of file Modified: sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/MockInstallableResource.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/MockInstallableResource.java?rev=1783196&r1=1783195&r2=1783196&view=diff ============================================================================== --- sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/MockInstallableResource.java (original) +++ sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/MockInstallableResource.java Thu Feb 16 10:43:39 2017 @@ -45,8 +45,8 @@ public class MockInstallableResource ext InstallableResource.TYPE_BUNDLE, null); } - public MockInstallableResource(String uri, InputStream is, String digest, String type, Integer priority) { - super(uri, is, + public MockInstallableResource(String id, InputStream is, String digest, String type, Integer priority) { + super(id, is, null, digest, type != null ? type : InstallableResource.TYPE_BUNDLE, priority); } Modified: sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java?rev=1783196&r1=1783195&r2=1783196&view=diff ============================================================================== --- sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java (original) +++ sling/trunk/installer/it/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java Thu Feb 16 10:43:39 2017 @@ -408,14 +408,17 @@ public class OsgiInstallerTestBase imple } protected InstallableResource[] getInstallableResource(File testBundle, String digest, int priority) throws IOException { - final String url = testBundle.getAbsolutePath(); + return getInstallableResource(testBundle, testBundle.getAbsolutePath(), digest, priority); + } + + protected InstallableResource[] getInstallableResource(File testBundle, String id, String digest, int priority) throws IOException { if (digest == null) { digest = String.valueOf(testBundle.lastModified()); } - final InstallableResource result = new MockInstallableResource(url, new FileInputStream(testBundle), digest, null, priority); + final InstallableResource result = new MockInstallableResource(id, new FileInputStream(testBundle), digest, null, priority); return new InstallableResource[] {result}; } - + protected InstallableResource[] getInstallableResource(String configPid, Dictionary<String, Object> data) { return getInstallableResource(configPid, copy(data), InstallableResource.DEFAULT_PRIORITY); }