/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.eclipse.mavenapi.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactScopeEnum;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.RepositoryPolicy;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.repository.metadata.ArtifactMetadata;
import org.apache.maven.repository.metadata.MetadataResolutionRequest;
import org.apache.maven.repository.metadata.MetadataResolutionResult;
import org.apache.maven.repository.metadata.MetadataTreeNode;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Profile;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.SettingsUtils;
import org.codehaus.plexus.PlexusContainer;
import org.ebayopensource.turmeric.eclipse.mavenapi.exception.MavenEclipseApiException;
import org.ebayopensource.turmeric.eclipse.mavenapi.internal.collections.ListUtil;
import org.ebayopensource.turmeric.eclipse.mavenapi.internal.resources.Messages;
import org.ebayopensource.turmeric.eclipse.mavenapi.internal.util.MavenApiUtil;
import org.ebayopensource.turmeric.eclipse.mavenapi.intf.IMavenEclipseApi;
import org.maven.ide.eclipse.MavenPlugin;
import org.maven.ide.eclipse.internal.embedder.MavenImpl;
/**
* The Class AbstractMavenApi.
*
* @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
*/
public abstract class AbstractMavenApi implements IMavenEclipseApi {
/** The Constant PACKAGING_TYPE_MAVENPLUGIN. */
public static final String PACKAGING_TYPE_MAVENPLUGIN = "maven-plugin";
/** The Constant PACKAGING_TYPE_POM. */
public static final String PACKAGING_TYPE_POM = "pom";
/**
* _get known repositories.
*
* @param embedder the maven implementation to use
* @param packagingType the packaging type to filter by
* @return A list of known repositories filtered by packaging type
* @throws MavenEclipseApiException the maven eclipse api exception
*/
protected List<ArtifactRepository> _getKnownRepositories(
MavenImpl embedder, String packagingType)
throws MavenEclipseApiException {
if (embedder == null)
throw new MavenEclipseApiException();
try {
Settings settings = embedder.getSettings();
if (settings == null) {
throw new MavenEclipseApiException(Messages.ERROR_NULL_SETTINGS);
}
return _getKnownRepositories(embedder.getPlexusContainer(),
settings, packagingType);
} catch (Exception anyEx) {
anyEx.printStackTrace();
throw new MavenEclipseApiException(anyEx);
}
}
/**
* Return the Maven remote repositories defined in the Maven settings.xml
* file. The returned list of repositories depend on the pacakgeType.
*
* For <code>maven-plugin</code> package type, it will return
* pluginRepositories, and all other types will return Mirrors and
* Repositories.
*
* @param plexus the plexus
* @param settings the settings.xml file to use
* @param packagingType the pom packaging type to return.
* @return the remote repositories defined in the Maven settings.xml file.
* @throws MavenEclipseApiException the maven eclipse api exception
*/
protected List<ArtifactRepository> _getKnownRepositories(
PlexusContainer plexus, Settings settings, String packagingType)
throws MavenEclipseApiException {
final boolean needPluginRepo = PACKAGING_TYPE_MAVENPLUGIN
.equalsIgnoreCase(packagingType);
if (settings == null) {
throw new MavenEclipseApiException(Messages.ERROR_NULL_SETTINGS);
}
List<String> activeProfiles = (List<String>) settings
.getActiveProfiles();
if (activeProfiles == null || activeProfiles.size() < 1) {
throw new MavenEclipseApiException(
Messages.ERROR_NO_ACTIVE_PROFILES);
}
List<ArtifactRepository> repositories = new ArrayList<ArtifactRepository>(
8);
try {
// MavenTools mtools = (MavenTools) plexus
// .lookup(org.apache.maven.MavenTools.class);
RepositorySystem rs = plexus.lookup(RepositorySystem.class);
if (needPluginRepo == false) {
for (Mirror mirror : (List<Mirror>) settings.getMirrors()) {
final org.apache.maven.model.Repository repo = new org.apache.maven.model.Repository();
repo.setId(mirror.getId());
// repo.setModelEncoding(mirror.getModelEncoding());
repo.setUrl(mirror.getUrl());
final RepositoryPolicy snapshotPolicty = new RepositoryPolicy();
snapshotPolicty.setEnabled(false);
// snapshotPolicty.setModelEncoding(mirror.getModelEncoding());
repo.setSnapshots(snapshotPolicty);
final RepositoryPolicy releasedPolicty = new RepositoryPolicy();
releasedPolicty.setEnabled(true);
// releasedPolicty.setModelEncoding(mirror.getModelEncoding());
repo.setReleases(releasedPolicty);
// repositories.add(mtools.buildArtifactRepository(repo));
repositories.add(rs.buildArtifactRepository(repo));
}
}
List<Profile> profiles = (List<Profile>) settings.getProfiles();
for (Profile p : profiles) {
if (activeProfiles.contains(p.getId())) {
org.apache.maven.model.Profile mp = SettingsUtils
.convertFromSettingsProfile(p);
if (needPluginRepo == true) {
// requires plugin repositories
final List<org.apache.maven.model.Repository> pluginRepos = mp
.getPluginRepositories();
// repositories
// .addAll((List<ArtifactRepository>) mtools
// .buildArtifactRepositories(pluginRepos));
for (org.apache.maven.model.Repository repo : pluginRepos) {
repositories.add(rs.buildArtifactRepository(repo));
}
} else {
final List<org.apache.maven.model.Repository> repos = mp
.getRepositories();
// repositories
// .addAll((List<ArtifactRepository>) mtools
// .buildArtifactRepositories(repos));
for (org.apache.maven.model.Repository repo : repos) {
repositories.add(rs.buildArtifactRepository(repo));
}
}
}
}
return repositories;
} catch (Exception anyEx) {
anyEx.printStackTrace();
throw new MavenEclipseApiException(anyEx);
}
}
/**
* Resolve an artifact using a particular maven implementation and repository.
*
* @param embedder the embedded version of maven to use
* @param repoSystem the repository to resolve against
* @param md the artifact metadata to search
* @return the resolved artifact
* @throws MavenEclipseApiException the maven eclipse api exception
*/
public Artifact resolveArtifact(MavenImpl embedder, RepositorySystem repoSystem, ArtifactMetadata md)
throws MavenEclipseApiException {
if (embedder == null)
throw new MavenEclipseApiException();
try {
List<ArtifactRepository> repos = _getKnownRepositories(embedder,
md.getType());
if (repos == null || repos.size() < 1) {
throw new MavenEclipseApiException(
Messages.ERROR_NO_REPOSITORIES);
}
Artifact artifact = null;
if (md.getClassifier() == null)
artifact = repoSystem.createArtifact(
md.getGroupId(), md.getArtifactId(), md.getVersion(),
md.getScope(), md.getType());
else
artifact = repoSystem
.createArtifactWithClassifier(md.getGroupId(),
md.getArtifactId(), md.getVersion(),
md.getType(), md.getClassifier());
if (artifact == null) {
throw new MavenEclipseApiException(Messages.ERROR_NULL_ARTIFACT);
}
// embedder.resolve(artifact, repos, embedder.getLocalRepository());
MavenApiUtil.resolveArtifact(repoSystem, artifact,
embedder.getLocalRepository(), repos);
return artifact;
} catch (Exception e) {
e.printStackTrace();
throw new MavenEclipseApiException(e);
}
}
private static void resolveArtifactAsClasspath(
final MetadataTreeNode treeNode, final ArtifactScopeEnum scope,
final Map<String, ArtifactMetadata> metadatas) {
final ArtifactMetadata md = treeNode.getMd();
if (metadatas.containsKey(md.toString()) == false
&& scope.equals(md.getScopeAsEnum()) && md.getGroupId() != null) {
metadatas.put(md.toString(), md);
if (treeNode.getChildren() != null) {
for (final MetadataTreeNode child : treeNode.getChildren()) {
resolveArtifactAsClasspath(child, scope, metadatas);
}
}
}
}
private void resolveArtifactDependencies(MavenImpl embedder, RepositorySystem repoSystem,
Artifact artifact, Set<Artifact> result) throws MavenEclipseApiException {
try {
MavenProject mProject = resolveArtifactAsProject(artifact);
for (Dependency dep : mProject.getDependencies()) {
ArtifactScopeEnum scope = ArtifactScopeEnum.valueOf(dep.getScope());
if (ArtifactScopeEnum.test.equals(scope) == false) {
Artifact art = resolveArtifact(embedder, repoSystem, new EclipseArtifactMetadata(
dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), dep.getType(),
scope, dep.getClassifier()));
if (result.contains(art) == false) {
result.add(art);
resolveArtifactDependencies(embedder, repoSystem, art, result);
}
}
}
} catch (Exception e) {
//ignore this one
}
}
/**
* Returns a list of Artifacts.
*
* @param embedder the maven implementation to use.
* @param md the artifact meta data.
* @return A list of Artifacts that were resolved.
* @throws MavenEclipseApiException the maven eclipse api exception
*/
public List<Artifact> resolveArtifactAsClasspath(MavenImpl embedder,
ArtifactMetadata md) throws MavenEclipseApiException {
List<Artifact> result = new ArrayList<Artifact>();
try {
if (embedder == null)
throw new MavenEclipseApiException("null embedder supplied");
if (md == null)
throw new MavenEclipseApiException(
"null metadata object supplied");
//FIXME below is a temp fix for the NPE from M2Eclipse, lets do this flow approach for now
RepositorySystem repoSystem = MavenApiHelper.getRepositorySystem();
Set<Artifact> data = new HashSet<Artifact>();
Artifact artifact = resolveArtifact(embedder, repoSystem, md);
data.add(artifact);
resolveArtifactDependencies(embedder, repoSystem, artifact, data);
result.addAll(ListUtil.array(data));
} catch (Exception e) {
e.printStackTrace();
throw new MavenEclipseApiException(e);
}
return result;
}
/**
* Resolves the artifact Metadata from the repository.
*
* @param embedder the maven implementation to use
* @param md the artifact metadata
* @return the MetadataResolutionResult
* @throws MavenEclipseApiException the maven eclipse api exception
*/
protected MetadataResolutionResult resolveArtifactMetadata(
MavenImpl embedder, ArtifactMetadata md)
throws MavenEclipseApiException {
if (embedder == null)
throw new MavenEclipseApiException("null embedder supplied");
if (md == null)
throw new MavenEclipseApiException("null metadata object supplied");
try {
List<ArtifactRepository> repos = _getKnownRepositories(embedder,
md.getType());
if (repos == null || repos.size() < 1) {
throw new MavenEclipseApiException(
Messages.ERROR_NO_REPOSITORIES);
}
//PlexusContainer plexus = embedder.getPlexusContainer();
ArtifactRepository localRepository = MavenPlugin.getDefault().getMaven().getLocalRepository();
List<ArtifactRepository> remoteRepositories = _getKnownRepositories(
embedder, md.getType());
MetadataResolutionRequest req = new MetadataResolutionRequest(md,
localRepository, remoteRepositories);
MetadataResolutionResult res = MavenApiUtil.resolveMetadata(
MavenApiHelper.getRepositorySystem(), req);
return res;
} catch (Exception e) {
e.printStackTrace();
throw new MavenEclipseApiException(e);
}
}
/**
* {@inheritDoc}
*/
@Override
public Model parsePom(final File file)
throws MavenEclipseApiException {
try {
return MavenPlugin.getDefault().getMaven().readModel(file);
} catch (Exception ex) {
throw new MavenEclipseApiException(ex);
}
}
}