Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
JENKINS-12735 - Maven version range resolution.
Originally-Committed-As: 65cd6555301535af4f8796a694c4d52664205778
  • Loading branch information
alexkoon committed Aug 9, 2012
1 parent d0dede3 commit 3d81dd6
Show file tree
Hide file tree
Showing 3 changed files with 353 additions and 1 deletion.
75 changes: 74 additions & 1 deletion src/main/java/hudson/maven/MavenModule.java
Expand Up @@ -478,10 +478,12 @@ protected void buildDependencyGraph(DependencyGraph graph) {
// not module.
AbstractProject<?, ?> dest = getParent().isAggregatorStyleBuild() ? getParent() : this;

//Create a map of groupId:artifact id keys to modules for faster look ups in findMatchingDependentModule
Map<String, List<ModuleDependency>> mapModules = createModuleDependencyMap(data.allModules.keySet());
for (ModuleDependency d : dependencies) {
MavenModule src = myParentsModules.get(d);
if (src==null) {
src = data.allModules.get(d);
src = findMatchingDependentModule(mapModules, data.allModules, d);
}

if(src!=null) {
Expand Down Expand Up @@ -661,4 +663,75 @@ public String toString() {

private static final Logger LOGGER = Logger.getLogger(MavenModule.class.getName());

/**
* Given a list of the same ModuleDependency objects for this MavenModule, this method finds the one that
* satisfies this MavenModule with the highest version defined.
*
* @param dependencyMap this map is defined by keys made up of groupId:artifactId and the value is a list of
* ModuleDependency objects that matches this.
* @param modules a map of all MavenModules in Jenkins keyed on ModuleDependency.
* @param dependencyDescription The ModuleDependency we are using as the search reference.
* @return The highest satisfying ModuleDependency for this MavenModule.
*/
private MavenModule findMatchingDependentModule(
final Map<String, List<ModuleDependency>> dependencyMap,
final Map<ModuleDependency, MavenModule> modules,
final ModuleDependency dependencyDescription) {

MavenModule module = null;
String lookupKey = buildDependencyKey(dependencyDescription);
List<ModuleDependency> dependencyList = dependencyMap.get(lookupKey);

if (dependencyList != null) {

//Shortcut for size 1 list...this is most common?
if (dependencyList.size() == 1) {
ModuleDependency moduleDependency = dependencyList.get(0);
if (dependencyDescription.isSatisfiedBy(moduleDependency)) {
module = modules.get(moduleDependency);
}
} else {

//We need to filter out the list to the set that is satisfied and then find sort this and
//get the highest one.
List<ModuleDependency> possibles = dependencyMap.get(buildDependencyKey(dependencyDescription));
if (possibles != null) {
ModuleDependency satisfyingModule = dependencyDescription.findHighestSatisfyingModule(possibles);
module = modules.get(satisfyingModule);
}
}
}
return module;
}

/**
* Builds a map of all the modules, keyed against the groupId and artifactId. The values are a list of modules
* that match this criteria.
*
* @param moduleSet The entire set in the Jenkins instance.
* @return A map of ModuleDependencies.
*/
private static Map<String, List<ModuleDependency>> createModuleDependencyMap(Set<ModuleDependency> moduleSet) {
Map<String, List<ModuleDependency>> map = new HashMap<String, List<ModuleDependency>>();

for (ModuleDependency dependency : moduleSet) {
String compositeKey = buildDependencyKey(dependency);

List<ModuleDependency> moduleDependencies = map.get(compositeKey);
if (moduleDependencies == null) {
moduleDependencies = new ArrayList<ModuleDependency>();
moduleDependencies.add(dependency);
} else {
moduleDependencies.add(dependency);
}

map.put(compositeKey, moduleDependencies);
}

return map;
}

private static String buildDependencyKey(ModuleDependency moduleDependency) {
return moduleDependency.groupId + ':' + moduleDependency.artifactId;
}
}
80 changes: 80 additions & 0 deletions src/main/java/hudson/maven/ModuleDependency.java
Expand Up @@ -23,12 +23,19 @@
*/
package hudson.maven;

import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.project.MavenProject;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.model.Extension;

import java.io.Serializable;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

import hudson.Functions;

Expand Down Expand Up @@ -163,4 +170,77 @@ protected Object readResolve() {
public static final String NONE = "-";

private static final long serialVersionUID = 1L;
/**
* Checks whether this ModuleDependency is satisfied by the dependency of the given ModuleDependency.
* This caters for versions where the version string defines a version range. It is assumed that the given
* ModuleDependency is of the same groupId and artifactId and only validates against the version.
*
* @param otherDependency The dependency to check for.
* @return true if contained false otherwise.
*/
public boolean isSatisfiedBy(ModuleDependency otherDependency) {
if (otherDependency == null) {
return false;
}

boolean result = false;
try {
VersionRange myRange = VersionRange.createFromVersionSpec(version);
ArtifactVersion otherVersion = new DefaultArtifactVersion(otherDependency.version);
result = myRange.containsVersion(otherVersion);
} catch (InvalidVersionSpecificationException ivse) {
//Do nothing. Return false.
}

return result;
}

/**
* Given a list of ModuleDependencies of the same groupId and artifactId, it will sort this list using the
* version and finds the highest version that satisfies this ModuleDependency.
*
* @param listModuleDependencies The list of ModuleDependencies.
* @return The highest satisfying ModuleDependency or null if none can be found.
*/
public ModuleDependency findHighestSatisfyingModule(List<ModuleDependency> listModuleDependencies) {

ModuleDependency highestDependency = null;

//Create a sorted map of the ModuleDependnecies sorted on version.
SortedMap<ArtifactVersion, ModuleDependency> sorted = new TreeMap<ArtifactVersion, ModuleDependency>();
for (ModuleDependency otherDependency : listModuleDependencies) {
sorted.put(new DefaultArtifactVersion(otherDependency.version), otherDependency);
}

try {
VersionRange myRange = VersionRange.createFromVersionSpec(version);

//Now find the highest version that satisfies this dependency.
ArtifactVersion highestVersion = null;
for (ArtifactVersion version : sorted.keySet()) {
if (myRange.containsVersion(version)) {
highestVersion = version;
} else {
break;
}
}

if (highestVersion != null) {
highestDependency = sorted.get(highestVersion);
}
} catch (InvalidVersionSpecificationException e) {
//Do nothing - return null.
}
return highestDependency;
}

@Override
public String toString() {
return "ModuleDependency{" +
"groupId='" + groupId + '\'' +
", artifactId='" + artifactId + '\'' +
", version='" + version + '\'' +
", plugin=" + plugin +
'}';
}
}

0 comments on commit 3d81dd6

Please sign in to comment.