From c604db3c3a103e2212f4628d8e2a997017fe579e Mon Sep 17 00:00:00 2001 From: Karl Heinz Marbaise Date: Thu, 30 Sep 2021 19:10:44 +0200 Subject: [PATCH] [MNG-7447] - Several Improvements by using Stream API --- .../java/org/apache/maven/ReactorReader.java | 120 +++++++++--------- .../org/apache/maven/RepositoryUtils.java | 47 +++---- .../filter/ExclusionArtifactFilter.java | 53 ++++---- .../apache/maven/execution/MavenSession.java | 12 +- .../maven/extension/internal/CoreExports.java | 14 +- .../mapping/DefaultLifecycleMapping.java | 32 ++++- .../DefaultProfileActivationContext.java | 27 ++-- 7 files changed, 150 insertions(+), 155 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/ReactorReader.java b/maven-core/src/main/java/org/apache/maven/ReactorReader.java index 84662ff875..d5cc3d7a2f 100644 --- a/maven-core/src/main/java/org/apache/maven/ReactorReader.java +++ b/maven-core/src/main/java/org/apache/maven/ReactorReader.java @@ -20,17 +20,17 @@ package org.apache.maven; */ 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; - -import javax.inject.Inject; -import javax.inject.Named; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.execution.MavenSession; @@ -41,6 +41,13 @@ import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.repository.WorkspaceRepository; import org.eclipse.aether.util.artifact.ArtifactIdUtils; +import javax.inject.Inject; +import javax.inject.Named; + +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toMap; + /** * An implementation of a workspace reader that knows how to search the Maven reactor for artifacts, either as packaged * jar if it has been built, or only compile output directory if packaging hasn't happened yet. @@ -57,32 +64,27 @@ class ReactorReader private static final Collection COMPILE_PHASE_TYPES = Arrays.asList( "jar", "ejb-client", "war", "rar", "ejb3", "par", "sar", "wsr", "har", "app-client" ); - private Map projectsByGAV; + private final MavenSession session; + private final Map projectsByGAV; + private final Map> projectsByGA; + private final WorkspaceRepository repository; - private Map> projectsByGA; + private Function projectIntoKey = + s -> ArtifactUtils.key( s.getGroupId(), s.getArtifactId(), s.getVersion() ); - private WorkspaceRepository repository; + private Function projectIntoVersionlessKey = + s -> ArtifactUtils.versionlessKey( s.getGroupId(), s.getArtifactId() ); @Inject ReactorReader( MavenSession session ) { - projectsByGAV = session.getProjectMap(); + this.session = session; + this.projectsByGAV = + session.getAllProjects().stream() + .collect( toMap( projectIntoKey, identity() ) ); - projectsByGA = new HashMap<>( projectsByGAV.size() * 2 ); - for ( MavenProject project : projectsByGAV.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 ); - } + this.projectsByGA = projectsByGAV.values().stream() + .collect( groupingBy( projectIntoVersionlessKey ) ); repository = new WorkspaceRepository( "reactor", new HashSet<>( projectsByGAV.keySet() ) ); } @@ -119,23 +121,11 @@ class ReactorReader { 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 ); + return Optional.ofNullable( projectsByGA.get( key ) ) + .orElse( Collections.emptyList() ).stream() + .filter( s -> Objects.nonNull( find( s, artifact ) ) ) + .map( MavenProject::getVersion ) + .collect( Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList ) ); } @Override @@ -190,6 +180,17 @@ class ReactorReader 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(); @@ -218,28 +219,27 @@ class ReactorReader return mainArtifact; } - for ( Artifact attachedArtifact : RepositoryUtils.toArtifacts( project.getAttachedArtifacts() ) ) - { - if ( attachedArtifactComparison( requestedArtifact, attachedArtifact ) ) - { - return attachedArtifact; - } - } - - return null; + return RepositoryUtils.toArtifacts( project.getAttachedArtifacts() ).stream() + .filter( isRequestedArtifact( requestedArtifact ) ) + .findFirst() + .orElse( null ); } - private boolean attachedArtifactComparison( Artifact requested, Artifact attached ) + /** + * We are taking as much as we can from the DefaultArtifact.equals(). The requested artifact has no file, so we want + * to remove that from the comparison. + * + * @param requestArtifact checked against the given artifact. + * @return true if equals, false otherwise. + */ + private Predicate isRequestedArtifact( Artifact requestArtifact ) { - // - // We are taking as much as we can from the DefaultArtifact.equals(). The requested artifact has no file so - // we want to remove that from the comparison. - // - return requested.getArtifactId().equals( attached.getArtifactId() ) - && requested.getGroupId().equals( attached.getGroupId() ) - && requested.getVersion().equals( attached.getVersion() ) - && requested.getExtension().equals( attached.getExtension() ) - && requested.getClassifier().equals( attached.getClassifier() ); + return s -> s.getArtifactId().equals( requestArtifact.getArtifactId() ) + && s.getGroupId().equals( requestArtifact.getGroupId() ) + && s.getVersion().equals( requestArtifact.getVersion() ) + && s.getExtension().equals( requestArtifact.getExtension() ) + && s.getClassifier().equals( requestArtifact.getClassifier() ); + } /** diff --git a/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java b/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java index 80e58743a7..579315628a 100644 --- a/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java +++ b/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java @@ -26,6 +26,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; @@ -170,32 +172,21 @@ public class RepositoryUtils Artifact result = toArtifact( artifact ); - List excl = null; - if ( exclusions != null ) - { - excl = new ArrayList<>( exclusions.size() ); - for ( org.apache.maven.model.Exclusion exclusion : exclusions ) - { - excl.add( toExclusion( exclusion ) ); - } - } - + List excl = Optional.ofNullable( exclusions ) + .orElse( Collections.emptyList() ) + .stream() + .map( RepositoryUtils::toExclusion ) + .collect( Collectors.toList() ); return new Dependency( result, artifact.getScope(), artifact.isOptional(), excl ); } public static List toRepos( List repos ) { - if ( repos == null ) - { - return null; - } - - List results = new ArrayList<>( repos.size() ); - for ( ArtifactRepository repo : repos ) - { - results.add( toRepo( repo ) ); - } - return results; + return Optional.ofNullable( repos ) + .orElse( Collections.emptyList() ) + .stream() + .map( RepositoryUtils::toRepo ) + .collect( Collectors.toList() ); } public static RemoteRepository toRepo( ArtifactRepository repo ) @@ -316,11 +307,8 @@ public class RepositoryUtils new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), dependency.getClassifier(), null, dependency.getVersion(), props, stereotype ); - List exclusions = new ArrayList<>( dependency.getExclusions().size() ); - for ( org.apache.maven.model.Exclusion exclusion : dependency.getExclusions() ) - { - exclusions.add( toExclusion( exclusion ) ); - } + List exclusions = + dependency.getExclusions().stream().map( RepositoryUtils::toExclusion ).collect( Collectors.toList() ); Dependency result = new Dependency( artifact, dependency.getScope(), @@ -363,12 +351,7 @@ public class RepositoryUtils public static Collection toArtifacts( Collection artifactsToConvert ) { - List artifacts = new ArrayList<>(); - for ( org.apache.maven.artifact.Artifact a : artifactsToConvert ) - { - artifacts.add( toArtifact( a ) ); - } - return artifacts; + return artifactsToConvert.stream().map( RepositoryUtils::toArtifact ).collect( Collectors.toList() ); } public static WorkspaceRepository getWorkspace( RepositorySystemSession session ) diff --git a/maven-core/src/main/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilter.java b/maven-core/src/main/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilter.java index dd50c31748..18d4e833a0 100644 --- a/maven-core/src/main/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilter.java +++ b/maven-core/src/main/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilter.java @@ -19,11 +19,12 @@ package org.apache.maven.artifact.resolver.filter; * under the License. */ +import java.util.List; +import java.util.function.Predicate; + import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Exclusion; -import java.util.List; - /** * Filter to exclude from a list of artifact patterns. */ @@ -38,31 +39,33 @@ public class ExclusionArtifactFilter implements ArtifactFilter this.exclusions = exclusions; } + private Predicate sameArtifactId( Artifact artifact ) + { + return exclusion -> exclusion.getArtifactId().equals( artifact.getArtifactId() ); + } + + private Predicate sameGroupId( Artifact artifact ) + { + return exclusion -> exclusion.getGroupId().equals( artifact.getGroupId() ); + } + + private Predicate groupIdIsWildcard = exclusion -> WILDCARD.equals( exclusion.getGroupId() ); + + private Predicate artifactIdIsWildcard = exclusion -> WILDCARD.equals( exclusion.getArtifactId() ); + + private Predicate groupIdAndArtifactIdIsWildcard = groupIdIsWildcard.and( artifactIdIsWildcard ); + + private Predicate exclude( Artifact artifact ) + { + return groupIdAndArtifactIdIsWildcard + .or( groupIdIsWildcard.and( sameArtifactId( artifact ) ) ) + .or( artifactIdIsWildcard.and( sameGroupId( artifact ) ) ) + .or( sameGroupId( artifact ).and( sameArtifactId( artifact ) ) ); + } + @Override public boolean include( Artifact artifact ) { - for ( Exclusion exclusion : exclusions ) - { - if ( WILDCARD.equals( exclusion.getGroupId() ) && WILDCARD.equals( exclusion.getArtifactId() ) ) - { - return false; - } - if ( WILDCARD.equals( exclusion.getGroupId() ) - && exclusion.getArtifactId().equals( artifact.getArtifactId() ) ) - { - return false; - } - if ( WILDCARD.equals( exclusion.getArtifactId() ) - && exclusion.getGroupId().equals( artifact.getGroupId() ) ) - { - return false; - } - if ( exclusion.getGroupId().equals( artifact.getGroupId() ) - && exclusion.getArtifactId().equals( artifact.getArtifactId() ) ) - { - return false; - } - } - return true; + return !exclusions.stream().anyMatch( exclude( artifact ) ); } } diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java index 5b56df36d0..98c5573c97 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java @@ -84,15 +84,9 @@ public class MavenSession if ( !projects.isEmpty() ) { this.currentProject = projects.get( 0 ); - this.topLevelProject = currentProject; - for ( MavenProject project : projects ) - { - if ( project.isExecutionRoot() ) - { - topLevelProject = project; - break; - } - } + this.topLevelProject = + projects.stream().filter( project -> project.isExecutionRoot() ).findFirst() + .orElse( currentProject ); } else { diff --git a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java index 331617cfa2..b769c38678 100644 --- a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java +++ b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExports.java @@ -20,14 +20,16 @@ package org.apache.maven.extension.internal; */ import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.codehaus.plexus.classworlds.realm.ClassRealm; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.toMap; + /** * Provides information about artifacts (identified by groupId:artifactId string key) and classpath elements exported by * Maven core itself and loaded Maven core extensions. @@ -47,13 +49,9 @@ public class CoreExports public CoreExports( ClassRealm realm, Set exportedArtifacts, Set exportedPackages ) { - Map packages = new LinkedHashMap<>(); - for ( String pkg : exportedPackages ) - { - packages.put( pkg, realm ); - } this.artifacts = Collections.unmodifiableSet( new HashSet<>( exportedArtifacts ) ); - this.packages = Collections.unmodifiableMap( new HashMap<>( packages ) ); + this.packages = exportedPackages.stream().collect( + collectingAndThen( toMap( identity(), v -> realm ), Collections::unmodifiableMap ) ); } /** diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/DefaultLifecycleMapping.java b/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/DefaultLifecycleMapping.java index e12debef5f..283a179d25 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/DefaultLifecycleMapping.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/DefaultLifecycleMapping.java @@ -19,10 +19,14 @@ package org.apache.maven.lifecycle.mapping; * under the License. */ +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; + /** * DefaultLifecycleMapping */ @@ -38,7 +42,28 @@ public class DefaultLifecycleMapping private Map phases; /** - * Populates the lifecycle map from the injected list of lifecycle mappings (if not already done). + * Default ctor for plexus compatibility: lifecycles are most commonly defined in Plexus XML, that does field + * injection. Still, for Plexus to be able to instantiate this class, default ctor is needed. + * + * @deprecated Should not be used in Java code. + */ + @Deprecated + public DefaultLifecycleMapping() + { + } + + /** + * Ctor to be used in Java code/providers. + */ + public DefaultLifecycleMapping( final List lifecycles ) + { + this.lifecycleMap = Collections.unmodifiableMap( + lifecycles.stream().collect( toMap( Lifecycle::getId, identity() ) ) + ); + } + + /** + * Plexus: Populates the lifecycle map from the injected list of lifecycle mappings (if not already done). */ private void initLifecycleMap() { @@ -79,6 +104,7 @@ public class DefaultLifecycleMapping } } + @Override public Map getLifecycles() { initLifecycleMap(); @@ -86,6 +112,8 @@ public class DefaultLifecycleMapping return lifecycleMap; } + @Deprecated + @Override public List getOptionalMojos( String lifecycle ) { return null; @@ -110,7 +138,7 @@ public class DefaultLifecycleMapping return null; } } - + @Deprecated public Map getPhases( String lifecycle ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java index 77d92a377c..4fb1b265e3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileActivationContext.java @@ -21,12 +21,13 @@ package org.apache.maven.model.profile; import java.io.File; import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.toMap; + /** * Describes the environmental context used to determine the activation status of profiles. * @@ -230,8 +231,11 @@ public class DefaultProfileActivationContext { if ( projectProperties != null ) { - - this.projectProperties = Collections.unmodifiableMap( toMap( projectProperties ) ); + this.projectProperties = projectProperties.entrySet().stream() + .collect( + collectingAndThen( + toMap( k -> String.valueOf( k.getKey() ), v -> String.valueOf( v ) ), + Collections::unmodifiableMap ) ); } else { @@ -241,19 +245,4 @@ public class DefaultProfileActivationContext return this; } - private Map toMap( Properties properties ) - { - if ( properties == null ) - { - return Collections.emptyMap(); - } - Map map = new HashMap<>(); - Enumeration keys = properties.keys(); - while ( keys.hasMoreElements() ) - { - String key = (String) keys.nextElement(); - map.put( key, properties.getProperty( key ) ); - } - return map; - } }