/*
* 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.sonatype.aether.artifact.Artifact;
import org.sonatype.aether.util.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() {
}
}