/* * Copyright (C) 2007-2012 Argeo GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.argeo.slc.repo.maven; import java.io.File; import java.util.Properties; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.aether.AetherTemplate; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Static utilities around Maven which are NOT using the Maven APIs (conventions * based). */ public class MavenConventionsUtils { private final static Log log = LogFactory .getLog(MavenConventionsUtils.class); /** * Path to the file identified by this artifact without using Maven * APIs (convention based). Default location of repository * (~/.m2/repository) is used here. * * @see MavenConventionsUtils#artifactToFile(String, Artifact) */ public static File artifactToFile(Artifact artifact) { return artifactToFile(System.getProperty("user.home") + File.separator + ".m2" + File.separator + "repository", artifact); } /** * Path to the file identified by this artifact without using Maven * APIs (convention based). * * @param repositoryPath * path to the related local repository location * @param artifact * the artifact */ public static File artifactToFile(String repositoryPath, Artifact artifact) { return new File(repositoryPath + File.separator + artifact.getGroupId().replace('.', File.separatorChar) + File.separator + artifact.getArtifactId() + File.separator + artifact.getVersion() + File.separator + artifactFileName(artifact)).getAbsoluteFile(); } /** The file name of this artifact when stored */ public static String artifactFileName(Artifact artifact) { return artifact.getArtifactId() + '-' + artifact.getVersion() + (artifact.getClassifier().equals("") ? "" : '-' + artifact .getClassifier()) + '.' + artifact.getExtension(); } /** Absolute path to the file */ public static String artifactPath(String artifactBasePath, Artifact artifact) { return artifactParentPath(artifactBasePath, artifact) + '/' + artifactFileName(artifact); } /** Absolute path to the directories where the files will be stored */ public static String artifactParentPath(String artifactBasePath, Artifact artifact) { return artifactBasePath + (artifactBasePath.endsWith("/") ? "" : "/") + artifactParentPath(artifact); } /** Absolute path to the directory of this group */ public static String groupPath(String artifactBasePath, String groupId) { return artifactBasePath + (artifactBasePath.endsWith("/") ? "" : "/") + groupId.replace('.', '/'); } /** Relative path to the directories where the files will be stored */ public static String artifactParentPath(Artifact artifact) { return artifact.getGroupId().replace('.', '/') + '/' + artifact.getArtifactId() + '/' + artifact.getBaseVersion(); } public static String artifactsAsDependencyPom(Artifact pomArtifact, Set artifacts, Artifact parent) { StringBuffer p = new StringBuffer(); // XML header p.append("\n"); p.append("\n"); p.append("4.0.0\n"); // Artifact if (parent != null) { p.append("\n"); p.append("").append(parent.getGroupId()) .append("\n"); p.append("").append(parent.getArtifactId()) .append("\n"); p.append("").append(parent.getVersion()) .append("\n"); p.append("\n"); } p.append("").append(pomArtifact.getGroupId()) .append("\n"); p.append("").append(pomArtifact.getArtifactId()) .append("\n"); p.append("").append(pomArtifact.getVersion()) .append("\n"); p.append("pom\n"); // Dependencies p.append("\n"); for (Artifact a : artifacts) { p.append("\t"); p.append("").append(a.getArtifactId()) .append(""); p.append("").append(a.getGroupId()).append(""); if (!a.getExtension().equals("jar")) p.append("").append(a.getExtension()).append(""); p.append("\n"); } p.append("\n"); // Dependency management p.append("\n"); p.append("\n"); for (Artifact a : artifacts) { p.append("\t"); p.append("").append(a.getArtifactId()) .append(""); p.append("").append(a.getVersion()).append(""); p.append("").append(a.getGroupId()).append(""); if (a.getExtension().equals("pom")) { p.append("").append(a.getExtension()).append(""); p.append("import"); } p.append("\n"); } p.append("\n"); p.append("\n"); // Repositories // p.append("\n"); // p.append("argeohttp://maven.argeo.org/argeo\n"); // p.append("\n"); p.append("\n"); return p.toString(); } /** * Directly parses Maven POM XML format in order to find all artifacts * references under the dependency and dependencyManagement tags. This is * meant to migrate existing pom registering a lot of artifacts, not to * replace Maven resolving. */ public static void gatherPomDependencies(AetherTemplate aetherTemplate, Set artifacts, Artifact pomArtifact) { if (log.isDebugEnabled()) log.debug("Gather dependencies for " + pomArtifact); try { File file = aetherTemplate.getResolvedFile(pomArtifact); DocumentBuilder documentBuilder = DocumentBuilderFactory .newInstance().newDocumentBuilder(); Document doc = documentBuilder.parse(file); // properties Properties props = new Properties(); props.setProperty("project.version", pomArtifact.getBaseVersion()); NodeList properties = doc.getElementsByTagName("properties"); if (properties.getLength() > 0) { NodeList propertiesElems = properties.item(0).getChildNodes(); for (int i = 0; i < propertiesElems.getLength(); i++) { if (propertiesElems.item(i) instanceof Element) { Element property = (Element) propertiesElems.item(i); props.put(property.getNodeName(), property.getTextContent()); } } } // dependencies (direct and dependencyManagement) NodeList dependencies = doc.getElementsByTagName("dependency"); for (int i = 0; i < dependencies.getLength(); i++) { Element dependency = (Element) dependencies.item(i); String groupId = dependency.getElementsByTagName("groupId") .item(0).getTextContent().trim(); String artifactId = dependency .getElementsByTagName("artifactId").item(0) .getTextContent().trim(); String version = dependency.getElementsByTagName("version") .item(0).getTextContent().trim(); if (version.startsWith("${")) { String versionKey = version.substring(0, version.length() - 1).substring(2); if (!props.containsKey(versionKey)) throw new SlcException("Cannot interpret version " + version); version = props.getProperty(versionKey); } NodeList scopes = dependency.getElementsByTagName("scope"); if (scopes.getLength() > 0 && scopes.item(0).getTextContent().equals("import")) { // recurse gatherPomDependencies(aetherTemplate, artifacts, new DefaultArtifact(groupId, artifactId, "pom", version)); } else { // TODO: deal with scope? // TODO: deal with type String type = "jar"; Artifact artifact = new DefaultArtifact(groupId, artifactId, type, version); artifacts.add(artifact); } } } catch (Exception e) { throw new SlcException("Cannot process " + pomArtifact, e); } } /** Prevent instantiation */ private MavenConventionsUtils() { } }