/*-
* Copyright (c) 2012-2015 Red Hat, Inc.
*
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fedoraproject.xmvn.mojo;
import static org.fedoraproject.xmvn.mojo.Utils.aetherArtifact;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Exclusion;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.RepositorySystemSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.fedoraproject.xmvn.artifact.Artifact;
import org.fedoraproject.xmvn.artifact.DefaultArtifact;
import org.fedoraproject.xmvn.deployer.Deployer;
import org.fedoraproject.xmvn.deployer.DeploymentRequest;
import org.fedoraproject.xmvn.deployer.DeploymentResult;
import org.fedoraproject.xmvn.utils.ArtifactUtils;
/**
* @author Mikolaj Izdebski
*/
@Mojo( name = "install", aggregator = true, requiresDependencyResolution = ResolutionScope.NONE )
@Named
public class InstallMojo
extends AbstractMojo
{
private static final Set<String> TYCHO_PACKAGING_TYPES = new LinkedHashSet<>();
static
{
TYCHO_PACKAGING_TYPES.add( "eclipse-plugin" );
TYCHO_PACKAGING_TYPES.add( "eclipse-test-plugin" );
TYCHO_PACKAGING_TYPES.add( "eclipse-feature" );
TYCHO_PACKAGING_TYPES.add( "eclipse-update-site" );
TYCHO_PACKAGING_TYPES.add( "eclipse-application" );
TYCHO_PACKAGING_TYPES.add( "eclipse-repository" );
}
private static boolean isTychoProject( MavenProject project )
{
return TYCHO_PACKAGING_TYPES.contains( project.getPackaging() );
}
private final Logger logger = LoggerFactory.getLogger( InstallMojo.class );
@Parameter( defaultValue = "${reactorProjects}", readonly = true, required = true )
private List<MavenProject> reactorProjects;
@Parameter( readonly = true, defaultValue = "${repositorySystemSession}" )
private RepositorySystemSession repoSession;
private final Deployer deployer;
@Inject
public InstallMojo( Deployer deployer )
{
this.deployer = deployer;
}
void setReactorProjects( List<MavenProject> reactorProjects )
{
this.reactorProjects = reactorProjects;
}
/**
* Dump project dependencies with "system" scope and fail if there are any such dependencies are found.
*/
private void handleSystemDependencies()
throws MojoFailureException
{
boolean systemDepsFound = false;
for ( MavenProject project : reactorProjects )
{
Set<Artifact> systemDeps = new LinkedHashSet<>();
for ( Dependency dependency : project.getModel().getDependencies() )
{
// Ignore dependencies injected by Tycho
if ( isTychoProject( project ) )
continue;
if ( dependency.getScope() != null && dependency.getScope().equals( "system" ) )
{
systemDeps.add( new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(),
dependency.getClassifier(), dependency.getType(),
dependency.getVersion() ) );
}
}
if ( !systemDeps.isEmpty() )
{
systemDepsFound = true;
logger.error( "Reactor project {} has system-scoped dependencies: {}",
aetherArtifact( project.getArtifact() ),
ArtifactUtils.collectionToString( systemDeps, true ) );
}
}
if ( systemDepsFound )
{
throw new MojoFailureException( "Some reactor artifacts have dependencies with scope \"system\"."
+ " Such dependencies are not supported by XMvn installer."
+ " You should either remove any dependencies with scope \"system\""
+ " before the build or not run XMvn instaler." );
}
}
private String getProjectProperty( Artifact artifact, String key )
{
Path propertiesPath = Paths.get( ".xmvn/properties" );
if ( !Files.exists( propertiesPath ) )
return null;
Properties properties = new Properties();
try (InputStream stream = Files.newInputStream( propertiesPath ))
{
properties.load( stream );
}
catch ( IOException e )
{
return null;
}
String artifactKey = artifact.getGroupId() + "/" + artifact.getArtifactId() + "/" + artifact.getVersion();
return properties.getProperty( artifactKey + "/" + key );
}
private void deployArtifact( Artifact artifact, String type, Model model )
throws MojoExecutionException
{
DeploymentRequest request = new DeploymentRequest();
request.setArtifact( artifact );
request.addProperty( "type", type );
request.addProperty( "requiresJava", getProjectProperty( artifact, "compilerTarget" ) );
for ( Dependency dependency : model.getDependencies() )
{
String scope = dependency.getScope();
if ( scope == null || scope.equals( "compile" ) || scope.equals( "runtime" ) )
{
Artifact dependencyArtifact = Utils.dependencyArtifact( repoSession, dependency );
List<Artifact> exclusions = new ArrayList<>();
for ( Exclusion e : dependency.getExclusions() )
{
exclusions.add( new DefaultArtifact( e.getGroupId(), e.getArtifactId() ) );
}
request.addDependency( dependencyArtifact, dependency.isOptional(), exclusions );
}
}
DeploymentResult result = deployer.deploy( request );
if ( result.getException() != null )
throw new MojoExecutionException( "Failed to deploy artifact " + artifact, result.getException() );
}
@Override
public void execute()
throws MojoExecutionException, MojoFailureException
{
handleSystemDependencies();
for ( MavenProject project : reactorProjects )
{
Artifact mainArtifact = aetherArtifact( project.getArtifact() );
Path mainArtifactPath = mainArtifact.getPath();
logger.debug( "Installing main artifact {}", mainArtifact );
logger.debug( "Artifact file is {}", mainArtifactPath );
if ( mainArtifactPath != null && !Files.isRegularFile( mainArtifactPath ) )
{
logger.info( "Skipping installation of artifact {}: artifact file is not a regular file",
mainArtifactPath );
mainArtifactPath = null;
}
String type = project.getPackaging();
if ( mainArtifactPath != null )
deployArtifact( mainArtifact, type, project.getModel() );
if ( !isTychoProject( project ) )
{
Artifact rawPomArtifact =
new DefaultArtifact( mainArtifact.getGroupId(), mainArtifact.getArtifactId(), "pom",
mainArtifact.getClassifier(), mainArtifact.getVersion() );
File rawPomFile = project.getFile();
Path rawPomPath = rawPomFile != null ? rawPomFile.toPath() : null;
logger.debug( "Raw POM path: {}", rawPomPath );
rawPomArtifact = rawPomArtifact.setPath( rawPomPath );
deployArtifact( rawPomArtifact, type, project.getModel() );
}
Set<Artifact> attachedArtifacts = new LinkedHashSet<>();
for ( org.apache.maven.artifact.Artifact mavenArtifact : project.getAttachedArtifacts() )
attachedArtifacts.add( aetherArtifact( mavenArtifact ) );
for ( Artifact attachedArtifact : attachedArtifacts )
{
Path attachedArtifactPath = attachedArtifact.getPath();
logger.debug( "Installing attached artifact {}", attachedArtifact );
logger.debug( "Artifact file is {}", attachedArtifactPath );
if ( attachedArtifactPath != null && !Files.isRegularFile( attachedArtifactPath ) )
{
logger.info( "Skipping installation of attached artifact {}: artifact file is not a regular file",
attachedArtifact );
continue;
}
deployArtifact( attachedArtifact, type, project.getModel() );
}
}
}
}