1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.artifact.buildinfo;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.nio.file.StandardCopyOption;
28 import java.time.Instant;
29 import java.time.format.DateTimeFormatter;
30 import java.util.Comparator;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.stream.Collectors;
34
35 import org.apache.commons.codec.digest.DigestUtils;
36 import org.apache.maven.RepositoryUtils;
37 import org.apache.maven.archiver.MavenArchiver;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugins.annotations.Mojo;
40 import org.apache.maven.project.MavenProject;
41 import org.apache.maven.shared.utils.logging.MessageUtils;
42 import org.eclipse.aether.artifact.Artifact;
43 import org.eclipse.aether.artifact.DefaultArtifact;
44
45
46
47
48
49
50
51 @Mojo(name = "describe-build-output", aggregator = true, threadSafe = true)
52 public class DescribeBuildOutputMojo extends AbstractBuildinfoMojo {
53
54 @Override
55 public void execute() throws MojoExecutionException {
56
57 Instant timestamp =
58 MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).orElse(null);
59 String effective = ((timestamp == null) ? "disabled" : DateTimeFormatter.ISO_INSTANT.format(timestamp));
60
61 diagnose(outputTimestamp, getLog(), project, session.getProjects(), effective);
62 getLog().info("");
63 describeBuildOutput();
64 }
65
66 private Path rootPath;
67 private BuildInfoWriter bi;
68
69 private void describeBuildOutput() throws MojoExecutionException {
70 rootPath = getExecutionRoot().getBasedir().toPath();
71 bi = newBuildInfoWriter(null, false);
72
73 Map<String, Long> groupIds = session.getProjects().stream()
74 .collect(Collectors.groupingBy(MavenProject::getGroupId, Collectors.counting()));
75 groupIds.entrySet().stream()
76 .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
77 .forEach(e -> getLog().info("groupId: " + e.getKey() + " (" + e.getValue() + " artifactId"
78 + ((e.getValue() > 1) ? "s" : "") + ")"));
79
80 Map<String, Set<String>> artifactIds = session.getProjects().stream()
81 .collect(Collectors.groupingBy(
82 MavenProject::getArtifactId, Collectors.mapping(MavenProject::getGroupId, Collectors.toSet())));
83 artifactIds.entrySet().stream()
84 .sorted(Map.Entry.comparingByKey())
85 .filter(e -> e.getValue().size() > 1)
86 .forEach(e ->
87 getLog().info("artifactId: " + e.getKey() + " defined for multiple groupIds: " + e.getValue()));
88
89 getLog().info("");
90 getLog().info(MessageUtils.buffer()
91 .a("skip/ignore? artifactId")
92 .strong("[:classifier][:extension]")
93 .a(" = build-path repository-filename size [sha256]")
94 .build());
95
96 for (MavenProject p : session.getProjects()) {
97 boolean skipped = isSkip(p);
98 String s = skipped ? "not-deployed " : " ";
99
100
101
102 Artifact consumerPom = RepositoryUtils.toArtifacts(p.getAttachedArtifacts()).stream()
103 .filter(a -> "pom".equals(a.getExtension()) && "consumer".equals(a.getClassifier()))
104 .findAny()
105 .orElse(null);
106
107 Artifact pomArtifact = new DefaultArtifact(p.getGroupId(), p.getArtifactId(), null, "pom", p.getVersion());
108 if (consumerPom != null) {
109
110
111 try {
112 Path pomFile = Files.createTempFile(Paths.get(p.getBuild().getDirectory()), "consumer-", ".pom");
113 Files.copy(consumerPom.getFile().toPath(), pomFile, StandardCopyOption.REPLACE_EXISTING);
114 pomArtifact = pomArtifact.setFile(pomFile.toFile());
115 getLog().info(s + describeArtifact(pomArtifact));
116
117 pomArtifact =
118 new DefaultArtifact(p.getGroupId(), p.getArtifactId(), "build", "pom", p.getVersion());
119 } catch (IOException e) {
120 throw new MojoExecutionException("Error processing consumer POM", e);
121 }
122 }
123 pomArtifact = pomArtifact.setFile(p.getFile());
124 getLog().info(s + describeArtifact(pomArtifact, skipped));
125
126
127 if (p.getArtifact().getFile() != null) {
128 getLog().info(s + describeArtifact(RepositoryUtils.toArtifact(p.getArtifact()), skipped));
129 }
130
131
132 for (Artifact a : RepositoryUtils.toArtifacts(p.getAttachedArtifacts())) {
133 if ("pom".equals(a.getExtension()) && "consumer".equals(a.getClassifier())) {
134
135 continue;
136 }
137 boolean ignored = skipped ? false : isIgnore(a);
138 String i = skipped ? s : (ignored ? "RB-ignored " : " ");
139 getLog().info(i + describeArtifact(a, skipped || ignored));
140 }
141 }
142 }
143
144 private boolean isIgnore(Artifact a) {
145 if (a.getExtension().endsWith(".asc")) {
146 return true;
147 }
148 if (bi.getIgnoreJavadoc() && "javadoc".equals(a.getClassifier())) {
149 return true;
150 }
151 return bi.isIgnore(a);
152 }
153
154 private String describeArtifact(Artifact a) throws MojoExecutionException {
155 return describeArtifact(a, false);
156 }
157
158 private String describeArtifact(Artifact a, boolean skipped) throws MojoExecutionException {
159 String sha256 = skipped ? "" : (" " + sha256(a.getFile()));
160 String ce = ("".equals(a.getClassifier()) ? "" : (':' + a.getClassifier()))
161 + ("jar".equals(a.getExtension()) ? "" : (":" + a.getExtension()));
162 String path = rootPath.relativize(a.getFile().toPath()).toString();
163 int i = path.indexOf("target/");
164 if (i >= 0) {
165 path = MessageUtils.buffer().mojo(path.substring(0, i + 7)).build() + path.substring(i + 7);
166 }
167 String remoteFilename = BuildInfoWriter.getArtifactFilename(a);
168 return a.getArtifactId()
169 + MessageUtils.buffer().strong(ce) + " = "
170 + path + " "
171 + (path.endsWith(remoteFilename)
172 ? "-"
173 : MessageUtils.buffer().strong(remoteFilename).build())
174 + " " + a.getFile().length() + sha256;
175 }
176
177 private String sha256(File file) throws MojoExecutionException {
178 try (InputStream is = Files.newInputStream(file.toPath())) {
179 return DigestUtils.sha256Hex(is);
180 } catch (IOException ioe) {
181 throw new MojoExecutionException("cannot read " + file, ioe);
182 }
183 }
184
185 @Override
186 public void execute(Map<org.eclipse.aether.artifact.Artifact, String> artifacts) throws MojoExecutionException {
187
188 }
189 }