public static ReferenceWithError install()

in core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynCatalogBundleResolvers.java [107:219]


    public static ReferenceWithError<OsgiBundleInstallationResult> install(ManagementContext mgmt, Supplier<InputStream> input,
                                                                           BundleInstallationOptions options) {
        LOG.debug("Installing bundle {} / {} for {}", input, (options==null ? null : options.knownBundleMetadata), Entitlements.getEntitlementContextUser());
        PrepareInstallResult prepareResult = null;
        if (input==null && options.knownBundleMetadata==null) {
            return ReferenceWithError.newInstanceThrowingError(null, new IllegalArgumentException("Bundle contents or reference must be supplied"));
        }
        if (input==null && options.knownBundleMetadata!=null) {
            try {
                // installing to brooklyn a bundle already installed to OSGi
                prepareResult = BrooklynBomOsgiArchiveInstaller.prepareInstall(mgmt, options.knownBundleMetadata, null, input, options.forceUpdateOfNonSnapshots, null);
                if (prepareResult.resultObject != null) {
                    return ReferenceWithError.newInstanceWithoutError(prepareResult.resultObject);
                }

                if (prepareResult.zipFile != null) {
                    input = InputStreamSource.of(prepareResult.zipFile.getFile().getName(), prepareResult.zipFile.getFile());
                } else {
                    return ReferenceWithError.newInstanceThrowingError(null, new IllegalArgumentException("Bundle contents or known reference must be supplied; " +
                            options.knownBundleMetadata + " not known"));
                }
            } catch (Exception e) {
                Exceptions.propagateIfFatal(e);
                return ReferenceWithError.newInstanceThrowingError(null, e);
            }
        }

        OsgiBundleInstallationResult firstResult = null;
        try {
            Map<BrooklynCatalogBundleResolver, Double> resolvers = forBundleWithScore(mgmt, input, options);
            Collection<String> resolversWhoDontSupport = new ArrayList<String>();
            Map<BrooklynCatalogBundleResolver, Exception> failuresFromResolvers = MutableMap.of();
            Double highestFailedScore = null;
            for (Entry<BrooklynCatalogBundleResolver,Double> ti : resolvers.entrySet()) {
                BrooklynCatalogBundleResolver t = ti.getKey();
                try {
                    ReferenceWithError<OsgiBundleInstallationResult> result = t.install(input, options);
                    if (result == null) {
                        resolversWhoDontSupport.add(t.getFormatCode() + " (returned null)");
                        continue;
                    }
                    if (firstResult == null) {
                        // capture the first result for more info; but do not return, as it is subsumed in error messages, and is not the most useful error
                        firstResult = result.getWithoutError();
                    }
                    result.get();  // assert there is no error
                    LOG.debug("Installed bundle {} / {} for {}: {}: {}", input, (options==null ? null : options.knownBundleMetadata), Entitlements.getEntitlementContextUser(), result.get().getCode(), result.get().getMessage());
                    if (highestFailedScore!=null) {
                        if (highestFailedScore > 0.9 && (ti.getValue() == null || highestFailedScore > ti.getValue() + 0.1)) {
                            // if there was an error from a high scoring resolver and a lower-scoring resolver accepted it, log a warning
                            LOG.warn("Bundle {} was installed by fallback resolver {} because preferred resolver(s) reported issues: {} / {} (scores {})",
                                    t, result.get().getMetadata(), resolversWhoDontSupport, failuresFromResolvers, resolvers);
                        } else {
                            // if there was an error from a high scoring resolver and a lower-scoring resolver accepted it, log a warning
                            LOG.debug("Bundle {} was installed by resolver {} after other resolver(s) reported issues: {} / {} (scores {})",
                                    t, result.get().getMetadata(), resolversWhoDontSupport, failuresFromResolvers, resolvers);
                        }
                    }
                    return result;
                } catch (@SuppressWarnings("deprecation") UnsupportedCatalogBundleException e) {
                    resolversWhoDontSupport.add(t.getFormatCode() +
                            (Strings.isNonBlank(e.getMessage()) ? " (" + e.getMessage() + ")" : ""));
                } catch (Throwable e) {
                    Exceptions.propagateIfFatal(e);
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Resolver for " + t.getFormatCode() + " gave an error creating this plan (may retry): " + e, e);
                    }
                    failuresFromResolvers.put(t, new PropagatedRuntimeException(
                            (t.getFormatCode() + " bundle installation error") + ": " +
                                    Exceptions.collapseText(e), e));
                }
                if (highestFailedScore==null) highestFailedScore = ti.getValue();
            }

            if (LOG.isDebugEnabled()) {
                LOG.debug("Failure resolving bundle; returning summary failure, but for reference "
                        + "potentially applicable resolvers were " + resolvers + " "
                        + "(available ones are " + MutableList.builder().addAll(all(mgmt)).build() + ")"
                        + (failuresFromResolvers.isEmpty() ? "" : "; failures: " + failuresFromResolvers)
                        + (resolversWhoDontSupport.isEmpty() ? "" : "; unsupported by: "+resolversWhoDontSupport)
                        + (firstResult==null ? "" : "; error result: "+firstResult));
            }

            // failed
            Exception exception;
            if (!failuresFromResolvers.isEmpty()) {
                // at least one thought he could do it
                Double score = resolvers.get(failuresFromResolvers.keySet().iterator().next());
                double minScore = score==null ? 0 : score/2;
                // ignore those which are < 1/2 the best score; they're probably items of last resort
                List<Exception> interestingFailures = failuresFromResolvers.entrySet().stream().filter(entry -> Maybe.ofDisallowingNull(resolvers.get(entry.getKey())).or(0d) > minScore).map(entry -> entry.getValue()).collect(Collectors.toList());
                exception = interestingFailures.size() == 1 ? Exceptions.create(null, interestingFailures) :
                        Exceptions.create("All applicable bundle resolvers failed", interestingFailures);
            } else {
                String prefix = Strings.isBlank(options.format) ? "Invalid bundle" : "Invalid '"+options.format+"' bundle";
                if (resolvers.isEmpty()) {
                    exception = new UnsupportedTypePlanException(prefix + "; format could not be recognized, none of the available resolvers " + all(mgmt) + " support it");
                } else {
                    exception = new UnsupportedTypePlanException(prefix + "; potentially applicable resolvers " + resolvers + " do not support it, and other available resolvers " +
//                    // the removeAll call below won't work until "all" caches it
//                    MutableList.builder().addAll(all(mgmt)).removeAll(transformers).build()+" "+
                            "do not accept it");
                }
            }
            return ReferenceWithError.newInstanceThrowingError(null, exception);
        } catch (Exception e) {
            return ReferenceWithError.newInstanceThrowingError(null, e);
        } finally {
            if (prepareResult!=null && prepareResult.zipFile!=null) {
                prepareResult.zipFile.deleteIfTemp();
            }
        }
    }