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 java.io.File;
22 import java.io.IOException;
23 import java.nio.charset.StandardCharsets;
24 import java.nio.file.FileVisitResult;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.SimpleFileVisitor;
28 import java.nio.file.attribute.BasicFileAttributes;
29 import java.nio.file.attribute.FileTime;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.List;
33 import java.util.NoSuchElementException;
34 import java.util.function.Supplier;
35 import java.util.zip.ZipEntry;
36 import java.util.zip.ZipInputStream;
37 import java.util.zip.ZipOutputStream;
38
39 import org.apache.commons.lang3.StringUtils;
40 import org.apache.maven.artifact.Artifact;
41 import org.apache.maven.artifact.handler.ArtifactHandler;
42 import org.apache.maven.buildcache.xml.build.Scm;
43 import org.apache.maven.execution.MavenSession;
44 import org.apache.maven.model.Dependency;
45 import org.apache.maven.plugin.MojoExecution;
46 import org.apache.maven.project.MavenProject;
47 import org.eclipse.aether.SessionData;
48 import org.slf4j.Logger;
49
50 import static org.apache.commons.lang3.StringUtils.removeStart;
51 import static org.apache.commons.lang3.StringUtils.trim;
52 import static org.apache.maven.artifact.Artifact.LATEST_VERSION;
53 import static org.apache.maven.artifact.Artifact.SNAPSHOT_VERSION;
54
55
56
57
58 public class CacheUtils {
59
60 public static boolean isPom(MavenProject project) {
61 return project.getPackaging().equals("pom");
62 }
63
64 public static boolean isPom(Dependency dependency) {
65 return dependency.getType().equals("pom");
66 }
67
68 public static boolean isSnapshot(String version) {
69 return version.endsWith(SNAPSHOT_VERSION) || version.endsWith(LATEST_VERSION);
70 }
71
72 public static String normalizedName(Artifact artifact) {
73 if (artifact.getFile() == null) {
74 return null;
75 }
76
77 StringBuilder filename = new StringBuilder(artifact.getArtifactId());
78
79 if (artifact.hasClassifier()) {
80 filename.append("-").append(artifact.getClassifier());
81 }
82
83 final ArtifactHandler artifactHandler = artifact.getArtifactHandler();
84 if (artifactHandler != null && StringUtils.isNotBlank(artifactHandler.getExtension())) {
85 filename.append(".").append(artifactHandler.getExtension());
86 }
87 return filename.toString();
88 }
89
90 public static String mojoExecutionKey(MojoExecution mojo) {
91 return StringUtils.join(
92 Arrays.asList(
93 StringUtils.defaultIfEmpty(mojo.getExecutionId(), "emptyExecId"),
94 StringUtils.defaultIfEmpty(mojo.getGoal(), "emptyGoal"),
95 StringUtils.defaultIfEmpty(mojo.getLifecyclePhase(), "emptyLifecyclePhase"),
96 StringUtils.defaultIfEmpty(mojo.getArtifactId(), "emptyArtifactId"),
97 StringUtils.defaultIfEmpty(mojo.getGroupId(), "emptyGroupId")),
98 ":");
99 }
100
101 public static Path getMultimoduleRoot(MavenSession session) {
102 return session.getRequest().getMultiModuleProjectDirectory().toPath();
103 }
104
105 public static Scm readGitInfo(MavenSession session) throws IOException {
106 final Scm scmCandidate = new Scm();
107 final Path gitDir = getMultimoduleRoot(session).resolve(".git");
108 if (Files.isDirectory(gitDir)) {
109 final Path headFile = gitDir.resolve("HEAD");
110 if (Files.exists(headFile)) {
111 String headRef = readFirstLine(headFile, "<missing branch>");
112 if (headRef.startsWith("ref: ")) {
113 String branch = trim(removeStart(headRef, "ref: "));
114 scmCandidate.setSourceBranch(branch);
115 final Path refPath = gitDir.resolve(branch);
116 if (Files.exists(refPath)) {
117 String revision = readFirstLine(refPath, "<missing revision>");
118 scmCandidate.setRevision(trim(revision));
119 }
120 } else {
121 scmCandidate.setSourceBranch(headRef);
122 scmCandidate.setRevision(headRef);
123 }
124 }
125 }
126 return scmCandidate;
127 }
128
129 private static String readFirstLine(Path path, String defaultValue) throws IOException {
130 return Files.lines(path, StandardCharsets.UTF_8).findFirst().orElse(defaultValue);
131 }
132
133 public static <T> T getLast(List<T> list) {
134 int size = list.size();
135 if (size > 0) {
136 return list.get(size - 1);
137 }
138 throw new NoSuchElementException();
139 }
140
141 public static <T> T getOrCreate(MavenSession session, Object key, Supplier<T> supplier) {
142 SessionData data = session.getRepositorySession().getData();
143 while (true) {
144 T t = (T) data.get(key);
145 if (t == null) {
146 t = supplier.get();
147 if (data.set(key, null, t)) {
148 continue;
149 }
150 }
151 return t;
152 }
153 }
154
155 public static boolean isArchive(File file) {
156 String fileName = file.getName();
157 if (!file.isFile() || file.isHidden()) {
158 return false;
159 }
160 return StringUtils.endsWithAny(fileName, ".jar", ".zip", ".war", ".ear");
161 }
162
163 public static void zip(Path dir, Path zip) throws IOException {
164 try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zip))) {
165 Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
166
167 @Override
168 public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
169 throws IOException {
170 final ZipEntry zipEntry = new ZipEntry(dir.relativize(path).toString());
171 zipOutputStream.putNextEntry(zipEntry);
172 Files.copy(path, zipOutputStream);
173 zipOutputStream.closeEntry();
174 return FileVisitResult.CONTINUE;
175 }
176 });
177 }
178 }
179
180 public static void unzip(Path zip, Path out) throws IOException {
181 try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(zip))) {
182 ZipEntry entry = zis.getNextEntry();
183 while (entry != null) {
184 Path file = out.resolve(entry.getName());
185 if (!file.normalize().startsWith(out.normalize())) {
186 throw new RuntimeException("Bad zip entry");
187 }
188 if (entry.isDirectory()) {
189 Files.createDirectory(file);
190 } else {
191 Path parent = file.getParent();
192 Files.createDirectories(parent);
193 Files.copy(zis, file);
194 }
195 Files.setLastModifiedTime(file, FileTime.fromMillis(entry.getTime()));
196 entry = zis.getNextEntry();
197 }
198 }
199 }
200
201 public static <T> void debugPrintCollection(
202 Logger logger, Collection<T> values, String heading, String elementCaption) {
203 if (logger.isDebugEnabled() && values != null && !values.isEmpty()) {
204 final int size = values.size();
205 int i = 0;
206 logger.debug("{} (total {})", heading, size);
207 for (T value : values) {
208 i++;
209 logger.debug("{} {} of {} : {}", elementCaption, i, size, value);
210 }
211 }
212 }
213 }