1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.transformation.impl;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.stream.Collectors;
33
34 import org.apache.maven.api.SessionData;
35 import org.apache.maven.api.model.Dependency;
36 import org.apache.maven.api.model.DependencyManagement;
37 import org.apache.maven.api.model.DistributionManagement;
38 import org.apache.maven.api.model.Model;
39 import org.apache.maven.api.model.ModelBase;
40 import org.apache.maven.api.model.Profile;
41 import org.apache.maven.api.model.Repository;
42 import org.apache.maven.api.services.ModelBuilder;
43 import org.apache.maven.api.services.ModelBuilderException;
44 import org.apache.maven.api.services.ModelBuilderRequest;
45 import org.apache.maven.api.services.ModelBuilderResult;
46 import org.apache.maven.api.services.ModelSource;
47 import org.apache.maven.api.services.Source;
48 import org.apache.maven.api.services.model.LifecycleBindingsInjector;
49 import org.apache.maven.internal.impl.InternalSession;
50 import org.apache.maven.model.v4.MavenModelVersion;
51 import org.apache.maven.project.MavenProject;
52 import org.eclipse.aether.RepositorySystemSession;
53
54 @Named
55 class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
56 private static final String BOM_PACKAGING = "bom";
57
58 public static final String POM_PACKAGING = "pom";
59
60 private final LifecycleBindingsInjector lifecycleBindingsInjector;
61
62 @Inject
63 @SuppressWarnings("checkstyle:ParameterNumber")
64 DefaultConsumerPomBuilder(LifecycleBindingsInjector lifecycleBindingsInjector) {
65 this.lifecycleBindingsInjector = lifecycleBindingsInjector;
66 }
67
68 @Override
69 public Model build(RepositorySystemSession session, MavenProject project, Path src) throws ModelBuilderException {
70 Model model = project.getModel().getDelegate();
71 String packaging = model.getPackaging();
72 String originalPackaging = project.getOriginalModel().getPackaging();
73 if (POM_PACKAGING.equals(packaging) && !BOM_PACKAGING.equals(originalPackaging)) {
74 return buildPom(session, project, src);
75 } else {
76 return buildNonPom(session, project, src);
77 }
78 }
79
80 protected Model buildPom(RepositorySystemSession session, MavenProject project, Path src)
81 throws ModelBuilderException {
82 ModelBuilderResult result = buildModel(session, project, src);
83 Model model = result.getRawModel();
84 return transform(model, project);
85 }
86
87 protected Model buildNonPom(RepositorySystemSession session, MavenProject project, Path src)
88 throws ModelBuilderException {
89 ModelBuilderResult result = buildModel(session, project, src);
90 Model model = result.getEffectiveModel();
91 return transform(model, project);
92 }
93
94 private ModelBuilderResult buildModel(RepositorySystemSession session, MavenProject project, Path src)
95 throws ModelBuilderException {
96 InternalSession iSession = InternalSession.from(session);
97 ModelBuilderRequest.ModelBuilderRequestBuilder request = ModelBuilderRequest.builder();
98 request.requestType(ModelBuilderRequest.RequestType.CONSUMER_POM);
99 request.session(iSession);
100
101 request.source(new PomConsumerModelSource(project.getModel().getPomPath(), src));
102 request.locationTracking(false);
103 request.systemProperties(session.getSystemProperties());
104 request.userProperties(session.getUserProperties());
105 request.lifecycleBindingsInjector(lifecycleBindingsInjector::injectLifecycleBindings);
106 ModelBuilder.ModelBuilderSession mbSession =
107 iSession.getData().get(SessionData.key(ModelBuilder.ModelBuilderSession.class));
108 return mbSession.build(request.build());
109 }
110
111 static Model transform(Model model, MavenProject project) {
112 String packaging = model.getPackaging();
113 if (POM_PACKAGING.equals(packaging)) {
114
115 model = model.withRoot(false).withModules(null).withSubprojects(null);
116 if (model.getParent() != null) {
117 model = model.withParent(model.getParent().withRelativePath(null));
118 }
119
120 if (!model.isPreserveModelVersion()) {
121 model = model.withPreserveModelVersion(false);
122 String modelVersion = new MavenModelVersion().getModelVersion(model);
123 model = model.withModelVersion(modelVersion);
124 }
125 } else if (BOM_PACKAGING.equals(packaging)) {
126 DependencyManagement dependencyManagement =
127 project.getOriginalModel().getDependencyManagement().getDelegate();
128 List<Dependency> dependencies = new ArrayList<>();
129 String version = model.getVersion();
130
131 dependencyManagement
132 .getDependencies()
133 .forEach((dependency) -> dependencies.add(dependency.withVersion(version)));
134 Model.Builder builder = prune(
135 Model.newBuilder(model, true)
136 .preserveModelVersion(false)
137 .root(false)
138 .parent(null)
139 .dependencyManagement(dependencyManagement.withDependencies(dependencies))
140 .build(null),
141 model);
142 builder.packaging(POM_PACKAGING);
143 builder.profiles(prune(model.getProfiles()));
144
145 model = builder.build();
146 String modelVersion = new MavenModelVersion().getModelVersion(model);
147 model = model.withModelVersion(modelVersion);
148 } else {
149 Model.Builder builder = prune(
150 Model.newBuilder(model, true)
151 .preserveModelVersion(false)
152 .root(false)
153 .parent(null)
154 .build(null),
155 model);
156 builder.profiles(prune(model.getProfiles()));
157
158 model = builder.build();
159 String modelVersion = new MavenModelVersion().getModelVersion(model);
160 model = model.withModelVersion(modelVersion);
161 }
162 return model;
163 }
164
165 private static List<Profile> prune(List<Profile> profiles) {
166 return profiles.stream()
167 .map(p -> {
168 Profile.Builder builder = Profile.newBuilder(p, true);
169 prune((ModelBase.Builder) builder, p);
170 return builder.build(null).build();
171 })
172 .filter(p -> !isEmpty(p))
173 .collect(Collectors.toList());
174 }
175
176 private static boolean isEmpty(Profile profile) {
177 return profile.getActivation() == null
178 && profile.getBuild() == null
179 && profile.getDependencies().isEmpty()
180 && (profile.getDependencyManagement() == null
181 || profile.getDependencyManagement().getDependencies().isEmpty())
182 && profile.getDistributionManagement() == null
183 && profile.getModules().isEmpty()
184 && profile.getSubprojects().isEmpty()
185 && profile.getProperties().isEmpty()
186 && profile.getRepositories().isEmpty()
187 && profile.getPluginRepositories().isEmpty()
188 && profile.getReporting() == null;
189 }
190
191 private static <T extends ModelBase.Builder> T prune(T builder, ModelBase model) {
192 builder.properties(null).reporting(null);
193 if (model.getDistributionManagement() != null
194 && model.getDistributionManagement().getRelocation() != null) {
195
196 builder.distributionManagement(DistributionManagement.newBuilder()
197 .relocation(model.getDistributionManagement().getRelocation())
198 .build());
199 }
200
201 builder.pluginRepositories(pruneRepositories(model.getPluginRepositories()));
202 builder.repositories(pruneRepositories(model.getRepositories()));
203 return builder;
204 }
205
206 private static List<Repository> pruneRepositories(List<Repository> repositories) {
207 return repositories.stream()
208 .filter(r -> !org.apache.maven.api.Repository.CENTRAL_ID.equals(r.getId()))
209 .collect(Collectors.toList());
210 }
211
212 static class PomConsumerModelSource implements ModelSource {
213 final Path path;
214 final Path src;
215
216 PomConsumerModelSource(Path path, Path src) {
217 this.path = path;
218 this.src = src;
219 }
220
221 @Override
222 public Path getPath() {
223 return path;
224 }
225
226 @Override
227 public InputStream openStream() throws IOException {
228 return Files.newInputStream(src);
229 }
230
231 @Override
232 public String getLocation() {
233 return src.toString();
234 }
235
236 @Override
237 public Source resolve(String relative) {
238 return ModelSource.fromPath(path.resolve(relative));
239 }
240
241 @Override
242 public ModelSource resolve(ModelLocator locator, String relative) {
243 String norm = relative.replace('\\', File.separatorChar).replace('/', File.separatorChar);
244 Path path = getPath().getParent().resolve(norm);
245 Path relatedPom = locator.locateExistingPom(path);
246 if (relatedPom != null) {
247 return ModelSource.fromPath(relatedPom);
248 }
249 return null;
250 }
251
252 @Override
253 public boolean equals(Object o) {
254 return this == o
255 || o.getClass() == getClass()
256 && Objects.equals(path, ((PomConsumerModelSource) o).path)
257 && Objects.equals(src, ((PomConsumerModelSource) o).src);
258 }
259
260 @Override
261 public int hashCode() {
262 return Objects.hash(path, src);
263 }
264
265 @Override
266 public String toString() {
267 return "PomConsumerModelSource[" + "path=" + path + ']';
268 }
269 }
270 }