1 package org.apache.archiva.metadata.repository.storage.maven2;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
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.repository.filter.Filter;
39 import org.apache.archiva.metadata.repository.storage.ReadMetadataRequest;
40 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
41 import org.apache.archiva.metadata.repository.storage.RepositoryStorage;
42 import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataInvalidException;
43 import org.apache.archiva.metadata.repository.storage.RepositoryStorageMetadataNotFoundException;
44 import org.apache.archiva.metadata.repository.storage.RepositoryStorageRuntimeException;
45 import org.apache.archiva.model.ArchivaRepositoryMetadata;
46 import org.apache.archiva.model.ArtifactReference;
47 import org.apache.archiva.model.SnapshotVersion;
48 import org.apache.archiva.policies.ProxyDownloadException;
49 import org.apache.archiva.proxy.common.WagonFactory;
50 import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
51 import org.apache.archiva.reports.RepositoryProblemFacet;
52 import org.apache.archiva.repository.ManagedRepositoryContent;
53 import org.apache.archiva.xml.XMLException;
54 import org.apache.commons.lang.StringUtils;
55 import org.apache.maven.model.CiManagement;
56 import org.apache.maven.model.Dependency;
57 import org.apache.maven.model.DistributionManagement;
58 import org.apache.maven.model.IssueManagement;
59 import org.apache.maven.model.License;
60 import org.apache.maven.model.MailingList;
61 import org.apache.maven.model.Model;
62 import org.apache.maven.model.Organization;
63 import org.apache.maven.model.Relocation;
64 import org.apache.maven.model.Scm;
65 import org.apache.maven.model.building.DefaultModelBuilderFactory;
66 import org.apache.maven.model.building.DefaultModelBuildingRequest;
67 import org.apache.maven.model.building.ModelBuilder;
68 import org.apache.maven.model.building.ModelBuildingException;
69 import org.apache.maven.model.building.ModelBuildingRequest;
70 import org.apache.maven.model.building.ModelProblem;
71 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
72 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75 import org.springframework.stereotype.Service;
77 import javax.annotation.PostConstruct;
78 import javax.inject.Inject;
79 import javax.inject.Named;
81 import java.io.FileNotFoundException;
82 import java.io.FileReader;
83 import java.io.FilenameFilter;
84 import java.io.IOException;
85 import java.util.ArrayList;
86 import java.util.Arrays;
87 import java.util.Collection;
88 import java.util.Collections;
89 import java.util.Date;
90 import java.util.HashMap;
91 import java.util.List;
95 * Maven 2 repository format storage implementation. This class currently takes parameters to indicate the repository to
96 * deal with rather than being instantiated per-repository.
97 * FIXME: instantiate one per repository and allocate permanently from a factory (which can be obtained within the session).
98 * TODO: finish Maven 1 implementation to prove this API
100 * The session is passed in as an argument to obtain any necessary resources, rather than the class being instantiated
101 * within the session in the context of a single managed repository's resolution needs.
104 @Service ( "repositoryStorage#maven2" )
105 public class Maven2RepositoryStorage
106 implements RepositoryStorage
111 private ModelBuilder builder;
117 private RemoteRepositoryAdmin remoteRepositoryAdmin;
120 private ManagedRepositoryAdmin managedRepositoryAdmin;
123 private ProxyConnectorAdmin proxyConnectorAdmin;
126 private NetworkProxyAdmin networkProxyAdmin;
132 @Named ( value = "repositoryPathTranslator#maven2" )
133 private RepositoryPathTranslator pathTranslator;
136 private WagonFactory wagonFactory;
139 @Named ( value = "repositoryProxyConnectors#default" )
140 private RepositoryProxyConnectors connectors;
142 private static final Logger log = LoggerFactory.getLogger( Maven2RepositoryStorage.class );
144 private static final String METADATA_FILENAME_START = "maven-metadata";
146 private static final String METADATA_FILENAME = METADATA_FILENAME_START + ".xml";
148 private static final MavenXpp3Reader MAVEN_XPP_3_READER = new MavenXpp3Reader();
152 public void initialize()
154 DefaultModelBuilderFactory defaultModelBuilderFactory = new DefaultModelBuilderFactory();
155 builder = defaultModelBuilderFactory.newInstance();
159 public ProjectMetadata readProjectMetadata( String repoId, String namespace, String projectId )
161 // TODO: could natively implement the "shared model" concept from the browse action to avoid needing it there?
165 public ProjectVersionMetadata readProjectVersionMetadata( ReadMetadataRequest readMetadataRequest )
166 throws RepositoryStorageMetadataNotFoundException, RepositoryStorageMetadataInvalidException,
167 RepositoryStorageRuntimeException
171 ManagedRepository managedRepository =
172 managedRepositoryAdmin.getManagedRepository( readMetadataRequest.getRepositoryId() );
174 String artifactVersion = readMetadataRequest.getProjectVersion();
175 if ( VersionUtil.isSnapshot(
176 readMetadataRequest.getProjectVersion() ) ) // skygo trying to improve speed by honoring managed configuration MRM-1658
178 if ( managedRepository.isReleases() && !managedRepository.isSnapshots() )
180 throw new RepositoryStorageRuntimeException( "lookforsnaponreleaseonly",
181 "managed repo is configured for release only" );
186 if ( !managedRepository.isReleases() && managedRepository.isSnapshots() )
188 throw new RepositoryStorageRuntimeException( "lookforsreleaseonsneponly",
189 "managed repo is configured for snapshot only" );
192 File basedir = new File( managedRepository.getLocation() );
193 if ( VersionUtil.isSnapshot( readMetadataRequest.getProjectVersion() ) )
195 File metadataFile = pathTranslator.toFile( basedir, readMetadataRequest.getNamespace(),
196 readMetadataRequest.getProjectId(),
197 readMetadataRequest.getProjectVersion(), METADATA_FILENAME );
200 ArchivaRepositoryMetadata metadata = MavenMetadataReader.read( metadataFile );
202 // re-adjust to timestamp if present, otherwise retain the original -SNAPSHOT filename
203 SnapshotVersion snapshotVersion = metadata.getSnapshotVersion();
204 if ( snapshotVersion != null )
207 artifactVersion.substring( 0, artifactVersion.length() - 8 ); // remove SNAPSHOT from end
209 artifactVersion + snapshotVersion.getTimestamp() + "-" + snapshotVersion.getBuildNumber();
212 catch ( XMLException e )
214 // unable to parse metadata - log it, and continue with the version as the original SNAPSHOT version
215 log.warn( "Invalid metadata: " + metadataFile + " - " + e.getMessage() );
219 // TODO: won't work well with some other layouts, might need to convert artifact parts to ID by path translator
220 String id = readMetadataRequest.getProjectId() + "-" + artifactVersion + ".pom";
222 pathTranslator.toFile( basedir, readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
223 readMetadataRequest.getProjectVersion(), id );
225 if ( !file.exists() )
227 // metadata could not be resolved
228 throw new RepositoryStorageMetadataNotFoundException(
229 "The artifact's POM file '" + file.getAbsolutePath() + "' was missing" );
232 // TODO: this is a workaround until we can properly resolve using proxies as well - this doesn't cache
234 List<RemoteRepository> remoteRepositories = new ArrayList<RemoteRepository>();
235 Map<String, NetworkProxy> networkProxies = new HashMap<String, NetworkProxy>();
237 Map<String, List<ProxyConnector>> proxyConnectorsMap = proxyConnectorAdmin.getProxyConnectorAsMap();
238 List<ProxyConnector> proxyConnectors = proxyConnectorsMap.get( readMetadataRequest.getRepositoryId() );
239 if ( proxyConnectors != null )
241 for ( ProxyConnector proxyConnector : proxyConnectors )
243 RemoteRepository remoteRepoConfig =
244 remoteRepositoryAdmin.getRemoteRepository( proxyConnector.getTargetRepoId() );
246 if ( remoteRepoConfig != null )
248 remoteRepositories.add( remoteRepoConfig );
250 NetworkProxy networkProxyConfig =
251 networkProxyAdmin.getNetworkProxy( proxyConnector.getProxyId() );
253 if ( networkProxyConfig != null )
255 // key/value: remote repo ID/proxy info
256 networkProxies.put( proxyConnector.getTargetRepoId(), networkProxyConfig );
262 ModelBuildingRequest req =
263 new DefaultModelBuildingRequest().setProcessPlugins( false ).setPomFile( file ).setTwoPhaseBuilding(
264 false ).setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
266 //MRM-1607. olamy this will resolve jdk profiles on the current running archiva jvm
267 req.setSystemProperties( System.getProperties() );
270 req.setModelResolver(
271 new RepositoryModelResolver( managedRepository, pathTranslator, wagonFactory, remoteRepositories,
272 networkProxies, managedRepository ) );
277 model = builder.build( req ).getEffectiveModel();
279 catch ( ModelBuildingException e )
281 String msg = "The artifact's POM file '" + file + "' was invalid: " + e.getMessage();
283 List<ModelProblem> modelProblems = e.getProblems();
284 for ( ModelProblem problem : modelProblems )
286 // MRM-1411, related to MRM-1335
287 // this means that the problem was that the parent wasn't resolved!
288 // olamy really hackhish but fail with java profile so use error message
289 // || ( StringUtils.startsWith( problem.getMessage(), "Failed to determine Java version for profile" ) )
290 // but setTwoPhaseBuilding(true) fix that
291 if ( ( problem.getException() instanceof FileNotFoundException && e.getModelId() != null &&
292 !e.getModelId().equals( problem.getModelId() ) ) )
294 log.warn( "The artifact's parent POM file '" + file + "' cannot be resolved. " +
295 "Using defaults for project version metadata.." );
297 ProjectVersionMetadata metadata = new ProjectVersionMetadata();
298 metadata.setId( readMetadataRequest.getProjectVersion() );
300 MavenProjectFacet facet = new MavenProjectFacet();
301 facet.setGroupId( readMetadataRequest.getNamespace() );
302 facet.setArtifactId( readMetadataRequest.getProjectId() );
303 facet.setPackaging( "jar" );
304 metadata.addFacet( facet );
307 "Error in resolving artifact's parent POM file. " + ( problem.getException() == null
308 ? problem.getMessage()
309 : problem.getException().getMessage() );
310 RepositoryProblemFacet repoProblemFacet = new RepositoryProblemFacet();
311 repoProblemFacet.setRepositoryId( readMetadataRequest.getRepositoryId() );
312 repoProblemFacet.setId( readMetadataRequest.getRepositoryId() );
313 repoProblemFacet.setMessage( errMsg );
314 repoProblemFacet.setProblem( errMsg );
315 repoProblemFacet.setProject( readMetadataRequest.getProjectId() );
316 repoProblemFacet.setVersion( readMetadataRequest.getProjectVersion() );
317 repoProblemFacet.setNamespace( readMetadataRequest.getNamespace() );
319 metadata.addFacet( repoProblemFacet );
325 throw new RepositoryStorageMetadataInvalidException( "invalid-pom", msg, e );
328 // Check if the POM is in the correct location
329 boolean correctGroupId = readMetadataRequest.getNamespace().equals( model.getGroupId() );
330 boolean correctArtifactId = readMetadataRequest.getProjectId().equals( model.getArtifactId() );
331 boolean correctVersion = readMetadataRequest.getProjectVersion().equals( model.getVersion() );
332 if ( !correctGroupId || !correctArtifactId || !correctVersion )
334 StringBuilder message = new StringBuilder( "Incorrect POM coordinates in '" + file + "':" );
335 if ( !correctGroupId )
337 message.append( "\nIncorrect group ID: " ).append( model.getGroupId() );
339 if ( !correctArtifactId )
341 message.append( "\nIncorrect artifact ID: " ).append( model.getArtifactId() );
343 if ( !correctVersion )
345 message.append( "\nIncorrect version: " ).append( model.getVersion() );
348 throw new RepositoryStorageMetadataInvalidException( "mislocated-pom", message.toString() );
351 ProjectVersionMetadata metadata = new ProjectVersionMetadata();
352 metadata.setCiManagement( convertCiManagement( model.getCiManagement() ) );
353 metadata.setDescription( model.getDescription() );
354 metadata.setId( readMetadataRequest.getProjectVersion() );
355 metadata.setIssueManagement( convertIssueManagement( model.getIssueManagement() ) );
356 metadata.setLicenses( convertLicenses( model.getLicenses() ) );
357 metadata.setMailingLists( convertMailingLists( model.getMailingLists() ) );
358 metadata.setDependencies( convertDependencies( model.getDependencies() ) );
359 metadata.setName( model.getName() );
360 metadata.setOrganization( convertOrganization( model.getOrganization() ) );
361 metadata.setScm( convertScm( model.getScm() ) );
362 metadata.setUrl( model.getUrl() );
364 MavenProjectFacet facet = new MavenProjectFacet();
365 facet.setGroupId( model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId() );
366 facet.setArtifactId( model.getArtifactId() );
367 facet.setPackaging( model.getPackaging() );
368 if ( model.getParent() != null )
370 MavenProjectParent parent = new MavenProjectParent();
371 parent.setGroupId( model.getParent().getGroupId() );
372 parent.setArtifactId( model.getParent().getArtifactId() );
373 parent.setVersion( model.getParent().getVersion() );
374 facet.setParent( parent );
376 metadata.addFacet( facet );
380 catch ( RepositoryAdminException e )
382 throw new RepositoryStorageRuntimeException( "repo-admin", e.getMessage() );
386 public void setWagonFactory( WagonFactory wagonFactory )
388 this.wagonFactory = wagonFactory;
391 private List<org.apache.archiva.metadata.model.Dependency> convertDependencies( List<Dependency> dependencies )
393 List<org.apache.archiva.metadata.model.Dependency> l =
394 new ArrayList<org.apache.archiva.metadata.model.Dependency>();
395 for ( Dependency dependency : dependencies )
397 org.apache.archiva.metadata.model.Dependency newDependency =
398 new org.apache.archiva.metadata.model.Dependency();
399 newDependency.setArtifactId( dependency.getArtifactId() );
400 newDependency.setClassifier( dependency.getClassifier() );
401 newDependency.setGroupId( dependency.getGroupId() );
402 newDependency.setOptional( dependency.isOptional() );
403 newDependency.setScope( dependency.getScope() );
404 newDependency.setSystemPath( dependency.getSystemPath() );
405 newDependency.setType( dependency.getType() );
406 newDependency.setVersion( dependency.getVersion() );
407 l.add( newDependency );
412 private org.apache.archiva.metadata.model.Scm convertScm( Scm scm )
414 org.apache.archiva.metadata.model.Scm newScm = null;
417 newScm = new org.apache.archiva.metadata.model.Scm();
418 newScm.setConnection( scm.getConnection() );
419 newScm.setDeveloperConnection( scm.getDeveloperConnection() );
420 newScm.setUrl( scm.getUrl() );
425 private org.apache.archiva.metadata.model.Organization convertOrganization( Organization organization )
427 org.apache.archiva.metadata.model.Organization org = null;
428 if ( organization != null )
430 org = new org.apache.archiva.metadata.model.Organization();
431 org.setName( organization.getName() );
432 org.setUrl( organization.getUrl() );
437 private List<org.apache.archiva.metadata.model.License> convertLicenses( List<License> licenses )
439 List<org.apache.archiva.metadata.model.License> l = new ArrayList<org.apache.archiva.metadata.model.License>();
440 for ( License license : licenses )
442 org.apache.archiva.metadata.model.License newLicense = new org.apache.archiva.metadata.model.License();
443 newLicense.setName( license.getName() );
444 newLicense.setUrl( license.getUrl() );
450 private List<org.apache.archiva.metadata.model.MailingList> convertMailingLists( List<MailingList> mailingLists )
452 List<org.apache.archiva.metadata.model.MailingList> l =
453 new ArrayList<org.apache.archiva.metadata.model.MailingList>();
454 for ( MailingList mailingList : mailingLists )
456 org.apache.archiva.metadata.model.MailingList newMailingList =
457 new org.apache.archiva.metadata.model.MailingList();
458 newMailingList.setName( mailingList.getName() );
459 newMailingList.setMainArchiveUrl( mailingList.getArchive() );
460 newMailingList.setPostAddress( mailingList.getPost() );
461 newMailingList.setSubscribeAddress( mailingList.getSubscribe() );
462 newMailingList.setUnsubscribeAddress( mailingList.getUnsubscribe() );
463 newMailingList.setOtherArchives( mailingList.getOtherArchives() );
464 l.add( newMailingList );
469 private org.apache.archiva.metadata.model.IssueManagement convertIssueManagement( IssueManagement issueManagement )
471 org.apache.archiva.metadata.model.IssueManagement im = null;
472 if ( issueManagement != null )
474 im = new org.apache.archiva.metadata.model.IssueManagement();
475 im.setSystem( issueManagement.getSystem() );
476 im.setUrl( issueManagement.getUrl() );
481 private org.apache.archiva.metadata.model.CiManagement convertCiManagement( CiManagement ciManagement )
483 org.apache.archiva.metadata.model.CiManagement ci = null;
484 if ( ciManagement != null )
486 ci = new org.apache.archiva.metadata.model.CiManagement();
487 ci.setSystem( ciManagement.getSystem() );
488 ci.setUrl( ciManagement.getUrl() );
493 public Collection<String> listRootNamespaces( String repoId, Filter<String> filter )
494 throws RepositoryStorageRuntimeException
496 File dir = getRepositoryBasedir( repoId );
498 return getSortedFiles( dir, filter );
501 private static Collection<String> getSortedFiles( File dir, Filter<String> filter )
503 List<String> fileNames;
504 String[] files = dir.list( new DirectoryFilter( filter ) );
507 fileNames = new ArrayList<String>( Arrays.asList( files ) );
508 Collections.sort( fileNames );
512 fileNames = Collections.emptyList();
517 private File getRepositoryBasedir( String repoId )
518 throws RepositoryStorageRuntimeException
522 ManagedRepository repositoryConfiguration = managedRepositoryAdmin.getManagedRepository( repoId );
524 return new File( repositoryConfiguration.getLocation() );
526 catch ( RepositoryAdminException e )
528 throw new RepositoryStorageRuntimeException( "repo-admin", e.getMessage() );
532 public Collection<String> listNamespaces( String repoId, String namespace, Filter<String> filter )
533 throws RepositoryStorageRuntimeException
535 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace );
537 // scan all the directories which are potential namespaces. Any directories known to be projects are excluded
538 List<String> namespaces = new ArrayList<String>();
539 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
542 for ( File file : files )
544 if ( !isProject( file, filter ) )
546 namespaces.add( file.getName() );
550 Collections.sort( namespaces );
554 public Collection<String> listProjects( String repoId, String namespace, Filter<String> filter )
555 throws RepositoryStorageRuntimeException
557 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace );
559 // scan all directories in the namespace, and only include those that are known to be projects
560 List<String> projects = new ArrayList<String>();
561 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
564 for ( File file : files )
566 if ( isProject( file, filter ) )
568 projects.add( file.getName() );
572 Collections.sort( projects );
576 public Collection<String> listProjectVersions( String repoId, String namespace, String projectId,
577 Filter<String> filter )
578 throws RepositoryStorageRuntimeException
580 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace, projectId );
582 // all directories in a project directory can be considered a version
583 return getSortedFiles( dir, filter );
586 public Collection<ArtifactMetadata> readArtifactsMetadata( ReadMetadataRequest readMetadataRequest )
587 throws RepositoryStorageRuntimeException
589 File dir = pathTranslator.toFile( getRepositoryBasedir( readMetadataRequest.getRepositoryId() ),
590 readMetadataRequest.getNamespace(), readMetadataRequest.getProjectId(),
591 readMetadataRequest.getProjectVersion() );
593 // all files that are not metadata and not a checksum / signature are considered artifacts
594 File[] files = dir.listFiles( new ArtifactDirectoryFilter( readMetadataRequest.getFilter() ) );
596 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
599 for ( File file : files )
601 ArtifactMetadata metadata =
602 getArtifactFromFile( readMetadataRequest.getRepositoryId(), readMetadataRequest.getNamespace(),
603 readMetadataRequest.getProjectId(), readMetadataRequest.getProjectVersion(),
605 artifacts.add( metadata );
611 public ArtifactMetadata readArtifactMetadataFromPath( String repoId, String path )
612 throws RepositoryStorageRuntimeException
614 ArtifactMetadata metadata = pathTranslator.getArtifactForPath( repoId, path );
616 populateArtifactMetadataFromFile( metadata, new File( getRepositoryBasedir( repoId ), path ) );
621 private ArtifactMetadata getArtifactFromFile( String repoId, String namespace, String projectId,
622 String projectVersion, File file )
624 ArtifactMetadata metadata =
625 pathTranslator.getArtifactFromId( repoId, namespace, projectId, projectVersion, file.getName() );
627 populateArtifactMetadataFromFile( metadata, file );
632 public void applyServerSideRelocation( ManagedRepositoryContent managedRepository, ArtifactReference artifact )
633 throws ProxyDownloadException
635 if ( "pom".equals( artifact.getType() ) )
640 // Build the artifact POM reference
641 ArtifactReference pomReference = new ArtifactReference();
642 pomReference.setGroupId( artifact.getGroupId() );
643 pomReference.setArtifactId( artifact.getArtifactId() );
644 pomReference.setVersion( artifact.getVersion() );
645 pomReference.setType( "pom" );
647 // Get the artifact POM from proxied repositories if needed
648 connectors.fetchFromProxies( managedRepository, pomReference );
650 // Open and read the POM from the managed repo
651 File pom = managedRepository.toFile( pomReference );
660 // MavenXpp3Reader leaves the file open, so we need to close it ourselves.
661 FileReader reader = new FileReader( pom );
665 model = MAVEN_XPP_3_READER.read( reader );
669 if ( reader != null )
675 DistributionManagement dist = model.getDistributionManagement();
678 Relocation relocation = dist.getRelocation();
679 if ( relocation != null )
681 // artifact is relocated : update the repositoryPath
682 if ( relocation.getGroupId() != null )
684 artifact.setGroupId( relocation.getGroupId() );
686 if ( relocation.getArtifactId() != null )
688 artifact.setArtifactId( relocation.getArtifactId() );
690 if ( relocation.getVersion() != null )
692 artifact.setVersion( relocation.getVersion() );
697 catch ( FileNotFoundException e )
699 // Artifact has no POM in repo : ignore
701 catch ( IOException e )
703 // Unable to read POM : ignore.
705 catch ( XmlPullParserException e )
707 // Invalid POM : ignore
711 //-----------------------------
713 //-----------------------------
714 private static void populateArtifactMetadataFromFile( ArtifactMetadata metadata, File file )
716 metadata.setWhenGathered( new Date() );
717 metadata.setFileLastModified( file.lastModified() );
718 ChecksummedFile checksummedFile = new ChecksummedFile( file );
721 metadata.setMd5( checksummedFile.calculateChecksum( ChecksumAlgorithm.MD5 ) );
723 catch ( IOException e )
725 log.error( "Unable to checksum file {}: {},MD5", file, e.getMessage() );
729 metadata.setSha1( checksummedFile.calculateChecksum( ChecksumAlgorithm.SHA1 ) );
731 catch ( IOException e )
733 log.error( "Unable to checksum file {}: {},SHA1", file, e.getMessage() );
735 metadata.setSize( file.length() );
738 private boolean isProject( File dir, Filter<String> filter )
740 // scan directories for a valid project version subdirectory, meaning this must be a project directory
741 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
744 for ( File file : files )
746 if ( isProjectVersion( file ) )
753 // if a metadata file is present, check if this is the "artifactId" directory, marking it as a project
754 ArchivaRepositoryMetadata metadata = readMetadata( dir );
755 if ( metadata != null && dir.getName().equals( metadata.getArtifactId() ) )
763 private boolean isProjectVersion( File dir )
765 final String artifactId = dir.getParentFile().getName();
766 final String projectVersion = dir.getName();
768 // check if there is a POM artifact file to ensure it is a version directory
770 if ( VersionUtil.isSnapshot( projectVersion ) )
772 files = dir.listFiles( new PomFilenameFilter( artifactId, projectVersion ) );
776 final String pomFile = artifactId + "-" + projectVersion + ".pom";
777 files = dir.listFiles( new PomFileFilter( pomFile ) );
779 if ( files != null && files.length > 0 )
784 // if a metadata file is present, check if this is the "version" directory, marking it as a project version
785 ArchivaRepositoryMetadata metadata = readMetadata( dir );
786 if ( metadata != null && projectVersion.equals( metadata.getVersion() ) )
794 private ArchivaRepositoryMetadata readMetadata( File directory )
796 ArchivaRepositoryMetadata metadata = null;
797 File metadataFile = new File( directory, METADATA_FILENAME );
798 if ( metadataFile.exists() )
802 metadata = MavenMetadataReader.read( metadataFile );
804 catch ( XMLException e )
806 // ignore missing or invalid metadata
812 private static class DirectoryFilter
813 implements FilenameFilter
815 private final Filter<String> filter;
817 public DirectoryFilter( Filter<String> filter )
819 this.filter = filter;
822 public boolean accept( File dir, String name )
824 if ( !filter.accept( name ) )
828 else if ( name.startsWith( "." ) )
832 else if ( !new File( dir, name ).isDirectory() )
840 private class ArtifactDirectoryFilter
841 implements FilenameFilter
843 private final Filter<String> filter;
845 public ArtifactDirectoryFilter( Filter<String> filter )
847 this.filter = filter;
850 public boolean accept( File dir, String name )
852 // TODO compare to logic in maven-repository-layer
853 if ( !filter.accept( name ) )
857 else if ( name.startsWith( "." ) )
861 else if ( name.endsWith( ".md5" ) || name.endsWith( ".sha1" ) || name.endsWith( ".asc" ) )
865 else if ( name.equals( METADATA_FILENAME ) )
869 else if ( new File( dir, name ).isDirectory() )
873 // some files from remote repositories can have name like maven-metadata-archiva-vm-all-public.xml
874 else if ( StringUtils.startsWith( name, METADATA_FILENAME_START ) && StringUtils.endsWith( name, ".xml" ) )
884 private static class PomFilenameFilter
885 implements FilenameFilter
888 private final String artifactId, projectVersion;
890 private PomFilenameFilter( String artifactId, String projectVersion )
892 this.artifactId = artifactId;
893 this.projectVersion = projectVersion;
896 public boolean accept( File dir, String name )
898 if ( name.startsWith( artifactId + "-" ) && name.endsWith( ".pom" ) )
900 String v = name.substring( artifactId.length() + 1, name.length() - 4 );
901 v = VersionUtil.getBaseVersion( v );
902 if ( v.equals( projectVersion ) )
911 private static class PomFileFilter
912 implements FilenameFilter
914 private final String pomFile;
916 private PomFileFilter( String pomFile )
918 this.pomFile = pomFile;
921 public boolean accept( File dir, String name )
923 return pomFile.equals( name );