Skip to content

Commit

Permalink
Reduce memory usage when applying dependency management and exclusions
Browse files Browse the repository at this point in the history
Closes gh-322
  • Loading branch information
wilkinsona committed Jun 7, 2022
1 parent 39b8691 commit 65889a9
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 46 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -64,8 +64,6 @@ public class DependencyManagement {

private final List<PomReference> importedBoms = new ArrayList<PomReference>();

private List<Pom> resolvedBoms = new ArrayList<Pom>();

DependencyManagement(Project project, PomResolver pomResolver) {
this(project, null, pomResolver);
}
Expand All @@ -80,16 +78,6 @@ void importBom(Coordinates coordinates, PropertySource properties) {
this.importedBoms.add(new PomReference(coordinates, properties));
}

/**
* Returns the {@link Pom Poms} that have been imported.
*
* @return the imported poms
*/
List<Pom> getImportedBoms() {
resolveIfNecessary();
return new ArrayList<Pom>(this.resolvedBoms);
}

List<PomReference> getImportedBomReferences() {
return this.importedBoms;
}
Expand Down Expand Up @@ -180,9 +168,9 @@ private void resolve() {

logger.debug("Preserving existing versions: {}", existingVersions);

this.resolvedBoms = this.pomResolver.resolvePoms(this.importedBoms, new ProjectPropertySource(this.project));
List<Pom> resolvedBoms = this.pomResolver.resolvePoms(this.importedBoms, new ProjectPropertySource(this.project));

for (Pom resolvedBom: this.resolvedBoms) {
for (Pom resolvedBom: resolvedBoms) {
for (Dependency dependency : resolvedBom.getManagedDependencies()) {
if (isEmpty(dependency.getClassifier())) {
Coordinates coordinates = dependency.getCoordinates();
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,8 +16,10 @@

package io.spring.gradle.dependencymanagement.internal;

import java.util.ArrayList;
import java.util.List;

import org.gradle.api.Action;
import org.gradle.api.DomainObjectCollection;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ConfigurationContainer;
Expand All @@ -31,7 +33,7 @@
*/
public class DependencyManagementConfigurationContainer {

private final DomainObjectCollection<Configuration> configurations;
private final List<Action<Configuration>> actions = new ArrayList<Action<Configuration>>();

private final ConfigurationContainer delegate;

Expand All @@ -43,7 +45,6 @@ public class DependencyManagementConfigurationContainer {
*/
public DependencyManagementConfigurationContainer(Project project) {
this.delegate = project.getConfigurations();
this.configurations = project.container(Configuration.class);
}

/**
Expand All @@ -70,7 +71,9 @@ Configuration newConfiguration(ConfigurationConfigurer configurer,
if (configurer != null) {
configurer.configure(configuration);
}
this.configurations.add(configuration);
for (Action<Configuration> action: this.actions) {
action.execute(configuration);
}
return configuration;
}

Expand All @@ -80,7 +83,7 @@ Configuration newConfiguration(ConfigurationConfigurer configurer,
* @param action the action to apply
*/
public void apply(Action<Configuration> action) {
this.configurations.all(action);
this.actions.add(action);
}

/**
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,6 +32,9 @@ class Exclusions {
private final Map<String, Set<Exclusion>> exclusionsByDependency = new HashMap<String, Set<Exclusion>>();

void add(String dependency, Collection<Exclusion> exclusionsForDependency) {
if (exclusionsForDependency.isEmpty()) {
return;
}
Set<Exclusion> exclusions = this.exclusionsByDependency.get(dependency);
if (exclusions == null) {
exclusions = new HashSet<Exclusion>();
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -140,9 +140,9 @@ private void configureBomImports(Node dependencies) {
for (Dependency override: overrides) {
appendDependencyNode(dependencies, override.getCoordinates(), override.getScope(), override.getType());
}
List<Pom> importedBoms = this.dependencyManagement.getImportedBoms();
List<PomReference> importedBoms = this.dependencyManagement.getImportedBomReferences();
Collections.reverse(importedBoms);
for (Pom resolvedBom: importedBoms) {
for (PomReference resolvedBom: importedBoms) {
addImport(dependencies, resolvedBom);
}
}
Expand Down Expand Up @@ -175,7 +175,7 @@ private boolean differentVersions(Dependency dependency1, Dependency dependency2
return !version1.equals(version2);
}

private void addImport(Node dependencies, Pom importedBom) {
private void addImport(Node dependencies, PomReference importedBom) {
appendDependencyNode(dependencies, importedBom.getCoordinates(), "import", "pom");
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -48,33 +48,40 @@ final class EffectiveModelBuilder {

private static final Logger logger = LoggerFactory.getLogger(EffectiveModelBuilder.class);

private final ModelCache modelCache = new InMemoryModelCache();

private final ModelResolver modelResolver;

EffectiveModelBuilder(Project project,
DependencyManagementConfigurationContainer configurationContainer, PlatformCategoryAttributeConfigurer attributeConfigurer) {
this.modelResolver = new ConfigurationModelResolver(project, configurationContainer, attributeConfigurer);
}

Model buildModel(File pom, PropertySource properties) {
List<Model> buildModels(List<ModelInput> inputs) {
List<Model> models = new ArrayList<Model>();
InMemoryModelCache cache = new InMemoryModelCache();
for (ModelInput input: inputs) {
models.add(buildModel(input, cache));
}
return models;
}

private Model buildModel(ModelInput input, InMemoryModelCache cache) {
DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
request.setSystemProperties(System.getProperties());
request.setModelSource(new FileModelSource(pom));
request.setModelSource(new FileModelSource(input.pom));
request.setModelResolver(this.modelResolver);
request.setModelCache(this.modelCache);
request.setModelCache(cache);

try {
ModelBuildingResult result = createModelBuilder(properties).build(request);
ModelBuildingResult result = createModelBuilder(input.properties).build(request);
List<ModelProblem> errors = extractErrors(result.getProblems());
if (!errors.isEmpty()) {
reportErrors(errors, pom);
reportErrors(errors, input.pom);
}
return result.getEffectiveModel();
}
catch (ModelBuildingException ex) {
logger.debug("Model building failed", ex);
reportErrors(extractErrors(ex.getProblems()), pom);
reportErrors(extractErrors(ex.getProblems()), input.pom);
return ex.getResult().getEffectiveModel();
}
}
Expand Down Expand Up @@ -105,6 +112,22 @@ private DefaultModelBuilder createModelBuilder(PropertySource properties) {
return modelBuilder;
}

/**
* Input to a model building request.
*/
static class ModelInput {

private final File pom;

private final PropertySource properties;

ModelInput(File pom, PropertySource properties) {
this.pom = pom;
this.properties = properties;
}

}

private static final class InMemoryModelCache implements ModelCache {

private final Map<Key, Object> cache = new ConcurrentHashMap<Key, Object>();
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@

package io.spring.gradle.dependencymanagement.internal.maven;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -36,6 +35,7 @@

import io.spring.gradle.dependencymanagement.internal.DependencyManagementConfigurationContainer;
import io.spring.gradle.dependencymanagement.internal.Exclusion;
import io.spring.gradle.dependencymanagement.internal.maven.EffectiveModelBuilder.ModelInput;
import io.spring.gradle.dependencymanagement.internal.pom.Coordinates;
import io.spring.gradle.dependencymanagement.internal.pom.Dependency;
import io.spring.gradle.dependencymanagement.internal.pom.Pom;
Expand Down Expand Up @@ -120,22 +120,26 @@ private List<Pom> createPoms(Set<ResolvedArtifact> resolvedArtifacts, List<PomRe
referencesById.put(createKey(pomReference.getCoordinates().getGroupId(),
pomReference.getCoordinates().getArtifactId()), pomReference);
}
List<Pom> resolvedPoms = new ArrayList<Pom>();
List<ModelInput> modelInputs = new ArrayList<ModelInput>();
for (ResolvedArtifact resolvedArtifact: resolvedArtifacts) {
ModuleVersionIdentifier id = resolvedArtifact.getModuleVersion().getId();
PomReference reference = referencesById.get(createKey(id.getGroup(), id.getName()));
CompositePropertySource allProperties = new CompositePropertySource(reference.getProperties(), properties);
resolvedPoms.add(createPom(resolvedArtifact.getFile(), allProperties));
modelInputs.add(new ModelInput(resolvedArtifact.getFile(), allProperties));
}
return resolvedPoms;
return createPoms(modelInputs);
}

private Pom createPom(File file, PropertySource properties) {
Model effectiveModel = this.effectiveModelBuilder.buildModel(file, properties);
Coordinates coordinates = new Coordinates(effectiveModel.getGroupId(), effectiveModel.getArtifactId(),
effectiveModel.getVersion());
return new Pom(coordinates, getManagedDependencies(effectiveModel), getDependencies(effectiveModel),
asMap(effectiveModel.getProperties()));
private List<Pom> createPoms(List<ModelInput> inputs) {
List<Model> effectiveModels = this.effectiveModelBuilder.buildModels(inputs);
List<Pom> poms = new ArrayList<Pom>(effectiveModels.size());
for (Model effectiveModel: effectiveModels) {
Coordinates coordinates = new Coordinates(effectiveModel.getGroupId(), effectiveModel.getArtifactId(),
effectiveModel.getVersion());
poms.add(new Pom(coordinates, getManagedDependencies(effectiveModel), getDependencies(effectiveModel),
asMap(effectiveModel.getProperties())));
}
return poms;
}

private List<Dependency> getManagedDependencies(Model model) {
Expand Down

0 comments on commit 65889a9

Please sign in to comment.