in src/main/java/org/apache/sling/feature/analyser/task/impl/CheckBundleExportsImports.java [62:146]
public void execute(final AnalyserTaskContext ctx) throws IOException {
// basic checks
final Map<BundleDescriptor, Report> reports = new HashMap<>();
final SortedMap<Integer, List<BundleDescriptor>> bundlesMap = new TreeMap<>();
for (final BundleDescriptor bi : ctx.getFeatureDescriptor().getBundleDescriptors()) {
bundlesMap
.computeIfAbsent(bi.getArtifact().getStartOrder(), key -> new ArrayList<>())
.add(bi);
}
// add all system packages
final List<BundleDescriptor> exportingBundles = new ArrayList<>();
if (ctx.getFrameworkDescriptor() != null) {
exportingBundles.add(ctx.getFrameworkDescriptor());
}
for (final Map.Entry<Integer, List<BundleDescriptor>> entry : bundlesMap.entrySet()) {
// first add all exporting bundles
for (final BundleDescriptor info : entry.getValue()) {
if (!info.getExportedPackages().isEmpty()) {
exportingBundles.add(info);
}
}
// check importing bundles
for (final BundleDescriptor info : entry.getValue()) {
for (final PackageInfo pck : info.getImportedPackages()) {
final List<BundleDescriptor> candidates = getCandidates(exportingBundles, pck);
if (candidates.isEmpty()) {
if (pck.isOptional()) {
getReport(reports, info).missingExportsForOptional.add(pck);
} else {
getReport(reports, info).missingExports.add(pck);
}
} else {
final List<BundleDescriptor> matchingCandidates = new ArrayList<>();
for (final BundleDescriptor i : candidates) {
if (i.isExportingPackage(pck)) {
matchingCandidates.add(i);
}
}
if (matchingCandidates.isEmpty()) {
if (pck.isOptional()) {
getReport(reports, info)
.missingExportsForOptional
.add(pck);
} else {
getReport(reports, info)
.missingExportsWithVersion
.add(pck);
}
} else if (matchingCandidates.size() > 1) {
getReport(reports, info).exportMatchingSeveral.add(pck);
}
}
}
}
}
boolean errorReported = false;
for (final Map.Entry<BundleDescriptor, Report> entry : reports.entrySet()) {
if (!entry.getValue().missingExports.isEmpty()) {
ctx.reportArtifactError(
entry.getKey().getArtifact().getId(),
"Bundle is importing " + getPackageInfo(entry.getValue().missingExports, false)
+ " with start order "
+ String.valueOf(entry.getKey().getArtifact().getStartOrder())
+ " but no bundle is exporting these for that start order.");
errorReported = true;
}
if (!entry.getValue().missingExportsWithVersion.isEmpty()) {
ctx.reportArtifactError(
entry.getKey().getArtifact().getId(),
"Bundle is importing "
+ getPackageInfo(entry.getValue().missingExportsWithVersion, true)
+ " with start order "
+ String.valueOf(entry.getKey().getArtifact().getStartOrder())
+ " but no bundle is exporting these for that start order in the required version range.");
errorReported = true;
}
}
if (errorReported && ctx.getFeature().isComplete()) {
ctx.reportError(ctx.getFeature().getId().toMvnId() + " is marked as 'complete' but has missing imports.");
}
}