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.buildcache.xml;
20  
21  import java.io.IOException;
22  import java.net.InetAddress;
23  import java.net.UnknownHostException;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Date;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Objects;
30  import java.util.stream.Collectors;
31  
32  import org.apache.maven.buildcache.CacheUtils;
33  import org.apache.maven.buildcache.checksum.MavenProjectInput;
34  import org.apache.maven.buildcache.hash.HashAlgorithm;
35  import org.apache.maven.buildcache.xml.build.Artifact;
36  import org.apache.maven.buildcache.xml.build.CompletedExecution;
37  import org.apache.maven.buildcache.xml.build.DigestItem;
38  import org.apache.maven.buildcache.xml.build.ProjectsInputInfo;
39  import org.apache.maven.model.Dependency;
40  import org.apache.maven.plugin.MojoExecution;
41  
42  import static org.apache.maven.buildcache.CacheUtils.mojoExecutionKey;
43  
44  /**
45   * Build
46   */
47  public class Build {
48  
49      final org.apache.maven.buildcache.xml.build.Build dto;
50      CacheSource source;
51      volatile Map<String, CompletedExecution> execMap;
52  
53      public Build(
54              List<String> goals,
55              Artifact artifact,
56              List<Artifact> attachedArtifacts,
57              ProjectsInputInfo projectsInputInfo,
58              List<CompletedExecution> completedExecutions,
59              String hashAlgorithm) {
60          this.dto = new org.apache.maven.buildcache.xml.build.Build();
61          this.dto.setCacheImplementationVersion(MavenProjectInput.CACHE_IMPLEMENTATION_VERSION);
62          this.dto.setBuildTime(new Date());
63          try {
64              this.dto.setBuildServer(InetAddress.getLocalHost().getCanonicalHostName());
65          } catch (UnknownHostException ignore) {
66              this.dto.setBuildServer("unknown");
67          }
68          this.dto.setHashFunction(hashAlgorithm);
69          this.dto.setArtifact(artifact);
70          this.dto.setGoals(goals);
71          this.dto.setAttachedArtifacts(attachedArtifacts);
72          this.dto.setExecutions(completedExecutions);
73          this.dto.setProjectsInputInfo(projectsInputInfo);
74          this.source = CacheSource.BUILD;
75      }
76  
77      public CacheSource getSource() {
78          return source;
79      }
80  
81      public Build(org.apache.maven.buildcache.xml.build.Build dto, CacheSource source) {
82          this.dto = dto;
83          this.source = source;
84      }
85  
86      public static List<Artifact> createAttachedArtifacts(
87              List<org.apache.maven.artifact.Artifact> artifacts, HashAlgorithm algorithm) throws IOException {
88          List<Artifact> attachedArtifacts = new ArrayList<>();
89          for (org.apache.maven.artifact.Artifact artifact : artifacts) {
90              final Artifact dto = DtoUtils.createDto(artifact);
91              if (artifact.getFile() != null) {
92                  dto.setFileHash(algorithm.hash(artifact.getFile().toPath()));
93              }
94              attachedArtifacts.add(dto);
95          }
96          return attachedArtifacts;
97      }
98  
99      public List<MojoExecution> getMissingExecutions(List<MojoExecution> mojos) {
100         return mojos.stream()
101                 .filter(mojo -> !hasCompletedExecution(mojoExecutionKey(mojo)))
102                 .collect(Collectors.toList());
103     }
104 
105     private boolean hasCompletedExecution(String mojoExecutionKey) {
106         return getExecutionMap().containsKey(mojoExecutionKey);
107     }
108 
109     @Override
110     public String toString() {
111         return "Build{" + "dto=" + dto + '}';
112     }
113 
114     public CompletedExecution findMojoExecutionInfo(MojoExecution mojoExecution) {
115         return getExecutionMap().get(mojoExecutionKey(mojoExecution));
116     }
117 
118     public String getCacheImplementationVersion() {
119         return dto.getCacheImplementationVersion();
120     }
121 
122     public Artifact getArtifact() {
123         return dto.getArtifact();
124     }
125 
126     public List<Artifact> getAttachedArtifacts() {
127         if (dto.getAttachedArtifacts() != null) {
128             return dto.getAttachedArtifacts();
129         }
130         return Collections.emptyList();
131     }
132 
133     public org.apache.maven.buildcache.xml.build.Build getDto() {
134         return dto;
135     }
136 
137     public String getHighestCompletedGoal() {
138         return CacheUtils.getLast(dto.getGoals());
139     }
140 
141     public DigestItem findArtifact(Dependency dependency) {
142         if (CacheUtils.isPom(dependency)) {
143             throw new IllegalArgumentException("Pom dependencies should not be treated as artifacts: " + dependency);
144         }
145         List<Artifact> artifacts = new ArrayList<>(getAttachedArtifacts());
146         artifacts.add(getArtifact());
147         for (Artifact artifact : artifacts) {
148             if (isEquals(dependency, artifact)) {
149                 return DtoUtils.createdDigestedByProjectChecksum(
150                         artifact, dto.getProjectsInputInfo().getChecksum());
151             }
152         }
153         return null;
154     }
155 
156     private boolean isEquals(Dependency dependency, Artifact artifact) {
157         return Objects.equals(dependency.getGroupId(), artifact.getGroupId())
158                 && Objects.equals(dependency.getArtifactId(), artifact.getArtifactId())
159                 && Objects.equals(dependency.getType(), artifact.getType())
160                 && Objects.equals(dependency.getClassifier(), artifact.getClassifier());
161     }
162 
163     private Map<String, CompletedExecution> getExecutionMap() {
164         if (execMap != null) {
165             return execMap;
166         }
167         List<CompletedExecution> executionsList = dto.getExecutions();
168         if (executionsList == null || executionsList.isEmpty()) {
169             execMap = Collections.emptyMap();
170             return execMap;
171         }
172         execMap = executionsList.stream()
173                 .collect(Collectors.toMap(CompletedExecution::getExecutionKey, v -> v, (oldV, newV) -> oldV));
174         return execMap;
175     }
176 }