SLING-5014 : Installer blacklist, to avoid reinstalling older bundles. Apply patch from Dominik Süß. Updated to latest parent pom and newer OSGi framework

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1765608 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 3f4f9ef..eb8ad04 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>26</version>
+        <version>29</version>
         <relativePath/>
     </parent>
 
@@ -54,6 +54,17 @@
     <build>
         <plugins>
             <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>src/test/resources/blacklisttest/sling_bootstrap.txt</exclude>
+                        <exclude>src/test/resources/blacklisttestempty/sling_bootstrap.txt</exclude>
+                        <exclude>src/test/resources/sling_bootstrap.txt</exclude>
+                    </excludes>
+                </configuration>
+             </plugin>
+             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
@@ -445,18 +456,18 @@
             <scope>provided</scope>
         </dependency>          
         <dependency>
+             <groupId>org.osgi</groupId>
+             <artifactId>org.osgi.service.cm</artifactId>
+             <version>1.5.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.log</artifactId>
             <version>2.1.2</version>
             <scope>provided</scope>
         </dependency>          
         <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <version>4.2.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam-container-native</artifactId>
             <version>${exam.version}</version>
@@ -489,7 +500,7 @@
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.framework</artifactId>
-            <version>4.4.1</version>
+            <version>5.6.0</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/src/test/java/org/apache/sling/installer/it/BundleInstallBlackListTest.java b/src/test/java/org/apache/sling/installer/it/BundleInstallBlackListTest.java
new file mode 100644
index 0000000..85d4626
--- /dev/null
+++ b/src/test/java/org/apache/sling/installer/it/BundleInstallBlackListTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.sling.installer.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.sling.installer.api.OsgiInstaller;
+import org.apache.sling.installer.core.impl.tasks.BundleInfo;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.options.FrameworkPropertyOption;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.Version;
+
+@RunWith(PaxExam.class)
+public class BundleInstallBlackListTest extends OsgiInstallerTestBase {
+    
+    final String symbolicName = "osgi-installer-testbundle";
+
+    @org.ops4j.pax.exam.Configuration
+    public Option[] config() {
+        return defaultConfiguration();
+    }
+
+    @Before
+    public void setUp() throws BundleException {
+        System.setProperty("sling.launchpad",new File("src/test/resources/blacklisttest").getAbsolutePath());
+        updateInstallerBundle();
+    }
+
+    @After
+    public void tearDown() {
+        super.tearDown();
+        System.clearProperty("sling.launchpad");
+    }
+
+    @Test
+    public void testBlacklistBundleVersion() throws Exception {
+
+        assertNull("Test bundle must not be present before test", findBundle(symbolicName));
+
+        // Install first test bundle and check version
+        long bundleId = 0;
+        {
+            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")), 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));
+            final Bundle b = assertBundle("After installing", symbolicName, "1.0", Bundle.ACTIVE);
+            bundleId = b.getBundleId();
+        }
+
+        // Try to install blacklisted version of bundle
+        {
+            final Object listener = this.startObservingBundleEvents();
+            installer.updateResources(URL_SCHEME, getInstallableResource(
+                getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.1.jar"), "digestA"), null);
+            sleep(150);
+            this.assertNoBundleEvents("Bundle install of blacklisted version should not cause any change.", listener,
+                symbolicName);
+            final Bundle b = assertBundle("After updating to 1.1", symbolicName, "1.0", Bundle.ACTIVE);
+            assertEquals("Bundle ID must not change after update", bundleId, b.getBundleId());
+        }
+
+    }
+
+    @Test
+    public void testUninstallWithBlacklistedVersions() throws Exception {
+        
+        // Reroute launchpad home containing empty blacklist for ramp up
+        System.setProperty("sling.launchpad",new File("src/test/resources/blacklisttestempty").getAbsolutePath());
+        updateInstallerBundle();
+
+        assertNull("Test bundle must not be present before test", findBundle(symbolicName));
+
+        // Install first test bundle and check version
+        long bundleId = 0;
+        {
+            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.1.jar")), null);
+            this.waitForBundleEvents(symbolicName + " must be installed", listener,
+                new BundleEvent(symbolicName, "1.1", org.osgi.framework.BundleEvent.INSTALLED),
+                new BundleEvent(symbolicName, "1.1", org.osgi.framework.BundleEvent.STARTED));
+            final Bundle b = assertBundle("After installing", symbolicName, "1.1", Bundle.ACTIVE);
+            bundleId = b.getBundleId();
+        }
+
+        // Upgrade to later version, verify
+        {
+            final Object listener = this.startObservingBundleEvents();
+            installer.updateResources(URL_SCHEME, getInstallableResource(
+                getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.2.jar"), "digestA"), null);
+            this.waitForBundleEvents(symbolicName + " must be installed", listener,
+                new BundleEvent(symbolicName, "1.1", org.osgi.framework.BundleEvent.STOPPED),
+                new BundleEvent(symbolicName, "1.2", org.osgi.framework.BundleEvent.STARTED));
+            final Bundle b = assertBundle("After updating to 1.2", symbolicName, "1.2", Bundle.ACTIVE);
+            assertEquals("Bundle ID must not change after update", bundleId, b.getBundleId());
+        }
+
+        // configure blacklist bundle to ignore older version
+        System.setProperty("sling.launchpad",new File("src/test/resources/blacklisttest").getAbsolutePath());
+        updateInstallerBundle();
+        
+        // Try to uninstall current version and verify uninstall instead of
+        // downgrade to blacklisted version
+        {
+            final Object listener = this.startObservingBundleEvents();
+            installer.updateResources(URL_SCHEME, null, getNonInstallableResourceUrl(
+                getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.2.jar")));
+            this.waitForBundleEvents(symbolicName + " must be installed", listener,
+                new BundleEvent(symbolicName, "1.2", org.osgi.framework.BundleEvent.STOPPED),
+                new BundleEvent(symbolicName, "1.2", org.osgi.framework.BundleEvent.UNINSTALLED));
+
+            final Bundle b = findBundle(symbolicName);
+            assertNull("Testbundle must be gone", b);
+        }
+
+    }
+
+    private void updateInstallerBundle() throws BundleException {
+        bundleContext.getServiceReference(OsgiInstaller.class).getBundle().update();
+        setupInstaller();
+    }
+
+    @Test
+    public void testUninstallWithBlacklistedIntermediateVersion() throws Exception {
+
+        // Reroute launchpad home containing empty blacklist for ramp up
+        System.setProperty("sling.launchpad",new File("src/test/resources/blacklisttestempty").getAbsolutePath());
+        updateInstallerBundle();
+
+        assertNull("Test bundle must not be present before test",
+            findBundle(symbolicName));
+
+        // Install first test bundle and check version
+        long bundleId = 0;
+        {
+            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")), 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));
+            final Bundle b = assertBundle("After installing", symbolicName, "1.0",
+                Bundle.ACTIVE);
+            bundleId = b.getBundleId();
+        }
+
+        // Upgrade to later version, verify
+        {
+            final Object listener = this.startObservingBundleEvents();
+            installer.updateResources(URL_SCHEME, getInstallableResource(
+                getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.1.jar"), "digestA"),
+                null);
+            this.waitForBundleEvents(symbolicName + " must be installed", listener,
+                new BundleEvent(symbolicName, "1.0",
+                    org.osgi.framework.BundleEvent.STOPPED),
+                new BundleEvent(symbolicName, "1.1",
+                    org.osgi.framework.BundleEvent.STARTED));
+            final Bundle b = assertBundle("After updating to 1.1", symbolicName,
+                "1.1", Bundle.ACTIVE);
+            assertEquals("Bundle ID must not change after update", bundleId,
+                b.getBundleId());
+        }
+
+        // upgrade to 3rd version
+        {
+            final Object listener = this.startObservingBundleEvents();
+            installer.updateResources(URL_SCHEME, getInstallableResource(
+                getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.2.jar"), "digestA"),
+                null);
+            this.waitForBundleEvents(symbolicName + " must be installed", listener,
+                new BundleEvent(symbolicName, "1.1",
+                    org.osgi.framework.BundleEvent.STOPPED),
+                new BundleEvent(symbolicName, "1.2",
+                    org.osgi.framework.BundleEvent.STARTED));
+            final Bundle b = assertBundle("After updating to 1.2", symbolicName,
+                "1.2", Bundle.ACTIVE);
+            assertEquals("Bundle ID must not change after update", bundleId,
+                b.getBundleId());
+        }
+
+        // configure blacklist bundle to ignore 1.1 version
+        // configure blacklist bundle to ignore older version
+        System.setProperty("sling.launchpad",new File("src/test/resources/blacklisttest").getAbsolutePath());
+        updateInstallerBundle();
+ 
+        // Try to uninstall current version and verify uninstall instead of
+        // downgrade to blacklisted version
+        {
+            final Object listener = this.startObservingBundleEvents();
+            installer.updateResources(URL_SCHEME, null, getNonInstallableResourceUrl(
+                getTestBundle(BUNDLE_BASE_NAME + "-testbundle-1.2.jar")));
+            this.waitForBundleEvents(symbolicName + " must be installed", listener,
+                new BundleEvent(symbolicName, "1.2",
+                    org.osgi.framework.BundleEvent.STOPPED),
+                new BundleEvent(symbolicName, "1.0",
+                    org.osgi.framework.BundleEvent.STARTED));
+
+            final Bundle b = assertBundle("After uninstalling 1.2", symbolicName,
+                "1.0", Bundle.ACTIVE);
+            assertEquals("Bundle ID must not change after update", bundleId,
+                b.getBundleId());
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java b/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java
index 69c5c73..3b6c7e2 100644
--- a/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java
+++ b/src/test/java/org/apache/sling/installer/it/OsgiInstallerTestBase.java
@@ -171,6 +171,7 @@
     /**
      * @see org.osgi.framework.FrameworkListener#frameworkEvent(org.osgi.framework.FrameworkEvent)
      */
+    @Override
     public void frameworkEvent(FrameworkEvent event) {
         if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
             packageRefreshEventsCount++;
@@ -503,16 +504,16 @@
                 ),
                 systemProperty( "org.ops4j.pax.logging.DefaultServiceLog.level" ).value(paxDebugLevel),
                 provision(
-                        mavenBundle("org.apache.sling", "org.apache.sling.commons.log", "3.0.0"),
-                        mavenBundle("org.apache.sling", "org.apache.sling.commons.logservice", "1.0.2"),
+                        mavenBundle("org.apache.sling", "org.apache.sling.commons.log", "4.0.6"),
+                        mavenBundle("org.apache.sling", "org.apache.sling.commons.logservice", "1.0.6"),
 
-                        mavenBundle("org.slf4j", "slf4j-api", "1.6.4"),
-                        mavenBundle("org.slf4j", "jcl-over-slf4j", "1.6.4"),
-                        mavenBundle("org.slf4j", "log4j-over-slf4j", "1.6.4"),
+                        mavenBundle("org.slf4j", "slf4j-api", "1.7.5"),
+                        mavenBundle("org.slf4j", "jcl-over-slf4j", "1.7.5"),
+                        mavenBundle("org.slf4j", "log4j-over-slf4j", "1.7.5"),
 
-        	            mavenBundle("org.apache.felix", "org.apache.felix.scr", "1.8.2"),
-        	            mavenBundle("org.apache.felix", "org.apache.felix.configadmin", "1.8.0"),
-                        mavenBundle("org.apache.felix", "org.apache.felix.metatype", "1.0.10"),
+        	            mavenBundle("org.apache.felix", "org.apache.felix.scr", "2.0.6"),
+        	            mavenBundle("org.apache.felix", "org.apache.felix.configadmin", "1.8.10"),
+                        mavenBundle("org.apache.felix", "org.apache.felix.metatype", "1.1.2"),
         	        	mavenBundle("org.apache.sling", "org.apache.sling.installer.core", POM_VERSION).startLevel(5),
                         mavenBundle("org.apache.sling", "org.apache.sling.installer.factory.configuration", CONFIG_VERSION).startLevel(5)
         		)
@@ -618,6 +619,7 @@
 
         private final List<BundleEvent> events = new ArrayList<BundleEvent>();
 
+        @Override
         public void bundleChanged(org.osgi.framework.BundleEvent event) {
             synchronized ( this ) {
                 events.add(new BundleEvent(event.getBundle().getSymbolicName(), event.getBundle().getVersion().toString(), event.getType()));
diff --git a/src/test/resources/blacklisttest/sling_bootstrap.txt b/src/test/resources/blacklisttest/sling_bootstrap.txt
new file mode 100644
index 0000000..1e3e2df
--- /dev/null
+++ b/src/test/resources/blacklisttest/sling_bootstrap.txt
@@ -0,0 +1 @@
+uninstall osgi-installer-testbundle [1.1,1.2)
\ No newline at end of file
diff --git a/src/test/resources/blacklisttestempty/sling_bootstrap.txt b/src/test/resources/blacklisttestempty/sling_bootstrap.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/blacklisttestempty/sling_bootstrap.txt
diff --git a/src/test/resources/sling_bootstrap.txt b/src/test/resources/sling_bootstrap.txt
new file mode 100644
index 0000000..1e3e2df
--- /dev/null
+++ b/src/test/resources/sling_bootstrap.txt
@@ -0,0 +1 @@
+uninstall osgi-installer-testbundle [1.1,1.2)
\ No newline at end of file