1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.release.plugin.mojos;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.io.PrintWriter;
24 import java.nio.file.Files;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Set;
30
31 import org.apache.commons.codec.digest.DigestUtils;
32 import org.apache.commons.collections4.properties.SortedProperties;
33 import org.apache.commons.lang3.StringUtils;
34 import org.apache.commons.lang3.reflect.MethodUtils;
35 import org.apache.commons.release.plugin.SharedFunctions;
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.plugin.AbstractMojo;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugins.annotations.LifecyclePhase;
40 import org.apache.maven.plugins.annotations.Mojo;
41 import org.apache.maven.plugins.annotations.Parameter;
42 import org.apache.maven.project.MavenProject;
43
44
45
46
47
48
49
50
51 @Mojo(name = "detach-distributions",
52 defaultPhase = LifecyclePhase.VERIFY,
53 threadSafe = true,
54 aggregator = true)
55 public class CommonsDistributionDetachmentMojo extends AbstractMojo {
56
57
58
59
60
61
62
63
64 private static final Set<String> ARTIFACT_TYPES_TO_DETACH;
65
66 static {
67 final Set<String> hashSet = new HashSet<>();
68 hashSet.add("zip");
69 hashSet.add("tar.gz");
70 hashSet.add("zip.asc");
71 hashSet.add("tar.gz.asc");
72 ARTIFACT_TYPES_TO_DETACH = Collections.unmodifiableSet(hashSet);
73 }
74
75
76
77
78
79 private final List<Artifact> detachedArtifacts = new ArrayList<>();
80
81
82
83
84
85
86 private final SortedProperties artifactSha512s = new SortedProperties();
87
88
89
90
91 @Parameter(defaultValue = "${project}", required = true)
92 private MavenProject project;
93
94
95
96
97 @Parameter(defaultValue = "${project.build.directory}/commons-release-plugin",
98 property = "commons.outputDirectory")
99 private File workingDirectory;
100
101
102
103
104 @Parameter(defaultValue = "", property = "commons.distSvnStagingUrl")
105 private String distSvnStagingUrl;
106
107
108
109
110 @Parameter(defaultValue = "false", property = "commons.release.isDistModule")
111 private Boolean isDistModule;
112
113
114
115
116 public CommonsDistributionDetachmentMojo() {
117
118 }
119
120
121
122
123
124
125
126
127 private void copyRemovedArtifactsToWorkingDirectory() throws MojoExecutionException {
128 final String wdAbsolutePath = workingDirectory.getAbsolutePath();
129 getLog().info(
130 "Copying " + detachedArtifacts.size() + " detached artifacts to working directory " + wdAbsolutePath);
131 for (final Artifact artifact: detachedArtifacts) {
132 final File artifactFile = artifact.getFile();
133 final StringBuilder copiedArtifactAbsolutePath = new StringBuilder(wdAbsolutePath);
134 copiedArtifactAbsolutePath.append("/");
135 copiedArtifactAbsolutePath.append(artifactFile.getName());
136 final File copiedArtifact = new File(copiedArtifactAbsolutePath.toString());
137 getLog().info("Copying: " + artifactFile.getName());
138 SharedFunctions.copyFile(getLog(), artifactFile, copiedArtifact);
139 }
140 }
141
142 @Override
143 public void execute() throws MojoExecutionException {
144 if (!isDistModule) {
145 getLog().info("This module is marked as a non distribution or assembly module, and the plugin will not run.");
146 return;
147 }
148 if (StringUtils.isEmpty(distSvnStagingUrl)) {
149 getLog().warn("commons.distSvnStagingUrl is not set, the commons-release-plugin will not run.");
150 return;
151 }
152 getLog().info("Detaching Assemblies");
153 for (final Artifact attachedArtifact : project.getAttachedArtifacts()) {
154 putAttachedArtifactInSha512Map(attachedArtifact);
155 if (ARTIFACT_TYPES_TO_DETACH.contains(attachedArtifact.getType())) {
156 detachedArtifacts.add(attachedArtifact);
157 }
158 }
159 if (detachedArtifacts.isEmpty()) {
160 getLog().info("Current project contains no distributions. Not executing.");
161 return;
162 }
163
164
165
166 try {
167
168
169
170 project.getAttachedArtifacts().removeAll(detachedArtifacts);
171 } catch (final UnsupportedOperationException e) {
172
173 final ArrayList<Artifact> arrayList = new ArrayList<>(project.getAttachedArtifacts());
174 arrayList.removeAll(detachedArtifacts);
175 try {
176
177 MethodUtils.invokeMethod(project, true, "setAttachedArtifacts", arrayList);
178 } catch (final ReflectiveOperationException roe) {
179 throw new MojoExecutionException(roe);
180 }
181 }
182 if (!workingDirectory.exists()) {
183 SharedFunctions.initDirectory(getLog(), workingDirectory);
184 }
185 writeAllArtifactsInSha512PropertiesFile();
186 copyRemovedArtifactsToWorkingDirectory();
187 getLog().info("");
188 hashArtifacts();
189 }
190
191
192
193
194
195
196
197
198 private String getArtifactKey(final Artifact artifact) {
199 return artifact.getFile().getName();
200 }
201
202
203
204
205
206
207
208
209 private String getSha512FilePath(final File directory, final File file) {
210 final StringBuilder buffer = new StringBuilder(directory.getAbsolutePath());
211 buffer.append("/");
212 buffer.append(file.getName());
213 buffer.append(".sha512");
214 return buffer.toString();
215 }
216
217
218
219
220
221
222
223
224
225 private void hashArtifacts() throws MojoExecutionException {
226 for (final Artifact artifact : detachedArtifacts) {
227 if (!StringUtils.toRootLowerCase(artifact.getFile().getName()).contains("asc")) {
228 final String artifactKey = getArtifactKey(artifact);
229 try {
230 final String digest;
231
232 digest = artifactSha512s.getProperty(artifactKey.toString());
233 getLog().info(artifact.getFile().getName() + " sha512: " + digest);
234 try (PrintWriter printWriter = new PrintWriter(
235 getSha512FilePath(workingDirectory, artifact.getFile()))) {
236 printWriter.println(digest);
237 }
238 } catch (final IOException e) {
239 throw new MojoExecutionException("Could not sign file: " + artifact.getFile().getName(), e);
240 }
241 }
242 }
243 }
244
245
246
247
248
249
250
251 private void putAttachedArtifactInSha512Map(final Artifact artifact) throws MojoExecutionException {
252 try {
253 final String artifactKey = getArtifactKey(artifact);
254 if (!artifactKey.endsWith(".asc")) {
255 try (InputStream fis = Files.newInputStream(artifact.getFile().toPath())) {
256 artifactSha512s.put(artifactKey, DigestUtils.sha512Hex(fis));
257 }
258 }
259 } catch (final IOException e) {
260 throw new MojoExecutionException(
261 "Could not find artifact signature for: "
262 + artifact.getArtifactId()
263 + "-"
264 + artifact.getClassifier()
265 + "-"
266 + artifact.getVersion()
267 + " type: "
268 + artifact.getType(),
269 e);
270 }
271 }
272
273
274
275
276
277
278 private void writeAllArtifactsInSha512PropertiesFile() throws MojoExecutionException {
279 final File propertiesFile = new File(workingDirectory, "sha512.properties");
280 getLog().info("Writing " + propertiesFile);
281 try (OutputStream fileWriter = Files.newOutputStream(propertiesFile.toPath())) {
282 artifactSha512s.store(fileWriter, "Release SHA-512s");
283 } catch (final IOException e) {
284 throw new MojoExecutionException("Failure to write SHA-512's", e);
285 }
286 }
287 }