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 import javax.inject.Provider;
24
25 import java.nio.file.Path;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.stream.Collectors;
31
32 import org.apache.maven.api.SessionData;
33 import org.apache.maven.api.model.Dependency;
34 import org.apache.maven.api.model.DependencyManagement;
35 import org.apache.maven.api.model.DistributionManagement;
36 import org.apache.maven.api.model.Model;
37 import org.apache.maven.api.model.ModelBase;
38 import org.apache.maven.api.model.Profile;
39 import org.apache.maven.api.model.Repository;
40 import org.apache.maven.api.services.ModelBuilderException;
41 import org.apache.maven.api.services.ModelBuilderRequest;
42 import org.apache.maven.api.services.ModelBuilderResult;
43 import org.apache.maven.api.services.ModelProblemCollector;
44 import org.apache.maven.api.services.ModelResolver;
45 import org.apache.maven.api.services.ModelSource;
46 import org.apache.maven.api.services.ModelTransformer;
47 import org.apache.maven.api.services.SuperPomProvider;
48 import org.apache.maven.api.services.model.DependencyManagementImporter;
49 import org.apache.maven.api.services.model.DependencyManagementInjector;
50 import org.apache.maven.api.services.model.InheritanceAssembler;
51 import org.apache.maven.api.services.model.LifecycleBindingsInjector;
52 import org.apache.maven.api.services.model.ModelInterpolator;
53 import org.apache.maven.api.services.model.ModelNormalizer;
54 import org.apache.maven.api.services.model.ModelPathTranslator;
55 import org.apache.maven.api.services.model.ModelProcessor;
56 import org.apache.maven.api.services.model.ModelUrlNormalizer;
57 import org.apache.maven.api.services.model.ModelValidator;
58 import org.apache.maven.api.services.model.ModelVersionParser;
59 import org.apache.maven.api.services.model.PluginConfigurationExpander;
60 import org.apache.maven.api.services.model.PluginManagementInjector;
61 import org.apache.maven.api.services.model.ProfileActivationContext;
62 import org.apache.maven.api.services.model.ProfileInjector;
63 import org.apache.maven.api.services.model.ProfileSelector;
64 import org.apache.maven.internal.impl.InternalSession;
65 import org.apache.maven.internal.impl.model.DefaultModelBuilder;
66 import org.apache.maven.internal.impl.model.DefaultProfileSelector;
67 import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
68 import org.apache.maven.internal.impl.resolver.DefaultModelCache;
69 import org.apache.maven.model.v4.MavenModelVersion;
70 import org.apache.maven.project.MavenProject;
71 import org.eclipse.aether.RepositorySystem;
72 import org.eclipse.aether.RepositorySystemSession;
73 import org.eclipse.aether.impl.RemoteRepositoryManager;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
76
77 @Named
78 class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
79 private static final String BOM_PACKAGING = "bom";
80
81 public static final String POM_PACKAGING = "pom";
82
83 @Inject
84 private ProfileInjector profileInjector;
85
86 @Inject
87 private InheritanceAssembler inheritanceAssembler;
88
89 @Inject
90 private DependencyManagementImporter dependencyManagementImporter;
91
92 @Inject
93 private DependencyManagementInjector dependencyManagementInjector;
94
95 @Inject
96 private LifecycleBindingsInjector lifecycleBindingsInjector;
97
98 @Inject
99 private ModelInterpolator modelInterpolator;
100
101 @Inject
102 private ModelNormalizer modelNormalizer;
103
104 @Inject
105 private ModelPathTranslator modelPathTranslator;
106
107 @Inject
108 private ModelProcessor modelProcessor;
109
110 @Inject
111 private ModelUrlNormalizer modelUrlNormalizer;
112
113 @Inject
114 private ModelValidator modelValidator;
115
116 @Inject
117 private PluginConfigurationExpander pluginConfigurationExpander;
118
119 @Inject
120 private PluginManagementInjector pluginManagementInjector;
121
122 @Inject
123 private SuperPomProvider superPomProvider;
124
125 @Inject
126 private ModelVersionParser versionParser;
127
128 @Inject
129 private ModelTransformer modelTransformer;
130
131
132 @Inject
133 private Provider<RepositorySystem> repositorySystem;
134
135 @Inject
136 private RemoteRepositoryManager remoteRepositoryManager;
137
138 @Inject
139 private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
140
141 Logger logger = LoggerFactory.getLogger(getClass());
142
143 @Override
144 public Model build(RepositorySystemSession session, MavenProject project, Path src) throws ModelBuilderException {
145 Model model = project.getModel().getDelegate();
146 String packaging = model.getPackaging();
147 String originalPackaging = project.getOriginalModel().getPackaging();
148 if (POM_PACKAGING.equals(packaging) && !BOM_PACKAGING.equals(originalPackaging)) {
149 return buildPom(session, project, src);
150 } else {
151 return buildNonPom(session, project, src);
152 }
153 }
154
155 protected Model buildPom(RepositorySystemSession session, MavenProject project, Path src)
156 throws ModelBuilderException {
157 ModelBuilderResult result = buildModel(session, project, src);
158 Model model = result.getRawModel();
159 return transform(model, project);
160 }
161
162 protected Model buildNonPom(RepositorySystemSession session, MavenProject project, Path src)
163 throws ModelBuilderException {
164 ModelBuilderResult result = buildModel(session, project, src);
165 Model model = result.getEffectiveModel();
166 return transform(model, project);
167 }
168
169 private ModelBuilderResult buildModel(RepositorySystemSession session, MavenProject project, Path src)
170 throws ModelBuilderException {
171 ProfileSelector customSelector = new DefaultProfileSelector() {
172 @Override
173 public List<Profile> getActiveProfiles(
174 Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
175 return new ArrayList<>();
176 }
177 };
178 DefaultModelBuilder modelBuilder = new DefaultModelBuilder(
179 modelProcessor,
180 modelValidator,
181 modelNormalizer,
182 modelInterpolator,
183 modelPathTranslator,
184 modelUrlNormalizer,
185 superPomProvider,
186 inheritanceAssembler,
187 customSelector,
188 profileInjector,
189 pluginManagementInjector,
190 dependencyManagementInjector,
191 dependencyManagementImporter,
192 lifecycleBindingsInjector,
193 pluginConfigurationExpander,
194 profileActivationFilePathInterpolator,
195 modelTransformer,
196 versionParser);
197 InternalSession iSession = InternalSession.from(session);
198 ModelBuilderRequest.ModelBuilderRequestBuilder request = ModelBuilderRequest.builder();
199 request.projectBuild(true);
200 request.session(iSession);
201 request.source(ModelSource.fromPath(src));
202 request.validationLevel(ModelBuilderRequest.VALIDATION_LEVEL_MINIMAL);
203 request.locationTracking(false);
204 request.modelResolver(iSession.getData().get(SessionData.key(ModelResolver.class)));
205 request.transformerContextBuilder(modelBuilder.newTransformerContextBuilder());
206 request.systemProperties(session.getSystemProperties());
207 request.userProperties(session.getUserProperties());
208 request.modelCache(DefaultModelCache.newInstance(session, false));
209 if (session.getCache() != null) {
210 Map<?, ?> map = (Map) session.getCache().get(session, DefaultModelCache.class.getName());
211 List<String> paths = map.keySet().stream()
212 .map(Object::toString)
213 .filter(s -> s.startsWith("SourceCacheKey"))
214 .map(s -> s.substring("SourceCacheKey[location=".length(), s.indexOf(", tag")))
215 .sorted()
216 .distinct()
217 .toList();
218 logger.debug("ModelCache contains " + paths.size());
219 paths.forEach(s -> logger.debug(" " + s));
220 }
221 return modelBuilder.build(request.build());
222 }
223
224 static Model transform(Model model, MavenProject project) {
225 String packaging = model.getPackaging();
226 if (POM_PACKAGING.equals(packaging)) {
227
228 model = model.withRoot(false).withModules(null).withSubprojects(null);
229 if (model.getParent() != null) {
230 model = model.withParent(model.getParent().withRelativePath(null));
231 }
232
233 if (!model.isPreserveModelVersion()) {
234 model = model.withPreserveModelVersion(false);
235 String modelVersion = new MavenModelVersion().getModelVersion(model);
236 model = model.withModelVersion(modelVersion);
237 }
238 } else if (BOM_PACKAGING.equals(packaging)) {
239 DependencyManagement dependencyManagement =
240 project.getOriginalModel().getDependencyManagement().getDelegate();
241 List<Dependency> dependencies = new ArrayList<>();
242 String version = model.getVersion();
243
244 dependencyManagement
245 .getDependencies()
246 .forEach((dependency) -> dependencies.add(dependency.withVersion(version)));
247 Model.Builder builder = prune(
248 Model.newBuilder(model, true)
249 .preserveModelVersion(false)
250 .root(false)
251 .parent(null)
252 .dependencyManagement(dependencyManagement.withDependencies(dependencies))
253 .build(null),
254 model);
255 builder.packaging(POM_PACKAGING);
256 builder.profiles(prune(model.getProfiles()));
257
258 model = builder.build();
259 String modelVersion = new MavenModelVersion().getModelVersion(model);
260 model = model.withModelVersion(modelVersion);
261 } else {
262 Model.Builder builder = prune(
263 Model.newBuilder(model, true)
264 .preserveModelVersion(false)
265 .root(false)
266 .parent(null)
267 .build(null),
268 model);
269 builder.profiles(prune(model.getProfiles()));
270
271 model = builder.build();
272 String modelVersion = new MavenModelVersion().getModelVersion(model);
273 model = model.withModelVersion(modelVersion);
274 }
275 return model;
276 }
277
278 private static List<Profile> prune(List<Profile> profiles) {
279 return profiles.stream()
280 .map(p -> {
281 Profile.Builder builder = Profile.newBuilder(p, true);
282 prune((ModelBase.Builder) builder, p);
283 return builder.build(null).build();
284 })
285 .filter(p -> !isEmpty(p))
286 .collect(Collectors.toList());
287 }
288
289 private static boolean isEmpty(Profile profile) {
290 return profile.getActivation() == null
291 && profile.getBuild() == null
292 && profile.getDependencies().isEmpty()
293 && (profile.getDependencyManagement() == null
294 || profile.getDependencyManagement().getDependencies().isEmpty())
295 && profile.getDistributionManagement() == null
296 && profile.getModules().isEmpty()
297 && profile.getSubprojects().isEmpty()
298 && profile.getProperties().isEmpty()
299 && profile.getRepositories().isEmpty()
300 && profile.getPluginRepositories().isEmpty()
301 && profile.getReporting() == null;
302 }
303
304 private static <T extends ModelBase.Builder> T prune(T builder, ModelBase model) {
305 builder.properties(null).reporting(null);
306 if (model.getDistributionManagement() != null
307 && model.getDistributionManagement().getRelocation() != null) {
308
309 builder.distributionManagement(DistributionManagement.newBuilder()
310 .relocation(model.getDistributionManagement().getRelocation())
311 .build());
312 }
313
314 builder.pluginRepositories(pruneRepositories(model.getPluginRepositories()));
315 builder.repositories(pruneRepositories(model.getRepositories()));
316 return builder;
317 }
318
319 private static List<Repository> pruneRepositories(List<Repository> repositories) {
320 return repositories.stream()
321 .filter(r -> !org.apache.maven.api.Repository.CENTRAL_ID.equals(r.getId()))
322 .collect(Collectors.toList());
323 }
324 }