1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.transformation.impl;
20
21 import javax.xml.stream.XMLStreamException;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException;
30 import java.util.Objects;
31 import java.util.concurrent.atomic.AtomicReference;
32 import java.util.function.Supplier;
33
34 import org.apache.maven.artifact.DefaultArtifact;
35 import org.apache.maven.internal.transformation.TransformationFailedException;
36 import org.apache.maven.model.building.ModelBuildingException;
37 import org.apache.maven.project.MavenProject;
38 import org.eclipse.aether.RepositorySystemSession;
39
40
41
42
43
44
45 class TransformedArtifact extends DefaultArtifact {
46
47 private static final int SHA1_BUFFER_SIZE = 8192;
48 private final DefaultConsumerPomArtifactTransformer defaultConsumerPomArtifactTransformer;
49 private final MavenProject project;
50 private final Supplier<Path> sourcePathProvider;
51 private final Path target;
52 private final RepositorySystemSession session;
53 private final AtomicReference<String> sourceState;
54
55 @SuppressWarnings("checkstyle:ParameterNumber")
56 TransformedArtifact(
57 DefaultConsumerPomArtifactTransformer defaultConsumerPomArtifactTransformer,
58 MavenProject project,
59 Path target,
60 RepositorySystemSession session,
61 org.apache.maven.artifact.Artifact source,
62 Supplier<Path> sourcePathProvider,
63 String classifier,
64 String extension) {
65 super(
66 source.getGroupId(),
67 source.getArtifactId(),
68 source.getVersionRange(),
69 source.getScope(),
70 extension,
71 classifier,
72 new TransformedArtifactHandler(
73 classifier, extension, source.getArtifactHandler().getPackaging()));
74 this.defaultConsumerPomArtifactTransformer = defaultConsumerPomArtifactTransformer;
75 this.project = project;
76 this.target = target;
77 this.session = session;
78 this.sourcePathProvider = sourcePathProvider;
79 this.sourceState = new AtomicReference<>(null);
80 }
81
82 @Override
83 public boolean isResolved() {
84 return getFile() != null;
85 }
86
87 @Override
88 public void setFile(File file) {
89 throw new UnsupportedOperationException("transformed artifact file cannot be set");
90 }
91
92 @Override
93 public synchronized File getFile() {
94 try {
95 String state = mayUpdate();
96 if (state == null) {
97 return null;
98 }
99 return target.toFile();
100 } catch (IOException | NoSuchAlgorithmException | XMLStreamException | ModelBuildingException e) {
101 throw new TransformationFailedException(e);
102 }
103 }
104
105 private String mayUpdate()
106 throws IOException, NoSuchAlgorithmException, XMLStreamException, ModelBuildingException {
107 String result;
108 Path src = sourcePathProvider.get();
109 if (src == null) {
110 Files.deleteIfExists(target);
111 result = null;
112 } else if (!Files.exists(src)) {
113 Files.deleteIfExists(target);
114 result = "";
115 } else {
116 String current = sha1(src);
117 String existing = sourceState.get();
118 if (!Files.exists(target) || !Objects.equals(current, existing)) {
119 defaultConsumerPomArtifactTransformer.transform(project, session, src, target);
120 Files.setLastModifiedTime(target, Files.getLastModifiedTime(src));
121 }
122 result = current;
123 }
124 sourceState.set(result);
125 return result;
126 }
127
128 static String sha1(Path path) throws NoSuchAlgorithmException, IOException {
129 MessageDigest md = MessageDigest.getInstance("SHA-1");
130 try (InputStream fis = Files.newInputStream(path)) {
131 byte[] buffer = new byte[SHA1_BUFFER_SIZE];
132 int read;
133 while ((read = fis.read(buffer)) != -1) {
134 md.update(buffer, 0, read);
135 }
136 }
137 StringBuilder result = new StringBuilder();
138 for (byte b : md.digest()) {
139 result.append(String.format("%02x", b));
140 }
141 return result.toString();
142 }
143 }