package net.sourceforge.javautil.classloader.resolver.impl.maven;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import net.sourceforge.javautil.classloader.resolver.IClassArtifactReference;
import net.sourceforge.javautil.classloader.resolver.IClassPackageDescriptor;
import net.sourceforge.javautil.classloader.resolver.IClassPackageReference;
import net.sourceforge.javautil.classloader.resolver.IClassPackageRepositoryLocal;
import net.sourceforge.javautil.classloader.resolver.IClassPackageRepositoryRemote;
import net.sourceforge.javautil.classloader.resolver.IClassPackage.IVersion;
import net.sourceforge.javautil.classloader.resolver.IClassPackageResolver;
import net.sourceforge.javautil.classloader.resolver.impl.ClassPackageImpl;
import net.sourceforge.javautil.classloader.util.ClassPackageUtil;
import net.sourceforge.javautil.common.ChecksumUtil;
import net.sourceforge.javautil.common.CollectionUtil;
import net.sourceforge.javautil.common.URLUtil;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.common.io.IVirtualPath;
import net.sourceforge.javautil.common.io.impl.SimplePath;
import net.sourceforge.javautil.common.logging.ILogger;
import net.sourceforge.javautil.common.logging.LoggingContext;
import net.sourceforge.javautil.common.xml.XMLDocument;
import net.sourceforge.javautil.common.io.IModifiableInputSource.URLInputSource;
/**
* A remote maven repository.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: MavenRepositoryRemote.java 2745 2011-02-05 04:23:36Z ponderator $
*/
public class MavenRepositoryRemote implements IClassPackageRepositoryRemote {
public static final ILogger log = LoggingContext.getContextualLogger(MavenRepositoryRemote.class);
public static final String DEFAULT_REPOSITORY_OVERRIDE = "net.sf.javautil.maven.repository.remote";
public static final String DEFAULT_APACHE_REPOSITORY = "http://repo1.maven.org/maven2/";
public static final String METADATA_FILENAME = "maven-metadata.xml";
public Map<String, MavenMetaData> metaData = new HashMap<String, MavenMetaData>();
protected Map<String, ProjectObjectModel> descriptorCache = new HashMap<String, ProjectObjectModel>();
public static MavenRepositoryRemote createDefault () {
try {
String url = System.getProperty(DEFAULT_REPOSITORY_OVERRIDE);
if (url == null) url = DEFAULT_APACHE_REPOSITORY;
return new MavenRepositoryRemote("central", new URL(url));
} catch (MalformedURLException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
private final String name;
private final URL repository;
/**
* @param repository The URL of the remote repository
*/
public MavenRepositoryRemote(String name, URL repository) {
if (!repository.toExternalForm().endsWith("/")) {
try {
this.repository = new URL(repository.toExternalForm() + "/");
} catch (MalformedURLException e) {
throw ThrowableManagerRegistry.caught(e);
}
} else
this.repository = repository;
this.name = name;
}
public URL getRepositoryURL() { return this.repository; }
public List<IVersion> getVersionsAvailable (IClassArtifactReference reference) {
log.info("Fetching versions for: " + reference);
List<IVersion> versions = new ArrayList<IVersion>();
MavenMetaData meta = this.getMetaData(reference);
if (meta != null) {
for (String version : meta.getVersioning().getVersions())
versions.add(ClassPackageImpl.decode(version));
}
return versions;
}
public IClassPackageDescriptor getDescriptor(IClassPackageResolver resolver, IClassPackageReference reference) {
String id = ClassPackageUtil.toPackageString(reference);
if (this.descriptorCache.containsKey(id)) {
return this.descriptorCache.get(id);
}
log.info("Fetching descriptor for: " + reference);
URL url = this.getResource(reference, this.createFilenamePrefix(reference) + ".pom");
ProjectObjectModel pom = url == null ? null : ProjectObjectModel.parse(resolver, new URLInputSource(url));
this.descriptorCache.put(id, pom);
return pom;
}
public boolean contains(IClassArtifactReference reference) {
log.info("Fetching contains for: " + reference);
return this.getResource(reference, "/") != null;
}
public boolean contains(IClassPackageResolver resolver, IClassPackageReference reference) {
log.info("Fetching contains for: " + reference);
return this.getDescriptor(resolver, reference) != null;
}
public String getName() { return this.name; }
public URL getResource(IClassPackageReference reference, String name) {
try {
if (reference.getGroupId() == null || reference.getArtifactId() == null || reference.getVersion() == null) return null;
if ("".equals(reference.getGroupId()) || "".equals(reference.getArtifactId())) return null;
URL url = new URL(repository, this.createPackagePath(reference).append(name).toString("/"));
return URLUtil.exists(url) ? url : null;
} catch (MalformedURLException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public URL getResource(IClassArtifactReference reference, String name) {
try {
if (reference.getGroupId() == null || reference.getArtifactId() == null) return null;
if ("".equals(reference.getGroupId()) || "".equals(reference.getArtifactId())) return null;
URL url = new URL(repository, this.createArtifactPath(reference).append(name).toString("/"));
return URLUtil.exists(url) ? url : null;
} catch (MalformedURLException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public String createFilenamePrefix(IClassPackageReference reference) {
return new StringBuffer()
.append( reference.getArtifactId() )
.append( "-" )
.append( reference.getVersion().toVersionString() )
.toString();
}
public IVirtualPath createPackagePath(IClassPackageReference reference) {
return new SimplePath( CollectionUtil.push(reference.getGroupId().split("\\."),
reference.getArtifactId(), reference.getVersion().toVersionString()) );
}
public IVirtualPath createArtifactPath(IClassArtifactReference reference) {
return new SimplePath( CollectionUtil.push(reference.getGroupId().split("\\."), reference.getArtifactId() ));
}
/**
* @param groupId The group id of the package
* @param artifactId The artifact id of the package
* @return The meta data wrapper if meta data was present, otherwise false
*/
public MavenMetaData getMetaData (IClassArtifactReference reference) {
if (log.isInfo())
log.info("Fetching meta data for: " + reference);
String id = reference.getGroupId() + ":" + reference.getArtifactId();
if (this.metaData.containsKey(id)) return this.metaData.get(id);
MavenMetaData meta = null;
URL url = this.getResource(reference, METADATA_FILENAME);
if (url != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ChecksumUtil.downloadWithChecksum(url, null, baos, false);
meta = XMLDocument.read(new ByteArrayInputStream(baos.toByteArray()), MavenMetaData.class);
} catch (Exception e) {
ThrowableManagerRegistry.caught(e);
}
}
this.metaData.put(id, meta);
return meta;
}
}