in src/main/java/org/apache/sling/feature/analyser/task/impl/CheckRequirementsCapabilities.java [51:144]
public void execute(AnalyserTaskContext ctx) throws Exception {
final SortedMap<Integer, List<Descriptor>> artifactsMap = new TreeMap<>();
for(final BundleDescriptor bi : ctx.getFeatureDescriptor().getBundleDescriptors()) {
List<Descriptor> list = getDescriptorList(bi.getArtifact().getStartOrder(), artifactsMap);
list.add(bi);
}
if (!ctx.getFeatureDescriptor().getArtifactDescriptors().isEmpty()) {
artifactsMap.put(
(artifactsMap.isEmpty() ? 0 : artifactsMap.lastKey()) + 1,
new ArrayList<>(ctx.getFeatureDescriptor().getArtifactDescriptors())
);
}
String featureMavenID = ctx.getFeature().getId().toMvnId();
// Add descriptor for feature capabilties. These are added at start level 0
Descriptor featureCaps = new ReqCapDescriptor(featureMavenID);
featureCaps.getCapabilities().addAll(ctx.getFeature().getCapabilities());
getDescriptorList(0, artifactsMap).add(featureCaps);
// Add descriptor for feature requirements. These are added at the highest start level found
Descriptor featureReqs = new ReqCapDescriptor(featureMavenID);
featureReqs.getRequirements().addAll(ctx.getFeature().getRequirements());
Integer highestStartLevel = artifactsMap.lastKey();
getDescriptorList(highestStartLevel, artifactsMap).add(featureReqs);
// add system artifact
final List<Descriptor> artifacts = new ArrayList<>();
if ( ctx.getFrameworkDescriptor() != null ) {
artifacts.add(ctx.getFrameworkDescriptor());
}
boolean errorReported = false;
for(final Map.Entry<Integer, List<Descriptor>> entry : artifactsMap.entrySet()) {
// first add all providing artifacts
for (final Descriptor info : entry.getValue()) {
if (info.getCapabilities() != null) {
artifacts.add(info);
}
}
// check requiring artifacts
for (final Descriptor info : entry.getValue()) {
if (info.getRequirements() != null)
{
for (Requirement requirement : info.getRequirements()) {
String ns = requirement.getNamespace();
// Package namespace is handled by the CheckBundleExportsImports analyzer.
// Service namespace is special - we don't provide errors or warnings in this case
if (!BundleRevision.PACKAGE_NAMESPACE.equals(ns) && !ServiceNamespace.SERVICE_NAMESPACE.equals(ns))
{
List<Descriptor> candidates = getCandidates(artifacts, requirement);
if (candidates.isEmpty())
{
if (!RequirementImpl.isOptional(requirement))
{
String message = String.format(format, info.getName(), requirement.toString(), entry.getKey(), "no artifact is providing a matching capability in this start level.");
if (info instanceof ArtifactDescriptor) {
ctx.reportArtifactError(((ArtifactDescriptor) info).getArtifact().getId(), message);
} else {
ctx.reportError(message);
}
errorReported = true;
}
else
{
String message = String.format(format, info.getName(), requirement.toString(), entry.getKey(), "while the requirement is optional no artifact is providing a matching capability in this start level.");
if (info instanceof ArtifactDescriptor) {
ctx.reportArtifactWarning(((ArtifactDescriptor) info).getArtifact().getId(), message);
} else {
ctx.reportWarning(message);
}
}
}
else if (candidates.size() > 1)
{
String message = String.format(format, info.getName(), requirement.toString(), entry.getKey(), "there is more than one matching capability in this start level: " + candidates);
if (info instanceof ArtifactDescriptor) {
ctx.reportArtifactWarning(((ArtifactDescriptor) info).getArtifact().getId(), message);
} else {
ctx.reportWarning(message);
}
}
}
}
}
}
}
if (errorReported && ctx.getFeature().isComplete()) {
ctx.reportError(ctx.getFeature().getId().toMvnId() + " is marked as 'complete' but has unsatisfied requirements.");
}
}