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