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.api.services.ModelBuilderException;
35 import org.apache.maven.artifact.DefaultArtifact;
36 import org.apache.maven.internal.transformation.TransformationFailedException;
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 | ModelBuilderException e) {
101 throw new TransformationFailedException(e);
102 }
103 }
104
105 private String mayUpdate() throws IOException, NoSuchAlgorithmException, XMLStreamException, ModelBuilderException {
106 String result;
107 Path src = sourcePathProvider.get();
108 if (src == null) {
109 Files.deleteIfExists(target);
110 result = null;
111 } else if (!Files.exists(src)) {
112 Files.deleteIfExists(target);
113 result = "";
114 } else {
115 String current = sha1(src);
116 String existing = sourceState.get();
117 if (!Files.exists(target) || !Objects.equals(current, existing)) {
118 defaultConsumerPomArtifactTransformer.transform(project, session, src, target);
119 Files.setLastModifiedTime(target, Files.getLastModifiedTime(src));
120 }
121 result = current;
122 }
123 sourceState.set(result);
124 return result;
125 }
126
127 static String sha1(Path path) throws NoSuchAlgorithmException, IOException {
128 MessageDigest md = MessageDigest.getInstance("SHA-1");
129 try (InputStream fis = Files.newInputStream(path)) {
130 byte[] buffer = new byte[SHA1_BUFFER_SIZE];
131 int read;
132 while ((read = fis.read(buffer)) != -1) {
133 md.update(buffer, 0, read);
134 }
135 }
136 StringBuilder result = new StringBuilder();
137 for (byte b : md.digest()) {
138 result.append(String.format("%02x", b));
139 }
140 return result.toString();
141 }
142 }