package org.dru.clay.respository.ivy;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.dru.clay.respository.Repository;
import org.dru.clay.respository.ResolveResult;
import org.dru.clay.respository.artifact.Artifact;
import org.dru.clay.respository.artifact.Group;
import org.dru.clay.respository.artifact.Module;
import org.dru.clay.respository.artifact.UnresolvedArtifact;
import org.dru.clay.respository.artifact.Version;
import org.dru.clay.respository.transport.FileInfo;
import org.dru.clay.respository.transport.Transport;
/**
*
* <ul>
* <li>[organisation]</li>
* <li>[module]</li>
* <li>[revision]</li>
* <li>[ext]</li>
* <li>[artifact]</li>
* </ul>
*
* @param ivyPattern
* /[organisation]/[module]/[module]-[revision]/ivy-[revision].xml
* @param artifactPattern
* /[organisation]/[module]/[module]-[revision]/[artifact].[ext]
* @author erikb
*/
public class IvyRepository implements Repository {
private static final String P_ORG = "\\[organisation\\]";
private static final String P_MODULE = "\\[module\\]";
private static final String P_VERSION = "\\[revision\\]";
private static final String P_EXT = "\\[ext\\]";
private static final String P_ARTIFACT = "\\[artifact\\]";
private static final Pattern VERSION_PATTERN = Pattern.compile(".+-([^-]+)", Pattern.DOTALL);
private final URI base;
private final String ivyPattern;
private final String searchPattern;
private final String artifactPattern;
public IvyRepository(URI base, String ivyPattern, String artifactPattern) {
this.base = base;
this.ivyPattern = ivyPattern;
this.artifactPattern = artifactPattern;
String pattern = "/";
final StringTokenizer tokenizer = new StringTokenizer(ivyPattern, "/");
while (tokenizer.hasMoreTokens()) {
final String token = tokenizer.nextToken();
if (token.indexOf("[revision]") >= 0) {
break;
}
pattern += token + "/";
}
this.searchPattern = pattern;
}
@Override
public URI getLocation() {
return base;
}
@Override
public Artifact lookup(Transport transport, Group group, UnresolvedArtifact artifact) {
if (!artifact.getVersionPattern().isDynamic()) {
// The version isn't dynamic so it can be 'looked-up' directly
final Version version = Version.fromString(artifact.getVersionPattern().getOriginal());
return new Artifact(artifact.getName(), version, artifact.getExtension(), artifact.getClassifier());
}
try {
Version latest = null;
final URI directory = calculateSearchURI(group, artifact);
for (URI uri : transport.list(directory)) {
final String moduleVersion = lastPathElement(uri.getPath());
final Matcher matcher = VERSION_PATTERN.matcher(moduleVersion);
if (!matcher.matches()) {
// invalid module link
continue;
}
final Version version = Version.fromString(matcher.group(1));
if (version.compareTo(latest) > 0) {
latest = version;
}
}
if (latest == null) {
throw new IllegalArgumentException("Unable to find latest version");
}
return new Artifact(artifact.getName(), latest, artifact.getExtension(), artifact.getClassifier());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override
public ResolveResult resolve(Transport transport, Module module) {
try {
final URI ivyUri = calculateIvyURI(module);
final FileInfo fileInfo = transport.get(ivyUri);
final IvyXml ivyXml = new IvyXmlParser().parse(module, fileInfo.getContent());
return ivyXml;
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override
public void get(Transport transport, Module module, Artifact artifact, File destination) {
try {
final URI uri = calculateArtifactURI(module, artifact);
transport.get(uri, destination);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override
public void put(Transport transport, Module module, Artifact artifact, File source) {
throw new UnsupportedOperationException("Not implemented");
}
protected URI calculateIvyURI(Module module) throws URISyntaxException {
final Group group = module.getGroup();
final Artifact artifact = module.getArtifact();
final String path = ivyPattern.replaceAll(P_ORG, group.get()).replaceAll(P_MODULE, artifact.getName())
.replaceAll(P_VERSION, artifact.getVersion().plain());
return new URI(base + path);
}
protected URI calculateSearchURI(Group group, UnresolvedArtifact artifact) throws URISyntaxException {
final String path = searchPattern.replaceAll(P_ORG, group.get()).replaceAll(P_MODULE, artifact.getName());
return new URI(base + path);
}
protected URI calculateArtifactURI(Module module, Artifact artifact) throws URISyntaxException {
final Group group = module.getGroup();
final String path = artifactPattern.replaceAll(P_ORG, group.get()).replaceAll(P_MODULE, module.getArtifact().getName())
.replaceAll(P_VERSION, module.getArtifact().getVersion().plain()).replaceAll(P_ARTIFACT, artifact.asString())
.replaceAll(P_EXT, artifact.getExtension());
return new URI(base + path);
}
protected String lastPathElement(String path) {
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
return path.substring(path.lastIndexOf('/') + 1);
}
}