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.admin.model.RepositoryAdminException;
23 import org.apache.archiva.admin.model.beans.ManagedRepository;
24 import org.apache.archiva.admin.model.beans.NetworkProxy;
25 import org.apache.archiva.admin.model.beans.ProxyConnector;
26 import org.apache.archiva.admin.model.beans.RemoteRepository;
27 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
28 import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
29 import org.apache.archiva.admin.model.proxyconnector.ProxyConnectorAdmin;
30 import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin;
31 import org.apache.archiva.checksum.ChecksumAlgorithm;
32 import org.apache.archiva.checksum.ChecksummedFile;
33 import org.apache.archiva.common.utils.VersionUtil;
34 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
35 import org.apache.archiva.metadata.model.ArtifactMetadata;
36 import org.apache.archiva.metadata.model.ProjectMetadata;
37 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
38 import org.apache.archiva.metadata.model.facets.RepositoryProblemFacet;
39 import org.apache.archiva.metadata.repository.filter.Filter;
40 import org.apache.archiva.metadata.repository.storage.ReadMetadataRequest;
41 import org.apache.archiva.metadata.repository.storage.RelocationException;
42 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
43 import org.apache.archiva.metadata.repository.storage.RepositoryStorage;
44 import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataInvalidException;
45 import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataNotFoundException;
46 import org.apache.archiva.metadata.repository.storage.RepositoryStorageRuntimeException;
47 import org.apache.archiva.model.ArchivaRepositoryMetadata;
48 import org.apache.archiva.model.ArtifactReference;
49 import org.apache.archiva.model.SnapshotVersion;
50 import org.apache.archiva.policies.ProxyDownloadException;
51 import org.apache.archiva.proxy.common.WagonFactory;
52 import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
53 import org.apache.archiva.repository.ManagedRepositoryContent;
54 import org.apache.archiva.repository.content.PathParser;
55 import org.apache.archiva.repository.layout.LayoutException;
56 import org.apache.archiva.xml.XMLException;
57 import org.apache.commons.lang.ArrayUtils;
58 import org.apache.commons.lang.StringUtils;
59 import org.apache.maven.model.CiManagement;
60 import org.apache.maven.model.Dependency;
61 import org.apache.maven.model.DistributionManagement;
62 import org.apache.maven.model.IssueManagement;
63 import org.apache.maven.model.License;
64 import org.apache.maven.model.MailingList;
65 import org.apache.maven.model.Model;
66 import org.apache.maven.model.Organization;
67 import org.apache.maven.model.Relocation;
68 import org.apache.maven.model.Scm;
69 import org.apache.maven.model.building.DefaultModelBuilderFactory;
70 import org.apache.maven.model.building.DefaultModelBuildingRequest;
71 import org.apache.maven.model.building.ModelBuilder;
72 import org.apache.maven.model.building.ModelBuildingException;
73 import org.apache.maven.model.building.ModelBuildingRequest;
74 import org.apache.maven.model.building.ModelProblem;
75 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
76 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
79 import org.springframework.context.ApplicationContext;
80 import org.springframework.stereotype.Service;
81
82 import javax.annotation.PostConstruct;
83 import javax.inject.Inject;
84 import javax.inject.Named;
85 import java.io.File;
86 import java.io.FileNotFoundException;
87 import java.io.FilenameFilter;
88 import java.io.IOException;
89 import java.io.Reader;
90 import java.nio.charset.Charset;
91 import java.nio.file.Files;
92 import java.util.ArrayList;
93 import java.util.Arrays;
94 import java.util.Collection;
95 import java.util.Collections;
96 import java.util.Date;
97 import java.util.HashMap;
98 import java.util.List;
99 import java.util.Map;
100
101
102
103
104
105
106
107
108
109
110
111
112 @Service( "repositoryStorage#maven2" )
113 public class Maven2RepositoryStorage
114 implements RepositoryStorage
115 {
116
117 private static final Logger LOGGER = LoggerFactory.getLogger( Maven2RepositoryStorage.class );
118
119 private ModelBuilder builder;
120
121 @Inject
122 private RemoteRepositoryAdmin remoteRepositoryAdmin;
123
124 @Inject
125 private ManagedRepositoryAdmin managedRepositoryAdmin;
126
127 @Inject
128 private ProxyConnectorAdmin proxyConnectorAdmin;
129
130 @Inject
131 private NetworkProxyAdmin networkProxyAdmin;
132
133 @Inject
134 @Named( "repositoryPathTranslator#maven2" )
135 private RepositoryPathTranslator pathTranslator;
136
137 @Inject
138 private WagonFactory wagonFactory;
139
140 @Inject
141 private ApplicationContext applicationContext;
142
143 @Inject
144 @Named( "pathParser#default" )
145 private PathParser pathParser;
146
147 private static final String METADATA_FILENAME_START = "maven-metadata";
148
149 private static final String METADATA_FILENAME = METADATA_FILENAME_START + ".xml";
150
151
152 private static final String[] IGNORED_FILES = { METADATA_FILENAME, "resolver-status.properties" };
153
154 private static final MavenXpp3Reader MAVEN_XPP_3_READER = new MavenXpp3Reader();
155
156
157 @PostConstruct
158 public void initialize()
159 {
160 builder = new DefaultModelBuilderFactory().newInstance();
161
162 }
163
164 @Override
165 public ProjectMetadata readProjectMetadata( String repoId, String namespace, String projectId )
166 {
167
168 return null;
169 }
170
171 @Override
172 public ProjectVersionMetadata readProjectVersionMetadata( ReadMetadataRequest readMetadataRequest )
173 throws RepositoryStorageMetadataNotFoundException, RepositoryStorageMetadataInvalidException,
174 RepositoryStorageRuntimeException
175 {
176 try
177 {
178 ManagedRepository managedRepository =
179 managedRepositoryAdmin.getManagedRepository( readMetadataRequest.getRepositoryId() );
180 String artifactVersion = readMetadataRequest.getProjectVersion();
181
182 if ( !readMetadataRequest.isBrowsingRequest() )
183 {
184 if ( VersionUtil.isSnapshot( artifactVersion ) )
185 {
186
187 if ( managedRepository.isReleases() && !managedRepository.isSnapshots() )
188 {
189 throw new RepositoryStorageRuntimeException( "lookforsnaponreleaseonly",
190 "managed repo is configured for release only" );
191 }
192 }
193 else
194 {
195 if ( !managedRepository.isReleases() && managedRepository.isSnapshots() )
196 {
197 throw new RepositoryStorageRuntimeException( "lookforsreleaseonsneponly",
198 "managed repo is configured for snapshot only" );
199 }
200 }
201 }
202 File basedir = new File( managedRepository.getLocation() );
203 if ( VersionUtil.isSnapshot( artifactVersion ) )
204 {
205 File metadataFile = pathTranslator.toFile( basedir, readMetadataRequest.getNamespace(),
206 readMetadataRequest.getProjectId(), artifactVersion,
207 METADATA_FILENAME );
208 try
209 {
210 ArchivaRepositoryMetadata metadata = MavenMetadataReader.read( metadataFile );
211
212
213 SnapshotVersion snapshotVersion = metadata.getSnapshotVersion();
214 if ( snapshotVersion != null )
215 {
216 artifactVersion =
217 artifactVersion.substring( 0, artifactVersion.length() - 8 );
218 artifactVersion =
219 artifactVersion + snapshotVersion.getTimestamp() + "-" + snapshotVersion.getBuildNumber();
220 }
221 }
222 catch ( XMLException e )
223 {
224
225 LOGGER.warn( "Invalid metadata: {} - {}", metadataFile, e.getMessage() );
226 }
227 }
228
229
230 String id = readMetadataRequest.getProjectId() + "-" + artifactVersion + ".pom";
231 File file =
232 pathTranslator.toFile( basedir, readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
233 readMetadataRequest.getProjectVersion(), id );
234
235 if ( !file.exists() )
236 {
237
238 throw new RepositoryStorageMetadataNotFoundException(
239 "The artifact's POM file '" + file.getAbsolutePath() + "' was missing" );
240 }
241
242
243
244 List<RemoteRepository> remoteRepositories = new ArrayList<>();
245 Map<String, NetworkProxy> networkProxies = new HashMap<>();
246
247 Map<String, List<ProxyConnector>> proxyConnectorsMap = proxyConnectorAdmin.getProxyConnectorAsMap();
248 List<ProxyConnector> proxyConnectors = proxyConnectorsMap.get( readMetadataRequest.getRepositoryId() );
249 if ( proxyConnectors != null )
250 {
251 for ( ProxyConnector proxyConnector : proxyConnectors )
252 {
253 RemoteRepository remoteRepoConfig =
254 remoteRepositoryAdmin.getRemoteRepository( proxyConnector.getTargetRepoId() );
255
256 if ( remoteRepoConfig != null )
257 {
258 remoteRepositories.add( remoteRepoConfig );
259
260 NetworkProxy networkProxyConfig =
261 networkProxyAdmin.getNetworkProxy( proxyConnector.getProxyId() );
262
263 if ( networkProxyConfig != null )
264 {
265
266 networkProxies.put( proxyConnector.getTargetRepoId(), networkProxyConfig );
267 }
268 }
269 }
270 }
271
272
273
274 if ( readMetadataRequest.isBrowsingRequest() )
275 {
276 remoteRepositories.addAll( remoteRepositoryAdmin.getRemoteRepositories() );
277 }
278
279 ModelBuildingRequest req =
280 new DefaultModelBuildingRequest().setProcessPlugins( false ).setPomFile( file ).setTwoPhaseBuilding(
281 false ).setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
282
283
284 req.setSystemProperties( System.getProperties() );
285
286
287 req.setModelResolver(
288 new RepositoryModelResolver( managedRepository, pathTranslator, wagonFactory, remoteRepositories,
289 networkProxies, managedRepository ) );
290
291 Model model;
292 try
293 {
294 model = builder.build( req ).getEffectiveModel();
295 }
296 catch ( ModelBuildingException e )
297 {
298 String msg = "The artifact's POM file '" + file + "' was invalid: " + e.getMessage();
299
300 List<ModelProblem> modelProblems = e.getProblems();
301 for ( ModelProblem problem : modelProblems )
302 {
303
304
305
306
307
308 if ( ( problem.getException() instanceof FileNotFoundException && e.getModelId() != null &&
309 !e.getModelId().equals( problem.getModelId() ) ) )
310 {
311 LOGGER.warn( "The artifact's parent POM file '{}' cannot be resolved. "
312 + "Using defaults for project version metadata..", file );
313
314 ProjectVersionMetadata metadata = new ProjectVersionMetadata();
315 metadata.setId( readMetadataRequest.getProjectVersion() );
316
317 MavenProjectFacet facet = new MavenProjectFacet();
318 facet.setGroupId( readMetadataRequest.getNamespace() );
319 facet.setArtifactId( readMetadataRequest.getProjectId() );
320 facet.setPackaging( "jar" );
321 metadata.addFacet( facet );
322
323 String errMsg =
324 "Error in resolving artifact's parent POM file. " + ( problem.getException() == null
325 ? problem.getMessage()
326 : problem.getException().getMessage() );
327 RepositoryProblemFacet repoProblemFacet = new RepositoryProblemFacet();
328 repoProblemFacet.setRepositoryId( readMetadataRequest.getRepositoryId() );
329 repoProblemFacet.setId( readMetadataRequest.getRepositoryId() );
330 repoProblemFacet.setMessage( errMsg );
331 repoProblemFacet.setProblem( errMsg );
332 repoProblemFacet.setProject( readMetadataRequest.getProjectId() );
333 repoProblemFacet.setVersion( readMetadataRequest.getProjectVersion() );
334 repoProblemFacet.setNamespace( readMetadataRequest.getNamespace() );
335
336 metadata.addFacet( repoProblemFacet );
337
338 return metadata;
339 }
340 }
341
342 throw new RepositoryStorageMetadataInvalidException( "invalid-pom", msg, e );
343 }
344
345
346 boolean correctGroupId = readMetadataRequest.getNamespace().equals( model.getGroupId() );
347 boolean correctArtifactId = readMetadataRequest.getProjectId().equals( model.getArtifactId() );
348 boolean correctVersion = readMetadataRequest.getProjectVersion().equals( model.getVersion() );
349 if ( !correctGroupId || !correctArtifactId || !correctVersion )
350 {
351 StringBuilder message = new StringBuilder( "Incorrect POM coordinates in '" + file + "':" );
352 if ( !correctGroupId )
353 {
354 message.append( "\nIncorrect group ID: " ).append( model.getGroupId() );
355 }
356 if ( !correctArtifactId )
357 {
358 message.append( "\nIncorrect artifact ID: " ).append( model.getArtifactId() );
359 }
360 if ( !correctVersion )
361 {
362 message.append( "\nIncorrect version: " ).append( model.getVersion() );
363 }
364
365 throw new RepositoryStorageMetadataInvalidException( "mislocated-pom", message.toString() );
366 }
367
368 ProjectVersionMetadata metadata = new ProjectVersionMetadata();
369 metadata.setCiManagement( convertCiManagement( model.getCiManagement() ) );
370 metadata.setDescription( model.getDescription() );
371 metadata.setId( readMetadataRequest.getProjectVersion() );
372 metadata.setIssueManagement( convertIssueManagement( model.getIssueManagement() ) );
373 metadata.setLicenses( convertLicenses( model.getLicenses() ) );
374 metadata.setMailingLists( convertMailingLists( model.getMailingLists() ) );
375 metadata.setDependencies( convertDependencies( model.getDependencies() ) );
376 metadata.setName( model.getName() );
377 metadata.setOrganization( convertOrganization( model.getOrganization() ) );
378 metadata.setScm( convertScm( model.getScm() ) );
379 metadata.setUrl( model.getUrl() );
380 metadata.setProperties( model.getProperties() );
381
382 MavenProjectFacet facet = new MavenProjectFacet();
383 facet.setGroupId( model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId() );
384 facet.setArtifactId( model.getArtifactId() );
385 facet.setPackaging( model.getPackaging() );
386 if ( model.getParent() != null )
387 {
388 MavenProjectParent parent = new MavenProjectParent();
389 parent.setGroupId( model.getParent().getGroupId() );
390 parent.setArtifactId( model.getParent().getArtifactId() );
391 parent.setVersion( model.getParent().getVersion() );
392 facet.setParent( parent );
393 }
394 metadata.addFacet( facet );
395
396 return metadata;
397 }
398 catch ( RepositoryAdminException e )
399 {
400 throw new RepositoryStorageRuntimeException( "repo-admin", e.getMessage(), e );
401 }
402 }
403
404 public void setWagonFactory( WagonFactory wagonFactory )
405 {
406 this.wagonFactory = wagonFactory;
407 }
408
409 private List<org.apache.archiva.metadata.model.Dependency> convertDependencies( List<Dependency> dependencies )
410 {
411 List<org.apache.archiva.metadata.model.Dependency> l = new ArrayList<>();
412 for ( Dependency dependency : dependencies )
413 {
414 org.apache.archiva.metadata.model.Dependency newDependency =
415 new org.apache.archiva.metadata.model.Dependency();
416 newDependency.setArtifactId( dependency.getArtifactId() );
417 newDependency.setClassifier( dependency.getClassifier() );
418 newDependency.setGroupId( dependency.getGroupId() );
419 newDependency.setOptional( dependency.isOptional() );
420 newDependency.setScope( dependency.getScope() );
421 newDependency.setSystemPath( dependency.getSystemPath() );
422 newDependency.setType( dependency.getType() );
423 newDependency.setVersion( dependency.getVersion() );
424 l.add( newDependency );
425 }
426 return l;
427 }
428
429 private org.apache.archiva.metadata.model.Scm convertScm( Scm scm )
430 {
431 org.apache.archiva.metadata.model.Scm newScm = null;
432 if ( scm != null )
433 {
434 newScm = new org.apache.archiva.metadata.model.Scm();
435 newScm.setConnection( scm.getConnection() );
436 newScm.setDeveloperConnection( scm.getDeveloperConnection() );
437 newScm.setUrl( scm.getUrl() );
438 }
439 return newScm;
440 }
441
442 private org.apache.archiva.metadata.model.Organization convertOrganization( Organization organization )
443 {
444 org.apache.archiva.metadata.model.Organization org = null;
445 if ( organization != null )
446 {
447 org = new org.apache.archiva.metadata.model.Organization();
448 org.setName( organization.getName() );
449 org.setUrl( organization.getUrl() );
450 }
451 return org;
452 }
453
454 private List<org.apache.archiva.metadata.model.License> convertLicenses( List<License> licenses )
455 {
456 List<org.apache.archiva.metadata.model.License> l = new ArrayList<>();
457 for ( License license : licenses )
458 {
459 org.apache.archiva.metadata.model.License newLicense = new org.apache.archiva.metadata.model.License();
460 newLicense.setName( license.getName() );
461 newLicense.setUrl( license.getUrl() );
462 l.add( newLicense );
463 }
464 return l;
465 }
466
467 private List<org.apache.archiva.metadata.model.MailingList> convertMailingLists( List<MailingList> mailingLists )
468 {
469 List<org.apache.archiva.metadata.model.MailingList> l = new ArrayList<>();
470 for ( MailingList mailingList : mailingLists )
471 {
472 org.apache.archiva.metadata.model.MailingList newMailingList =
473 new org.apache.archiva.metadata.model.MailingList();
474 newMailingList.setName( mailingList.getName() );
475 newMailingList.setMainArchiveUrl( mailingList.getArchive() );
476 newMailingList.setPostAddress( mailingList.getPost() );
477 newMailingList.setSubscribeAddress( mailingList.getSubscribe() );
478 newMailingList.setUnsubscribeAddress( mailingList.getUnsubscribe() );
479 newMailingList.setOtherArchives( mailingList.getOtherArchives() );
480 l.add( newMailingList );
481 }
482 return l;
483 }
484
485 private org.apache.archiva.metadata.model.IssueManagement convertIssueManagement( IssueManagement issueManagement )
486 {
487 org.apache.archiva.metadata.model.IssueManagement im = null;
488 if ( issueManagement != null )
489 {
490 im = new org.apache.archiva.metadata.model.IssueManagement();
491 im.setSystem( issueManagement.getSystem() );
492 im.setUrl( issueManagement.getUrl() );
493 }
494 return im;
495 }
496
497 private org.apache.archiva.metadata.model.CiManagement convertCiManagement( CiManagement ciManagement )
498 {
499 org.apache.archiva.metadata.model.CiManagement ci = null;
500 if ( ciManagement != null )
501 {
502 ci = new org.apache.archiva.metadata.model.CiManagement();
503 ci.setSystem( ciManagement.getSystem() );
504 ci.setUrl( ciManagement.getUrl() );
505 }
506 return ci;
507 }
508
509 @Override
510 public Collection<String> listRootNamespaces( String repoId, Filter<String> filter )
511 throws RepositoryStorageRuntimeException
512 {
513 File dir = getRepositoryBasedir( repoId );
514
515 return getSortedFiles( dir, filter );
516 }
517
518 private static Collection<String> getSortedFiles( File dir, Filter<String> filter )
519 {
520 List<String> fileNames;
521 String[] files = dir.list( new DirectoryFilter( filter ) );
522 if ( files != null )
523 {
524 fileNames = new ArrayList<>( Arrays.asList( files ) );
525 Collections.sort( fileNames );
526 }
527 else
528 {
529 fileNames = Collections.emptyList();
530 }
531 return fileNames;
532 }
533
534 private File getRepositoryBasedir( String repoId )
535 throws RepositoryStorageRuntimeException
536 {
537 try
538 {
539 ManagedRepository repositoryConfiguration = managedRepositoryAdmin.getManagedRepository( repoId );
540
541 return new File( repositoryConfiguration.getLocation() );
542 }
543 catch ( RepositoryAdminException e )
544 {
545 throw new RepositoryStorageRuntimeException( "repo-admin", e.getMessage(), e );
546 }
547 }
548
549 @Override
550 public Collection<String> listNamespaces( String repoId, String namespace, Filter<String> filter )
551 throws RepositoryStorageRuntimeException
552 {
553 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace );
554
555
556 List<String> namespaces = new ArrayList<>();
557 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
558 if ( files != null )
559 {
560 for ( File file : files )
561 {
562 if ( !isProject( file, filter ) )
563 {
564 namespaces.add( file.getName() );
565 }
566 }
567 }
568 Collections.sort( namespaces );
569 return namespaces;
570 }
571
572 @Override
573 public Collection<String> listProjects( String repoId, String namespace, Filter<String> filter )
574 throws RepositoryStorageRuntimeException
575 {
576 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace );
577
578
579 List<String> projects = new ArrayList<>();
580
581 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
582 if ( files != null )
583 {
584 for ( File file : files )
585 {
586 if ( isProject( file, filter ) )
587 {
588 projects.add( file.getName() );
589 }
590 }
591 }
592 Collections.sort( projects );
593 return projects;
594 }
595
596 @Override
597 public Collection<String> listProjectVersions( String repoId, String namespace, String projectId,
598 Filter<String> filter )
599 throws RepositoryStorageRuntimeException
600 {
601 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace, projectId );
602
603
604 return getSortedFiles( dir, filter );
605 }
606
607 @Override
608 public Collection<ArtifactMetadata> readArtifactsMetadata( ReadMetadataRequest readMetadataRequest )
609 throws RepositoryStorageRuntimeException
610 {
611 File dir = pathTranslator.toFile( getRepositoryBasedir( readMetadataRequest.getRepositoryId() ),
612 readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
613 readMetadataRequest.getProjectVersion() );
614
615
616 File[] files = dir.listFiles( new ArtifactDirectoryFilter( readMetadataRequest.getFilter() ) );
617
618 List<ArtifactMetadata> artifacts = new ArrayList<>();
619 if ( files != null )
620 {
621 int errorCount=0;
622 for ( File file : files )
623 {
624 try {
625 ArtifactMetadata metadata =
626 getArtifactFromFile(readMetadataRequest.getRepositoryId(), readMetadataRequest.getNamespace(),
627 readMetadataRequest.getProjectId(), readMetadataRequest.getProjectVersion(),
628 file);
629 artifacts.add(metadata);
630 } catch (Exception ex) {
631 LOGGER.error("Error while retrieving metadata of file {} (Project: {}, Repository: {}): {}",
632 file.getName(), readMetadataRequest.getProjectId(), readMetadataRequest.getRepositoryId(),
633 ex.getMessage());
634 errorCount++;
635 }
636 }
637
638 if (errorCount>0 && errorCount==files.length) {
639 throw new RepositoryStorageRuntimeException(readMetadataRequest.getRepositoryId(), "Could not retrieve metadata of the files");
640 }
641 }
642 return artifacts;
643 }
644
645 @Override
646 public ArtifactMetadata readArtifactMetadataFromPath( String repoId, String path )
647 throws RepositoryStorageRuntimeException
648 {
649 ArtifactMetadata metadata = pathTranslator.getArtifactForPath( repoId, path );
650
651 populateArtifactMetadataFromFile( metadata, new File( getRepositoryBasedir( repoId ), path ) );
652
653 return metadata;
654 }
655
656 private ArtifactMetadata getArtifactFromFile( String repoId, String namespace, String projectId,
657 String projectVersion, File file )
658 {
659 ArtifactMetadata metadata =
660 pathTranslator.getArtifactFromId( repoId, namespace, projectId, projectVersion, file.getName() );
661
662 populateArtifactMetadataFromFile( metadata, file );
663
664 return metadata;
665 }
666
667 @Override
668 public void applyServerSideRelocation( ManagedRepositoryContent managedRepository, ArtifactReference artifact )
669 throws ProxyDownloadException
670 {
671 if ( "pom".equals( artifact.getType() ) )
672 {
673 return;
674 }
675
676
677 ArtifactReference pomReference = new ArtifactReference();
678 pomReference.setGroupId( artifact.getGroupId() );
679 pomReference.setArtifactId( artifact.getArtifactId() );
680 pomReference.setVersion( artifact.getVersion() );
681 pomReference.setType( "pom" );
682
683 RepositoryProxyConnectors connectors =
684 applicationContext.getBean( "repositoryProxyConnectors#default", RepositoryProxyConnectors.class );
685
686
687 connectors.fetchFromProxies( managedRepository, pomReference );
688
689
690 File pom = managedRepository.toFile( pomReference );
691
692 if ( !pom.exists() )
693 {
694 return;
695 }
696
697 try
698 {
699
700
701 Model model = null;
702 try (Reader reader = Files.newBufferedReader( pom.toPath(), Charset.defaultCharset() ))
703 {
704 model = MAVEN_XPP_3_READER.read( reader );
705 }
706
707 DistributionManagement dist = model.getDistributionManagement();
708 if ( dist != null )
709 {
710 Relocation relocation = dist.getRelocation();
711 if ( relocation != null )
712 {
713
714 if ( relocation.getGroupId() != null )
715 {
716 artifact.setGroupId( relocation.getGroupId() );
717 }
718 if ( relocation.getArtifactId() != null )
719 {
720 artifact.setArtifactId( relocation.getArtifactId() );
721 }
722 if ( relocation.getVersion() != null )
723 {
724 artifact.setVersion( relocation.getVersion() );
725 }
726 }
727 }
728 }
729 catch ( IOException e )
730 {
731
732 }
733 catch ( XmlPullParserException e )
734 {
735
736 }
737 }
738
739
740 @Override
741 public String getFilePath( String requestPath, ManagedRepository managedRepository )
742 {
743
744
745
746
747 String logicalResource = null;
748 String requestPathInfo = StringUtils.defaultString( requestPath );
749
750
751 requestPathInfo = removePrefix( requestPathInfo );
752
753
754 if ( requestPathInfo.startsWith( "/" ) )
755 {
756 requestPathInfo = requestPathInfo.substring( 1 );
757 }
758
759 int slash = requestPathInfo.indexOf( '/' );
760 if ( slash > 0 )
761 {
762 logicalResource = requestPathInfo.substring( slash );
763
764 if ( logicalResource.endsWith( "/.." ) )
765 {
766 logicalResource += "/";
767 }
768
769 if ( logicalResource != null && logicalResource.startsWith( "//" ) )
770 {
771 logicalResource = logicalResource.substring( 1 );
772 }
773
774 if ( logicalResource == null )
775 {
776 logicalResource = "/";
777 }
778 }
779 else
780 {
781 logicalResource = "/";
782 }
783 return logicalResource;
784
785 }
786
787 @Override
788 public String getFilePathWithVersion( final String requestPath, ManagedRepositoryContent managedRepositoryContent )
789 throws XMLException, RelocationException
790 {
791
792 if ( StringUtils.endsWith( requestPath, METADATA_FILENAME ) )
793 {
794 return getFilePath( requestPath, managedRepositoryContent.getRepository() );
795 }
796
797 String filePath = getFilePath( requestPath, managedRepositoryContent.getRepository() );
798
799 ArtifactReference artifactReference = null;
800 try
801 {
802 artifactReference = pathParser.toArtifactReference( filePath );
803 }
804 catch ( LayoutException e )
805 {
806 return filePath;
807 }
808
809 if ( StringUtils.endsWith( artifactReference.getVersion(), VersionUtil.SNAPSHOT ) )
810 {
811
812 File metadataDir = new File( managedRepositoryContent.getRepoRoot(), filePath ).getParentFile();
813 if ( !metadataDir.exists() )
814 {
815 return filePath;
816 }
817 File metadataFile = new File( metadataDir, METADATA_FILENAME );
818 if ( !metadataFile.exists() )
819 {
820 return filePath;
821 }
822 ArchivaRepositoryMetadata archivaRepositoryMetadata = MavenMetadataReader.read( metadataFile );
823 int buildNumber = archivaRepositoryMetadata.getSnapshotVersion().getBuildNumber();
824 String timestamp = archivaRepositoryMetadata.getSnapshotVersion().getTimestamp();
825
826
827 if ( buildNumber < 1 && timestamp == null )
828 {
829 return filePath;
830 }
831
832
833
834
835 filePath = StringUtils.replace( filePath,
836 artifactReference.getArtifactId()
837 + "-" + artifactReference.getVersion(),
838 artifactReference.getArtifactId()
839 + "-" + StringUtils.remove( artifactReference.getVersion(),
840 "-" + VersionUtil.SNAPSHOT )
841 + "-" + timestamp
842 + "-" + buildNumber );
843
844 throw new RelocationException( "/repository/" + managedRepositoryContent.getRepository().getId() +
845 ( StringUtils.startsWith( filePath, "/" ) ? "" : "/" ) + filePath,
846 RelocationException.RelocationType.TEMPORARY );
847
848 }
849
850 return filePath;
851 }
852
853
854
855
856
857
858
859
860
861
862
863 private static String removePrefix( final String href )
864 {
865 String[] parts = StringUtils.split( href, '/' );
866 parts = (String[]) ArrayUtils.subarray( parts, 1, parts.length );
867 if ( parts == null || parts.length == 0 )
868 {
869 return "/";
870 }
871
872 String joinedString = StringUtils.join( parts, '/' );
873 if ( href.endsWith( "/" ) )
874 {
875 joinedString = joinedString + "/";
876 }
877
878 return joinedString;
879 }
880
881 private static void populateArtifactMetadataFromFile( ArtifactMetadata metadata, File file )
882 {
883 metadata.setWhenGathered( new Date() );
884 metadata.setFileLastModified( file.lastModified() );
885 ChecksummedFile checksummedFile = new ChecksummedFile( file );
886 try
887 {
888 metadata.setMd5( checksummedFile.calculateChecksum( ChecksumAlgorithm.MD5 ) );
889 }
890 catch ( IOException e )
891 {
892 LOGGER.error( "Unable to checksum file {}: {},MD5", file, e.getMessage() );
893 }
894 try
895 {
896 metadata.setSha1( checksummedFile.calculateChecksum( ChecksumAlgorithm.SHA1 ) );
897 }
898 catch ( IOException e )
899 {
900 LOGGER.error( "Unable to checksum file {}: {},SHA1", file, e.getMessage() );
901 }
902 metadata.setSize( file.length() );
903 }
904
905 private boolean isProject( File dir, Filter<String> filter )
906 {
907
908 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
909 if ( files != null )
910 {
911 for ( File file : files )
912 {
913 if ( isProjectVersion( file ) )
914 {
915 return true;
916 }
917 }
918 }
919
920
921 ArchivaRepositoryMetadata metadata = readMetadata( dir );
922 if ( metadata != null && dir.getName().equals( metadata.getArtifactId() ) )
923 {
924 return true;
925 }
926
927 return false;
928 }
929
930 private boolean isProjectVersion( File dir )
931 {
932 final String artifactId = dir.getParentFile().getName();
933 final String projectVersion = dir.getName();
934
935
936 File[] files;
937 if ( VersionUtil.isSnapshot( projectVersion ) )
938 {
939 files = dir.listFiles( new PomFilenameFilter( artifactId, projectVersion ) );
940 }
941 else
942 {
943 final String pomFile = artifactId + "-" + projectVersion + ".pom";
944 files = dir.listFiles( new PomFileFilter( pomFile ) );
945 }
946 if ( files != null && files.length > 0 )
947 {
948 return true;
949 }
950
951
952 ArchivaRepositoryMetadata metadata = readMetadata( dir );
953 if ( metadata != null && projectVersion.equals( metadata.getVersion() ) )
954 {
955 return true;
956 }
957
958 return false;
959 }
960
961 private ArchivaRepositoryMetadata readMetadata( File directory )
962 {
963 ArchivaRepositoryMetadata metadata = null;
964 File metadataFile = new File( directory, METADATA_FILENAME );
965 if ( metadataFile.exists() )
966 {
967 try
968 {
969 metadata = MavenMetadataReader.read( metadataFile );
970 }
971 catch ( XMLException e )
972 {
973
974 }
975 }
976 return metadata;
977 }
978
979 private static class DirectoryFilter
980 implements FilenameFilter
981 {
982 private final Filter<String> filter;
983
984 public DirectoryFilter( Filter<String> filter )
985 {
986 this.filter = filter;
987 }
988
989 @Override
990 public boolean accept( File dir, String name )
991 {
992 if ( !filter.accept( name ) )
993 {
994 return false;
995 }
996 else if ( name.startsWith( "." ) )
997 {
998 return false;
999 }
1000 else if ( !new File( dir, name ).isDirectory() )
1001 {
1002 return false;
1003 }
1004 return true;
1005 }
1006 }
1007
1008 private static class ArtifactDirectoryFilter
1009 implements FilenameFilter
1010 {
1011 private final Filter<String> filter;
1012
1013 private ArtifactDirectoryFilter( Filter<String> filter )
1014 {
1015 this.filter = filter;
1016 }
1017
1018 @Override
1019 public boolean accept( File dir, String name )
1020 {
1021
1022 if ( !filter.accept( name ) )
1023 {
1024 return false;
1025 }
1026 else if ( name.startsWith( "." ) )
1027 {
1028 return false;
1029 }
1030 else if ( name.endsWith( ".md5" ) || name.endsWith( ".sha1" ) || name.endsWith( ".asc" ) )
1031 {
1032 return false;
1033 }
1034 else if ( Arrays.binarySearch(IGNORED_FILES, name)>=0 )
1035 {
1036 return false;
1037 }
1038 else if ( new File( dir, name ).isDirectory() )
1039 {
1040 return false;
1041 }
1042
1043 else if ( StringUtils.startsWith( name, METADATA_FILENAME_START ) && StringUtils.endsWith( name, ".xml" ) )
1044 {
1045 return false;
1046 }
1047
1048 return true;
1049
1050 }
1051 }
1052
1053
1054 private static final class PomFilenameFilter
1055 implements FilenameFilter
1056 {
1057
1058 private final String artifactId, projectVersion;
1059
1060 private PomFilenameFilter( String artifactId, String projectVersion )
1061 {
1062 this.artifactId = artifactId;
1063 this.projectVersion = projectVersion;
1064 }
1065
1066 @Override
1067 public boolean accept( File dir, String name )
1068 {
1069 if ( name.startsWith( artifactId + "-" ) && name.endsWith( ".pom" ) )
1070 {
1071 String v = name.substring( artifactId.length() + 1, name.length() - 4 );
1072 v = VersionUtil.getBaseVersion( v );
1073 if ( v.equals( projectVersion ) )
1074 {
1075 return true;
1076 }
1077 }
1078 return false;
1079 }
1080 }
1081
1082 private static class PomFileFilter
1083 implements FilenameFilter
1084 {
1085 private final String pomFile;
1086
1087 private PomFileFilter( String pomFile )
1088 {
1089 this.pomFile = pomFile;
1090 }
1091
1092 @Override
1093 public boolean accept( File dir, String name )
1094 {
1095 return pomFile.equals( name );
1096 }
1097 }
1098
1099
1100 public PathParser getPathParser()
1101 {
1102 return pathParser;
1103 }
1104
1105 public void setPathParser( PathParser pathParser )
1106 {
1107 this.pathParser = pathParser;
1108 }
1109 }