+ public void blueprintEvent(final BlueprintEvent event) {
+ if (event.getType() == BlueprintEvent.CREATED) {
+ LOG.info("Blueprint container for bundle {} was successfully created", event.getBundle());
+ return;
+ }
+
+ // If the container timed out waiting for dependencies, we'll destroy it and start it again. This
+ // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
+ // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
+ // be set at the bundle level in the manifest - there's no way to set it globally.
+ if (event.getType() == BlueprintEvent.FAILURE && event.getDependencies() != null) {
+ Bundle bundle = event.getBundle();
+
+ List<Object> paths = findBlueprintPaths(bundle);
+ if (!paths.isEmpty()) {
+ LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
+ bundle);
+
+ restartService.restartContainer(bundle, paths);
+ }
+ }
+ }
+
+ static List<Object> findBlueprintPaths(final Bundle bundle) {
+ List<Object> paths = findBlueprintPaths(bundle, STANDARD_BLUEPRINT_FILE_PATH);
+ return !paths.isEmpty() ? paths : findBlueprintPaths(bundle, ODL_CUSTOM_BLUEPRINT_FILE_PATH);
+ }
+
+ private static List<Object> findBlueprintPaths(final Bundle bundle, final String path) {
+ Enumeration<?> rntries = bundle.findEntries(path, BLUEPRINT_FLE_PATTERN, false);
+ if (rntries == null) {
+ return List.of();
+ } else {
+ return List.copyOf(Collections.list(rntries));
+ }
+ }
+
+ private void shutdownAllContainers() {
+ shuttingDown = true;
+
+ restartService.close();
+
+ LOG.info("Shutting down all blueprint containers...");
+
+ Collection<Bundle> containerBundles = new HashSet<>(Arrays.asList(bundleContext.getBundles()));
+ while (!containerBundles.isEmpty()) {
+ // For each iteration of getBundlesToDestroy, as containers are destroyed, other containers become
+ // eligible to be destroyed. We loop until we've destroyed them all.
+ for (Bundle bundle : getBundlesToDestroy(containerBundles)) {
+ containerBundles.remove(bundle);
+ BlueprintContainer container = blueprintExtenderService.getContainer(bundle);
+ if (container != null) {
+ blueprintExtenderService.destroyContainer(bundle, container);
+ }
+ }