View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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   * ModelSourceTransformer for the build pom
37   *
38   * @since 4.0.0
39   * @deprecated use {@link org.apache.maven.api.services.ModelBuilder} instead
40   */
41  @Named
42  @Singleton
43  @Deprecated(since = "4.0.0")
44  class BuildModelSourceTransformer implements ModelSourceTransformer {
45  
46      public static final String NAMESPACE_PREFIX = "http://maven.apache.org/POM/";
47  
48      @Override
49      public void transform(Path pomFile, TransformerContext context, Model model) {
50          handleModelVersion(model);
51          handleParent(pomFile, context, model);
52          handleReactorDependencies(context, model);
53          handleCiFriendlyVersion(context, model);
54      }
55  
56      //
57      // Infer modelVersion from namespace URI
58      //
59      void handleModelVersion(Model model) {
60          String namespace = model.getDelegate().getNamespaceUri();
61          if (model.getModelVersion() == null && namespace != null && namespace.startsWith(NAMESPACE_PREFIX)) {
62              model.setModelVersion(namespace.substring(NAMESPACE_PREFIX.length()));
63          }
64      }
65  
66      //
67      // Infer parent information
68      //
69      void handleParent(Path pomFile, TransformerContext context, Model model) {
70          Parent parent = model.getParent();
71          if (parent != null) {
72              String version = parent.getVersion();
73              String path = Optional.ofNullable(parent.getRelativePath()).orElse("..");
74              if (version == null && !path.isEmpty()) {
75                  Optional<RelativeProject> resolvedParent = resolveRelativePath(
76                          pomFile, context, Paths.get(path), parent.getGroupId(), parent.getArtifactId());
77                  resolvedParent.ifPresent(relativeProject -> parent.setVersion(relativeProject.getVersion()));
78              }
79          }
80      }
81  
82      //
83      // CI friendly versions
84      //
85      void handleCiFriendlyVersion(TransformerContext context, Model model) {
86          String version = model.getVersion();
87          String modVersion = replaceCiFriendlyVersion(context, version);
88          model.setVersion(modVersion);
89  
90          Parent parent = model.getParent();
91          if (parent != null) {
92              version = parent.getVersion();
93              modVersion = replaceCiFriendlyVersion(context, version);
94              parent.setVersion(modVersion);
95          }
96      }
97  
98      //
99      // Infer inner reactor dependencies version
100     //
101     void handleReactorDependencies(TransformerContext context, Model model) {
102         for (Dependency dep : model.getDependencies()) {
103             if (dep.getVersion() == null) {
104                 Model depModel =
105                         context.getRawModel(model.getDelegate().getPomFile(), dep.getGroupId(), dep.getArtifactId());
106                 if (depModel != null) {
107                     String v = depModel.getVersion();
108                     if (v == null && depModel.getParent() != null) {
109                         v = depModel.getParent().getVersion();
110                     }
111                     dep.setVersion(v);
112                 }
113             }
114         }
115     }
116 
117     protected String replaceCiFriendlyVersion(TransformerContext context, String version) {
118         if (version != null) {
119             for (String key : Arrays.asList("changelist", "revision", "sha1")) {
120                 String val = context.getUserProperty(key);
121                 if (val != null) {
122                     version = version.replace("${" + key + "}", val);
123                 }
124             }
125         }
126         return version;
127     }
128 
129     protected Optional<RelativeProject> resolveRelativePath(
130             Path pomFile, TransformerContext context, Path relativePath, String groupId, String artifactId) {
131         Path pomPath = pomFile.resolveSibling(relativePath).normalize();
132         if (Files.isDirectory(pomPath)) {
133             pomPath = context.locate(pomPath);
134         }
135 
136         if (pomPath == null || !Files.isRegularFile(pomPath)) {
137             return Optional.empty();
138         }
139 
140         Optional<RelativeProject> mappedProject = Optional.ofNullable(context.getRawModel(pomFile, pomPath.normalize()))
141                 .map(BuildModelSourceTransformer::toRelativeProject);
142 
143         if (mappedProject.isPresent()) {
144             RelativeProject project = mappedProject.get();
145 
146             if (Objects.equals(groupId, project.getGroupId()) && Objects.equals(artifactId, project.getArtifactId())) {
147                 return mappedProject;
148             }
149         }
150         return Optional.empty();
151     }
152 
153     private static RelativeProject toRelativeProject(final org.apache.maven.model.Model m) {
154         String groupId = m.getGroupId();
155         if (groupId == null && m.getParent() != null) {
156             groupId = m.getParent().getGroupId();
157         }
158 
159         String version = m.getVersion();
160         if (version == null && m.getParent() != null) {
161             version = m.getParent().getVersion();
162         }
163 
164         return new RelativeProject(groupId, m.getArtifactId(), version);
165     }
166 
167     static class RelativeProject {
168         private final String groupId;
169 
170         private final String artifactId;
171 
172         private final String version;
173 
174         RelativeProject(String groupId, String artifactId, String version) {
175             this.groupId = groupId;
176             this.artifactId = artifactId;
177             this.version = version;
178         }
179 
180         public String getGroupId() {
181             return groupId;
182         }
183 
184         public String getArtifactId() {
185             return artifactId;
186         }
187 
188         public String getVersion() {
189             return version;
190         }
191     }
192 }