From 1b21340cef3b1cdcc22ccf687835be9e925cc344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sat, 30 Dec 2023 09:59:36 +0100 Subject: [PATCH] Do not use PackageAdmin for refresh bundles Currently there are two ways to refresh packages, one using the deprecated PackageAdmin and one using the FrameworkWiring. This do the following: - always use FrameworkWiring - use collections over arrays - remove some redundant checks and copy of collections --- .../simpleconfigurator/ConfigApplier.java | 73 ++++++------------- 1 file changed, 21 insertions(+), 52 deletions(-) diff --git a/bundles/org.eclipse.equinox.simpleconfigurator/src/org/eclipse/equinox/internal/simpleconfigurator/ConfigApplier.java b/bundles/org.eclipse.equinox.simpleconfigurator/src/org/eclipse/equinox/internal/simpleconfigurator/ConfigApplier.java index f543127b43..c4637d9e59 100644 --- a/bundles/org.eclipse.equinox.simpleconfigurator/src/org/eclipse/equinox/internal/simpleconfigurator/ConfigApplier.java +++ b/bundles/org.eclipse.equinox.simpleconfigurator/src/org/eclipse/equinox/internal/simpleconfigurator/ConfigApplier.java @@ -19,6 +19,7 @@ import java.net.*; import java.util.*; import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.equinox.internal.simpleconfigurator.utils.*; import org.eclipse.osgi.report.resolution.ResolutionReport.Entry.Type; @@ -105,7 +106,7 @@ void install(URL url, boolean exclusiveMode) throws IOException { } Set prevouslyResolved = getResolvedBundles(); - Collection toRefresh = new ArrayList<>(); + Collection toRefresh = new LinkedHashSet<>(); Collection toStart = new ArrayList<>(); if (exclusiveMode) { toRefresh.addAll(installBundles(expectedState, toStart)); @@ -123,12 +124,19 @@ void install(URL url, boolean exclusiveMode) throws IOException { } else { // In this case the platform is up, we should try to do an incremental resolve // TODO consider removing this case because it can cause inconsistent results. - refreshPackages(toRefresh.toArray(new Bundle[toRefresh.size()]), manipulatingContext); - if (toRefresh.size() > 0) { - Bundle[] additionalRefresh = getAdditionalRefresh(prevouslyResolved, toRefresh); - if (additionalRefresh.length > 0) - refreshPackages(additionalRefresh, manipulatingContext); + Map> bundlesByBsn = Arrays.stream(manipulatingContext.getBundles()) + .filter(bundle -> bundle.getSymbolicName() != null) + .collect(Collectors.groupingBy(Bundle::getSymbolicName)); + // Prior to Luna the Equinox framework would refresh all bundles with the same + // BSN automatically. This is no longer the case for Luna or other framework + // implementations. Here we want to make sure all existing bundles with the + // same BSN are refreshed also. + Set allSameBSNs = new LinkedHashSet<>(); // maintain order and avoid duplicates + for (Bundle bundle : toRefresh) { + allSameBSNs.addAll(bundlesByBsn.getOrDefault(bundle.getSymbolicName(), List.of(bundle))); } + refreshPackages(allSameBSNs); + refreshPackages(getAdditionalRefresh(prevouslyResolved, toRefresh)); } if (deepRefresh) { // when refreshing large sets of bundles the resolver sometimes take a choice @@ -218,11 +226,10 @@ private Collection getUnresolvedRequirementsProvider(Set doNotRe .distinct().filter(bundle -> !doNotRefresh.contains(bundle)).toList(); } - private Bundle[] getAdditionalRefresh(Set previouslyResolved, Collection toRefresh) { + private Collection getAdditionalRefresh(Set previouslyResolved, Collection toRefresh) { // This is the luna equinox framework or a non-equinox framework. // Use standard OSGi API. final Set additionalRefresh = new HashSet<>(); - final Set originalRefresh = new HashSet<>(toRefresh); for (Bundle bundle : toRefresh) { BundleRevision revision = bundle.adapt(BundleRevision.class); if (bundle.getState() == Bundle.INSTALLED && revision != null && (revision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) { @@ -243,7 +250,7 @@ private Bundle[] getAdditionalRefresh(Set previouslyResolved, Collection if (foundPayLoadReq) { Collection candidates = frameworkWiring.findProviders(hostReq); for (BundleCapability candidate : candidates) { - if (!originalRefresh.contains(candidate.getRevision().getBundle())) { + if (!toRefresh.contains(candidate.getRevision().getBundle())) { additionalRefresh.add(candidate.getRevision().getBundle()); } } @@ -297,7 +304,7 @@ private Bundle[] getAdditionalRefresh(Set previouslyResolved, Collection } } } - return additionalRefresh.toArray(new Bundle[additionalRefresh.size()]); + return additionalRefresh; } private BundleWiring getHostWiring(BundleWiring wiring) { @@ -331,19 +338,7 @@ private void refreshAllBundles() { toRefresh.add(bundle); } } - - CountDownLatch latch = new CountDownLatch(1); - FrameworkListener listener = event -> { - if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) { - latch.countDown(); - } - }; - frameworkWiring.refreshBundles(toRefresh, listener); - try { - latch.await(); - } catch (InterruptedException e) { - // ignore - } + refreshPackages(toRefresh); } private Set getDoNotRefresh() { @@ -531,26 +526,9 @@ private boolean isFragment(Bundle current) { return (revision != null) && ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0); } - private void refreshPackages(Bundle[] bundles, BundleContext context) { - if (bundles.length == 0 || packageAdminService == null) + private void refreshPackages(Collection bundles) { + if (bundles.isEmpty()) { return; - - // Prior to Luna the Equinox framework would refresh all bundles with the same - // BSN automatically. This is no longer the case for Luna or other framework - // implementations. Here we want to make sure all existing bundles with the - // same BSN are refreshed also. - Set allSameBSNs = new LinkedHashSet<>(); // maintain order and avoid duplicates - for (Bundle bundle : bundles) { - allSameBSNs.add(bundle); - String bsn = bundle.getSymbolicName(); - if (bsn != null) { - // look for others with same BSN - Bundle[] sameBSNs = packageAdminService.getBundles(bsn, null); - if (sameBSNs != null) { - // likely contains the bundle we just added above but a set is used - allSameBSNs.addAll(Arrays.asList(sameBSNs)); - } - } } CountDownLatch latch = new CountDownLatch(1); @@ -559,21 +537,12 @@ private void refreshPackages(Bundle[] bundles, BundleContext context) { latch.countDown(); } }; - context.addFrameworkListener(listener); - packageAdminService.refreshPackages(allSameBSNs.toArray(new Bundle[0])); - + frameworkWiring.refreshBundles(bundles, listener); try { latch.await(); } catch (InterruptedException e) { // ignore } - - // if (DEBUG) { - // for (int i = 0; i < bundles.length; i++) { - // System.out.println(SimpleConfiguratorUtils.getBundleStateString(bundles[i])); - // } - // } - context.removeFrameworkListener(listener); } private void startBundles(Bundle[] bundles) {