Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
58f1004
[MNG-4660] Include already built submodules in Reactor for local depe…
MartinKanters Jan 29, 2020
d957f72
[MNG-4660] Do not check whether calculated directory actually exists
mthmulders Jan 29, 2020
9eea00e
[MNG-4660] Inspect all projects in Reactor when retrieving metadata
mthmulders Feb 14, 2020
5474e22
[MNG-4660] Update comment
mthmulders Feb 14, 2020
5878623
[MNG-4660] Make ReactorReader aware of possible previous built artifacts
mthmulders Feb 14, 2020
ea4ce10
[MNG-4660] Only use module output directory when it has been compiled…
mthmulders Feb 14, 2020
0e9c66d
[MNG-4660] Update contributors list
mthmulders Feb 14, 2020
ea09c47
[MNG-4660] Prefer the target/classes directory when the packaged arti…
MartinKanters Mar 9, 2020
8056b59
[MNG-4660] Use Files.walk instead of .list to recursively check for n…
MartinKanters Mar 9, 2020
90acb01
Merge branch 'apache/master' into mng-4660-resume-from
MartinKanters Mar 26, 2020
0c98c5e
[mng-4660] Also include build output directory when the project does …
MartinKanters Mar 26, 2020
c496592
[mng-4660] Checkstyle fixes
MartinKanters Mar 26, 2020
bff090b
[MNG-4660] More sophisticated rules for determining project artifact
mthmulders Mar 26, 2020
a79ee04
[MNG-4660] Remove obsolete comment
mthmulders Mar 26, 2020
8ffb33c
[MNG-4660] Replace checking if the project has the lifecyclePhase "va…
MartinKanters Mar 26, 2020
3064231
[MNG-4660] Checkstyle - Removed unused import
MartinKanters Mar 28, 2020
a466d8a
[MNG-4660] Using Files.getLastModifiedTime instead of File#lastModifi…
MartinKanters Mar 29, 2020
ee8ff87
[MNG-4660] Use Stream#iterator to lazily traverse outputFiles
mthmulders Mar 29, 2020
043b59d
[MNG-4660] Take the build time into account when determining if the p…
MartinKanters Mar 30, 2020
7291407
[MNG-4660] Fix potential nullpointer
MartinKanters Mar 31, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 99 additions & 6 deletions maven-core/src/main/java/org/apache/maven/ReactorReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@
*/

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
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.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import javax.inject.Inject;
import javax.inject.Named;
Expand All @@ -37,6 +43,7 @@
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.internal.MavenWorkspaceReader;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.repository.WorkspaceRepository;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
Expand All @@ -57,16 +64,27 @@ class ReactorReader
private static final Collection<String> COMPILE_PHASE_TYPES =
Arrays.asList( "jar", "ejb-client", "war", "rar", "ejb3", "par", "sar", "wsr", "har", "app-client" );

private Logger logger;

private MavenSession session;

private Map<String, MavenProject> projectsByGAV;

private Map<String, List<MavenProject>> projectsByGA;

private WorkspaceRepository repository;

@Inject
ReactorReader( MavenSession session )
ReactorReader( MavenSession session, Logger logger )
{
projectsByGAV = session.getProjectMap();
this.logger = logger;
this.session = session;
this.projectsByGAV = new HashMap<>( session.getAllProjects().size() * 2 );
session.getAllProjects().forEach( project ->
{
String projectId = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
this.projectsByGAV.put( projectId, project );
} );

projectsByGA = new HashMap<>( projectsByGAV.size() * 2 );
for ( MavenProject project : projectsByGAV.values() )
Expand Down Expand Up @@ -152,12 +170,19 @@ private File find( MavenProject project, Artifact artifact )
}

Artifact projectArtifact = findMatchingArtifact( project, artifact );
File packagedArtifactFile = determinePreviouslyPackagedArtifactFile( project, projectArtifact );

