1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.BufferedOutputStream;
26 import java.io.File;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.nio.charset.StandardCharsets;
31 import java.nio.file.Path;
32 import java.nio.file.Paths;
33 import java.util.Enumeration;
34 import java.util.jar.Attributes;
35 import java.util.jar.JarEntry;
36 import java.util.jar.JarFile;
37 import java.util.jar.JarOutputStream;
38
39 import org.apache.commons.io.FilenameUtils;
40 import org.apache.commons.io.IOUtils;
41 import org.apache.maven.buildcache.xml.CacheConfig;
42 import org.apache.maven.project.MavenProject;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 @Singleton
47 @Named
48 public class DefaultRestoredArtifactHandler implements RestoredArtifactHandler {
49
50 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRestoredArtifactHandler.class);
51 private static final String DIR_NAME = "cache-build-tmp";
52
53 private final boolean adjustMetaInfVersion;
54
55 @Inject
56 public DefaultRestoredArtifactHandler(CacheConfig cacheConfig) {
57 this.adjustMetaInfVersion = cacheConfig.adjustMetaInfVersion();
58 }
59
60 @Override
61 public Path adjustArchiveArtifactVersion(MavenProject project, String originalArtifactVersion, Path artifactFile)
62 throws IOException {
63 if (!adjustMetaInfVersion) {
64
65 return artifactFile;
66 }
67
68 File file = artifactFile.toFile();
69 if (project.getVersion().equals(originalArtifactVersion) || !CacheUtils.isArchive(file)) {
70
71 return artifactFile;
72 }
73
74 File tempDirName = Paths.get(project.getBuild().getDirectory())
75 .normalize()
76 .resolve(DIR_NAME)
77 .toFile();
78 if (tempDirName.mkdirs()) {
79 LOGGER.debug(
80 "Temporary directory to restore artifact was created [artifactFile={}, "
81 + "originalVersion={}, tempDir={}]",
82 artifactFile,
83 originalArtifactVersion,
84 tempDirName);
85 }
86
87 String currentVersion = project.getVersion();
88 File tmpJarFile = File.createTempFile(
89 artifactFile.toFile().getName(), '.' + FilenameUtils.getExtension(file.getName()), tempDirName);
90 tmpJarFile.deleteOnExit();
91 String originalImplVersion = Attributes.Name.IMPLEMENTATION_VERSION + ": " + originalArtifactVersion;
92 String implVersion = Attributes.Name.IMPLEMENTATION_VERSION + ": " + currentVersion;
93 String commonXmlOriginalVersion = "<version>" + originalArtifactVersion + "</version>";
94 String commonXmlVersion = "<version>" + currentVersion + "</version>";
95 String originalPomPropsVersion = "version=" + originalArtifactVersion;
96 String pomPropsVersion = "version=" + currentVersion;
97 try (JarFile jarFile = new JarFile(artifactFile.toFile())) {
98 try (JarOutputStream jos =
99 new JarOutputStream(new BufferedOutputStream(new FileOutputStream(tmpJarFile)))) {
100
101 Enumeration<JarEntry> jarEntries = jarFile.entries();
102 byte[] buffer = new byte[1024];
103 while (jarEntries.hasMoreElements()) {
104 JarEntry entry = jarEntries.nextElement();
105 String entryName = entry.getName();
106
107 if (entryName.startsWith("META-INF/maven")
108 && (entryName.endsWith("plugin.xml") || entryName.endsWith("plugin-help.xml"))) {
109 replaceEntry(jarFile, entry, commonXmlOriginalVersion, commonXmlVersion, jos);
110 continue;
111 }
112
113 if (entryName.endsWith("pom.xml")) {
114 replaceEntry(jarFile, entry, commonXmlOriginalVersion, commonXmlVersion, jos);
115 continue;
116 }
117
118 if (entryName.endsWith("pom.properties")) {
119 replaceEntry(jarFile, entry, originalPomPropsVersion, pomPropsVersion, jos);
120 continue;
121 }
122
123 if (JarFile.MANIFEST_NAME.equals(entryName)) {
124 replaceEntry(jarFile, entry, originalImplVersion, implVersion, jos);
125 continue;
126 }
127 jos.putNextEntry(entry);
128 try (InputStream entryInputStream = jarFile.getInputStream(entry)) {
129 int bytesRead;
130 while ((bytesRead = entryInputStream.read(buffer)) != -1) {
131 jos.write(buffer, 0, bytesRead);
132 }
133 }
134 }
135 }
136 }
137 return tmpJarFile.toPath();
138 }
139
140 private static void replaceEntry(
141 JarFile jarFile, JarEntry entry, String toReplace, String replacement, JarOutputStream jos)
142 throws IOException {
143 String fullManifest = IOUtils.toString(jarFile.getInputStream(entry), StandardCharsets.UTF_8.name());
144 String modified = fullManifest.replaceAll(toReplace, replacement);
145
146 byte[] bytes = modified.getBytes(StandardCharsets.UTF_8);
147 JarEntry newEntry = new JarEntry(entry.getName());
148 jos.putNextEntry(newEntry);
149 jos.write(bytes);
150 }
151 }