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 TransformedArtifact(
56 DefaultConsumerPomArtifactTransformer defaultConsumerPomArtifactTransformer,
57 MavenProject project,
58 Path target,
59 RepositorySystemSession session,
60 org.apache.maven.artifact.Artifact source,
61 Supplier<Path> sourcePathProvider,
62 String classifier,
63 String extension) {
64 super(
65 source.getGroupId(),
66 source.getArtifactId(),
67 source.getVersionRange(),
68 source.getScope(),
69 extension,
70 classifier,
71 new TransformedArtifactHandler(
72 classifier, extension, source.getArtifactHandler().getPackaging()));
73 this.defaultConsumerPomArtifactTransformer = defaultConsumerPomArtifactTransformer;
74 this.project = project;
75 this.target = target;
76 this.session = session;
77 this.sourcePathProvider = sourcePathProvider;
78 this.sourceState = new AtomicReference<>(null);
79 }
80
81 @Override
82 public boolean isResolved() {
83 return getFile() != null;
84 }
85
86 @Override
87 public void setFile(File file) {
88 throw new UnsupportedOperationException("transformed artifact file cannot be set");
89 }
90
91 @Override
92 public synchronized File getFile() {
93 try {
94 String state = mayUpdate();
95 if (state == null) {
96 return null;
97 }
98 return target.toFile();
99 } catch (IOException | NoSuchAlgorithmException | XMLStreamException | ModelBuildingException e) {
100 throw new TransformationFailedException(e);
101 }
102 }
103
104 private String mayUpdate()
105 throws IOException, NoSuchAlgorithmException, XMLStreamException, ModelBuildingException {
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 (!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 }