This is an automated email from the ASF dual-hosted git repository.

sagarmiglani pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-launchpad-base.git


The following commit(s) were added to refs/heads/master by this push:
     new 639339f  SLING-12829 - Sling launchpad ignores startlevel change of 
startup di… (#16)
639339f is described below

commit 639339f384fb44b993bee93f2af4ffafa33ef398
Author: Sagar Miglani <[email protected]>
AuthorDate: Mon Jun 23 13:20:19 2025 +0530

    SLING-12829 - Sling launchpad ignores startlevel change of startup di… (#16)
    
    * SLING-12829 - Sling launchpad ignores startlevel change of startup 
directory bundles
    
    * SLING-12829 - Sling launchpad ignores startlevel change of startup 
directory bundles
    
    * SLING-12829 - Sling launchpad ignores startlevel change of startup 
directory bundles
    
    * SLING-12829 - test ignore method
    
    * SLING-12829 - spotless fixes
    
    * SLING-12829 - unused variable
    
    ---------
    
    Co-authored-by: Sagar Miglani <[email protected]>
---
 .../launchpad/base/impl/BootstrapInstaller.java    |  12 +-
 .../base/impl/BootstrapInstallerTest.java          | 211 +++++++++++++++++++++
 2 files changed, 221 insertions(+), 2 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/launchpad/base/impl/BootstrapInstaller.java 
b/src/main/java/org/apache/sling/launchpad/base/impl/BootstrapInstaller.java
index a2239b0..103ce54 100644
--- a/src/main/java/org/apache/sling/launchpad/base/impl/BootstrapInstaller.java
+++ b/src/main/java/org/apache/sling/launchpad/base/impl/BootstrapInstaller.java
@@ -446,7 +446,7 @@ class BootstrapInstaller {
 
         // check for an installed Bundle with the symbolic name
         Bundle installedBundle = currentBundles.get(symbolicName);
-        if (ignore(installedBundle, manifest)) {
+        if (ignore(installedBundle, startLevel, manifest)) {
             logger.log(Logger.LOG_INFO, "Ignoring " + bundleJar + ": More 
recent version already installed");
             return false; // SHORT CIRCUIT
         }
@@ -602,7 +602,7 @@ class BootstrapInstaller {
      * @return <code>true</code> if the manifest does not describe a bundle 
with
      *         a higher version number.
      */
-    private boolean ignore(final Bundle installedBundle, final Manifest 
manifest) {
+    private boolean ignore(final Bundle installedBundle, int startLevel, final 
Manifest manifest) {
 
         // the bundle is not installed yet, so we have to install it
         if (installedBundle == null) {
@@ -624,6 +624,14 @@ class BootstrapInstaller {
             return false;
         }
 
+        if (newVersion.equals(installedVersion)) {
+            int installedBundleStartLevel =
+                    
installedBundle.adapt(BundleStartLevel.class).getStartLevel();
+            if (startLevel != installedBundleStartLevel) {
+                return false;
+            }
+        }
+
         return newVersion.compareTo(installedVersion) <= 0;
     }
 
diff --git 
a/src/test/java/org/apache/sling/launchpad/base/impl/BootstrapInstallerTest.java
 
b/src/test/java/org/apache/sling/launchpad/base/impl/BootstrapInstallerTest.java
index 5003c90..1d6eb85 100644
--- 
a/src/test/java/org/apache/sling/launchpad/base/impl/BootstrapInstallerTest.java
+++ 
b/src/test/java/org/apache/sling/launchpad/base/impl/BootstrapInstallerTest.java
@@ -23,10 +23,25 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
 
+import org.apache.felix.framework.Logger;
+import org.apache.sling.launchpad.api.LaunchpadContentProvider;
+import org.apache.sling.launchpad.api.StartupMode;
 import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.startlevel.BundleStartLevel;
 
 import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 /**
  * Testing the bootstrap installer methods
@@ -184,6 +199,202 @@ public class BootstrapInstallerTest {
         assertFalse(BootstrapInstaller.isBlank(" asdf "));
     }
 
+    @Test
+    public void testIgnoreSameVersionSameStartLevel()
+            throws NoSuchMethodException, InvocationTargetException, 
IllegalAccessException {
+
+        // prepare for invoking the installBundle method
+        BundleContext mockBundleContext = mock(BundleContext.class);
+        Logger mockLogger = mock(Logger.class);
+        LaunchpadContentProvider mockLaunchpadContentProvider = 
mock(LaunchpadContentProvider.class);
+        BootstrapInstaller bsi =
+                new BootstrapInstaller(mockBundleContext, mockLogger, 
mockLaunchpadContentProvider, StartupMode.UPDATE);
+
+        Method ignoreMethod =
+                BootstrapInstaller.class.getDeclaredMethod("ignore", 
Bundle.class, int.class, Manifest.class);
+        ignoreMethod.setAccessible(true);
+
+        // prepare already installed bundle
+        Bundle mockInstalledBundle = mock(Bundle.class);
+        Dictionary<String, String> headers = new Hashtable<>();
+        headers.put(Constants.BUNDLE_VERSION, "1.1.0");
+        when(mockInstalledBundle.getSymbolicName()).thenReturn("test.bundle");
+        when(mockInstalledBundle.getHeaders()).thenReturn(headers);
+
+        BundleStartLevel mockBundleStartLevel = mock(BundleStartLevel.class);
+        
when(mockInstalledBundle.adapt(BundleStartLevel.class)).thenReturn(mockBundleStartLevel);
+        when(mockBundleStartLevel.getStartLevel()).thenReturn(1);
+
+        // new bundle to install
+        Attributes mockNewBundleAttributes = mock(Attributes.class);
+        
when(mockNewBundleAttributes.getValue(Constants.BUNDLE_VERSION)).thenReturn("1.1.0");
+        Manifest mockNewBundleManifest = mock(Manifest.class);
+        
when(mockNewBundleManifest.getMainAttributes()).thenReturn(mockNewBundleAttributes);
+
+        assertTrue((Boolean) ignoreMethod.invoke(bsi, mockInstalledBundle, 1, 
mockNewBundleManifest));
+    }
+
+    @Test
+    public void testIgnoreSnapshotVersion()
+            throws NoSuchMethodException, InvocationTargetException, 
IllegalAccessException {
+
+        // prepare for invoking the installBundle method
+        BundleContext mockBundleContext = mock(BundleContext.class);
+        Logger mockLogger = mock(Logger.class);
+        LaunchpadContentProvider mockLaunchpadContentProvider = 
mock(LaunchpadContentProvider.class);
+        BootstrapInstaller bsi =
+                new BootstrapInstaller(mockBundleContext, mockLogger, 
mockLaunchpadContentProvider, StartupMode.UPDATE);
+
+        Method ignoreMethod =
+                BootstrapInstaller.class.getDeclaredMethod("ignore", 
Bundle.class, int.class, Manifest.class);
+        ignoreMethod.setAccessible(true);
+
+        // prepare already installed bundle
+        Bundle mockInstalledBundle = mock(Bundle.class);
+        Dictionary<String, String> headers = new Hashtable<>();
+        headers.put(Constants.BUNDLE_VERSION, "1.1.0");
+        when(mockInstalledBundle.getSymbolicName()).thenReturn("test.bundle");
+        when(mockInstalledBundle.getHeaders()).thenReturn(headers);
+
+        BundleStartLevel mockBundleStartLevel = mock(BundleStartLevel.class);
+        
when(mockInstalledBundle.adapt(BundleStartLevel.class)).thenReturn(mockBundleStartLevel);
+        when(mockBundleStartLevel.getStartLevel()).thenReturn(1);
+
+        // new bundle to install
+        Attributes mockNewBundleAttributes = mock(Attributes.class);
+        
when(mockNewBundleAttributes.getValue(Constants.BUNDLE_VERSION)).thenReturn("1.1.0.SNAPSHOT");
+        Manifest mockNewBundleManifest = mock(Manifest.class);
+        
when(mockNewBundleManifest.getMainAttributes()).thenReturn(mockNewBundleAttributes);
+
+        assertFalse((Boolean) ignoreMethod.invoke(bsi, mockInstalledBundle, 1, 
mockNewBundleManifest));
+    }
+
+    @Test
+    public void testIgnoreDifferentStartLevel()
+            throws NoSuchMethodException, InvocationTargetException, 
IllegalAccessException {
+
+        // prepare for invoking the installBundle method
+        BundleContext mockBundleContext = mock(BundleContext.class);
+        Logger mockLogger = mock(Logger.class);
+        LaunchpadContentProvider mockLaunchpadContentProvider = 
mock(LaunchpadContentProvider.class);
+        BootstrapInstaller bsi =
+                new BootstrapInstaller(mockBundleContext, mockLogger, 
mockLaunchpadContentProvider, StartupMode.UPDATE);
+
+        Method ignoreMethod =
+                BootstrapInstaller.class.getDeclaredMethod("ignore", 
Bundle.class, int.class, Manifest.class);
+        ignoreMethod.setAccessible(true);
+
+        // prepare already installed bundle
+        Bundle mockInstalledBundle = mock(Bundle.class);
+        Dictionary<String, String> headers = new Hashtable<>();
+        headers.put(Constants.BUNDLE_VERSION, "1.1.0");
+        when(mockInstalledBundle.getSymbolicName()).thenReturn("test.bundle");
+        when(mockInstalledBundle.getHeaders()).thenReturn(headers);
+
+        BundleStartLevel mockBundleStartLevel = mock(BundleStartLevel.class);
+        
when(mockInstalledBundle.adapt(BundleStartLevel.class)).thenReturn(mockBundleStartLevel);
+        when(mockBundleStartLevel.getStartLevel()).thenReturn(20);
+
+        // new bundle to install
+        Attributes mockNewBundleAttributes = mock(Attributes.class);
+        
when(mockNewBundleAttributes.getValue(Constants.BUNDLE_VERSION)).thenReturn("1.1.0");
+        Manifest mockNewBundleManifest = mock(Manifest.class);
+        
when(mockNewBundleManifest.getMainAttributes()).thenReturn(mockNewBundleAttributes);
+
+        assertFalse((Boolean) ignoreMethod.invoke(bsi, mockInstalledBundle, 1, 
mockNewBundleManifest));
+    }
+
+    @Test
+    public void testIgnoreNewBundleHigherVersion()
+            throws NoSuchMethodException, InvocationTargetException, 
IllegalAccessException {
+
+        // prepare for invoking the installBundle method
+        BundleContext mockBundleContext = mock(BundleContext.class);
+        Logger mockLogger = mock(Logger.class);
+        LaunchpadContentProvider mockLaunchpadContentProvider = 
mock(LaunchpadContentProvider.class);
+        BootstrapInstaller bsi =
+                new BootstrapInstaller(mockBundleContext, mockLogger, 
mockLaunchpadContentProvider, StartupMode.UPDATE);
+
+        Method ignoreMethod =
+                BootstrapInstaller.class.getDeclaredMethod("ignore", 
Bundle.class, int.class, Manifest.class);
+        ignoreMethod.setAccessible(true);
+
+        // prepare already installed bundle
+        Bundle mockInstalledBundle = mock(Bundle.class);
+        Dictionary<String, String> headers = new Hashtable<>();
+        headers.put(Constants.BUNDLE_VERSION, "1.1.0");
+        when(mockInstalledBundle.getSymbolicName()).thenReturn("test.bundle");
+        when(mockInstalledBundle.getHeaders()).thenReturn(headers);
+
+        BundleStartLevel mockBundleStartLevel = mock(BundleStartLevel.class);
+        
when(mockInstalledBundle.adapt(BundleStartLevel.class)).thenReturn(mockBundleStartLevel);
+        when(mockBundleStartLevel.getStartLevel()).thenReturn(1);
+
+        // new bundle to install
+        Attributes mockNewBundleAttributes = mock(Attributes.class);
+        
when(mockNewBundleAttributes.getValue(Constants.BUNDLE_VERSION)).thenReturn("1.2.0");
+        Manifest mockNewBundleManifest = mock(Manifest.class);
+        
when(mockNewBundleManifest.getMainAttributes()).thenReturn(mockNewBundleAttributes);
+
+        assertFalse((Boolean) ignoreMethod.invoke(bsi, mockInstalledBundle, 1, 
mockNewBundleManifest));
+    }
+
+    @Test
+    public void testIgnoreNewBundleLowerVersion()
+            throws NoSuchMethodException, InvocationTargetException, 
IllegalAccessException {
+
+        // prepare for invoking the installBundle method
+        BundleContext mockBundleContext = mock(BundleContext.class);
+        Logger mockLogger = mock(Logger.class);
+        LaunchpadContentProvider mockLaunchpadContentProvider = 
mock(LaunchpadContentProvider.class);
+        BootstrapInstaller bsi =
+                new BootstrapInstaller(mockBundleContext, mockLogger, 
mockLaunchpadContentProvider, StartupMode.UPDATE);
+
+        Method ignoreMethod =
+                BootstrapInstaller.class.getDeclaredMethod("ignore", 
Bundle.class, int.class, Manifest.class);
+        ignoreMethod.setAccessible(true);
+
+        // prepare already installed bundle
+        Bundle mockInstalledBundle = mock(Bundle.class);
+        Dictionary<String, String> headers = new Hashtable<>();
+        headers.put(Constants.BUNDLE_VERSION, "1.1.0");
+        when(mockInstalledBundle.getSymbolicName()).thenReturn("test.bundle");
+        when(mockInstalledBundle.getHeaders()).thenReturn(headers);
+
+        BundleStartLevel mockBundleStartLevel = mock(BundleStartLevel.class);
+        
when(mockInstalledBundle.adapt(BundleStartLevel.class)).thenReturn(mockBundleStartLevel);
+        when(mockBundleStartLevel.getStartLevel()).thenReturn(1);
+
+        // new bundle to install
+        Attributes mockNewBundleAttributes = mock(Attributes.class);
+        
when(mockNewBundleAttributes.getValue(Constants.BUNDLE_VERSION)).thenReturn("1.0.0");
+        Manifest mockNewBundleManifest = mock(Manifest.class);
+        
when(mockNewBundleManifest.getMainAttributes()).thenReturn(mockNewBundleAttributes);
+
+        assertTrue((Boolean) ignoreMethod.invoke(bsi, mockInstalledBundle, 1, 
mockNewBundleManifest));
+    }
+
+    @Test
+    public void testIgnoreNewBundleInstallation()
+            throws NoSuchMethodException, InvocationTargetException, 
IllegalAccessException {
+
+        // prepare for invoking the installBundle method
+        BundleContext mockBundleContext = mock(BundleContext.class);
+        Logger mockLogger = mock(Logger.class);
+        LaunchpadContentProvider mockLaunchpadContentProvider = 
mock(LaunchpadContentProvider.class);
+        BootstrapInstaller bsi =
+                new BootstrapInstaller(mockBundleContext, mockLogger, 
mockLaunchpadContentProvider, StartupMode.UPDATE);
+
+        Method ignoreMethod =
+                BootstrapInstaller.class.getDeclaredMethod("ignore", 
Bundle.class, int.class, Manifest.class);
+        ignoreMethod.setAccessible(true);
+
+        // new bundle to install
+        Manifest mockNewBundleManifest = mock(Manifest.class);
+
+        assertFalse((Boolean) ignoreMethod.invoke(bsi, null, 1, 
mockNewBundleManifest));
+    }
+
     // TODO eventually add in tests that create a context so we can test more
     // things in detail
 

Reply via email to