This project has retired. For details please refer to its
Attic page.
Maven2RepositoryStorage xref
1 package org.apache.archiva.metadata.repository.storage.maven2;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.archiva.checksum.ChecksumAlgorithm;
23 import org.apache.archiva.checksum.ChecksummedFile;
24 import org.apache.archiva.common.Try;
25 import org.apache.archiva.common.utils.VersionUtil;
26 import org.apache.archiva.filter.Filter;
27 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
28 import org.apache.archiva.metadata.model.ArtifactMetadata;
29 import org.apache.archiva.metadata.model.ProjectMetadata;
30 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
31 import org.apache.archiva.metadata.model.facets.RepositoryProblemFacet;
32 import org.apache.archiva.metadata.repository.storage.*;
33 import org.apache.archiva.model.ArchivaRepositoryMetadata;
34 import org.apache.archiva.model.ArtifactReference;
35 import org.apache.archiva.model.SnapshotVersion;
36 import org.apache.archiva.policies.ProxyDownloadException;
37 import org.apache.archiva.proxy.ProxyRegistry;
38 import org.apache.archiva.proxy.maven.WagonFactory;
39 import org.apache.archiva.proxy.model.NetworkProxy;
40 import org.apache.archiva.proxy.model.ProxyConnector;
41 import org.apache.archiva.proxy.model.RepositoryProxyHandler;
42 import org.apache.archiva.repository.*;
43 import org.apache.archiva.repository.content.PathParser;
44 import org.apache.archiva.repository.maven2.MavenSystemManager;
45 import org.apache.archiva.repository.storage.StorageAsset;
46 import org.apache.archiva.xml.XMLException;
47 import org.apache.commons.lang3.ArrayUtils;
48 import org.apache.commons.lang3.StringUtils;
49 import org.apache.maven.model.*;
50 import org.apache.maven.model.building.*;
51 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
52 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.context.ApplicationContext;
56 import org.springframework.stereotype.Service;
57
58 import javax.annotation.PostConstruct;
59 import javax.inject.Inject;
60 import javax.inject.Named;
61 import java.io.FileNotFoundException;
62 import java.io.IOException;
63 import java.io.Reader;
64 import java.nio.channels.Channels;
65 import java.nio.charset.Charset;
66 import java.nio.file.NoSuchFileException;
67 import java.time.ZoneId;
68 import java.time.ZonedDateTime;
69 import java.util.*;
70 import java.util.function.Predicate;
71 import java.util.stream.Collectors;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 @Service("repositoryStorage#maven2")
87 public class Maven2RepositoryStorage
88 implements RepositoryStorage {
89
90 private static final Logger LOGGER = LoggerFactory.getLogger(Maven2RepositoryStorage.class);
91
92 private ModelBuilder builder;
93
94 @Inject
95 RepositoryRegistry repositoryRegistry;
96
97 @Inject
98 @Named("repositoryPathTranslator#maven2")
99 private RepositoryPathTranslator pathTranslator;
100
101 @Inject
102 private WagonFactory wagonFactory;
103
104 @Inject
105 private ApplicationContext applicationContext;
106
107 @Inject
108 @Named("pathParser#default")
109 private PathParser pathParser;
110
111 @Inject
112 private ProxyRegistry proxyRegistry;
113
114 @Inject
115 private MavenSystemManager mavenSystemManager;
116
117 private static final String METADATA_FILENAME_START = "maven-metadata";
118
119 private static final String METADATA_FILENAME = METADATA_FILENAME_START + ".xml";
120
121
122 private static final String[] IGNORED_FILES = {METADATA_FILENAME, "resolver-status.properties"};
123
124 private static final MavenXpp3Reader MAVEN_XPP_3_READER = new MavenXpp3Reader();
125
126
127 @PostConstruct
128 public void initialize() {
129 builder = new DefaultModelBuilderFactory().newInstance();
130
131 }
132
133 @Override
134 public ProjectMetadata readProjectMetadata(String repoId, String namespace, String projectId) {
135
136 return null;
137 }
138
139 @Override
140 public ProjectVersionMetadata readProjectVersionMetadata(ReadMetadataRequest readMetadataRequest)
141 throws RepositoryStorageMetadataNotFoundException, RepositoryStorageMetadataInvalidException,
142 RepositoryStorageRuntimeException {
143
144 ManagedRepository managedRepository = repositoryRegistry.getManagedRepository(readMetadataRequest.getRepositoryId());
145 boolean isReleases = managedRepository.getActiveReleaseSchemes().contains(ReleaseScheme.RELEASE);
146 boolean isSnapshots = managedRepository.getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT);
147 String artifactVersion = readMetadataRequest.getProjectVersion();
148
149 if (!readMetadataRequest.isBrowsingRequest()) {
150 if (VersionUtil.isSnapshot(artifactVersion)) {
151
152 if (isReleases && !isSnapshots) {
153 throw new RepositoryStorageRuntimeException("lookforsnaponreleaseonly",
154 "managed repo is configured for release only");
155 }
156 } else {
157 if (!isReleases && isSnapshots) {
158 throw new RepositoryStorageRuntimeException("lookforsreleaseonsneponly",
159 "managed repo is configured for snapshot only");
160 }
161 }
162 }
163 StorageAsset basedir = managedRepository.getAsset("");
164 if (VersionUtil.isSnapshot(artifactVersion)) {
165 StorageAsset metadataFile = pathTranslator.toFile(basedir, readMetadataRequest.getNamespace(),
166 readMetadataRequest.getProjectId(), artifactVersion,
167 METADATA_FILENAME);
168 try {
169 ArchivaRepositoryMetadata metadata = MavenMetadataReader.read(metadataFile);
170
171
172 SnapshotVersion snapshotVersion = metadata.getSnapshotVersion();
173 if (snapshotVersion != null) {
174 artifactVersion =
175 artifactVersion.substring(0, artifactVersion.length() - 8);
176 artifactVersion =
177 artifactVersion + snapshotVersion.getTimestamp() + "-" + snapshotVersion.getBuildNumber();
178 }
179 } catch (XMLException | IOException e) {
180
181 LOGGER.warn("Invalid metadata: {} - {}", metadataFile, e.getMessage());
182 }
183 }
184
185
186 String id = readMetadataRequest.getProjectId() + "-" + artifactVersion + ".pom";
187 StorageAsset file =
188 pathTranslator.toFile(basedir, readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
189 readMetadataRequest.getProjectVersion(), id);
190
191 if (!file.exists()) {
192
193 throw new RepositoryStorageMetadataNotFoundException(
194 "The artifact's POM file '" + file.getPath() + "' was missing");
195 }
196
197
198
199 List<RemoteRepository> remoteRepositories = new ArrayList<>();
200 Map<String, NetworkProxy> networkProxies = new HashMap<>();
201
202 Map<String, List<ProxyConnector>> proxyConnectorsMap = proxyRegistry.getProxyConnectorAsMap();
203 List<ProxyConnector> proxyConnectors = proxyConnectorsMap.get(readMetadataRequest.getRepositoryId());
204 if (proxyConnectors != null) {
205 for (ProxyConnector proxyConnector : proxyConnectors) {
206 RemoteRepository remoteRepoConfig =
207 repositoryRegistry.getRemoteRepository(proxyConnector.getTargetRepository().getId());
208
209 if (remoteRepoConfig != null) {
210 remoteRepositories.add(remoteRepoConfig);
211
212 NetworkProxy networkProxyConfig =
213 proxyRegistry.getNetworkProxy(proxyConnector.getProxyId());
214
215 if (networkProxyConfig != null) {
216
217 networkProxies.put(proxyConnector.getTargetRepository().getId(), networkProxyConfig);
218 }
219 }
220 }
221 }
222
223
224
225 if (readMetadataRequest.isBrowsingRequest()) {
226 remoteRepositories.addAll(repositoryRegistry.getRemoteRepositories());
227 }
228
229 ModelBuildingRequest req =
230 new DefaultModelBuildingRequest().setProcessPlugins(false).setPomFile(file.getFilePath().toFile()).setTwoPhaseBuilding(
231 false).setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
232
233
234 req.setSystemProperties(System.getProperties());
235
236
237 req.setModelResolver(
238 new RepositoryModelResolver(managedRepository, pathTranslator, wagonFactory, remoteRepositories,
239 networkProxies, managedRepository, mavenSystemManager));
240
241 Model model;
242 try {
243 model = builder.build(req).getEffectiveModel();
244 } catch (ModelBuildingException e) {
245 String msg = "The artifact's POM file '" + file + "' was invalid: " + e.getMessage();
246
247 List<ModelProblem> modelProblems = e.getProblems();
248 for (ModelProblem problem : modelProblems) {
249
250
251
252
253
254 if (((problem.getException() instanceof FileNotFoundException
255 || problem.getException() instanceof NoSuchFileException
256 ) && e.getModelId() != null &&
257 !e.getModelId().equals(problem.getModelId()))) {
258 LOGGER.warn("The artifact's parent POM file '{}' cannot be resolved. "
259 + "Using defaults for project version metadata..", file);
260
261 ProjectVersionMetadatajectVersionMetadata.html#ProjectVersionMetadata">ProjectVersionMetadata metadata = new ProjectVersionMetadata();
262 metadata.setId(readMetadataRequest.getProjectVersion());
263
264 MavenProjectFacetepository/storage/maven2/MavenProjectFacet.html#MavenProjectFacet">MavenProjectFacet facet = new MavenProjectFacet();
265 facet.setGroupId(readMetadataRequest.getNamespace());
266 facet.setArtifactId(readMetadataRequest.getProjectId());
267 facet.setPackaging("jar");
268 metadata.addFacet(facet);
269
270 String errMsg =
271 "Error in resolving artifact's parent POM file. " + (problem.getException() == null
272 ? problem.getMessage()
273 : problem.getException().getMessage());
274 RepositoryProblemFacetsitoryProblemFacet.html#RepositoryProblemFacet">RepositoryProblemFacet repoProblemFacet = new RepositoryProblemFacet();
275 repoProblemFacet.setRepositoryId(readMetadataRequest.getRepositoryId());
276 repoProblemFacet.setId(readMetadataRequest.getRepositoryId());
277 repoProblemFacet.setMessage(errMsg);
278 repoProblemFacet.setProblem(errMsg);
279 repoProblemFacet.setProject(readMetadataRequest.getProjectId());
280 repoProblemFacet.setVersion(readMetadataRequest.getProjectVersion());
281 repoProblemFacet.setNamespace(readMetadataRequest.getNamespace());
282
283 metadata.addFacet(repoProblemFacet);
284
285 return metadata;
286 }
287 }
288
289 throw new RepositoryStorageMetadataInvalidException("invalid-pom", msg, e);
290 }
291
292
293 boolean correctGroupId = readMetadataRequest.getNamespace().equals(model.getGroupId());
294 boolean correctArtifactId = readMetadataRequest.getProjectId().equals(model.getArtifactId());
295 boolean correctVersion = readMetadataRequest.getProjectVersion().equals(model.getVersion());
296 if (!correctGroupId || !correctArtifactId || !correctVersion) {
297 StringBuilder message = new StringBuilder("Incorrect POM coordinates in '" + file + "':");
298 if (!correctGroupId) {
299 message.append("\nIncorrect group ID: ").append(model.getGroupId());
300 }
301 if (!correctArtifactId) {
302 message.append("\nIncorrect artifact ID: ").append(model.getArtifactId());
303 }
304 if (!correctVersion) {
305 message.append("\nIncorrect version: ").append(model.getVersion());
306 }
307
308 throw new RepositoryStorageMetadataInvalidException("mislocated-pom", message.toString());
309 }
310
311 ProjectVersionMetadatajectVersionMetadata.html#ProjectVersionMetadata">ProjectVersionMetadata metadata = new ProjectVersionMetadata();
312 metadata.setCiManagement(convertCiManagement(model.getCiManagement()));
313 metadata.setDescription(model.getDescription());
314 metadata.setId(readMetadataRequest.getProjectVersion());
315 metadata.setIssueManagement(convertIssueManagement(model.getIssueManagement()));
316 metadata.setLicenses(convertLicenses(model.getLicenses()));
317 metadata.setMailingLists(convertMailingLists(model.getMailingLists()));
318 metadata.setDependencies(convertDependencies(model.getDependencies()));
319 metadata.setName(model.getName());
320 metadata.setOrganization(convertOrganization(model.getOrganization()));
321 metadata.setScm(convertScm(model.getScm()));
322 metadata.setUrl(model.getUrl());
323 metadata.setProperties(model.getProperties());
324
325 MavenProjectFacetepository/storage/maven2/MavenProjectFacet.html#MavenProjectFacet">MavenProjectFacet facet = new MavenProjectFacet();
326 facet.setGroupId(model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId());
327 facet.setArtifactId(model.getArtifactId());
328 facet.setPackaging(model.getPackaging());
329 if (model.getParent() != null) {
330 MavenProjectParentository/storage/maven2/MavenProjectParent.html#MavenProjectParent">MavenProjectParent parent = new MavenProjectParent();
331 parent.setGroupId(model.getParent().getGroupId());
332 parent.setArtifactId(model.getParent().getArtifactId());
333 parent.setVersion(model.getParent().getVersion());
334 facet.setParent(parent);
335 }
336 metadata.addFacet(facet);
337
338 return metadata;
339
340
341 }
342
343 public void setWagonFactory(WagonFactory wagonFactory) {
344 this.wagonFactory = wagonFactory;
345 }
346
347 private List<org.apache.archiva.metadata.model.Dependency> convertDependencies(List<Dependency> dependencies) {
348 List<org.apache.archiva.metadata.model.Dependency> l = new ArrayList<>();
349 for (Dependency dependency : dependencies) {
350 org.apache.archiva.metadata.model.Dependency newDependency =
351 new org.apache.archiva.metadata.model.Dependency();
352 newDependency.setArtifactId(dependency.getArtifactId());
353 newDependency.setClassifier(dependency.getClassifier());
354 newDependency.setNamespace(dependency.getGroupId());
355 newDependency.setOptional(dependency.isOptional());
356 newDependency.setScope(dependency.getScope());
357 newDependency.setSystemPath(dependency.getSystemPath());
358 newDependency.setType(dependency.getType());
359 newDependency.setVersion(dependency.getVersion());
360 l.add(newDependency);
361 }
362 return l;
363 }
364
365 private org.apache.archiva.metadata.model.Scm convertScm(Scm scm) {
366 org.apache.archiva.metadata.model.Scm newScm = null;
367 if (scm != null) {
368 newScm = new org.apache.archiva.metadata.model.Scm();
369 newScm.setConnection(scm.getConnection());
370 newScm.setDeveloperConnection(scm.getDeveloperConnection());
371 newScm.setUrl(scm.getUrl());
372 }
373 return newScm;
374 }
375
376 private org.apache.archiva.metadata.model.Organization convertOrganization(Organization organization) {
377 org.apache.archiva.metadata.model.Organization org = null;
378 if (organization != null) {
379 org = new org.apache.archiva.metadata.model.Organization();
380 org.setName(organization.getName());
381 org.setUrl(organization.getUrl());
382 }
383 return org;
384 }
385
386 private List<org.apache.archiva.metadata.model.License> convertLicenses(List<License> licenses) {
387 List<org.apache.archiva.metadata.model.License> l = new ArrayList<>();
388 for (License license : licenses) {
389 org.apache.archiva.metadata.model.License newLicense = new org.apache.archiva.metadata.model.License();
390 newLicense.setName(license.getName());
391 newLicense.setUrl(license.getUrl());
392 l.add(newLicense);
393 }
394 return l;
395 }
396
397 private List<org.apache.archiva.metadata.model.MailingList> convertMailingLists(List<MailingList> mailingLists) {
398 List<org.apache.archiva.metadata.model.MailingList> l = new ArrayList<>();
399 for (MailingList mailingList : mailingLists) {
400 org.apache.archiva.metadata.model.MailingList newMailingList =
401 new org.apache.archiva.metadata.model.MailingList();
402 newMailingList.setName(mailingList.getName());
403 newMailingList.setMainArchiveUrl(mailingList.getArchive());
404 newMailingList.setPostAddress(mailingList.getPost());
405 newMailingList.setSubscribeAddress(mailingList.getSubscribe());
406 newMailingList.setUnsubscribeAddress(mailingList.getUnsubscribe());
407 newMailingList.setOtherArchives(mailingList.getOtherArchives());
408 l.add(newMailingList);
409 }
410 return l;
411 }
412
413 private org.apache.archiva.metadata.model.IssueManagement convertIssueManagement(IssueManagement issueManagement) {
414 org.apache.archiva.metadata.model.IssueManagement im = null;
415 if (issueManagement != null) {
416 im = new org.apache.archiva.metadata.model.IssueManagement();
417 im.setSystem(issueManagement.getSystem());
418 im.setUrl(issueManagement.getUrl());
419 }
420 return im;
421 }
422
423 private org.apache.archiva.metadata.model.CiManagement convertCiManagement(CiManagement ciManagement) {
424 org.apache.archiva.metadata.model.CiManagement ci = null;
425 if (ciManagement != null) {
426 ci = new org.apache.archiva.metadata.model.CiManagement();
427 ci.setSystem(ciManagement.getSystem());
428 ci.setUrl(ciManagement.getUrl());
429 }
430 return ci;
431 }
432
433 @Override
434 public Collection<String> listRootNamespaces(String repoId, Filter<String> filter)
435 throws RepositoryStorageRuntimeException {
436 StorageAsset dir = getRepositoryBasedir(repoId);
437
438 return getSortedFiles(dir, filter);
439 }
440
441 private static Collection<String> getSortedFiles(StorageAsset dir, Filter<String> filter) {
442
443 final Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
444 return dir.list().stream().filter(f -> f.isContainer())
445 .filter(dFilter)
446 .map(path -> path.getName().toString())
447 .sorted().collect(Collectors.toList());
448
449 }
450
451 private StorageAsset getRepositoryBasedir(String repoId)
452 throws RepositoryStorageRuntimeException {
453 ManagedRepository repositoryConfiguration = repositoryRegistry.getManagedRepository(repoId);
454
455 return repositoryConfiguration.getAsset("");
456 }
457
458 @Override
459 public Collection<String> listNamespaces(String repoId, String namespace, Filter<String> filter)
460 throws RepositoryStorageRuntimeException {
461 StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(repoId), namespace);
462 if (!(dir.exists()) && !dir.isContainer()) {
463 return Collections.emptyList();
464 }
465
466 Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
467 return dir.list().stream().filter(dFilter).filter(path -> !isProject(path, filter)).map(path -> path.getName().toString())
468 .sorted().collect(Collectors.toList());
469 }
470
471 @Override
472 public Collection<String> listProjects(String repoId, String namespace, Filter<String> filter)
473 throws RepositoryStorageRuntimeException {
474 StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(repoId), namespace);
475 if (!(dir.exists() && dir.isContainer())) {
476 return Collections.emptyList();
477 }
478
479 final Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
480 return dir.list().stream().filter(dFilter).filter(path -> isProject(path, filter)).map(path -> path.getName().toString())
481 .sorted().collect(Collectors.toList());
482
483 }
484
485 @Override
486 public Collection<String> listProjectVersions(String repoId, String namespace, String projectId,
487 Filter<String> filter)
488 throws RepositoryStorageRuntimeException {
489 StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(repoId), namespace, projectId);
490 if (!(dir.exists() && dir.isContainer())) {
491 return Collections.emptyList();
492 }
493
494
495 return getSortedFiles(dir, filter);
496 }
497
498 @Override
499 public Collection<ArtifactMetadata> readArtifactsMetadata(ReadMetadataRequest readMetadataRequest)
500 throws RepositoryStorageRuntimeException {
501 StorageAsset dir = pathTranslator.toFile(getRepositoryBasedir(readMetadataRequest.getRepositoryId()),
502 readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
503 readMetadataRequest.getProjectVersion());
504 if (!(dir.exists() && dir.isContainer())) {
505 return Collections.emptyList();
506 }
507
508
509 final Predicate<StorageAsset> dFilter = new ArtifactDirectoryFilter(readMetadataRequest.getFilter());
510
511 Map<Boolean, List<Try<ArtifactMetadata>>> result = dir.list().stream().filter(dFilter).map(path -> {
512 try {
513 return Try.success(getArtifactFromFile(readMetadataRequest.getRepositoryId(), readMetadataRequest.getNamespace(),
514 readMetadataRequest.getProjectId(), readMetadataRequest.getProjectVersion(),
515 path));
516 } catch (Exception e) {
517 LOGGER.debug("Could not create metadata for {}: {}", path, e.getMessage(), e);
518 return Try.<ArtifactMetadata>failure(e);
519 }
520 }
521 ).collect(Collectors.groupingBy(Try::isSuccess));
522 if (result.containsKey(Boolean.FALSE) && result.get(Boolean.FALSE).size() > 0 && (!result.containsKey(Boolean.TRUE) || result.get(Boolean.TRUE).size() == 0)) {
523 LOGGER.error("Could not get artifact metadata. Directory: {}. Number of errors {}.", dir, result.get(Boolean.FALSE).size());
524 Try<ArtifactMetadata> failure = result.get(Boolean.FALSE).get(0);
525 LOGGER.error("Sample exception {}", failure.getError().getMessage(), failure.getError());
526 throw new RepositoryStorageRuntimeException(readMetadataRequest.getRepositoryId(), "Could not retrieve metadata of the files");
527 } else {
528 if (!result.containsKey(Boolean.TRUE) || result.get(Boolean.TRUE) == null) {
529 return Collections.emptyList();
530 }
531 return result.get(Boolean.TRUE).stream().map(tr -> tr.get()).collect(Collectors.toList());
532 }
533
534 }
535
536 @Override
537 public ArtifactMetadata readArtifactMetadataFromPath(String repoId, String path)
538 throws RepositoryStorageRuntimeException {
539 ArtifactMetadata metadata = pathTranslator.getArtifactForPath(repoId, path);
540
541 try {
542 populateArtifactMetadataFromFile(metadata, getRepositoryBasedir(repoId).resolve(path));
543 } catch (IOException e) {
544 throw new RepositoryStorageRuntimeException(repoId, "Error during metadata retrieval of " + path + " :" + e.getMessage(), e);
545 }
546
547 return metadata;
548 }
549
550 private ArtifactMetadata getArtifactFromFile(String repoId, String namespace, String projectId,
551 String projectVersion, StorageAsset file) throws IOException {
552 ArtifactMetadata metadata =
553 pathTranslator.getArtifactFromId(repoId, namespace, projectId, projectVersion, file.getName());
554
555 populateArtifactMetadataFromFile(metadata, file);
556
557 return metadata;
558 }
559
560 @Override
561 public void applyServerSideRelocation(ManagedRepository managedRepository, ArtifactReference artifact)
562 throws ProxyDownloadException {
563 if ("pom".equals(artifact.getType())) {
564 return;
565 }
566
567
568 ArtifactReferenceerence.html#ArtifactReference">ArtifactReference pomReference = new ArtifactReference();
569 pomReference.setGroupId(artifact.getGroupId());
570 pomReference.setArtifactId(artifact.getArtifactId());
571 pomReference.setVersion(artifact.getVersion());
572 pomReference.setType("pom");
573
574 RepositoryType repositoryType = managedRepository.getType();
575 if (!proxyRegistry.hasHandler(repositoryType)) {
576 throw new ProxyDownloadException("No proxy handler found for repository type " + repositoryType, new HashMap<>());
577 }
578
579 RepositoryProxyHandler proxyHandler = proxyRegistry.getHandler(repositoryType).get(0);
580
581
582 proxyHandler.fetchFromProxies(managedRepository, pomReference);
583
584
585 StorageAsset pom = managedRepository.getContent().toFile(pomReference);
586
587 if (!pom.exists()) {
588 return;
589 }
590
591 try {
592
593
594 Model model;
595 try (Reader reader = Channels.newReader(pom.getReadChannel(), Charset.defaultCharset().name())) {
596 model = MAVEN_XPP_3_READER.read(reader);
597 }
598
599 DistributionManagement dist = model.getDistributionManagement();
600 if (dist != null) {
601 Relocation relocation = dist.getRelocation();
602 if (relocation != null) {
603
604 if (relocation.getGroupId() != null) {
605 artifact.setGroupId(relocation.getGroupId());
606 }
607 if (relocation.getArtifactId() != null) {
608 artifact.setArtifactId(relocation.getArtifactId());
609 }
610 if (relocation.getVersion() != null) {
611 artifact.setVersion(relocation.getVersion());
612 }
613 }
614 }
615 } catch (IOException e) {
616
617 } catch (XmlPullParserException e) {
618
619 }
620 }
621
622
623 @Override
624 public String getFilePath(String requestPath, org.apache.archiva.repository.ManagedRepository managedRepository) {
625
626
627
628
629 String logicalResource = null;
630 String requestPathInfo = StringUtils.defaultString(requestPath);
631
632
633 requestPathInfo = removePrefix(requestPathInfo);
634
635
636 if (requestPathInfo.startsWith("/")) {
637 requestPathInfo = requestPathInfo.substring(1);
638 }
639
640 int slash = requestPathInfo.indexOf('/');
641 if (slash > 0) {
642 logicalResource = requestPathInfo.substring(slash);
643
644 if (logicalResource.endsWith("/..")) {
645 logicalResource += "/";
646 }
647
648 if (logicalResource != null && logicalResource.startsWith("//")) {
649 logicalResource = logicalResource.substring(1);
650 }
651
652 if (logicalResource == null) {
653 logicalResource = "/";
654 }
655 } else {
656 logicalResource = "/";
657 }
658 return logicalResource;
659
660 }
661
662 @Override
663 public String getFilePathWithVersion(final String requestPath, ManagedRepositoryContent managedRepositoryContent)
664 throws RelocationException, XMLException, IOException {
665
666 if (StringUtils.endsWith(requestPath, METADATA_FILENAME)) {
667 return getFilePath(requestPath, managedRepositoryContent.getRepository());
668 }
669
670 String filePath = getFilePath(requestPath, managedRepositoryContent.getRepository());
671
672 ArtifactReference artifactReference = null;
673 try {
674 artifactReference = pathParser.toArtifactReference(filePath);
675 } catch (LayoutException e) {
676 return filePath;
677 }
678
679 if (StringUtils.endsWith(artifactReference.getVersion(), VersionUtil.SNAPSHOT)) {
680
681 StorageAsset metadataDir = managedRepositoryContent.getRepository().getAsset(filePath).getParent();
682 if (!metadataDir.exists()) {
683 return filePath;
684 }
685 StorageAsset metadataFile = metadataDir.resolve(METADATA_FILENAME);
686 if (!metadataFile.exists()) {
687 return filePath;
688 }
689 ArchivaRepositoryMetadata archivaRepositoryMetadata = MavenMetadataReader.read(metadataFile);
690 int buildNumber = archivaRepositoryMetadata.getSnapshotVersion().getBuildNumber();
691 String timestamp = archivaRepositoryMetadata.getSnapshotVersion().getTimestamp();
692
693
694 if (buildNumber < 1 && timestamp == null) {
695 return filePath;
696 }
697
698
699
700
701 filePath = StringUtils.replace(filePath,
702 artifactReference.getArtifactId()
703 + "-" + artifactReference.getVersion(),
704 artifactReference.getArtifactId()
705 + "-" + StringUtils.remove(artifactReference.getVersion(),
706 "-" + VersionUtil.SNAPSHOT)
707 + "-" + timestamp
708 + "-" + buildNumber);
709
710 throw new RelocationException("/repository/" + managedRepositoryContent.getRepository().getId() +
711 (StringUtils.startsWith(filePath, "/") ? "" : "/") + filePath,
712 RelocationException.RelocationType.TEMPORARY);
713
714 }
715
716 return filePath;
717 }
718
719
720
721
722
723
724
725
726
727
728
729 private static String removePrefix(final String href) {
730 String[] parts = StringUtils.split(href, '/');
731 parts = (String[]) ArrayUtils.subarray(parts, 1, parts.length);
732 if (parts == null || parts.length == 0) {
733 return "/";
734 }
735
736 String joinedString = StringUtils.join(parts, '/');
737 if (href.endsWith("/")) {
738 joinedString = joinedString + "/";
739 }
740
741 return joinedString;
742 }
743
744 private static void populateArtifactMetadataFromFile(ArtifactMetadata metadata, StorageAsset file) throws IOException {
745 metadata.setWhenGathered(ZonedDateTime.now(ZoneId.of("GMT")));
746 metadata.setFileLastModified(file.getModificationTime().toEpochMilli());
747 ChecksummedFileedFile.html#ChecksummedFile">ChecksummedFile checksummedFile = new ChecksummedFile(file.getFilePath());
748 try {
749 metadata.setMd5(checksummedFile.calculateChecksum(ChecksumAlgorithm.MD5));
750 } catch (IOException e) {
751 LOGGER.error("Unable to checksum file {}: {},MD5", file, e.getMessage());
752 }
753 try {
754 metadata.setSha1(checksummedFile.calculateChecksum(ChecksumAlgorithm.SHA1));
755 } catch (IOException e) {
756 LOGGER.error("Unable to checksum file {}: {},SHA1", file, e.getMessage());
757 }
758 metadata.setSize(file.getSize());
759 }
760
761 private boolean isProject(StorageAsset dir, Filter<String> filter) {
762
763 final Predicate<StorageAsset> dFilter = new DirectoryFilter(filter);
764 boolean projFound = dir.list().stream().filter(dFilter)
765 .anyMatch(path -> isProjectVersion(path));
766 if (projFound) {
767 return true;
768 }
769
770
771 ArchivaRepositoryMetadata metadata = readMetadata(dir);
772 if (metadata != null && dir.getName().toString().equals(metadata.getArtifactId())) {
773 return true;
774 }
775
776 return false;
777 }
778
779 private boolean isProjectVersion(StorageAsset dir) {
780 final String artifactId = dir.getParent().getName();
781 final String projectVersion = dir.getName();
782
783
784
785 Predicate<StorageAsset> filter;
786 if (VersionUtil.isSnapshot(projectVersion)) {
787 filter = new PomFilenameFilter(artifactId, projectVersion);
788 } else {
789 final String pomFile = artifactId + "-" + projectVersion + ".pom";
790 filter = new PomFileFilter(pomFile);
791 }
792 if (dir.list().stream().filter(f -> !f.isContainer()).anyMatch(filter)) {
793 return true;
794 }
795
796 ArchivaRepositoryMetadata metadata = readMetadata(dir);
797 if (metadata != null && projectVersion.equals(metadata.getVersion())) {
798 return true;
799 }
800
801 return false;
802 }
803
804 private ArchivaRepositoryMetadata readMetadata(StorageAsset directory) {
805 ArchivaRepositoryMetadata metadata = null;
806 StorageAsset metadataFile = directory.resolve(METADATA_FILENAME);
807 if (metadataFile.exists()) {
808 try {
809 metadata = MavenMetadataReader.read(metadataFile);
810 } catch (XMLException | IOException e) {
811
812 }
813 }
814 return metadata;
815 }
816
817 private static class DirectoryFilter
818 implements Predicate<StorageAsset> {
819 private final Filter<String> filter;
820
821 public DirectoryFilter(Filter<String> filter) {
822 this.filter = filter;
823 }
824
825 @Override
826 public boolean test(StorageAsset dir) {
827 final String name = dir.getName();
828 if (!filter.accept(name)) {
829 return false;
830 } else if (name.startsWith(".")) {
831 return false;
832 } else if (!dir.isContainer()) {
833 return false;
834 }
835 return true;
836 }
837 }
838
839 private static class ArtifactDirectoryFilter
840 implements Predicate<StorageAsset> {
841 private final Filter<String> filter;
842
843 private ArtifactDirectoryFilter(Filter<String> filter) {
844 this.filter = filter;
845 }
846
847 @Override
848 public boolean test(StorageAsset file) {
849 final Set<String> checksumExts = ChecksumAlgorithm.getAllExtensions();
850 final String path = file.getPath();
851 final String name = file.getName();
852 final String extension = StringUtils.substringAfterLast(name, ".").toLowerCase();
853
854 if (file.isContainer()) {
855 return false;
856 } else if (!filter.accept(name)) {
857 return false;
858 } else if (name.startsWith(".") || path.contains("/.") ) {
859 return false;
860 } else if (checksumExts.contains(extension)) {
861 return false;
862 } else if (Arrays.binarySearch(IGNORED_FILES, name) >= 0) {
863 return false;
864 }
865
866 else if (StringUtils.startsWith(name, METADATA_FILENAME_START) && StringUtils.endsWith(name, ".xml")) {
867 return false;
868 }
869
870 return true;
871
872 }
873 }
874
875
876 private static final class PomFilenameFilter
877 implements Predicate<StorageAsset> {
878
879 private final String artifactId, projectVersion;
880
881 private PomFilenameFilter(String artifactId, String projectVersion) {
882 this.artifactId = artifactId;
883 this.projectVersion = projectVersion;
884 }
885
886 @Override
887 public boolean test(StorageAsset dir) {
888 final String name = dir.getName();
889 if (name.startsWith(artifactId + "-") && name.endsWith(".pom")) {
890 String v = name.substring(artifactId.length() + 1, name.length() - 4);
891 v = VersionUtil.getBaseVersion(v);
892 if (v.equals(projectVersion)) {
893 return true;
894 }
895 }
896 return false;
897 }
898
899 }
900
901 private static class PomFileFilter
902 implements Predicate<StorageAsset> {
903 private final String pomFile;
904
905 private PomFileFilter(String pomFile) {
906 this.pomFile = pomFile;
907 }
908
909 @Override
910 public boolean test(StorageAsset dir) {
911 return pomFile.equals(dir.getName());
912 }
913 }
914
915
916 public PathParser getPathParser() {
917 return pathParser;
918 }
919
920 public void setPathParser(PathParser pathParser) {
921 this.pathParser = pathParser;
922 }
923 }