package aQute.bnd.maven.lib.resolve;
import static java.util.Collections.singletonList;
import static org.eclipse.aether.metadata.Metadata.Nature.RELEASE;
import static org.eclipse.aether.metadata.Metadata.Nature.SNAPSHOT;
import java.io.File;
import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.Versioning;
import org.apache.maven.artifact.repository.metadata.io.MetadataReader;
import org.apache.maven.plugin.MojoExecutionException;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.metadata.DefaultMetadata;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RemotePostProcessor implements PostProcessor {
private static final Logger logger = LoggerFactory.getLogger(RemotePostProcessor.class);
private final LocalURLs localURLs;
private final MetadataReader metadataReader;
private final RepositorySystemSession session;
private final RepositorySystem system;
public RemotePostProcessor(
RepositorySystemSession session, RepositorySystem system, MetadataReader metadataReader,
LocalURLs localURLs) {
this.session = session;
this.system = system;
this.metadataReader = metadataReader;
this.localURLs = localURLs;
}
@Override
public ArtifactResult postProcessResult(ArtifactResult resolvedArtifact) throws MojoExecutionException {
if (localURLs == LocalURLs.REQUIRED) {
// Skip the search as we will use the local file anyway
return resolvedArtifact;
}
String repoId = resolvedArtifact.getRepository().getId();
Artifact artifact = resolvedArtifact.getArtifact();
if ("workspace".equals(repoId) || "local".equals(repoId)) {
logger.debug("Post processing {} to determine a remote source", artifact);
ArtifactResult postProcessed;
if (artifact.isSnapshot()) {
postProcessed = postProcessSnapshot(resolvedArtifact.getRequest(), artifact);
} else {
postProcessed = postProcessRelease(resolvedArtifact.getRequest(), artifact);
}
if (postProcessed != null) {
return postProcessed;
}
}
return resolvedArtifact;
}
private ArtifactResult postProcessSnapshot(ArtifactRequest request, Artifact artifact)
throws MojoExecutionException {
for (RemoteRepository repository : request.getRepositories()) {
if (!repository.getPolicy(true).isEnabled()) {
// Skip the repo if it isn't enabled for snapshots
continue;
}
// Remove the workspace from the session so that we don't use it
DefaultRepositorySystemSession newSession = new DefaultRepositorySystemSession(session);
newSession.setWorkspaceReader(null);
// Find the snapshot metadata for the module
MetadataRequest mr = new MetadataRequest().setRepository(repository)
.setMetadata(new DefaultMetadata(artifact.getGroupId(), artifact.getArtifactId(),
artifact.getVersion(), "maven-metadata.xml", SNAPSHOT));
for (MetadataResult metadataResult : system.resolveMetadata(newSession, singletonList(mr))) {
if (metadataResult.isResolved()) {
String version;
try {
Metadata read = metadataReader.read(metadataResult.getMetadata().getFile(), null);
Versioning versioning = read.getVersioning();
if (versioning == null || versioning.getSnapshotVersions() == null
|| versioning.getSnapshotVersions().isEmpty()) {
continue;
} else {
version = versioning.getSnapshotVersions().get(0).getVersion();
}
} catch (Exception e) {
throw new MojoExecutionException("Unable to read project metadata for " + artifact, e);
}
Artifact fullVersionArtifact = new org.eclipse.aether.artifact.DefaultArtifact(
artifact.getGroupId(), artifact.getArtifactId(), artifact.getClassifier(),
artifact.getExtension(), version);
try {
ArtifactResult result = system.resolveArtifact(newSession,
new ArtifactRequest().setArtifact(fullVersionArtifact).addRepository(repository));
if (result.isResolved()) {
File toUse = new File(session.getLocalRepository().getBasedir(),
session.getLocalRepositoryManager().getPathForRemoteArtifact(fullVersionArtifact,
repository, artifact.toString()));
if (!toUse.exists()) {
logger.warn("The resolved artifact {} does not exist at {}", fullVersionArtifact,
toUse);
continue;
} else {
logger.debug("Located snapshot file {} for artifact {}", toUse, artifact);
}
result.getArtifact().setFile(toUse);
return result;
}
} catch (ArtifactResolutionException e) {
logger.debug("Unable to locate the artifact {}", fullVersionArtifact, e);
}
}
}
}
logger.debug("Unable to resolve a remote repository containing {}", artifact);
return null;
}
private ArtifactResult postProcessRelease(ArtifactRequest request, Artifact artifact)
throws MojoExecutionException {
for (RemoteRepository repository : request.getRepositories()) {
if (!repository.getPolicy(false).isEnabled()) {
// Skip the repo if it isn't enabled for releases
continue;
}
// Remove the workspace from the session so that we don't use it
DefaultRepositorySystemSession newSession = new DefaultRepositorySystemSession(session);
newSession.setWorkspaceReader(null);
// Find the snapshot metadata for the module
MetadataRequest mr = new MetadataRequest().setRepository(repository).setMetadata(new DefaultMetadata(
artifact.getGroupId(), artifact.getArtifactId(), null, "maven-metadata.xml", RELEASE));
for (MetadataResult metadataResult : system.resolveMetadata(newSession, singletonList(mr))) {
if (metadataResult.isResolved()) {
try {
Metadata read = metadataReader.read(metadataResult.getMetadata().getFile(), null);
Versioning versioning = read.getVersioning();
if (versioning == null || versioning.getVersions() == null
|| versioning.getVersions().isEmpty()) {
continue;
} else if (versioning.getVersions().contains(artifact.getVersion())) {
ArtifactResult result = system.resolveArtifact(newSession,
new ArtifactRequest().setArtifact(artifact).addRepository(repository));
if (result.isResolved()) {
File toUse = new File(session.getLocalRepository().getBasedir(),
session.getLocalRepositoryManager().getPathForLocalArtifact(artifact));
if (!toUse.exists()) {
logger.warn("The resolved artifact {} does not exist at {}", artifact, toUse);
continue;
} else {
logger.debug("Located snapshot file {} for artifact {}", toUse, artifact);
}
result.getArtifact().setFile(toUse);
return result;
}
}
} catch (Exception e) {
throw new MojoExecutionException("Unable to read project metadata for " + artifact, e);
}
}
}
}
logger.debug("Unable to resolve a remote repository containing {}", artifact);
return null;
}
}