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();
}
}
}