blob: 5e5ad564e6a006bae0e34cd9c6b35f2eb0d5d04d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2014 Xored Software Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.maven.util;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.io.URLInputStreamFacade;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.metadata.Metadata.Nature;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.resolution.MetadataRequest;
import org.eclipse.aether.resolution.MetadataResult;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
import org.eclipse.aether.resolution.VersionRangeResult;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.metadata.DefaultMetadata;
import org.eclipse.aether.util.version.GenericVersionScheme;
import org.eclipse.aether.version.InvalidVersionSpecificationException;
import org.eclipse.aether.version.Version;
import org.eclipse.aether.version.VersionScheme;
public class CoordResolver {
private final RepositorySystem repoSys;
private final RepositorySystemSession repoSession;
private final File baseDir;
private final File targetDir;
private final Log log;
public CoordResolver(File baseDir, File targetDir, RepositorySystem repoSys, RepositorySystemSession repoSession,
Log log) {
this.repoSys = repoSys;
this.repoSession = repoSession;
this.baseDir = baseDir;
this.targetDir = targetDir;
this.log = log;
}
/**
* Resolves given coordinates against given repos. Returns absolute location
* of artifact archive If artifact is not resolved, throws
* MojoExecutionException, never returns {@code null}
*
* @param codename
* The name of artifact denoted by coords, for friendly messages
* in log
* @param coords
* Artifact coords
* @param repos
* List or remote repositories
* @return
* @throws MojoFailureException
* in case of failure
* @throws MojoExecutionException
*/
public File resolve(String codename, Coords coords, List<RemoteRepository> repos)
throws MojoFailureException, MojoExecutionException {
return coords.getExplicit() == null ? resolveArtifact(codename, coords, repos)
: resolveFile(coords.getExplicit());
}
private File resolveArtifact(String codename, Coords coords, List<RemoteRepository> repos)
throws MojoExecutionException, MojoFailureException {
if (coords.getExtension() == null) {
coords.setExtension(ArchiveUtil.DEFAULT_EXTENSION);
logDefaultValue(codename, "extension", coords.getExtension());
}
if (coords.getClassifier() == null) {
coords.setClassifier(PlatformUtil.getEclipseClassifier());
log.info("Sys arch is " + System.getProperty("os.arch"));
logDefaultValue(codename, "classifier", coords.getClassifier());
}
Artifact artifact = new DefaultArtifact(coords.getGroupId(), coords.getArtifactId(), coords.getClassifier(),
coords.getExtension(), coords.getVersion());
if (coords.getVersion() == null) {
artifact = resolveVersion(artifact, repos);
logDefaultValue(codename, "version", artifact.getVersion());
}
if (artifact.isSnapshot() && hasRemoteUpdates(artifact, repos)) {
log.info(String.format("%s is at snapshot version and has remote updates, purging local versions...",
codename));
purgeLocalVersion(artifact);
}
log.info(String.format("Resolving artifact %s, this may take a while ...", artifact));
ArtifactRequest request = new ArtifactRequest(artifact, repos, null);
try {
ArtifactResult result = repoSys.resolveArtifact(repoSession, request);
File resultFile = result.getArtifact().getFile();
log.info(String.format("Artifact %s is resolved to %s", artifact, resultFile));
return resultFile;
} catch (ArtifactResolutionException e) {
throw new MojoExecutionException(String.format("Failed to resolve artifact %s", artifact), e);
}
}
private void purgeLocalVersion(Artifact artifact) throws MojoExecutionException {
LocalRepositoryManager localManager = repoSession.getLocalRepositoryManager();
File dir = new File(localManager.getRepository().getBasedir(), localManager.getPathForLocalArtifact(artifact))
.getParentFile();
log.info("Removing directory " + dir);
try {
FileUtils.deleteDirectory(dir);
} catch (IOException e) {
throw new MojoExecutionException("FAiled to clean repo", e);
}
}
private final VersionScheme scheme = new GenericVersionScheme();
private boolean hasRemoteUpdates(Artifact artifact, List<RemoteRepository> repos) {
List<MetadataRequest> metadataRequests = new ArrayList<MetadataRequest>();
for (RemoteRepository repo : repos) {
Metadata metadata = new DefaultMetadata(artifact.getGroupId(), artifact.getArtifactId(),
artifact.getVersion(), "", Nature.SNAPSHOT);
MetadataRequest req = new MetadataRequest(metadata, repo, null);
metadataRequests.add(req);
}
List<MetadataResult> results = repoSys.resolveMetadata(repoSession, metadataRequests);
boolean haveUpdates = false;
try {
Version currentVersion = scheme.parseVersion(artifact.getVersion());
for (MetadataResult result : results) {
if (result.getException() == null && !result.isMissing() && result.isResolved() && result.isUpdated()) {
haveUpdates |= scheme.parseVersion(result.getMetadata().getVersion()).compareTo(currentVersion) > 0;
}
}
} catch (InvalidVersionSpecificationException e) {
log.warn(String.format("Cannot parse version %s", e.getVersion()));
return false;
}
return haveUpdates;
}
/**
* For given artifact, resolves available versions and returns the same
* artifact with version set to the latest
*
* @param artifact
* @param repos
* @return
* @throws MojoExecutionException
* @throws MojoFailureException
*/
private Artifact resolveVersion(Artifact artifact, List<RemoteRepository> repos)
throws MojoExecutionException, MojoFailureException {
artifact = artifact.setVersion("[0.0.1,)");
VersionRangeRequest versionRequest = new VersionRangeRequest();
versionRequest.setArtifact(artifact);
versionRequest.setRepositories(repos);
try {
VersionRangeResult versionResult = repoSys.resolveVersionRange(repoSession, versionRequest);
List<Version> versions = versionResult.getVersions();
if (versions.isEmpty()) {
throw new MojoFailureException(String.format("Failed to resolve artifact %s", artifact));
}
return artifact.setVersion(versions.get(versions.size() - 1).toString());
} catch (VersionRangeResolutionException e) {
throw new MojoExecutionException(String.format("Failed to resolve versions for artifact %s", artifact), e);
}
}
private File resolveFile(String path) throws MojoFailureException, MojoExecutionException {
path = performSubstitution(path);
// dummy http downloader
if (path.startsWith("http://") || path.startsWith("https://")) {
return downloadFromHttp(path);
}
File result = new File(path);
if (!result.isAbsolute()) {
result = new File(baseDir, path);
}
if (!result.exists()) {
throw new MojoFailureException(String.format("The explicit location %s is not valid", result));
}
return result;
}
private File downloadFromHttp(String path) throws MojoExecutionException {
URL url;
try {
url = new URL(path);
} catch (MalformedURLException e) {
throw new MojoExecutionException(String.format("Malformed URL in explicit AUT location: %s", path), e);
}
int lastSlashIndex = path.lastIndexOf('/');
String fileName = lastSlashIndex == -1 ? "unknown_file" : path.substring(lastSlashIndex);
File resultFile = new File(targetDir, fileName);
try {
log.info(String.format("Downloading artifact from %s...", path));
FileUtils.copyStreamToFile(new URLInputStreamFacade(url), resultFile);
} catch (IOException e) {
throw new MojoExecutionException("Download failed", e);
}
return resultFile;
}
private String performSubstitution(String str) {
if (str.indexOf("[platform]") > 0) {
str = str.replaceAll("\\[platform\\]", PlatformUtil.getEclipseClassifier());
}
if (str.indexOf("[classifier]") > 0) {
str = str.replaceAll("\\[classifier\\]", PlatformUtil.getEclipseClassifier());
}
return str;
}
/**
* Displays information about value specified for omitted properties
*
* @param codename
* @param property
* @param value
* @return
*/
private void logDefaultValue(String codename, String property, String value) {
log.info(String.format("%s is not specified for %s, setting to %s by default", property, codename, value));
}
}