Skip to content
Draft
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 @@ -157,8 +157,7 @@ private List<MavenProject> trimProjectsToRequest(
if (request.getPom() != null) {
result = getProjectsInRequestScope(request, activeProjects);

List<MavenProject> sortedProjects = graph.getSortedProjects();
result.sort(comparing(sortedProjects::indexOf));
result.sort(comparing(buildProjectIndexMap(graph.getSortedProjects())::get));

result = includeAlsoMakeTransitively(result, request, graph);
}
Expand Down Expand Up @@ -189,8 +188,7 @@ private List<MavenProject> trimSelectedProjects(
result = includeAlsoMakeTransitively(result, request, graph);

// Order the new list in the original order
List<MavenProject> sortedProjects = graph.getSortedProjects();
result.sort(comparing(sortedProjects::indexOf));
result.sort(comparing(buildProjectIndexMap(graph.getSortedProjects())::get));
}
}

Expand Down Expand Up @@ -290,13 +288,24 @@ private List<MavenProject> includeAlsoMakeTransitively(
result = new ArrayList<>(projectsSet);

// Order the new list in the original order
List<MavenProject> sortedProjects = graph.getSortedProjects();
result.sort(comparing(sortedProjects::indexOf));
result.sort(comparing(buildProjectIndexMap(graph.getSortedProjects())::get));
}

return result;
}

/**
* Builds a Map from MavenProject to its index in the sorted list, enabling O(1) index lookups
* for sorting instead of O(n) ArrayList.indexOf() scans that cause O(n² log n) sort performance.
*/
private static Map<MavenProject, Integer> buildProjectIndexMap(List<MavenProject> sortedProjects) {
Map<MavenProject, Integer> indexMap = new HashMap<>(sortedProjects.size() * 2);
for (int i = 0; i < sortedProjects.size(); i++) {
indexMap.put(sortedProjects.get(i), i);
}
return indexMap;
}

private void enrichRequestFromResumptionData(List<MavenProject> projects, MavenExecutionRequest request) {
if (request.isResume()) {
projects.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,47 @@
package org.apache.maven.lifecycle.internal;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Compares phases within the context of a specific lifecycle with secondary sorting based on the {@link PhaseId}.
*/
public class PhaseComparator implements Comparator<String> {
/**
* The lifecycle phase ordering.
* Map from phase name to its index in the lifecycle, enabling O(1) lookups
* instead of O(n) List.indexOf() scans on every comparison.
*/
private final List<String> lifecyclePhases;
private final Map<String, Integer> phaseIndexMap;

/**
* Constructor.
*
* @param lifecyclePhases the lifecycle phase ordering.
*/
public PhaseComparator(List<String> lifecyclePhases) {
this.lifecyclePhases = lifecyclePhases;
this.phaseIndexMap = new HashMap<>(lifecyclePhases.size() * 2);
for (int i = 0; i < lifecyclePhases.size(); i++) {
phaseIndexMap.put(lifecyclePhases.get(i), i);
}
}

@Override
public int compare(String o1, String o2) {
PhaseId p1 = PhaseId.of(o1);
PhaseId p2 = PhaseId.of(o2);
int i1 = lifecyclePhases.indexOf(p1.executionPoint().prefix() + p1.phase());
int i2 = lifecyclePhases.indexOf(p2.executionPoint().prefix() + p2.phase());
if (i1 == -1 && i2 == -1) {
Integer i1 = phaseIndexMap.get(p1.executionPoint().prefix() + p1.phase());
Integer i2 = phaseIndexMap.get(p2.executionPoint().prefix() + p2.phase());
if (i1 == null && i2 == null) {
// unknown phases, leave in existing order
return 0;
}
if (i1 == -1) {
if (i1 == null) {
// second one is known, so it comes first
return 1;
}
if (i2 == -1) {
if (i2 == null) {
// first one is known, so it comes first
return -1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ public class DefaultModelObjectPool implements ModelObjectProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultModelObjectPool.class);

private final Map<?, ?> properties;
private final Set<String> pooledTypes;

public DefaultModelObjectPool() {
this(System.getProperties());
}

DefaultModelObjectPool(Map<?, ?> properties) {
this.properties = properties;
this.pooledTypes = parsePooledTypes(properties);
}

@Override
Expand All @@ -79,8 +81,8 @@ public <T> T process(T object) {
Class<?> objectType = object.getClass();
String simpleClassName = objectType.getSimpleName();

// Check if this object type should be pooled (read configuration dynamically)
if (!getPooledTypes(properties).contains(simpleClassName)) {
// Check if this object type should be pooled
if (!pooledTypes.contains(simpleClassName)) {
return object;
}

Expand All @@ -96,14 +98,16 @@ private String getProperty(String name, String defaultValue) {
}

/**
* Gets the set of object types that should be pooled.
* Parses the set of object types that should be pooled from properties.
* Called once at construction time to avoid re-parsing on every {@link #process} call.
*/
private Set<String> getPooledTypes(Map<?, ?> properties) {
String pooledTypesProperty = getProperty(Constants.MAVEN_MODEL_PROCESSOR_POOLED_TYPES, "Dependency");
private static Set<String> parsePooledTypes(Map<?, ?> properties) {
Object value = properties.get(Constants.MAVEN_MODEL_PROCESSOR_POOLED_TYPES);
String pooledTypesProperty = value instanceof String str ? str : "Dependency";
return Arrays.stream(pooledTypesProperty.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toSet());
.collect(Collectors.toUnmodifiableSet());
}

/**
Expand Down Expand Up @@ -199,6 +203,9 @@ public boolean equals(Object obj) {
if (!(obj instanceof PoolKey other)) {
return false;
}
if (hashCode != other.hashCode) {
return false;
}

return objectsEqual(object, other.object);
}
Expand Down Expand Up @@ -283,21 +290,23 @@ private static int computeHashCode(Object obj) {

/**
* Custom hash code for Dependency objects based on all fields.
* Inlined to avoid the Object[] varargs allocation from Objects.hash().
*/
private static int dependencyHashCode(org.apache.maven.api.model.Dependency dep) {
return Objects.hash(
dep.getGroupId(),
dep.getArtifactId(),
dep.getVersion(),
dep.getType(),
dep.getClassifier(),
dep.getScope(),
dep.getSystemPath(),
dep.getExclusions(),
dep.getOptional(),
dep.getLocationKeys(),
locationsHashCode(dep),
dep.getImportedFrom());
int h = 1;
h = 31 * h + Objects.hashCode(dep.getGroupId());
h = 31 * h + Objects.hashCode(dep.getArtifactId());
h = 31 * h + Objects.hashCode(dep.getVersion());
h = 31 * h + Objects.hashCode(dep.getType());
h = 31 * h + Objects.hashCode(dep.getClassifier());
h = 31 * h + Objects.hashCode(dep.getScope());
h = 31 * h + Objects.hashCode(dep.getSystemPath());
h = 31 * h + Objects.hashCode(dep.getExclusions());
h = 31 * h + Objects.hashCode(dep.getOptional());
h = 31 * h + Objects.hashCode(dep.getLocationKeys());
h = 31 * h + locationsHashCode(dep);
h = 31 * h + Objects.hashCode(dep.getImportedFrom());
return h;
}

/**
Expand Down
Loading