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.Locale;
30 import java.util.Set;
31
32 import org.apache.commons.codec.digest.DigestUtils;
33 import org.apache.commons.collections4.properties.SortedProperties;
34 import org.apache.commons.lang3.StringUtils;
35 import org.apache.commons.lang3.reflect.MethodUtils;
36 import org.apache.commons.release.plugin.SharedFunctions;
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.plugin.AbstractMojo;
39 import org.apache.maven.plugin.MojoExecutionException;
40 import org.apache.maven.plugins.annotations.LifecyclePhase;
41 import org.apache.maven.plugins.annotations.Mojo;
42 import org.apache.maven.plugins.annotations.Parameter;
43 import org.apache.maven.project.MavenProject;
44
45
46
47
48
49
50
51
52 @Mojo(name = "detach-distributions",
53 defaultPhase = LifecyclePhase.VERIFY,
54 threadSafe = true,
55 aggregator = true)
56 public class CommonsDistributionDetachmentMojo extends AbstractMojo {
57
58
59
60
61
62
63
64
65 private static final Set<String> ARTIFACT_TYPES_TO_DETACH;
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 @Override
114 public void execute() throws MojoExecutionException {
115 if (!isDistModule) {
116 getLog().info("This module is marked as a non distribution or assembly module, and the plugin will not run.");
117 return;
118 }
119 if (StringUtils.isEmpty(distSvnStagingUrl)) {
120 getLog().warn("commons.distSvnStagingUrl is not set, the commons-release-plugin will not run.");
121 return;
122 }
123 getLog().info("Detaching Assemblies");
124 for (final Artifact attachedArtifact : project.getAttachedArtifacts()) {
125 putAttachedArtifactInSha512Map(attachedArtifact);
126 if (ARTIFACT_TYPES_TO_DETACH.contains(attachedArtifact.getType())) {
127 detachedArtifacts.add(attachedArtifact);
128 }
129 }
130 if (detachedArtifacts.isEmpty()) {
131 getLog().info("Current project contains no distributions. Not executing.");
132 return;
133 }
134
135
136
137 try {
138
139
140
141 project.getAttachedArtifacts().removeAll(detachedArtifacts);
142 } catch (final UnsupportedOperationException e) {
143
144 final ArrayList<Artifact> arrayList = new ArrayList<>(project.getAttachedArtifacts());
145 arrayList.removeAll(detachedArtifacts);
146 try {
147
148 MethodUtils.invokeMethod(project, true, "setAttachedArtifacts", arrayList);
149 } catch (final ReflectiveOperationException roe) {
150 throw new MojoExecutionException(roe);
151 }
152 }
153 if (!workingDirectory.exists()) {
154 SharedFunctions.initDirectory(getLog(), workingDirectory);
155 }
156 writeAllArtifactsInSha512PropertiesFile();
157 copyRemovedArtifactsToWorkingDirectory();
158 getLog().info("");
159 hashArtifacts();
160 }
161
162
163
164
165
166
167
168 private void putAttachedArtifactInSha512Map(final Artifact artifact) throws MojoExecutionException {
169 try {
170 final String artifactKey = getArtifactKey(artifact);
171 if (!artifactKey.endsWith(".asc")) {
172 try (InputStream fis = Files.newInputStream(artifact.getFile().toPath())) {
173 artifactSha512s.put(artifactKey, DigestUtils.sha512Hex(fis));
174 }
175 }
176 } catch (final IOException e) {
177 throw new MojoExecutionException(
178 "Could not find artifact signature for: "
179 + artifact.getArtifactId()
180 + "-"
181 + artifact.getClassifier()
182 + "-"
183 + artifact.getVersion()
184 + " type: "
185 + artifact.getType(),
186 e);
187 }
188 }
189
190
191
192
193
194
195 private void writeAllArtifactsInSha512PropertiesFile() throws MojoExecutionException {
196 final File propertiesFile = new File(workingDirectory, "sha512.properties");
197 getLog().info("Writing " + propertiesFile);
198 try (OutputStream fileWriter = Files.newOutputStream(propertiesFile.toPath())) {
199 artifactSha512s.store(fileWriter, "Release SHA-512s");
200 } catch (final IOException e) {
201 throw new MojoExecutionException("Failure to write SHA-512's", e);
202 }
203 }
204
205
206
207
208
209
210
211
212 private void copyRemovedArtifactsToWorkingDirectory() throws MojoExecutionException {
213 final String wdAbsolutePath = workingDirectory.getAbsolutePath();
214 getLog().info(
215 "Copying " + detachedArtifacts.size() + " detached artifacts to working directory " + wdAbsolutePath);
216 for (final Artifact artifact: detachedArtifacts) {
217 final File artifactFile = artifact.getFile();
218 final StringBuilder copiedArtifactAbsolutePath = new StringBuilder(wdAbsolutePath);
219 copiedArtifactAbsolutePath.append("/");
220 copiedArtifactAbsolutePath.append(artifactFile.getName());
221 final File copiedArtifact = new File(copiedArtifactAbsolutePath.toString());
222 getLog().info("Copying: " + artifactFile.getName());
223 SharedFunctions.copyFile(getLog(), artifactFile, copiedArtifact);
224 }
225 }
226
227
228
229
230
231
232
233
234
235 private void hashArtifacts() throws MojoExecutionException {
236 for (final Artifact artifact : detachedArtifacts) {
237 if (!artifact.getFile().getName().toLowerCase(Locale.ROOT).contains("asc")) {
238 final String artifactKey = getArtifactKey(artifact);
239 try {
240 final String digest;
241
242 digest = artifactSha512s.getProperty(artifactKey.toString());
243 getLog().info(artifact.getFile().getName() + " sha512: " + digest);
244 try (PrintWriter printWriter = new PrintWriter(
245 getSha512FilePath(workingDirectory, artifact.getFile()))) {
246 printWriter.println(digest);
247 }
248 } catch (final IOException e) {
249 throw new MojoExecutionException("Could not sign file: " + artifact.getFile().getName(), e);
250 }
251 }
252 }
253 }
254
255
256
257
258
259
260
261
262 private String getSha512FilePath(final File directory, final File file) {
263 final StringBuilder buffer = new StringBuilder(directory.getAbsolutePath());
264 buffer.append("/");
265 buffer.append(file.getName());
266 buffer.append(".sha512");
267 return buffer.toString();
268 }
269
270
271
272
273
274
275
276
277 private String getArtifactKey(final Artifact artifact) {
278 return artifact.getFile().getName();
279 }
280 }