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