Skip to content

Commit f8f5335

Browse files
authored
Feat: user relocations backport (#11937)
Backport of user relocations. Fixes #11917
1 parent 9aecb15 commit f8f5335

5 files changed

Lines changed: 458 additions & 40 deletions

File tree

maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java

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

25+
import java.util.LinkedHashMap;
2526
import java.util.LinkedHashSet;
2627
import java.util.List;
2728
import java.util.Map;
2829
import java.util.Objects;
2930
import java.util.Properties;
3031
import java.util.Set;
3132

32-
import org.apache.maven.model.DistributionManagement;
3333
import org.apache.maven.model.Model;
34-
import org.apache.maven.model.Relocation;
3534
import org.apache.maven.model.building.DefaultModelBuilderFactory;
3635
import org.apache.maven.model.building.DefaultModelBuildingRequest;
3736
import org.apache.maven.model.building.FileModelSource;
@@ -42,6 +41,8 @@
4241
import org.apache.maven.model.building.ModelProblem;
4342
import org.apache.maven.model.building.ModelProblemUtils;
4443
import org.apache.maven.model.resolution.UnresolvableModelException;
44+
import org.apache.maven.repository.internal.relocation.DistributionManagementArtifactRelocationSource;
45+
import org.apache.maven.repository.internal.relocation.UserPropertiesArtifactRelocationSource;
4546
import org.codehaus.plexus.util.StringUtils;
4647
import org.eclipse.aether.RepositoryEvent;
4748
import org.eclipse.aether.RepositoryEvent.EventType;
@@ -94,6 +95,8 @@ public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader
9495

9596
private ModelCacheFactory modelCacheFactory;
9697

98+
private Map<String, MavenArtifactRelocationSource> artifactRelocationSources;
99+
97100
private final ArtifactDescriptorReaderDelegate artifactDescriptorReaderDelegate =
98101
new ArtifactDescriptorReaderDelegate();
99102

@@ -104,7 +107,10 @@ public DefaultArtifactDescriptorReader() {
104107
// enable no-arg constructor
105108
}
106109

107-
@Inject
110+
/**
111+
* Just here for "static" resolver providers.
112+
*/
113+
@Deprecated
108114
public DefaultArtifactDescriptorReader(
109115
RemoteRepositoryManager remoteRepositoryManager,
110116
VersionResolver versionResolver,
@@ -120,6 +126,34 @@ public DefaultArtifactDescriptorReader(
120126
setModelBuilder(modelBuilder);
121127
setRepositoryEventDispatcher(repositoryEventDispatcher);
122128
setModelCacheFactory(modelCacheFactory);
129+
Map<String, MavenArtifactRelocationSource> artifactRelocationSources = new LinkedHashMap<>(); // order!
130+
artifactRelocationSources.put(
131+
UserPropertiesArtifactRelocationSource.NAME, new UserPropertiesArtifactRelocationSource());
132+
artifactRelocationSources.put(
133+
DistributionManagementArtifactRelocationSource.NAME,
134+
new DistributionManagementArtifactRelocationSource());
135+
setArtifactRelocationSources(artifactRelocationSources);
136+
}
137+
138+
@SuppressWarnings("checkstyle:parameternumber")
139+
@Inject
140+
public DefaultArtifactDescriptorReader(
141+
RemoteRepositoryManager remoteRepositoryManager,
142+
VersionResolver versionResolver,
143+
VersionRangeResolver versionRangeResolver,
144+
ArtifactResolver artifactResolver,
145+
ModelBuilder modelBuilder,
146+
RepositoryEventDispatcher repositoryEventDispatcher,
147+
ModelCacheFactory modelCacheFactory,
148+
Map<String, MavenArtifactRelocationSource> artifactRelocationSources) {
149+
setRemoteRepositoryManager(remoteRepositoryManager);
150+
setVersionResolver(versionResolver);
151+
setVersionRangeResolver(versionRangeResolver);
152+
setArtifactResolver(artifactResolver);
153+
setModelBuilder(modelBuilder);
154+
setRepositoryEventDispatcher(repositoryEventDispatcher);
155+
setModelCacheFactory(modelCacheFactory);
156+
setArtifactRelocationSources(artifactRelocationSources);
123157
}
124158

125159
@Deprecated
@@ -175,6 +209,13 @@ public DefaultArtifactDescriptorReader setModelCacheFactory(ModelCacheFactory mo
175209
return this;
176210
}
177211

212+
public DefaultArtifactDescriptorReader setArtifactRelocationSources(
213+
Map<String, MavenArtifactRelocationSource> artifactRelocationSources) {
214+
this.artifactRelocationSources =
215+
Objects.requireNonNull(artifactRelocationSources, "artifactRelocationSources cannot be null");
216+
return this;
217+
}
218+
178219
@Override
179220
public ArtifactDescriptorResult readArtifactDescriptor(
180221
RepositorySystemSession session, ArtifactDescriptorRequest request) throws ArtifactDescriptorException {
@@ -336,23 +377,28 @@ private Model loadPom(
336377
throw new ArtifactDescriptorException(result);
337378
}
338379

339-
Relocation relocation = getRelocation(model);
340-
341-
if (relocation != null) {
342-
result.addRelocation(a);
343-
a = new RelocatedArtifact(
344-
a,
345-
relocation.getGroupId(),
346-
relocation.getArtifactId(),
347-
relocation.getVersion(),
348-
relocation.getMessage());
349-
result.setArtifact(a);
380+
Artifact relocatedArtifact = getRelocation(session, result, model);
381+
if (relocatedArtifact != null) {
382+
if (withinSameGav(relocatedArtifact, a)) {
383+
result.setArtifact(relocatedArtifact);
384+
return model; // they share same model
385+
} else {
386+
result.addRelocation(a);
387+
a = relocatedArtifact;
388+
result.setArtifact(a);
389+
}
350390
} else {
351391
return model;
352392
}
353393
}
354394
}
355395

396+
private boolean withinSameGav(Artifact a1, Artifact a2) {
397+
return Objects.equals(a1.getGroupId(), a2.getGroupId())
398+
&& Objects.equals(a1.getArtifactId(), a2.getArtifactId())
399+
&& Objects.equals(a1.getVersion(), a2.getVersion());
400+
}
401+
356402
private Properties toProperties(Map<String, String> dominant, Map<String, String> recessive) {
357403
Properties props = new Properties();
358404
if (recessive != null) {
@@ -364,13 +410,17 @@ private Properties toProperties(Map<String, String> dominant, Map<String, String
364410
return props;
365411
}
366412

367-
private Relocation getRelocation(Model model) {
368-
Relocation relocation = null;
369-
DistributionManagement distMgmt = model.getDistributionManagement();
370-
if (distMgmt != null) {
371-
relocation = distMgmt.getRelocation();
413+
private Artifact getRelocation(
414+
RepositorySystemSession session, ArtifactDescriptorResult artifactDescriptorResult, Model model)
415+
throws ArtifactDescriptorException {
416+
Artifact result = null;
417+
for (MavenArtifactRelocationSource source : artifactRelocationSources.values()) {
418+
result = source.relocatedTarget(session, artifactDescriptorResult, model);
419+
if (result != null) {
420+
break;
421+
}
372422
}
373-
return relocation;
423+
return result;
374424
}
375425

376426
private void missingDescriptor(
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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.repository.internal;
20+
21+
import org.apache.maven.model.Model;
22+
import org.eclipse.aether.RepositorySystemSession;
23+
import org.eclipse.aether.artifact.Artifact;
24+
import org.eclipse.aether.resolution.ArtifactDescriptorException;
25+
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
26+
27+
/**
28+
* Maven relocation source.
29+
* Note: implementations of this component should avoid the "default" name (has special meaning in Eclipse Sisu) and
30+
* explicitly order implementations using Sisu priorities.
31+
*
32+
* @since 3.10.0
33+
*/
34+
public interface MavenArtifactRelocationSource {
35+
/**
36+
* Returns {@link Artifact} instance where to relocate to, or {@code null}.
37+
*
38+
* @param session The session, never {@code null}.
39+
* @param result The artifact descriptor result, never {@code null}.
40+
* @param model The artifact model, never {@code null}.
41+
* @return The {@link Artifact} to relocate to, or {@code null} if no relocation wanted.
42+
*/
43+
Artifact relocatedTarget(RepositorySystemSession session, ArtifactDescriptorResult result, Model model)
44+
throws ArtifactDescriptorException;
45+
}

maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,29 @@ public final class RelocatedArtifact extends AbstractArtifact {
3636

3737
private final String artifactId;
3838

39+
private final String classifier;
40+
41+
private final String extension;
42+
3943
private final String version;
4044

4145
private final String message;
4246

43-
RelocatedArtifact(Artifact artifact, String groupId, String artifactId, String version, String message) {
47+
public RelocatedArtifact(
48+
Artifact artifact,
49+
String groupId,
50+
String artifactId,
51+
String classifier,
52+
String extension,
53+
String version,
54+
String message) {
4455
this.artifact = Objects.requireNonNull(artifact, "artifact cannot be null");
45-
// TODO Use StringUtils here
46-
this.groupId = (groupId != null && groupId.length() > 0) ? groupId : null;
47-
this.artifactId = (artifactId != null && artifactId.length() > 0) ? artifactId : null;
48-
this.version = (version != null && version.length() > 0) ? version : null;
49-
this.message = (message != null && message.length() > 0) ? message : null;
56+
this.groupId = (groupId != null && !groupId.isEmpty()) ? groupId : null;
57+
this.artifactId = (artifactId != null && !artifactId.isEmpty()) ? artifactId : null;
58+
this.classifier = (classifier != null && !classifier.isEmpty()) ? classifier : null;
59+
this.extension = (extension != null && !extension.isEmpty()) ? extension : null;
60+
this.version = (version != null && !version.isEmpty()) ? version : null;
61+
this.message = (message != null && !message.isEmpty()) ? message : null;
5062
}
5163

5264
@Override
@@ -67,6 +79,24 @@ public String getArtifactId() {
6779
}
6880
}
6981

82+
@Override
83+
public String getClassifier() {
84+
if (classifier != null) {
85+
return classifier;
86+
} else {
87+
return artifact.getClassifier();
88+
}
89+
}
90+
91+
@Override
92+
public String getExtension() {
93+
if (extension != null) {
94+
return extension;
95+
} else {
96+
return artifact.getExtension();
97+
}
98+
}
99+
70100
@Override
71101
public String getVersion() {
72102
if (version != null) {
@@ -80,10 +110,10 @@ public String getVersion() {
80110
@Override
81111
public Artifact setVersion(String version) {
82112
String current = getVersion();
83-
if (current.equals(version) || (version == null && current.length() <= 0)) {
113+
if (current.equals(version) || (version == null && current.isEmpty())) {
84114
return this;
85115
}
86-
return new RelocatedArtifact(artifact, groupId, artifactId, version, message);
116+
return new RelocatedArtifact(artifact, groupId, artifactId, classifier, extension, version, message);
87117
}
88118

89119
@Override
@@ -92,7 +122,8 @@ public Artifact setFile(File file) {
92122
if (Objects.equals(current, file)) {
93123
return this;
94124
}
95-
return new RelocatedArtifact(artifact.setFile(file), groupId, artifactId, version, message);
125+
return new RelocatedArtifact(
126+
artifact.setFile(file), groupId, artifactId, classifier, extension, version, message);
96127
}
97128

98129
@Override
@@ -101,17 +132,8 @@ public Artifact setProperties(Map<String, String> properties) {
101132
if (current.equals(properties) || (properties == null && current.isEmpty())) {
102133
return this;
103134
}
104-
return new RelocatedArtifact(artifact.setProperties(properties), groupId, artifactId, version, message);
105-
}
106-
107-
@Override
108-
public String getClassifier() {
109-
return artifact.getClassifier();
110-
}
111-
112-
@Override
113-
public String getExtension() {
114-
return artifact.getExtension();
135+
return new RelocatedArtifact(
136+
artifact.setProperties(properties), groupId, artifactId, classifier, extension, version, message);
115137
}
116138

117139
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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.repository.internal.relocation;
20+
21+
import javax.inject.Named;
22+
import javax.inject.Singleton;
23+
24+
import org.apache.maven.model.DistributionManagement;
25+
import org.apache.maven.model.Model;
26+
import org.apache.maven.model.Relocation;
27+
import org.apache.maven.repository.internal.MavenArtifactRelocationSource;
28+
import org.apache.maven.repository.internal.RelocatedArtifact;
29+
import org.eclipse.aether.RepositorySystemSession;
30+
import org.eclipse.aether.artifact.Artifact;
31+
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
32+
import org.eclipse.sisu.Priority;
33+
import org.slf4j.Logger;
34+
import org.slf4j.LoggerFactory;
35+
36+
/**
37+
* Relocation source from standard distribution management. This is the "one and only" relocation implementation that
38+
* existed in Maven 3 land, uses POM distributionManagement/relocation.
39+
* <p>
40+
* Note: this component should kick-in last regarding relocations.
41+
*
42+
* @since 3.10.0
43+
*/
44+
@Singleton
45+
@Named(DistributionManagementArtifactRelocationSource.NAME)
46+
@Priority(5)
47+
public final class DistributionManagementArtifactRelocationSource implements MavenArtifactRelocationSource {
48+
public static final String NAME = "distributionManagement";
49+
private static final Logger LOGGER = LoggerFactory.getLogger(DistributionManagementArtifactRelocationSource.class);
50+
51+
@Override
52+
public Artifact relocatedTarget(
53+
RepositorySystemSession session, ArtifactDescriptorResult artifactDescriptorResult, Model model) {
54+
DistributionManagement distMgmt = model.getDistributionManagement();
55+
if (distMgmt != null) {
56+
Relocation relocation = distMgmt.getRelocation();
57+
if (relocation != null) {
58+
Artifact result = new RelocatedArtifact(
59+
artifactDescriptorResult.getRequest().getArtifact(),
60+
relocation.getGroupId(),
61+
relocation.getArtifactId(),
62+
null,
63+
null,
64+
relocation.getVersion(),
65+
relocation.getMessage());
66+
LOGGER.debug(
67+
"The artifact {} has been relocated to {}: {}",
68+
artifactDescriptorResult.getRequest().getArtifact(),
69+
result,
70+
relocation.getMessage());
71+
return result;
72+
}
73+
}
74+
return null;
75+
}
76+
}

0 commit comments

Comments
 (0)