in src/main/java/org/apache/sling/feature/builder/FeatureBuilder.java [298:375]
private static Feature internalAssemble(final List<String> processedFeatures,
final Feature feature,
final BuilderContext context) {
if ( feature.isAssembled() ) {
return feature;
}
if ( processedFeatures.contains(feature.getId().toMvnId()) ) {
throw new IllegalStateException("Recursive inclusion of " + feature.getId().toMvnId() + " via " + processedFeatures);
}
processedFeatures.add(feature.getId().toMvnId());
// we copy the feature as we set the assembled flag on the result
final Feature result = feature.copy();
if ( result.getPrototype() != null) {
// clear everything in the result, will be added in the process
result.getVariables().clear();
result.getBundles().clear();
result.getFrameworkProperties().clear();
result.getConfigurations().clear();
result.getRequirements().clear();
result.getCapabilities().clear();
result.setPrototype(null);
result.getExtensions().clear();
final Prototype i = feature.getPrototype();
final Feature f = context.getFeatureProvider().provide(i.getId());
if ( f == null ) {
throw new IllegalStateException("Unable to find prototype feature " + i.getId());
}
if (f.isFinal()) {
throw new IllegalStateException(
"Prototype feature " + i.getId() + " is marked as final and can't be used in a prototype.");
}
final Feature prototypeFeature = internalAssemble(processedFeatures, f, context);
// process prototype instructions
processPrototype(prototypeFeature, i);
// and now merge the prototype feature into the result. No overrides should be needed since the result is empty before
merge(result, prototypeFeature, context, Collections.emptyList(), Collections.emptyMap(), TRACKING_KEY, true, true);
// and merge the current feature over the prototype feature into the result
merge(result, feature, context, Collections.singletonList(
ArtifactId.parse(BuilderUtil.CATCHALL_OVERRIDE + BuilderContext.VERSION_OVERRIDE_ALL)),
Collections.singletonMap("*", BuilderContext.CONFIG_MERGE_LATEST),
TRACKING_KEY, true, false);
for (Artifact a : result.getBundles()) {
a.getMetadata().remove(TRACKING_KEY);
LinkedHashSet<ArtifactId> originList = new LinkedHashSet<>(Arrays.asList(a.getFeatureOrigins()));
originList.remove(prototypeFeature.getId());
originList.add(feature.getId());
a.setFeatureOrigins(originList.toArray(new ArtifactId[0]));
}
for (Extension e : result.getExtensions()) {
if (ExtensionType.ARTIFACTS == e.getType()) {
for (Artifact a : e.getArtifacts()) {
a.getMetadata().remove(TRACKING_KEY);
}
}
}
// correct feature origins
for(final Configuration cfg : result.getConfigurations()) {
final List<ArtifactId> origins = cfg.getFeatureOrigins();
if ( origins.size() == 1 && origins.contains(feature.getId())) {
cfg.setFeatureOrigins(null);
}
}
}
result.setAssembled(true);
processedFeatures.remove(feature.getId().toMvnId());
return result;
}