1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.index.artifact;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.text.ParseException;
25 import java.text.SimpleDateFormat;
26
27
28
29
30
31
32
33 @Singleton
34 @Named("maven2")
35 public class M2GavCalculator implements GavCalculator {
36 public Gav pathToGav(String str) {
37 try {
38 String s = str.startsWith("/") ? str.substring(1) : str;
39
40 int vEndPos = s.lastIndexOf('/');
41
42 if (vEndPos == -1) {
43 return null;
44 }
45
46 int aEndPos = s.lastIndexOf('/', vEndPos - 1);
47
48 if (aEndPos == -1) {
49 return null;
50 }
51
52 int gEndPos = s.lastIndexOf('/', aEndPos - 1);
53
54 if (gEndPos == -1) {
55 return null;
56 }
57
58 String groupId = s.substring(0, gEndPos).replace('/', '.');
59 String artifactId = s.substring(gEndPos + 1, aEndPos);
60 String version = s.substring(aEndPos + 1, vEndPos);
61 String fileName = s.substring(vEndPos + 1);
62
63 boolean checksum = false;
64 boolean signature = false;
65 Gav.HashType checksumType = null;
66 Gav.SignatureType signatureType = null;
67 if (s.endsWith(".md5")) {
68 checksum = true;
69 checksumType = Gav.HashType.md5;
70 s = s.substring(0, s.length() - 4);
71 } else if (s.endsWith(".sha1")) {
72 checksum = true;
73 checksumType = Gav.HashType.sha1;
74 s = s.substring(0, s.length() - 5);
75 } else if (s.endsWith(".sha256")) {
76 checksum = true;
77 checksumType = Gav.HashType.sha256;
78 s = s.substring(0, s.length() - 7);
79 } else if (s.endsWith(".sha512")) {
80 checksum = true;
81 checksumType = Gav.HashType.sha512;
82 s = s.substring(0, s.length() - 7);
83 }
84
85 if (s.endsWith(".asc")) {
86 signature = true;
87 signatureType = Gav.SignatureType.gpg;
88 s = s.substring(0, s.length() - 4);
89 }
90
91 if (s.endsWith("maven-metadata.xml")
92 || (fileName.startsWith("maven-metadata-") && fileName.contains(".xml"))
93 || (fileName.startsWith("_") && fileName.endsWith(".repositories"))) {
94 return null;
95 }
96
97 boolean snapshot = version.endsWith("SNAPSHOT");
98
99 if (snapshot) {
100 return getSnapshotGav(
101 s,
102 vEndPos,
103 groupId,
104 artifactId,
105 version,
106 fileName,
107 checksum,
108 signature,
109 checksumType,
110 signatureType);
111 } else {
112 return getReleaseGav(
113 s,
114 vEndPos,
115 groupId,
116 artifactId,
117 version,
118 fileName,
119 checksum,
120 signature,
121 checksumType,
122 signatureType);
123 }
124 } catch (NumberFormatException | StringIndexOutOfBoundsException e) {
125 return null;
126 }
127 }
128
129 private Gav getReleaseGav(
130 String s,
131 int vEndPos,
132 String groupId,
133 String artifactId,
134 String version,
135 String fileName,
136 boolean checksum,
137 boolean signature,
138 Gav.HashType checksumType,
139 Gav.SignatureType signatureType) {
140 if (!fileName.startsWith(artifactId + "-" + version + ".")
141 && !fileName.startsWith(artifactId + "-" + version + "-")) {
142
143 return null;
144 }
145
146 int nTailPos = vEndPos + artifactId.length() + version.length() + 2;
147
148 String tail = s.substring(nTailPos);
149
150 int nExtPos = tail.indexOf('.');
151
152 if (nExtPos == -1) {
153
154 return null;
155 }
156
157 String ext = tail.substring(nExtPos + 1);
158
159 String classifier = tail.charAt(0) == '-' ? tail.substring(1, nExtPos) : null;
160
161 return new Gav(
162 groupId,
163 artifactId,
164 version,
165 classifier,
166 ext,
167 null,
168 null,
169 fileName,
170 checksum,
171 checksumType,
172 signature,
173 signatureType);
174 }
175
176 private Gav getSnapshotGav(
177 String s,
178 int vEndPos,
179 String groupId,
180 String artifactId,
181 String version,
182 String fileName,
183 boolean checksum,
184 boolean signature,
185 Gav.HashType checksumType,
186 Gav.SignatureType signatureType) {
187
188 Integer snapshotBuildNo = null;
189
190 Long snapshotTimestamp = null;
191
192 int vSnapshotStart = vEndPos + artifactId.length() + version.length() - 9 + 3;
193
194 String vSnapshot = s.substring(vSnapshotStart, vSnapshotStart + 8);
195
196 String classifier;
197
198 String ext;
199
200 if ("SNAPSHOT".equals(vSnapshot)) {
201 int nTailPos = vEndPos + artifactId.length() + version.length() + 2;
202
203 String tail = s.substring(nTailPos);
204
205 int nExtPos = tail.indexOf('.');
206
207 if (nExtPos == -1) {
208
209 return null;
210 }
211
212 ext = tail.substring(nExtPos + 1);
213
214 classifier = tail.charAt(0) == '-' ? tail.substring(1, nExtPos) : null;
215 } else {
216 StringBuilder sb = new StringBuilder(vSnapshot);
217 sb.append(s, vSnapshotStart + sb.length(), vSnapshotStart + sb.length() + 8);
218
219 try {
220 SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd.HHmmss");
221 snapshotTimestamp = df.parse(sb.toString()).getTime();
222 } catch (ParseException e) {
223 }
224
225 int buildNumberPos = vSnapshotStart + sb.length();
226 StringBuilder bnr = new StringBuilder();
227 while (s.charAt(buildNumberPos) >= '0' && s.charAt(buildNumberPos) <= '9') {
228 sb.append(s.charAt(buildNumberPos));
229 bnr.append(s.charAt(buildNumberPos));
230 buildNumberPos++;
231 }
232 String snapshotBuildNumber = sb.toString();
233 snapshotBuildNo = Integer.parseInt(bnr.toString());
234
235 int n = version.length() > 9 ? version.length() - 9 + 1 : 0;
236
237 String tail = s.substring(vEndPos + artifactId.length() + n + snapshotBuildNumber.length() + 2);
238
239 int nExtPos = tail.indexOf('.');
240
241 if (nExtPos == -1) {
242
243 return null;
244 }
245
246 ext = tail.substring(nExtPos + 1);
247
248 classifier = tail.charAt(0) == '-' ? tail.substring(1, nExtPos) : null;
249
250 version = version.substring(0, version.length() - 8) + snapshotBuildNumber;
251 }
252
253 return new Gav(
254 groupId,
255 artifactId,
256 version,
257 classifier,
258 ext,
259 snapshotBuildNo,
260 snapshotTimestamp,
261 fileName,
262 checksum,
263 checksumType,
264 signature,
265 signatureType);
266 }
267
268 public String gavToPath(Gav gav) {
269
270 return "/" + gav.getGroupId().replaceAll("(?m)(.)\\.", "$1/")
271 + "/" + gav.getArtifactId() + "/" + gav.getBaseVersion() + "/" + calculateArtifactName(gav);
272 }
273
274 public String calculateArtifactName(Gav gav) {
275 if (gav.getName() != null && !gav.getName().isBlank()) {
276 return gav.getName();
277 } else {
278 StringBuilder path = new StringBuilder(gav.getArtifactId());
279
280 path.append("-");
281
282 path.append(gav.getVersion());
283
284 if (gav.getClassifier() != null && !gav.getClassifier().isBlank()) {
285 path.append("-");
286
287 path.append(gav.getClassifier());
288 }
289
290 if (gav.getExtension() != null) {
291 path.append(".");
292
293 path.append(gav.getExtension());
294 }
295
296 if (gav.isSignature()) {
297 path.append(".");
298
299 path.append(gav.getSignatureType().toString());
300 }
301
302 if (gav.isHash()) {
303 path.append(".");
304
305 path.append(gav.getHashType().toString());
306 }
307
308 return path.toString();
309 }
310 }
311 }