Skip to content

Commit

Permalink
Do not use PackageAdmin for refresh bundles
Browse files Browse the repository at this point in the history
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
  • Loading branch information
laeubi committed Dec 30, 2023
1 parent dc136d3 commit 2f4b5e5
Showing 1 changed file with 11 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void install(URL url, boolean exclusiveMode) throws IOException {
}

Set<Bundle> prevouslyResolved = getResolvedBundles();
Collection<Bundle> toRefresh = new ArrayList<>();
Collection<Bundle> toRefresh = new LinkedHashSet<>();
Collection<Bundle> toStart = new ArrayList<>();
if (exclusiveMode) {
toRefresh.addAll(installBundles(expectedState, toStart));
Expand All @@ -109,24 +109,17 @@ 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);
}
}

refreshPackages(toRefresh);
refreshPackages(getAdditionalRefresh(prevouslyResolved, toRefresh));
}
}

startBundles(toStart.toArray(new Bundle[toStart.size()]));
}

private Bundle[] getAdditionalRefresh(Set<Bundle> previouslyResolved, Collection<Bundle> toRefresh) {
private Collection<Bundle> getAdditionalRefresh(Set<Bundle> previouslyResolved, Collection<Bundle> toRefresh) {
// This is the luna equinox framework or a non-equinox framework.
// Use standard OSGi API.
final Set<Bundle> additionalRefresh = new HashSet<>();
final Set<Bundle> 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) {
Expand All @@ -147,7 +140,7 @@ private Bundle[] getAdditionalRefresh(Set<Bundle> previouslyResolved, Collection
if (foundPayLoadReq) {
Collection<BundleCapability> 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());
}
}
Expand Down Expand Up @@ -201,7 +194,7 @@ private Bundle[] getAdditionalRefresh(Set<Bundle> previouslyResolved, Collection
}
}
}
return additionalRefresh.toArray(new Bundle[additionalRefresh.size()]);
return additionalRefresh;
}

private BundleWiring getHostWiring(BundleWiring wiring) {
Expand Down Expand Up @@ -235,19 +228,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<Bundle> getDoNotRefresh() {
Expand Down Expand Up @@ -435,49 +416,22 @@ 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<Bundle> 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<Bundle> 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);
FrameworkListener listener = event -> {
if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
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) {
Expand Down

0 comments on commit 2f4b5e5

Please sign in to comment.