if ( hasArtifactFileFromPackagePhase( projectArtifact ) )
{
return projectArtifact.getFile();
}
else if ( !hasBeenPackaged( project ) )
// Check whether an earlier Maven run might have produced an artifact that is still on disk.
else if ( packagedArtifactFile != null && packagedArtifactFile.exists()
&& isPackagedArtifactUpToDate( project, packagedArtifactFile ) )
{
return packagedArtifactFile;
}
else if ( !hasBeenPackagedDuringThisSession( 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.
Expand All @@ -172,9 +197,21 @@ else if ( !hasBeenPackaged( project ) )
else
{
String type = artifact.getProperty( "type", "" );
if ( project.hasLifecyclePhase( "compile" ) && COMPILE_PHASE_TYPES.contains( type ) )
File outputDirectory = new File( project.getBuild().getOutputDirectory() );

// Check if the project is being built during this session, and if we can expect any output.
// There is no need to check if the build has created any outputs, see MNG-2222.
boolean projectCompiledDuringThisSession
= project.hasLifecyclePhase( "compile" ) && COMPILE_PHASE_TYPES.contains( type );

// Check if the project is part of the session (not filtered by -pl, -rf, etc). If so, we check
// if a possible earlier Maven invocation produced some output for that project which we can use.
boolean projectHasOutputFromPreviousSession
= !session.getProjects().contains( project ) && outputDirectory.exists();

if ( projectHasOutputFromPreviousSession || projectCompiledDuringThisSession )
{
return new File( project.getBuild().getOutputDirectory() );
return outputDirectory;
}
}
}
Expand All @@ -184,12 +221,68 @@ else if ( !hasBeenPackaged( project ) )
return null;
}

private File determinePreviouslyPackagedArtifactFile( MavenProject project, Artifact artifact )
{
if ( artifact == null )
{
return null;
}

String fileName = String.format( "%s.%s", project.getBuild().getFinalName(), artifact.getExtension() );
return new File( project.getBuild().getDirectory(), fileName );
}

private boolean hasArtifactFileFromPackagePhase( Artifact projectArtifact )
{
return projectArtifact != null && projectArtifact.getFile() != null && projectArtifact.getFile().exists();
}

private boolean hasBeenPackaged( MavenProject project )
private boolean isPackagedArtifactUpToDate( MavenProject project, File packagedArtifactFile )
{
Path outputDirectory = Paths.get( project.getBuild().getOutputDirectory() );
if ( !outputDirectory.toFile().exists() )
{
return true;
}

try ( Stream<Path> outputFiles = Files.walk( outputDirectory ) )
{
// Not using File#lastModified() to avoid a Linux JDK8 milliseconds precision bug: JDK-8177809.
long artifactLastModified = Files.getLastModifiedTime( packagedArtifactFile.toPath() ).toMillis();

if ( session.getProjectBuildingRequest().getBuildStartTime() != null )
{
long buildStartTime = session.getProjectBuildingRequest().getBuildStartTime().getTime();
if ( artifactLastModified > buildStartTime )
{
return true;
}
}

Iterator<Path> iterator = outputFiles.iterator();
while ( iterator.hasNext() )
{
Path outputFile = iterator.next();
long outputFileLastModified = Files.getLastModifiedTime( outputFile ).toMillis();
if ( outputFileLastModified > artifactLastModified )
{
logger.warn( "Packaged artifact is not up-to-date compared to the build output directory" );
return false;
}
}

return true;
}
catch ( IOException e )
{
logger.warn( "An I/O error occurred while checking if the packaged artifact is up-to-date "
+ "against the build output directory. "
+ "Continuing with the assumption that it is up-to-date.", e );
return true;
}
}

private boolean hasBeenPackagedDuringThisSession( MavenProject project )
{
return project.hasLifecyclePhase( "package" ) || project.hasLifecyclePhase( "install" )
|| project.hasLifecyclePhase( "deploy" );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ public void setAllProjects( List<MavenProject> allProjects )
private final Settings settings;

@Deprecated
/** @deprecated This appears to only be used in the ReactorReader and we can do any processing required there */
/** @deprecated This appears not to be used anywhere within Maven itself. */
public Map<String, MavenProject> getProjectMap()
{
return projectMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
Expand Down Expand Up @@ -194,9 +193,11 @@ public ResolutionGroup retrieve( MetadataResolutionRequest request )
DependencyManagement dependencyManagement = model.getDependencyManagement();
managedDependencies = dependencyManagement == null ? null : dependencyManagement.getDependencies();
MavenSession session = legacySupport.getSession();
MavenProject project = session.getProjectMap().get(
ArtifactUtils.key( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() ) );
pomRepositories = project.getRemoteArtifactRepositories();
pomRepositories = session.getProjects().stream()
.filter( p -> artifact.equals( p.getArtifact() ) )
.map( MavenProject::getRemoteArtifactRepositories )
.findFirst()
.orElseGet( ArrayList::new );
}
else if ( artifact instanceof ArtifactWithDependencies )
{
Expand Down
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ under the License.
<name>Mike Mol (MNG-6665)</name>
</contributor>
<contributor>
<name>Martin Kanters (MNG-6665, MNG-6065)</name>
<name>Martin Kanters</name>
<organization>Info Support</organization>
</contributor>
<contributor>
<name>Maarten Mulders</name>
<organization>Info Support</organization>
</contributor>
<contributor>
<name>Luc Klaassen (MNG-6065)</name>
Expand Down