org.apache.maven.ReactorReader Maven / Gradle / Ivy
The newest version!
package org.apache.maven;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.repository.WorkspaceRepository;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* An implementation of a workspace reader that knows how to search the Maven reactor for artifacts.
*
* @author Jason van Zyl
*/
class ReactorReader
implements WorkspaceReader
{
private static final Collection JAR_LIKE_TYPES = Arrays.asList( "jar", "test-jar", "ejb-client" );
private static final Collection COMPILE_PHASE_TYPES = Arrays.asList( "jar", "ejb-client" );
private Map projectsByGAV;
private Map> projectsByGA;
private WorkspaceRepository repository;
public ReactorReader( Map reactorProjects )
{
projectsByGAV = reactorProjects;
projectsByGA = new HashMap>( reactorProjects.size() * 2 );
for ( MavenProject project : reactorProjects.values() )
{
String key = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
List projects = projectsByGA.get( key );
if ( projects == null )
{
projects = new ArrayList( 1 );
projectsByGA.put( key, projects );
}
projects.add( project );
}
repository = new WorkspaceRepository( "reactor", new HashSet( projectsByGAV.keySet() ) );
}
private File find( MavenProject project, Artifact artifact )
{
if ( "pom".equals( artifact.getExtension() ) )
{
return project.getFile();
}
org.apache.maven.artifact.Artifact projectArtifact = findMatchingArtifact( project, artifact );
if ( hasArtifactFileFromPackagePhase( projectArtifact ) )
{
return projectArtifact.getFile();
}
else if ( !hasBeenPackaged( project ) )
{
// fallback to loose class files only if artifacts haven't been packaged yet
// and only for plain old jars. Not war files, not ear files, not anything else.
if ( isTestArtifact( artifact ) )
{
if ( project.hasLifecyclePhase( "test-compile" ) )
{
return new File( project.getBuild().getTestOutputDirectory() );
}
}
else
{
String type = artifact.getProperty( "type", "" );
if ( project.hasLifecyclePhase( "compile" ) && COMPILE_PHASE_TYPES.contains( type ) )
{
return new File( project.getBuild().getOutputDirectory() );
}
}
}
// The fall-through indicates that the artifact cannot be found;
// for instance if package produced nothing or classifier problems.
return null;
}
private boolean hasArtifactFileFromPackagePhase( org.apache.maven.artifact.Artifact projectArtifact )
{
return projectArtifact != null && projectArtifact.getFile() != null && projectArtifact.getFile().exists();
}
private boolean hasBeenPackaged( MavenProject project )
{
return project.hasLifecyclePhase( "package" ) || project.hasLifecyclePhase( "install" )
|| project.hasLifecyclePhase( "deploy" );
}
/**
* Tries to resolve the specified artifact from the artifacts of the given project.
*
* @param project The project to try to resolve the artifact from, must not be null
.
* @param requestedArtifact The artifact to resolve, must not be null
.
* @return The matching artifact from the project or null
if not found.
*
* Note that this
*/
private org.apache.maven.artifact.Artifact findMatchingArtifact( MavenProject project, Artifact requestedArtifact )
{
String requestedRepositoryConflictId = getConflictId( requestedArtifact );
org.apache.maven.artifact.Artifact mainArtifact = project.getArtifact();
if ( requestedRepositoryConflictId.equals( getConflictId( mainArtifact ) ) )
{
return mainArtifact;
}
Collection attachedArtifacts = project.getAttachedArtifacts();
if ( attachedArtifacts != null && !attachedArtifacts.isEmpty() )
{
for ( org.apache.maven.artifact.Artifact attachedArtifact : attachedArtifacts )
{
/*
* Don't use the conflict ids, use a customized comparison that takes various ideas into account.
*/
if ( attachedArtifactComparison ( requestedArtifact, attachedArtifact ) )
{
return attachedArtifact;
}
}
}
return null;
}
/**
* Try to satisfy both MNG-4065 and MNG-5214. Consider jar and test-jar equivalent.
* @param requestedType
* @param artifactType
* @return
*/
private boolean attachedArtifactComparison ( Artifact requestedArtifact, org.apache.maven.artifact.Artifact attachedArtifact )
{
if ( ! requestedArtifact.getGroupId().equals ( attachedArtifact.getGroupId() ) )
{
return false;
}
if ( ! requestedArtifact.getArtifactId().equals ( attachedArtifact.getArtifactId() ) )
{
return false;
}
String requestedExtension = requestedArtifact.getExtension();
String attachedExtension = null;
if ( attachedArtifact.getArtifactHandler() != null )
{
attachedExtension = attachedArtifact.getArtifactHandler().getExtension();
}
String requestedType = requestedArtifact.getProperty ( "type", "" );
String attachedType = attachedArtifact.getType();
boolean typeOk = false;
if ( requestedExtension.equals ( attachedExtension ) )
{
// the ideal case.
typeOk = true;
}
else if ( requestedType.equals( attachedType ) )
{
typeOk = true;
}
else if ( JAR_LIKE_TYPES.contains( requestedType ) && JAR_LIKE_TYPES.contains( attachedType ) )
{
typeOk = true;
}
if ( !typeOk )
{
return false;
}
return requestedArtifact.getClassifier().equals ( attachedArtifact.getClassifier() );
}
/**
* Gets the repository conflict id of the specified artifact. Unlike the dependency conflict id, the repository
* conflict id uses the artifact file extension instead of the artifact type. Hence, the repository conflict id more
* closely reflects the identity of artifacts as perceived by a repository.
*
* @param artifact The artifact, must not be null
.
* @return The repository conflict id, never null
.
*/
private String getConflictId( org.apache.maven.artifact.Artifact artifact )
{
StringBuilder buffer = new StringBuilder( 128 );
buffer.append( artifact.getGroupId() );
buffer.append( ':' ).append( artifact.getArtifactId() );
if ( artifact.getArtifactHandler() != null )
{
buffer.append( ':' ).append( artifact.getArtifactHandler().getExtension() );
}
else
{
buffer.append( ':' ).append( artifact.getType() );
}
if ( artifact.hasClassifier() )
{
buffer.append( ':' ).append( artifact.getClassifier() );
}
return buffer.toString();
}
private String getConflictId( Artifact artifact )
{
StringBuilder buffer = new StringBuilder( 128 );
buffer.append( artifact.getGroupId() );
buffer.append( ':' ).append( artifact.getArtifactId() );
buffer.append( ':' ).append( artifact.getExtension() );
if ( artifact.getClassifier().length() > 0 )
{
buffer.append( ':' ).append( artifact.getClassifier() );
}
return buffer.toString();
}
/**
* Determines whether the specified artifact refers to test classes.
*
* @param artifact The artifact to check, must not be {@code null}.
* @return {@code true} if the artifact refers to test classes, {@code false} otherwise.
*/
private static boolean isTestArtifact( Artifact artifact )
{
return ( "test-jar".equals( artifact.getProperty( "type", "" ) ) )
|| ( "jar".equals( artifact.getExtension() ) && "tests".equals( artifact.getClassifier() ) );
}
public File findArtifact( Artifact artifact )
{
String projectKey = ArtifactUtils.key( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() );
MavenProject project = projectsByGAV.get( projectKey );
if ( project != null )
{
File file = find( project, artifact );
if ( file == null && project != project.getExecutionProject() )
{
file = find( project.getExecutionProject(), artifact );
}
return file;
}
return null;
}
public List findVersions( Artifact artifact )
{
String key = ArtifactUtils.versionlessKey( artifact.getGroupId(), artifact.getArtifactId() );
List projects = projectsByGA.get( key );
if ( projects == null || projects.isEmpty() )
{
return Collections.emptyList();
}
List versions = new ArrayList();
for ( MavenProject project : projects )
{
if ( find( project, artifact ) != null )
{
versions.add( project.getVersion() );
}
}
return Collections.unmodifiableList( versions );
}
public WorkspaceRepository getRepository()
{
return repository;
}
}