1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl.model;
20
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.Objects;
28 import java.util.Optional;
29
30 import org.apache.maven.api.di.Named;
31 import org.apache.maven.api.di.Singleton;
32 import org.apache.maven.api.model.Dependency;
33 import org.apache.maven.api.model.Model;
34 import org.apache.maven.api.model.Parent;
35 import org.apache.maven.api.services.ModelTransformer;
36 import org.apache.maven.api.services.ModelTransformerContext;
37
38
39
40
41
42
43 @Named
44 @Singleton
45 public class BuildModelTransformer implements ModelTransformer {
46
47 @Override
48 public Model transform(ModelTransformerContext context, Model model, Path path) {
49 Model.Builder builder = Model.newBuilder(model);
50 handleParent(context, model, path, builder);
51 handleReactorDependencies(context, model, path, builder);
52 handleCiFriendlyVersion(context, model, path, builder);
53 return builder.build();
54 }
55
56
57
58
59 void handleParent(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
60 Parent parent = model.getParent();
61 if (parent != null) {
62 String version = parent.getVersion();
63 String path = Optional.ofNullable(parent.getRelativePath()).orElse("..");
64 if (version == null && !path.isEmpty()) {
65 Optional<RelativeProject> resolvedParent = resolveRelativePath(
66 pomFile, context, Paths.get(path), parent.getGroupId(), parent.getArtifactId());
67 if (resolvedParent.isPresent()) {
68 version = resolvedParent.get().getVersion();
69 }
70 }
71
72 String modVersion = replaceCiFriendlyVersion(context, version);
73 builder.parent(parent.withVersion(modVersion));
74 }
75 }
76
77
78
79
80 void handleCiFriendlyVersion(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
81 String version = model.getVersion();
82 String modVersion = replaceCiFriendlyVersion(context, version);
83 builder.version(modVersion);
84 }
85
86
87
88
89 void handleReactorDependencies(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
90 List<Dependency> newDeps = new ArrayList<>();
91 boolean modified = false;
92 for (Dependency dep : model.getDependencies()) {
93 if (dep.getVersion() == null) {
94 Model depModel = context.getRawModel(model.getPomFile(), dep.getGroupId(), dep.getArtifactId());
95 if (depModel != null) {
96 String v = depModel.getVersion();
97 if (v == null && depModel.getParent() != null) {
98 v = depModel.getParent().getVersion();
99 }
100 dep = dep.withVersion(v);
101 modified = true;
102 }
103 }
104 newDeps.add(dep);
105 }
106 if (modified) {
107 builder.dependencies(newDeps);
108 }
109 }
110
111 protected String replaceCiFriendlyVersion(ModelTransformerContext context, String version) {
112 if (version != null) {
113 for (String key : Arrays.asList("changelist", "revision", "sha1")) {
114 String val = context.getUserProperty(key);
115 if (val != null) {
116 version = version.replace("${" + key + "}", val);
117 }
118 }
119 }
120 return version;
121 }
122
123 protected Optional<RelativeProject> resolveRelativePath(
124 Path pomFile, ModelTransformerContext context, Path relativePath, String groupId, String artifactId) {
125 Path pomPath = pomFile.resolveSibling(relativePath).normalize();
126 if (Files.isDirectory(pomPath)) {
127 pomPath = context.locate(pomPath);
128 }
129
130 if (pomPath == null || !Files.isRegularFile(pomPath)) {
131 return Optional.empty();
132 }
133
134 Optional<RelativeProject> mappedProject = Optional.ofNullable(context.getRawModel(pomFile, pomPath.normalize()))
135 .map(BuildModelTransformer::toRelativeProject);
136
137 if (mappedProject.isPresent()) {
138 RelativeProject project = mappedProject.get();
139
140 if (Objects.equals(groupId, project.getGroupId()) && Objects.equals(artifactId, project.getArtifactId())) {
141 return mappedProject;
142 }
143 }
144 return Optional.empty();
145 }
146
147 private static RelativeProject toRelativeProject(final Model m) {
148 String groupId = m.getGroupId();
149 if (groupId == null && m.getParent() != null) {
150 groupId = m.getParent().getGroupId();
151 }
152
153 String version = m.getVersion();
154 if (version == null && m.getParent() != null) {
155 version = m.getParent().getVersion();
156 }
157
158 return new RelativeProject(groupId, m.getArtifactId(), version);
159 }
160
161 protected static class RelativeProject {
162 private final String groupId;
163
164 private final String artifactId;
165
166 private final String version;
167
168 protected RelativeProject(String groupId, String artifactId, String version) {
169 this.groupId = groupId;
170 this.artifactId = artifactId;
171 this.version = version;
172 }
173
174 public String getGroupId() {
175 return groupId;
176 }
177
178 public String getArtifactId() {
179 return artifactId;
180 }
181
182 public String getVersion() {
183 return version;
184 }
185 }
186 }