From ab2f71a525c4734255b63d43b48882c792d651ff Mon Sep 17 00:00:00 2001 From: Stanislav Ochotnicky Date: Oct 18 2012 13:51:02 +0000 Subject: Finalize support for compatibility packages Now our resolvers will correctly handle multiple packages providing identical GAs provided that just one has unversioned jar. Packages wanting to use non-defaul GAV will have to either specify that exactly, or ask given package to add additional compat version mapping manually (-v switch for add_maven_depmap) --- diff --git a/JavadirWorkspaceReader.java b/JavadirWorkspaceReader.java index 35e9368..83fded4 100644 --- a/JavadirWorkspaceReader.java +++ b/JavadirWorkspaceReader.java @@ -1,6 +1,7 @@ package org.apache.maven.artifact.resolver; import java.io.File; +import java.util.ArrayList; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; @@ -14,7 +15,7 @@ public class JavadirWorkspaceReader implements WorkspaceReader { private WorkspaceRepository workspaceRepository; private static final char GROUP_SEPARATOR = '.'; - private static final char PATH_SEPARATOR = '/'; + private static final char PATH_SEPARATOR = File.separatorChar; public JavadirWorkspaceReader() { workspaceRepository = new WorkspaceRepository("javadir-workspace"); @@ -24,26 +25,28 @@ public class JavadirWorkspaceReader implements WorkspaceReader { return workspaceRepository; } - private static final String LOG_FILE = System.getProperty("maven.resolver.logfile"); - private static final java.util.concurrent.Semaphore LOG_SEMAPHORE = new java.util.concurrent.Semaphore(1); + private static final String LOG_FILE = System + .getProperty("maven.resolver.logfile"); + private static final java.util.concurrent.Semaphore LOG_SEMAPHORE = new java.util.concurrent.Semaphore( + 1); public File findArtifact(Artifact artifact) { - File f = findArtifactImpl(artifact); - - LOG_SEMAPHORE.acquireUninterruptibly(); - try { - if (LOG_FILE != null && f != null) { - java.io.FileOutputStream fos = new java.io.FileOutputStream(LOG_FILE, true); - java.io.PrintStream ps = new java.io.PrintStream(fos); - ps.println(f.getAbsolutePath()); - ps.close(); - } - } - catch (Exception _) {} - finally { - LOG_SEMAPHORE.release(); - return f; - } + File f = findArtifactImpl(artifact); + + LOG_SEMAPHORE.acquireUninterruptibly(); + try { + if (LOG_FILE != null && f != null) { + java.io.FileOutputStream fos = new java.io.FileOutputStream( + LOG_FILE, true); + java.io.PrintStream ps = new java.io.PrintStream(fos); + ps.println(f.getAbsolutePath()); + ps.close(); + } + } catch (Exception _) { + } finally { + LOG_SEMAPHORE.release(); + return f; + } } private File findArtifactImpl(Artifact artifact) { @@ -59,9 +62,9 @@ public class JavadirWorkspaceReader implements WorkspaceReader { // let's check out local repo first String m2_path = System.getProperty("maven.repo.local"); String gid_path = groupId.replace(".", File.separator); - String art_path = m2_path + File.separator + gid_path + File.separator + artifactId + - File.separator + version + File.separator + artifactId + "-" + - version + "." + artifact.getExtension(); + String art_path = m2_path + File.separator + gid_path + File.separator + + artifactId + File.separator + version + File.separator + + artifactId + "-" + version + "." + artifact.getExtension(); ret = new File(art_path); if (ret.isFile()) { @@ -69,63 +72,80 @@ public class JavadirWorkspaceReader implements WorkspaceReader { return ret; } + // maven.repo.local does not have needed GAV (that's normal), so let's + // just continue with system packages MavenJPackageDepmap.debug("Wanted GROUPID=" + groupId); MavenJPackageDepmap.debug("Wanted ARTIFACTID=" + artifactId); MavenJPackageDepmap.debug("Wanted VERSION=" + version); + ArrayList> maps = new ArrayList>(); if (!groupId.startsWith("JPP")) { MavenJPackageDepmap map = MavenJPackageDepmap.getInstance(); + // let's try to get exact GAV first Hashtable newInfo = map.getMappedInfo(groupId, artifactId, version); - - groupId = (String) newInfo.get("group"); - artifactId = (String) newInfo.get("artifact"); - version = (String) newInfo.get("version"); + if (newInfo == null) { + // exact GAV does not exist in our mapping so let's just get all + // GAs and iterate until we find one that exists. Note that only + // one non-versioned jar/pom for given GA should exist in order + // to ensure reproducibility + + maps = map.getUnversionedMappedInfo(groupId, artifactId, + version); + } else { + maps.add(newInfo); + } } - MavenJPackageDepmap.debug("Resolved GROUPID=" + groupId); - MavenJPackageDepmap.debug("Resolved ARTIFACTID=" + artifactId); - MavenJPackageDepmap.debug("Resolved VERSION=" + version); - - if (artifact.getExtension().equals("pom")) { - path = getPOMPath(groupId, artifactId, version); - ret = new File(path.toString()); - } else { - String repos[] = { "/usr/share/maven/repository/", - "/usr/share/maven/repository-java-jni/", - "/usr/share/maven/repository-jni/" }; - String verRelativeArtifactPath = groupId + "/" + artifactId + "-" - + wantedVersion + "." + artifact.getExtension(); - String relativeArtifactPath = groupId + "/" + artifactId + "." - + artifact.getExtension(); - for (String repo : repos) { - path = new StringBuffer(repo + verRelativeArtifactPath); - ret = new File(path.toString()); - if (ret.isFile()) { - MavenJPackageDepmap.debug("Returning " + repo - + verRelativeArtifactPath); - return ret; - } - path = new StringBuffer(repo + relativeArtifactPath); + for (Hashtable map : maps) { + groupId = map.get("group"); + artifactId = map.get("artifact"); + version = map.get("version"); + + MavenJPackageDepmap.debug("Resolved GROUPID=" + groupId); + MavenJPackageDepmap.debug("Resolved ARTIFACTID=" + artifactId); + MavenJPackageDepmap.debug("Resolved VERSION=" + version); + + if (artifact.getExtension().equals("pom")) { + path = getPOMPath(groupId, artifactId, version); ret = new File(path.toString()); if (ret.isFile()) { - MavenJPackageDepmap.debug("Returning " + repo - + relativeArtifactPath); + MavenJPackageDepmap.debug("Returning " + path.toString()); return ret; } + } else { + String repos[] = { "/usr/share/maven/repository/", + "/usr/share/maven/repository-java-jni/", + "/usr/share/maven/repository-jni/" }; + String verRelativeArtifactPath = groupId + "/" + artifactId + + "-" + wantedVersion + "." + artifact.getExtension(); + String relativeArtifactPath = groupId + "/" + artifactId + "." + + artifact.getExtension(); + for (String repo : repos) { + path = new StringBuffer(repo + verRelativeArtifactPath); + ret = new File(path.toString()); + if (ret.isFile()) { + MavenJPackageDepmap.debug("Returning " + repo + + verRelativeArtifactPath); + return ret; + } + + path = new StringBuffer(repo + relativeArtifactPath); + ret = new File(path.toString()); + if (ret.isFile()) { + MavenJPackageDepmap.debug("Returning " + repo + + relativeArtifactPath); + return ret; + } + } } - } + } // if file doesn't exist return null to delegate to other // resolvers (reactor/local repo) - if (ret.isFile()) { - MavenJPackageDepmap.debug("Returning " + path.toString()); - return ret; - } else { - MavenJPackageDepmap.debug("Returning null for gid:aid =>" + groupId - + ":" + artifactId); - return null; - } + MavenJPackageDepmap.debug("Returning null for gid:aid =>" + groupId + + ":" + artifactId); + return null; } public List findVersions(Artifact artifact) { @@ -134,11 +154,12 @@ public class JavadirWorkspaceReader implements WorkspaceReader { return ret; } - private StringBuffer getPOMPath(String groupId, String artifactId, String version) { + private StringBuffer getPOMPath(String groupId, String artifactId, + String version) { String fName = groupId.replace(PATH_SEPARATOR, GROUP_SEPARATOR) + "-" + artifactId + ".pom"; - String verfName = groupId.replace(PATH_SEPARATOR, GROUP_SEPARATOR) + "-" - + artifactId + "-" + version + ".pom"; + String verfName = groupId.replace(PATH_SEPARATOR, GROUP_SEPARATOR) + + "-" + artifactId + "-" + version + ".pom"; File f; String[] pomRepos = { "/usr/share/maven2/poms/", "/usr/share/maven/poms/", "/usr/share/maven-poms/" }; diff --git a/MavenJPackageDepmap.java b/MavenJPackageDepmap.java index 089bbbb..5004255 100644 --- a/MavenJPackageDepmap.java +++ b/MavenJPackageDepmap.java @@ -5,7 +5,9 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Hashtable; +import java.util.List; import java.util.StringTokenizer; import javax.xml.parsers.DocumentBuilder; @@ -71,9 +73,11 @@ public class MavenJPackageDepmap { private static MavenJPackageDepmap instance; private static Hashtable jppArtifactMap; + private static Hashtable> jppUnversionedArtifactMap; private MavenJPackageDepmap() { jppArtifactMap = new Hashtable(); + jppUnversionedArtifactMap = new Hashtable>(); buildJppArtifactMap(); } @@ -85,71 +89,78 @@ public class MavenJPackageDepmap { return instance; } - public Hashtable getMappedInfo( - Hashtable mavenDep) { - return getMappedInfo((String) mavenDep.get("group"), - (String) mavenDep.get("artifact"), - (String) mavenDep.get("version")); - } - + /** + * This function can be used to query exact version of an artifact. + * + * @param groupId + * @param artifactId + * @param version + * @return Hashtable mapping for groupId, artifactId and version or null if + * exact mapping not found + */ public Hashtable getMappedInfo(String groupId, String artifactId, String version) { Hashtable jppDep; String idToCheck, jppCombination; - if (System.getProperty("maven.ignore.versions") == null - && System.getProperty("maven.local.mode") == null) { - idToCheck = groupId + "," + artifactId + "," + version; - } else { - idToCheck = groupId + "," + artifactId; - } + idToCheck = groupId + "," + artifactId + "," + version; jppCombination = (String) jppArtifactMap.get(idToCheck); - jppDep = new Hashtable(); + jppDep = null; if (jppCombination != null && jppCombination != "") { - StringTokenizer st = new StringTokenizer(jppCombination, ","); - + jppDep = new Hashtable(); jppDep.put("group", st.nextToken()); jppDep.put("artifact", st.nextToken()); jppDep.put("version", st.nextToken()); - } else { - jppDep.put("group", groupId); - jppDep.put("artifact", artifactId); - jppDep.put("version", version); } return jppDep; } /** - * Returns whether or not the given dependency should be dropped. + * This function can be used to query for all possible artifact resolutions. + * It works with multiple duplicate gid:aid mappings, but only one should + * have unversioned files (default version) to work properly later + * + * @param groupId + * @param artifactId + * @param version + * @return */ - public boolean shouldEliminate(String groupId, String artifactId, - String version) { + public ArrayList> getUnversionedMappedInfo( + String groupId, String artifactId, String version) { + + Hashtable jppDep; String idToCheck; + List maps; - if (System.getProperty("maven.ignore.versions") == null - && System.getProperty("maven.local.mode") == null) { - idToCheck = groupId + "," + artifactId + "," + version; - } else { - idToCheck = groupId + "," + artifactId; - } + idToCheck = groupId + "," + artifactId; + + maps = jppUnversionedArtifactMap.get(idToCheck); + ArrayList> ret = new ArrayList>(); + if (maps != null) { + for (String jppPart : maps) { + jppDep = new Hashtable(); + StringTokenizer st = new StringTokenizer(jppPart, ","); - return jppArtifactMap.get(idToCheck) != null - && jppArtifactMap.get(idToCheck).equals(""); + jppDep.put("group", st.nextToken()); + jppDep.put("artifact", st.nextToken()); + jppDep.put("version", st.nextToken()); + // we add to index 0 to make it reversed order for compatibility + // with older code + ret.add(0, jppDep); + } + } + return ret; } private static void buildJppArtifactMap() { - if (System.getProperty("maven.ignore.versions") != null - || System.getProperty("maven.local.mode") != null) { - debug("Processing file: /usr/share/java-utils/xml/maven2-versionless-depmap.xml"); - processDepmapFile("/etc/maven/maven2-versionless-depmap.xml"); - } + processDepmapFile("/etc/maven/maven2-versionless-depmap.xml"); // process fragments in etc File fragmentDir = new File("/etc/maven/fragments"); @@ -173,7 +184,6 @@ public class MavenJPackageDepmap { String customFileName = System.getProperty("maven.local.depmap.file", null); if (customFileName != null) { - debug("Processing file: " + customFileName); processDepmapFile(customFileName); } @@ -233,32 +243,34 @@ public class MavenJPackageDepmap { if (jppNodeList.getLength() == 1) { jppAD = getArtifactDefinition((Element) jppNodeList.item(0)); - if (System.getProperty("maven.ignore.versions") == null - && System.getProperty("maven.local.mode") == null) { - debug("*** Adding: " + mavenAD.groupId + "," - + mavenAD.artifactId + "," + mavenAD.version - + " => " + jppAD.groupId + "," + jppAD.artifactId - + "," + jppAD.version + " to map..."); - - jppArtifactMap.put(mavenAD.groupId + "," - + mavenAD.artifactId + "," + mavenAD.version, - jppAD.groupId + "," + jppAD.artifactId + "," - + jppAD.version); - } else { - debug("*** Adding: " + mavenAD.groupId + "," - + mavenAD.artifactId + " => " + jppAD.groupId + "," - + jppAD.artifactId + "," + jppAD.version - + " to map..."); - - jppArtifactMap.put(mavenAD.groupId + "," - + mavenAD.artifactId, jppAD.groupId + "," - + jppAD.artifactId + "," + jppAD.version); + debug("*** Adding: " + mavenAD.groupId + "," + + mavenAD.artifactId + " => " + jppAD.groupId + "," + + jppAD.artifactId + "," + jppAD.version + " to map..."); + + jppArtifactMap.put(mavenAD.groupId + "," + mavenAD.artifactId + + "," + mavenAD.version, jppAD.groupId + "," + + jppAD.artifactId + "," + jppAD.version); + ArrayList maps = jppUnversionedArtifactMap + .get(mavenAD.groupId + "," + mavenAD.artifactId); + if (maps == null) { + maps = new ArrayList(); } + + maps.add(jppAD.groupId + "," + jppAD.artifactId + "," + + jppAD.version); + + jppUnversionedArtifactMap.put(mavenAD.groupId + "," + + mavenAD.artifactId, maps); } else { debug("Number of jpp sub-elements is not 1. Dropping dependency for " + mavenAD.groupId + ":" + mavenAD.artifactId); - jppArtifactMap.put(mavenAD.groupId + "," + mavenAD.artifactId, - "JPP/maven,empty-dep," + mavenAD.version); + jppArtifactMap.put(mavenAD.groupId + "," + mavenAD.artifactId + + "," + mavenAD.version, "JPP/maven,empty-dep," + + mavenAD.version); + ArrayList maps = new ArrayList(); + maps.add("JPP/maven,empty-dep," + mavenAD.version); + jppUnversionedArtifactMap.put(mavenAD.groupId + "," + + mavenAD.artifactId, maps); } } }