Skip to content

Commit 5000b59

Browse files
authored
Maven4 "legacy" mode and more (#2380)
Simple ability to make Maven 4 "work like Maven 3" would. Changes: * Resolver session (scope manager, transitive dep mgr) - DONE * model validation (in "Maven3" mode model 4.1.0 should be rejected) - DONE * scope validation (obey what scopeMgr holds) - DONE * inline POM transformation in Maven3 mode (instead of consumer POM transformation) - DONE * added IT that confirms: maven4 in maven3 mode does not need flatten plugin Issues: https://issues.apache.org/jira/browse/MNG-8742 https://issues.apache.org/jira/browse/MNG-8743 https://issues.apache.org/jira/browse/MNG-8744
1 parent 275bf82 commit 5000b59

File tree

39 files changed

+955
-285
lines changed

39 files changed

+955
-285
lines changed

api/maven-api-core/src/main/java/org/apache/maven/api/Constants.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,15 @@ public final class Constants {
462462
@Config(type = "java.lang.Boolean", defaultValue = "true")
463463
public static final String MAVEN_CONSUMER_POM = "maven.consumer.pom";
464464

465+
/**
466+
* User property for controlling "maven personality". If activated Maven will behave
467+
* as previous major version, Maven 3.
468+
*
469+
* @since 4.0.0
470+
*/
471+
@Config(type = "java.lang.Boolean", defaultValue = "false")
472+
public static final String MAVEN_MAVEN3_PERSONALITY = "maven.maven3Personality";
473+
465474
/**
466475
* User property for disabling version resolver cache.
467476
*

api/maven-api-core/src/main/java/org/apache/maven/api/feature/Features.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@ public final class Features {
3535
private Features() {}
3636

3737
/**
38-
* Check if the consumer POM feature is active.
38+
* Check if the personality is "maven3".
3939
*/
40-
public static boolean consumerPom(@Nullable Properties userProperties) {
41-
return doGet(userProperties, Constants.MAVEN_CONSUMER_POM, true);
40+
public static boolean mavenMaven3Personality(@Nullable Map<String, ?> userProperties) {
41+
return doGet(userProperties, Constants.MAVEN_MAVEN3_PERSONALITY, false);
4242
}
4343

4444
/**
4545
* Check if the consumer POM feature is active.
4646
*/
47-
public static boolean consumerPom(@Nullable Map<String, String> userProperties, boolean def) {
48-
return doGet(userProperties, Constants.MAVEN_CONSUMER_POM, def);
47+
public static boolean consumerPom(@Nullable Map<String, ?> userProperties) {
48+
return doGet(userProperties, Constants.MAVEN_CONSUMER_POM, !mavenMaven3Personality(userProperties));
4949
}
5050

5151
private static boolean doGet(Properties userProperties, String key, boolean def) {

api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public interface ModelBuilder extends Service {
2929

3030
String MODEL_VERSION_4_1_0 = "4.1.0";
3131

32-
List<String> VALID_MODEL_VERSIONS = List.of(MODEL_VERSION_4_0_0, MODEL_VERSION_4_1_0);
32+
List<String> KNOWN_MODEL_VERSIONS = List.of(MODEL_VERSION_4_0_0, MODEL_VERSION_4_1_0);
3333

3434
ModelBuilderSession newSession();
3535

compat/maven-compat/src/test/java/org/apache/maven/project/AbstractMavenProjectTestCase.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.maven.execution.DefaultMavenExecutionResult;
3535
import org.apache.maven.execution.MavenSession;
3636
import org.apache.maven.impl.InternalSession;
37+
import org.apache.maven.impl.resolver.scopes.Maven4ScopeManagerConfiguration;
3738
import org.apache.maven.internal.impl.DefaultLookup;
3839
import org.apache.maven.internal.impl.DefaultSession;
3940
import org.apache.maven.internal.impl.InternalMavenSession;
@@ -45,6 +46,7 @@
4546
import org.codehaus.plexus.PlexusContainer;
4647
import org.codehaus.plexus.testing.PlexusTest;
4748
import org.eclipse.aether.DefaultRepositorySystemSession;
49+
import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl;
4850
import org.junit.jupiter.api.BeforeEach;
4951

5052
import static org.junit.jupiter.api.Assertions.fail;
@@ -158,6 +160,7 @@ protected MavenProject getProject(File pom) throws Exception {
158160
protected void initRepoSession(ProjectBuildingRequest request) throws Exception {
159161
File localRepo = new File(request.getLocalRepository().getBasedir());
160162
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
163+
session.setScopeManager(new ScopeManagerImpl(Maven4ScopeManagerConfiguration.INSTANCE));
161164
session.setLocalRepositoryManager(new LegacyLocalRepositoryManager(localRepo));
162165
request.setRepositorySession(session);
163166

impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.maven.api.di.Inject;
3535
import org.apache.maven.api.di.Named;
3636
import org.apache.maven.api.di.Singleton;
37+
import org.apache.maven.api.feature.Features;
3738
import org.apache.maven.api.services.TypeRegistry;
3839
import org.apache.maven.api.xml.XmlNode;
3940
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
@@ -155,14 +156,15 @@ public RepositorySystemSession newRepositorySession(MavenExecutionRequest reques
155156
public SessionBuilder newRepositorySessionBuilder(MavenExecutionRequest request) {
156157
requireNonNull(request, "request");
157158

158-
MavenSessionBuilderSupplier supplier = new MavenSessionBuilderSupplier(repoSystem);
159+
// this map is read ONLY to get config from (profiles + env + system + user)
160+
Map<String, String> mergedProps = createMergedProperties(request);
161+
162+
boolean mavenMaven3Personality = Features.mavenMaven3Personality(mergedProps);
163+
MavenSessionBuilderSupplier supplier = new MavenSessionBuilderSupplier(repoSystem, mavenMaven3Personality);
159164
SessionBuilder sessionBuilder = supplier.get();
160165
sessionBuilder.setArtifactTypeRegistry(new TypeRegistryAdapter(typeRegistry)); // dynamic
161166
sessionBuilder.setCache(request.getRepositoryCache());
162167

163-
// this map is read ONLY to get config from (profiles + env + system + user)
164-
Map<String, String> mergedProps = createMergedProperties(request);
165-
166168
// configProps map is kept "pristine", is written ONLY, the mandatory resolver config
167169
Map<String, Object> configProps = new LinkedHashMap<>();
168170
configProps.put(ConfigurationProperties.USER_AGENT, getUserAgent());
@@ -356,7 +358,7 @@ public SessionBuilder newRepositorySessionBuilder(MavenExecutionRequest request)
356358

357359
// may be overridden
358360
String resolverDependencyManagerTransitivity = mergedProps.getOrDefault(
359-
Constants.MAVEN_RESOLVER_DEPENDENCY_MANAGER_TRANSITIVITY, Boolean.TRUE.toString());
361+
Constants.MAVEN_RESOLVER_DEPENDENCY_MANAGER_TRANSITIVITY, Boolean.toString(!mavenMaven3Personality));
360362
sessionBuilder.setDependencyManager(
361363
supplier.getDependencyManager(Boolean.parseBoolean(resolverDependencyManagerTransitivity)));
362364

impl/maven-core/src/main/java/org/apache/maven/internal/aether/MavenTransformer.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import javax.inject.Named;
2323
import javax.inject.Singleton;
2424

25-
import org.apache.maven.internal.transformation.ConsumerPomArtifactTransformer;
25+
import org.apache.maven.internal.transformation.TransformerManager;
2626
import org.eclipse.aether.RepositorySystemSession;
2727
import org.eclipse.aether.deployment.DeployRequest;
2828
import org.eclipse.aether.installation.InstallRequest;
@@ -36,20 +36,20 @@
3636
@Singleton
3737
@Named
3838
final class MavenTransformer implements ArtifactTransformer {
39-
private final ConsumerPomArtifactTransformer consumerPomArtifactTransformer;
39+
private final TransformerManager transformerManager;
4040

4141
@Inject
42-
MavenTransformer(ConsumerPomArtifactTransformer consumerPomArtifactTransformer) {
43-
this.consumerPomArtifactTransformer = requireNonNull(consumerPomArtifactTransformer);
42+
MavenTransformer(TransformerManager transformerManager) {
43+
this.transformerManager = requireNonNull(transformerManager);
4444
}
4545

4646
@Override
4747
public InstallRequest transformInstallArtifacts(RepositorySystemSession session, InstallRequest request) {
48-
return consumerPomArtifactTransformer.remapInstallArtifacts(session, request);
48+
return transformerManager.remapInstallArtifacts(session, request);
4949
}
5050

5151
@Override
5252
public DeployRequest transformDeployArtifacts(RepositorySystemSession session, DeployRequest request) {
53-
return consumerPomArtifactTransformer.remapDeployArtifacts(session, request);
53+
return transformerManager.remapDeployArtifacts(session, request);
5454
}
5555
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.internal.transformation;
20+
21+
import javax.xml.stream.XMLStreamException;
22+
23+
import java.io.IOException;
24+
import java.nio.file.Path;
25+
26+
import org.apache.maven.api.services.ModelBuilderException;
27+
import org.apache.maven.project.MavenProject;
28+
import org.eclipse.aether.RepositorySystemSession;
29+
import org.eclipse.aether.deployment.DeployRequest;
30+
import org.eclipse.aether.installation.InstallRequest;
31+
32+
/**
33+
* Maven POM transformer.
34+
* TODO: rename this interface to "Transformer" as it can do much more than just transform POM.
35+
* @since TBD
36+
*/
37+
public interface PomArtifactTransformer {
38+
InstallRequest remapInstallArtifacts(RepositorySystemSession session, InstallRequest request);
39+
40+
DeployRequest remapDeployArtifacts(RepositorySystemSession session, DeployRequest request);
41+
42+
void injectTransformedArtifacts(RepositorySystemSession session, MavenProject currentProject) throws IOException;
43+
44+
void transform(MavenProject project, RepositorySystemSession session, Path src, Path tgt)
45+
throws ModelBuilderException, XMLStreamException, IOException;
46+
}
Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,11 @@
2626
import org.eclipse.aether.installation.InstallRequest;
2727

2828
/**
29-
* Consumer POM transformer.
29+
* Maven transformer manager.
3030
*
31-
* @since TBD
31+
* @since 4.0.0
3232
*/
33-
public interface ConsumerPomArtifactTransformer {
34-
35-
String CONSUMER_POM_CLASSIFIER = "consumer";
36-
37-
String BUILD_POM_CLASSIFIER = "build";
38-
33+
public interface TransformerManager {
3934
InstallRequest remapInstallArtifacts(RepositorySystemSession session, InstallRequest request);
4035

4136
DeployRequest remapDeployArtifacts(RepositorySystemSession session, DeployRequest request);
Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import javax.xml.stream.XMLStreamException;
2525

2626
import java.io.IOException;
27-
import java.io.Writer;
2827
import java.nio.file.Files;
2928
import java.nio.file.Path;
3029
import java.nio.file.Paths;
@@ -37,8 +36,6 @@
3736
import org.apache.maven.api.feature.Features;
3837
import org.apache.maven.api.model.Model;
3938
import org.apache.maven.api.services.ModelBuilderException;
40-
import org.apache.maven.internal.transformation.ConsumerPomArtifactTransformer;
41-
import org.apache.maven.model.v4.MavenStaxWriter;
4239
import org.apache.maven.project.MavenProject;
4340
import org.apache.maven.project.artifact.ProjectArtifact;
4441
import org.eclipse.aether.RepositorySystemSession;
@@ -54,30 +51,29 @@
5451
* @since TBD
5552
*/
5653
@Singleton
57-
@Named("consumer-pom")
58-
class DefaultConsumerPomArtifactTransformer implements ConsumerPomArtifactTransformer {
54+
@Named
55+
class ConsumerPomArtifactTransformer extends TransformerSupport {
56+
private static final String CONSUMER_POM_CLASSIFIER = "consumer";
5957

60-
private static final String NAMESPACE_FORMAT = "http://maven.apache.org/POM/%s";
61-
62-
private static final String SCHEMA_LOCATION_FORMAT = "https://maven.apache.org/xsd/maven-%s.xsd";
58+
private static final String BUILD_POM_CLASSIFIER = "build";
6359

6460
private final Set<Path> toDelete = new CopyOnWriteArraySet<>();
6561

66-
private final ConsumerPomBuilder builder;
62+
private final PomBuilder builder;
6763

6864
@Inject
69-
DefaultConsumerPomArtifactTransformer(ConsumerPomBuilder builder) {
65+
ConsumerPomArtifactTransformer(PomBuilder builder) {
7066
this.builder = builder;
7167
}
7268

73-
@Override
7469
@SuppressWarnings("deprecation")
70+
@Override
7571
public void injectTransformedArtifacts(RepositorySystemSession session, MavenProject project) throws IOException {
7672
if (project.getFile() == null) {
7773
// If there is no build POM there is no reason to inject artifacts for the consumer POM.
7874
return;
7975
}
80-
if (Features.consumerPom(session.getUserProperties(), true)) {
76+
if (Features.consumerPom(session.getConfigProperties())) {
8177
Path buildDir =
8278
project.getBuild() != null ? Paths.get(project.getBuild().getDirectory()) : null;
8379
if (buildDir != null) {
@@ -108,7 +104,8 @@ TransformedArtifact createConsumerPomArtifact(
108104
"pom");
109105
}
110106

111-
void transform(MavenProject project, RepositorySystemSession session, Path src, Path tgt)
107+
@Override
108+
public void transform(MavenProject project, RepositorySystemSession session, Path src, Path tgt)
112109
throws ModelBuilderException, XMLStreamException, IOException {
113110
Model model = builder.build(session, project, src);
114111
write(model, tgt);
@@ -173,7 +170,7 @@ private Collection<Artifact> replacePom(Collection<Artifact> artifacts) {
173170
main.getExtension(),
174171
main.getVersion(),
175172
main.getProperties(),
176-
main.getFile()));
173+
main.getPath()));
177174
}
178175
for (Artifact consumer : consumers) {
179176
result.remove(consumer);
@@ -184,22 +181,10 @@ private Collection<Artifact> replacePom(Collection<Artifact> artifacts) {
184181
consumer.getExtension(),
185182
consumer.getVersion(),
186183
consumer.getProperties(),
187-
consumer.getFile()));
184+
consumer.getPath()));
188185
}
189186
artifacts = result;
190187
}
191188
return artifacts;
192189
}
193-
194-
void write(Model model, Path dest) throws IOException, XMLStreamException {
195-
String version = model.getModelVersion();
196-
Files.createDirectories(dest.getParent());
197-
try (Writer w = Files.newBufferedWriter(dest)) {
198-
MavenStaxWriter writer = new MavenStaxWriter();
199-
writer.setNamespace(String.format(NAMESPACE_FORMAT, version));
200-
writer.setSchemaLocation(String.format(SCHEMA_LOCATION_FORMAT, version));
201-
writer.setAddLocationInformation(false);
202-
writer.write(w, model);
203-
}
204-
}
205190
}

impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
import org.slf4j.LoggerFactory;
5454

5555
@Named
56-
class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
56+
class DefaultConsumerPomBuilder implements PomBuilder {
5757
private static final String BOM_PACKAGING = "bom";
5858

5959
public static final String POM_PACKAGING = "pom";
@@ -198,8 +198,7 @@ private ModelBuilderResult buildModel(RepositorySystemSession session, Path src)
198198
request.lifecycleBindingsInjector(lifecycleBindingsInjector::injectLifecycleBindings);
199199
ModelBuilder.ModelBuilderSession mbSession =
200200
iSession.getData().get(SessionData.key(ModelBuilder.ModelBuilderSession.class));
201-
ModelBuilderResult result = mbSession.build(request.build());
202-
return result;
201+
return mbSession.build(request.build());
203202
}
204203

205204
static Model transformNonPom(Model model, MavenProject project) {

0 commit comments

Comments
 (0)