1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Objects;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.ConcurrentMap;
29 import java.util.stream.Collectors;
30
31 import org.apache.maven.SessionScoped;
32 import org.apache.maven.buildcache.xml.CacheConfig;
33 import org.apache.maven.lifecycle.internal.builder.BuilderCommon;
34 import org.apache.maven.model.Build;
35 import org.apache.maven.model.Dependency;
36 import org.apache.maven.model.Model;
37 import org.apache.maven.model.Plugin;
38 import org.apache.maven.model.PluginExecution;
39 import org.apache.maven.project.MavenProject;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 @SessionScoped
44 @Named
45 public class DefaultNormalizedModelProvider implements NormalizedModelProvider {
46
47 private static final String NORMALIZED_VERSION = "cache-extension-version";
48
49 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultNormalizedModelProvider.class);
50
51 private final CacheConfig cacheConfig;
52 private final MultiModuleSupport multiModuleSupport;
53 private final ConcurrentMap<String, Model> modelCache = new ConcurrentHashMap<>();
54
55 @Inject
56 public DefaultNormalizedModelProvider(MultiModuleSupport multiModuleSupport, CacheConfig cacheConfig) {
57 this.multiModuleSupport = multiModuleSupport;
58 this.cacheConfig = cacheConfig;
59 }
60
61 @Override
62 public Model normalizedModel(MavenProject project) {
63 MavenProject validatedProject = Objects.requireNonNull(project, "project");
64 return modelCache.computeIfAbsent(
65 BuilderCommon.getKey(validatedProject), k -> normalizedModelInner(validatedProject));
66 }
67
68 private Model normalizedModelInner(MavenProject project) {
69
70
71 MavenProject projectToNormalize = multiModuleSupport
72 .tryToResolveProject(project.getGroupId(), project.getArtifactId(), project.getVersion())
73 .orElse(project);
74 Model prototype = projectToNormalize.getModel();
75
76
77 Model resultModel = new Model();
78
79 resultModel.setGroupId(prototype.getGroupId());
80 resultModel.setArtifactId(prototype.getArtifactId());
81
82 resultModel.setVersion(NORMALIZED_VERSION);
83 resultModel.setModules(prototype.getModules());
84
85 resultModel.setDependencies(normalizeDependencies(prototype.getDependencies()));
86
87 org.apache.maven.model.Build protoBuild = prototype.getBuild();
88 if (protoBuild == null) {
89 return resultModel;
90 }
91
92 Build build = new Build();
93 List<Plugin> plugins = prototype.getBuild().getPlugins();
94 build.setPlugins(normalizePlugins(plugins));
95 resultModel.setBuild(build);
96 return resultModel;
97 }
98
99 private List<Dependency> normalizeDependencies(Collection<Dependency> source) {
100 return source.stream()
101 .map(it -> {
102 if (!multiModuleSupport.isPartOfMultiModule(it.getGroupId(), it.getArtifactId(), it.getVersion())) {
103 return it;
104 }
105 Dependency cloned = it.clone();
106 cloned.setVersion(NORMALIZED_VERSION);
107 return cloned;
108 })
109 .sorted(DefaultNormalizedModelProvider::compareDependencies)
110 .collect(Collectors.toList());
111 }
112
113 private List<Plugin> normalizePlugins(List<Plugin> plugins) {
114 if (plugins.isEmpty()) {
115 return plugins;
116 }
117
118 return plugins.stream()
119 .map(plugin -> {
120 Plugin copy = plugin.clone();
121 List<String> excludeProperties = cacheConfig.getEffectivePomExcludeProperties(copy);
122 if (!excludeProperties.isEmpty()) {
123 CacheUtils.debugPrintCollection(
124 LOGGER,
125 excludeProperties,
126 String.format("List of excluded properties for %s", copy.getArtifactId()),
127 "Excluded property");
128 removeBlacklistedAttributes(copy.getConfiguration(), excludeProperties);
129 for (PluginExecution execution : copy.getExecutions()) {
130 removeBlacklistedAttributes(execution.getConfiguration(), excludeProperties);
131 }
132 }
133
134 copy.setDependencies(normalizeDependencies(copy.getDependencies().stream()
135 .sorted(DefaultNormalizedModelProvider::compareDependencies)
136 .collect(Collectors.toList())));
137 if (multiModuleSupport.isPartOfMultiModule(
138 copy.getGroupId(), copy.getArtifactId(), copy.getVersion())) {
139 copy.setVersion(NORMALIZED_VERSION);
140 }
141 return copy;
142 })
143 .collect(Collectors.toList());
144 }
145
146 private void removeBlacklistedAttributes(Object node, List<String> excludeProperties) {
147 if (node == null) {
148 return;
149 }
150
151 Object[] children = Xpp3DomUtils.getChildren(node);
152 int indexToRemove = 0;
153 for (Object child : children) {
154 if (excludeProperties.contains(Xpp3DomUtils.getName(child))) {
155 Xpp3DomUtils.removeChild(node, indexToRemove);
156 continue;
157 }
158 indexToRemove++;
159 removeBlacklistedAttributes(child, excludeProperties);
160 }
161 }
162
163 private static int compareDependencies(Dependency d1, Dependency d2) {
164 return d1.getArtifactId().compareTo(d2.getArtifactId());
165 }
166 }