Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,21 @@ Model importManagement(
List<? extends DependencyManagement> sources,
ModelBuilderRequest request,
ModelProblemCollector problems);

/**
* Builder-accepting variant of {@link #importManagement}.
*
* @since 4.0.0
*/
default void importManagement(
Model.Builder builder,
List<? extends DependencyManagement> sources,
ModelBuilderRequest request,
ModelProblemCollector problems) {
Model built = builder.build();
Model result = importManagement(built, sources, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,24 @@ public interface DependencyManagementInjector {
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
Model injectManagement(Model model, ModelBuilderRequest request, ModelProblemCollector problems);

/**
* Builder-accepting variant that operates on a {@link Model.Builder} directly,
* avoiding an intermediate {@code Model.build()} between pipeline stages.
* <p>
* The default implementation bridges to {@link #injectManagement(Model, ModelBuilderRequest, ModelProblemCollector)}
* by building the model, processing it, and resetting the builder to the result.
*
* @param builder The model builder to modify in place, must not be {@code null}.
* @param request The model building request, must not be {@code null}.
* @param problems The container used to collect problems, must not be {@code null}.
* @since 4.0.0
*/
default void injectManagement(Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {
Model built = builder.build();
Model result = injectManagement(built, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,18 @@ public interface InheritanceAssembler {
*/
Model assembleModelInheritance(
Model child, Model parent, ModelBuilderRequest request, ModelProblemCollector problems);

/**
* Builder-accepting variant that merges parent values into the child builder directly.
*
* @since 4.0.0
*/
default void assembleModelInheritance(
Model.Builder childBuilder, Model parent, ModelBuilderRequest request, ModelProblemCollector problems) {
Model built = childBuilder.build();
Model result = assembleModelInheritance(built, parent, request, problems);
if (result != built) {
childBuilder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,21 @@ Model interpolateModel(
@Nullable Path projectDir,
@Nonnull ModelBuilderRequest request,
@Nonnull ModelProblemCollector problems);

/**
* Builder-accepting variant of {@link #interpolateModel}.
*
* @since 4.0.0
*/
default void interpolateModel(
@Nonnull Model.Builder builder,
@Nullable Path projectDir,
@Nonnull ModelBuilderRequest request,
@Nonnull ModelProblemCollector problems) {
Model built = builder.build();
Model result = interpolateModel(built, projectDir, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,31 @@ public interface ModelNormalizer {
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
Model injectDefaultValues(Model model, ModelBuilderRequest request, ModelProblemCollector problems);

/**
* Builder-accepting variant of {@link #mergeDuplicates}.
*
* @since 4.0.0
*/
default void mergeDuplicates(Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {
Model built = builder.build();
Model result = mergeDuplicates(built, request, problems);
if (result != built) {
builder.reset(result);
}
}

/**
* Builder-accepting variant of {@link #injectDefaultValues}.
*
* @since 4.0.0
*/
default void injectDefaultValues(
Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {
Model built = builder.build();
Model result = injectDefaultValues(built, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,17 @@ public interface ModelPathTranslator {
* @since 4.0.0
*/
Model alignToBaseDirectory(Model model, Path basedir, ModelBuilderRequest request);

/**
* Builder-accepting variant of {@link #alignToBaseDirectory}.
*
* @since 4.0.0
*/
default void alignToBaseDirectory(Model.Builder builder, Path basedir, ModelBuilderRequest request) {
Model built = builder.build();
Model result = alignToBaseDirectory(built, basedir, request);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,17 @@ public interface ModelUrlNormalizer {
* @param request The model building request that holds further settings, must not be {@code null}.
*/
Model normalize(Model model, ModelBuilderRequest request);

/**
* Builder-accepting variant of {@link #normalize}.
*
* @since 4.0.0
*/
default void normalize(Model.Builder builder, ModelBuilderRequest request) {
Model built = builder.build();
Model result = normalize(built, request);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,18 @@ public interface PluginConfigurationExpander {
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
Model expandPluginConfiguration(Model model, ModelBuilderRequest request, ModelProblemCollector problems);

/**
* Builder-accepting variant of {@link #expandPluginConfiguration}.
*
* @since 4.0.0
*/
default void expandPluginConfiguration(
Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {
Model built = builder.build();
Model result = expandPluginConfiguration(built, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,17 @@ public interface PluginManagementInjector {
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
Model injectManagement(Model model, ModelBuilderRequest request, ModelProblemCollector problems);

/**
* Builder-accepting variant of {@link #injectManagement}.
*
* @since 4.0.0
*/
default void injectManagement(Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {
Model built = builder.build();
Model result = injectManagement(built, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,21 @@ default Model injectProfile(
*/
Model injectProfiles(
Model model, List<Profile> profiles, ModelBuilderRequest request, ModelProblemCollector problems);

/**
* Builder-accepting variant that injects profile values into the model builder directly.
*
* @since 4.0.0
*/
default void injectProfiles(
Model.Builder builder,
List<Profile> profiles,
ModelBuilderRequest request,
ModelProblemCollector problems) {
Model built = builder.build();
Model result = injectProfiles(built, profiles, request, problems);
if (result != built) {
builder.reset(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class FileToRawModelMergerTest {
void testOverriddenMergeMethods() {
List<String> methodNames = Stream.of(MavenMerger.class.getDeclaredMethods())
.filter(m -> m.getName().startsWith("merge"))
// Exclude *ToBuilder variants and void methods whose first parameter
// is a Builder — only the object-returning merge methods need overriding
.filter(m -> !m.getName().endsWith("ToBuilder"))
.filter(m -> !m.getParameterTypes()[0].getSimpleName().equals("Builder"))
.filter(m -> {
String baseName = m.getName().substring(5 /* merge */);
String entity = baseName.substring(baseName.indexOf('_') + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,30 @@
@Singleton
public class DefaultPluginConfigurationExpander implements PluginConfigurationExpander {

@Override
public void expandPluginConfiguration(
Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {

// Use builder getters instead of builder.build() to avoid materializing
// all model-object lists (especially dependencies) just to read Build/Reporting
Build build = builder.getBuild();
if (build != null) {
Build newBuild = build.withPlugins(expandPlugin(build.getPlugins()));
PluginManagement pluginManagement = newBuild.getPluginManagement();
if (pluginManagement != null) {
newBuild = newBuild.withPluginManagement(
pluginManagement.withPlugins(expandPlugin(pluginManagement.getPlugins())));
}
if (newBuild != build) {
builder.build(newBuild);
}
}
Reporting reporting = builder.getReporting();
if (reporting != null) {
expandReport(reporting.getPlugins());
}
}

@Override
public Model expandPluginConfiguration(Model model, ModelBuilderRequest request, ModelProblemCollector problems) {
Build build = model.getBuild();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ static Dependency updateWithImportedFrom(Dependency dependency, DependencyManage
if (dependencySource == null
|| bomSource == null
|| Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) {
// Use forceCopy=true since we only set importedFrom (no field changes that would
// trigger copy-on-write), and build immediately as we need the immutable result.
return Dependency.newBuilder(dependency, true)
.importedFrom(bomLocation)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ public class DefaultDependencyManagementInjector implements DependencyManagement

private ManagementModelMerger merger = new ManagementModelMerger();

@Override
public void injectManagement(Model.Builder builder, ModelBuilderRequest request, ModelProblemCollector problems) {
// Use builder getters instead of builder.build() to avoid materializing
// all model-object lists just to read Dependencies and DependencyManagement
DependencyManagement depMgmt = builder.getDependencyManagement();
if (depMgmt != null) {
List<Dependency> deps = builder.getBuiltDependencies();
List<Dependency> merged = merger.computeMergedDependencies(deps, depMgmt);
if (merged != null) {
builder.dependencies(merged);
}
}
}

@Override
public Model injectManagement(Model model, ModelBuilderRequest request, ModelProblemCollector problems) {
return merger.mergeManagedDependencies(model);
Expand All @@ -55,41 +69,60 @@ public Model injectManagement(Model model, ModelBuilderRequest request, ModelPro
*/
protected static class ManagementModelMerger extends MavenModelMerger {

public Model mergeManagedDependencies(Model model) {
/**
* Computes the merged dependency list, or returns {@code null} if no dependencies were modified.
*/
List<Dependency> computeMergedDependencies(Model model) {
DependencyManagement dependencyManagement = model.getDependencyManagement();
if (dependencyManagement != null) {
Map<Object, Dependency> dependencies = new HashMap<>();
Map<Object, Object> context = Collections.emptyMap();
return computeMergedDependencies(model.getDependencies(), dependencyManagement);
}
return null;
}

for (Dependency dependency : model.getDependencies()) {
Object key = getDependencyKey().apply(dependency);
dependencies.put(key, dependency);
}
/**
* Computes the merged dependency list from pre-extracted deps and dep management,
* or returns {@code null} if no dependencies were modified.
*/
List<Dependency> computeMergedDependencies(
List<Dependency> dependencies, DependencyManagement dependencyManagement) {
Map<Object, Dependency> originalDeps = new HashMap<>();
Map<Object, Dependency.Builder> builderDeps = new HashMap<>();
Map<Object, Object> context = Collections.emptyMap();

for (Dependency dependency : dependencies) {
Object key = getDependencyKey().apply(dependency);
originalDeps.put(key, dependency);
}

boolean modified = false;
for (Dependency managedDependency : dependencyManagement.getDependencies()) {
Object key = getDependencyKey().apply(managedDependency);
Dependency dependency = dependencies.get(key);
if (dependency != null) {
Dependency merged = mergeDependency(dependency, managedDependency, false, context);
if (merged != dependency) {
dependencies.put(key, merged);
modified = true;
}
boolean modified = false;
for (Dependency managedDependency : dependencyManagement.getDependencies()) {
Object key = getDependencyKey().apply(managedDependency);
Dependency dependency = originalDeps.get(key);
if (dependency != null) {
Dependency.Builder merged = mergeDependencyToBuilder(dependency, managedDependency, false, context);
if (merged != null) {
builderDeps.put(key, merged);
modified = true;
}
}
}

if (modified) {
List<Dependency> newDeps = new ArrayList<>(dependencies.size());
for (Dependency dep : model.getDependencies()) {
Object key = getDependencyKey().apply(dep);
Dependency dependency = dependencies.get(key);
newDeps.add(dependency);
}
return Model.newBuilder(model).dependencies(newDeps).build();
if (modified) {
List<Dependency> newDeps = new ArrayList<>(originalDeps.size());
for (Dependency dep : dependencies) {
Object key = getDependencyKey().apply(dep);
Dependency.Builder builder = builderDeps.get(key);
newDeps.add(builder != null ? builder.build() : dep);
}
return newDeps;
}
return model;
return null;
}

public Model mergeManagedDependencies(Model model) {
List<Dependency> merged = computeMergedDependencies(model);
return merged != null ? Model.newBuilder(model).dependencies(merged).build() : model;
}

@Override
Expand Down
Loading
Loading