1 package org.apache.archiva.repository.metadata;
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.checksum.ChecksumAlgorithm;
23 import org.apache.archiva.checksum.ChecksummedFile;
24 import org.apache.archiva.common.utils.PathUtil;
25 import org.apache.archiva.common.utils.VersionComparator;
26 import org.apache.archiva.common.utils.VersionUtil;
27 import org.apache.archiva.configuration.ArchivaConfiguration;
28 import org.apache.archiva.configuration.ConfigurationNames;
29 import org.apache.archiva.configuration.FileTypes;
30 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
31 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
32 import org.apache.archiva.model.ArchivaRepositoryMetadata;
33 import org.apache.archiva.model.ArtifactReference;
34 import org.apache.archiva.model.Plugin;
35 import org.apache.archiva.model.ProjectReference;
36 import org.apache.archiva.model.SnapshotVersion;
37 import org.apache.archiva.model.VersionedReference;
38 import org.apache.archiva.redback.components.registry.Registry;
39 import org.apache.archiva.redback.components.registry.RegistryListener;
40 import org.apache.archiva.repository.ContentNotFoundException;
41 import org.apache.archiva.repository.ManagedRepositoryContent;
42 import org.apache.archiva.repository.RemoteRepositoryContent;
43 import org.apache.archiva.repository.layout.LayoutException;
44 import org.apache.archiva.xml.XMLException;
45 import org.apache.commons.collections.CollectionUtils;
46 import org.apache.commons.io.FileUtils;
47 import org.apache.commons.lang.StringUtils;
48 import org.apache.commons.lang.math.NumberUtils;
49 import org.apache.commons.lang.time.DateUtils;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.springframework.stereotype.Service;
54 import javax.annotation.PostConstruct;
55 import javax.inject.Inject;
56 import javax.inject.Named;
58 import java.io.IOException;
59 import java.text.ParseException;
60 import java.text.SimpleDateFormat;
61 import java.util.ArrayList;
62 import java.util.Calendar;
63 import java.util.Collection;
64 import java.util.Collections;
65 import java.util.Date;
66 import java.util.HashMap;
67 import java.util.HashSet;
68 import java.util.Iterator;
69 import java.util.LinkedHashSet;
70 import java.util.List;
73 import java.util.regex.Matcher;
80 @Service( "metadataTools#default" )
81 public class MetadataTools
82 implements RegistryListener
84 private Logger log = LoggerFactory.getLogger( getClass() );
86 public static final String MAVEN_METADATA = "maven-metadata.xml";
88 private static final char PATH_SEPARATOR = '/';
90 private static final char GROUP_SEPARATOR = '.';
96 @Named( value = "archivaConfiguration#default" )
97 private ArchivaConfiguration configuration;
103 @Named( value = "fileTypes" )
104 private FileTypes filetypes;
106 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
108 private List<String> artifactPatterns;
110 private Map<String, Set<String>> proxies;
112 private static final char NUMS[] = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
114 private SimpleDateFormat lastUpdatedFormat;
116 public MetadataTools()
118 lastUpdatedFormat = new SimpleDateFormat( "yyyyMMddHHmmss" );
119 lastUpdatedFormat.setTimeZone( DateUtils.UTC_TIME_ZONE );
122 public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
124 if ( ConfigurationNames.isProxyConnector( propertyName ) )
126 initConfigVariables();
130 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
136 * Gather the set of snapshot versions found in a particular versioned reference.
138 * @return the Set of snapshot artifact versions found.
139 * @throws LayoutException
140 * @throws ContentNotFoundException
142 public Set<String> gatherSnapshotVersions( ManagedRepositoryContent managedRepository,
143 VersionedReference reference )
144 throws LayoutException, IOException, ContentNotFoundException
146 Set<String> foundVersions = managedRepository.getVersions( reference );
148 // Next gather up the referenced 'latest' versions found in any proxied repositories
149 // maven-metadata-${proxyId}.xml files that may be present.
151 // Does this repository have a set of remote proxied repositories?
152 Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
154 if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
156 String baseVersion = VersionUtil.getBaseVersion( reference.getVersion() );
157 baseVersion = baseVersion.substring( 0, baseVersion.indexOf( VersionUtil.SNAPSHOT ) - 1 );
159 // Add in the proxied repo version ids too.
160 Iterator<String> it = proxiedRepoIds.iterator();
161 while ( it.hasNext() )
163 String proxyId = it.next();
165 ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
166 if ( proxyMetadata == null )
168 // There is no proxy metadata, skip it.
172 // Is there some snapshot info?
173 SnapshotVersion snapshot = proxyMetadata.getSnapshotVersion();
174 if ( snapshot != null )
176 String timestamp = snapshot.getTimestamp();
177 int buildNumber = snapshot.getBuildNumber();
179 // Only interested in the timestamp + buildnumber.
180 if ( StringUtils.isNotBlank( timestamp ) && ( buildNumber > 0 ) )
182 foundVersions.add( baseVersion + "-" + timestamp + "-" + buildNumber );
188 return foundVersions;
192 * Take a path to a maven-metadata.xml, and attempt to translate it to a VersionedReference.
197 public VersionedReference toVersionedReference( String path )
198 throws RepositoryMetadataException
200 if ( !path.endsWith( "/" + MAVEN_METADATA ) )
202 throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " );
205 VersionedReference reference = new VersionedReference();
207 String normalizedPath = StringUtils.replace( path, "\\", "/" );
208 String pathParts[] = StringUtils.split( normalizedPath, '/' );
210 int versionOffset = pathParts.length - 2;
211 int artifactIdOffset = versionOffset - 1;
212 int groupIdEnd = artifactIdOffset - 1;
214 reference.setVersion( pathParts[versionOffset] );
216 if ( !hasNumberAnywhere( reference.getVersion() ) )
218 // Scary check, but without it, all paths are version references;
219 throw new RepositoryMetadataException(
220 "Not a versioned reference, as version id on path has no number in it." );
223 reference.setArtifactId( pathParts[artifactIdOffset] );
225 StringBuilder gid = new StringBuilder();
226 for ( int i = 0; i <= groupIdEnd; i++ )
232 gid.append( pathParts[i] );
235 reference.setGroupId( gid.toString() );
240 private boolean hasNumberAnywhere( String version )
242 return StringUtils.indexOfAny( version, NUMS ) != ( -1 );
245 public ProjectReference toProjectReference( String path )
246 throws RepositoryMetadataException
248 if ( !path.endsWith( "/" + MAVEN_METADATA ) )
250 throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " );
253 ProjectReference reference = new ProjectReference();
255 String normalizedPath = StringUtils.replace( path, "\\", "/" );
256 String pathParts[] = StringUtils.split( normalizedPath, '/' );
258 // Assume last part of the path is the version.
260 int artifactIdOffset = pathParts.length - 2;
261 int groupIdEnd = artifactIdOffset - 1;
263 reference.setArtifactId( pathParts[artifactIdOffset] );
265 StringBuilder gid = new StringBuilder();
266 for ( int i = 0; i <= groupIdEnd; i++ )
272 gid.append( pathParts[i] );
275 reference.setGroupId( gid.toString() );
280 public String toPath( ProjectReference reference )
282 StringBuilder path = new StringBuilder();
284 path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR );
285 path.append( reference.getArtifactId() ).append( PATH_SEPARATOR );
286 path.append( MAVEN_METADATA );
288 return path.toString();
291 public String toPath( VersionedReference reference )
293 StringBuilder path = new StringBuilder();
295 path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR );
296 path.append( reference.getArtifactId() ).append( PATH_SEPARATOR );
297 if ( reference.getVersion() != null )
299 // add the version only if it is present
300 path.append( VersionUtil.getBaseVersion( reference.getVersion() ) ).append( PATH_SEPARATOR );
302 path.append( MAVEN_METADATA );
304 return path.toString();
307 private String formatAsDirectory( String directory )
309 return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
313 * Adjusts a path for a metadata.xml file to its repository specific path.
315 * @param repository the repository to base new path off of.
316 * @param path the path to the metadata.xml file to adjust the name of.
317 * @return the newly adjusted path reference to the repository specific metadata path.
319 public String getRepositorySpecificName( RemoteRepositoryContent repository, String path )
321 return getRepositorySpecificName( repository.getId(), path );
325 * Adjusts a path for a metadata.xml file to its repository specific path.
327 * @param proxyId the repository id to base new path off of.
328 * @param path the path to the metadata.xml file to adjust the name of.
329 * @return the newly adjusted path reference to the repository specific metadata path.
331 public String getRepositorySpecificName( String proxyId, String path )
333 StringBuilder ret = new StringBuilder();
335 int idx = path.lastIndexOf( "/" );
338 ret.append( path.substring( 0, idx + 1 ) );
341 // TODO: need to filter out 'bad' characters from the proxy id.
342 ret.append( "maven-metadata-" ).append( proxyId ).append( ".xml" );
344 return ret.toString();
348 public void initialize()
350 this.artifactPatterns = new ArrayList<String>();
351 this.proxies = new HashMap<String, Set<String>>();
352 initConfigVariables();
354 configuration.addChangeListener( this );
357 public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
358 ProjectReference reference, String proxyId )
360 String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) );
361 File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
363 if ( !metadataFile.exists() || !metadataFile.isFile() )
365 // Nothing to do. return null.
371 return MavenMetadataReader.read( metadataFile );
373 catch ( XMLException e )
375 // TODO: [monitor] consider a monitor for this event.
376 // TODO: consider a read-redo on monitor return code?
377 log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
382 public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
383 String logicalResource, String proxyId )
385 String metadataPath = getRepositorySpecificName( proxyId, logicalResource );
386 File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
388 if ( !metadataFile.exists() || !metadataFile.isFile() )
390 // Nothing to do. return null.
396 return MavenMetadataReader.read( metadataFile );
398 catch ( XMLException e )
400 // TODO: [monitor] consider a monitor for this event.
401 // TODO: consider a read-redo on monitor return code?
402 log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
407 public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
408 VersionedReference reference, String proxyId )
410 String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) );
411 File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
413 if ( !metadataFile.exists() || !metadataFile.isFile() )
415 // Nothing to do. return null.
421 return MavenMetadataReader.read( metadataFile );
423 catch ( XMLException e )
425 // TODO: [monitor] consider a monitor for this event.
426 // TODO: consider a read-redo on monitor return code?
427 log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
432 public void updateMetadata( ManagedRepositoryContent managedRepository, String logicalResource )
433 throws RepositoryMetadataException
435 final File metadataFile = new File( managedRepository.getRepoRoot(), logicalResource );
436 ArchivaRepositoryMetadata metadata = null;
438 //Gather and merge all metadata available
439 List<ArchivaRepositoryMetadata> metadatas =
440 getMetadatasForManagedRepository( managedRepository, logicalResource );
441 for ( ArchivaRepositoryMetadata proxiedMetadata : metadatas )
443 if ( metadata == null )
445 metadata = proxiedMetadata;
448 metadata = RepositoryMetadataMerge.merge( metadata, proxiedMetadata );
451 if ( metadata == null )
453 log.debug( "No metadata to update for {}", logicalResource );
457 Set<String> availableVersions = new HashSet<String>();
458 List<String> metadataAvailableVersions = metadata.getAvailableVersions();
459 if ( metadataAvailableVersions != null )
461 availableVersions.addAll( metadataAvailableVersions );
463 availableVersions = findPossibleVersions( availableVersions, metadataFile.getParentFile() );
465 if ( availableVersions.size() > 0 )
467 updateMetadataVersions( availableVersions, metadata );
470 RepositoryMetadataWriter.write( metadata, metadataFile );
472 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
473 checksum.fixChecksums( algorithms );
477 * Skims the parent directory of a metadata in vain hope of finding
478 * subdirectories that contain poms.
480 * @param metadataParentDirectory
481 * @return origional set plus newley found versions
483 private Set<String> findPossibleVersions( Set<String> versions, File metadataParentDirectory )
485 Set<String> result = new HashSet<String>( versions );
486 for ( File directory : metadataParentDirectory.listFiles() )
488 if ( directory.isDirectory() )
490 for ( File possiblePom : directory.listFiles() )
492 if ( possiblePom.getName().endsWith( ".pom" ) )
494 result.add( directory.getName() );
502 private List<ArchivaRepositoryMetadata> getMetadatasForManagedRepository(
503 ManagedRepositoryContent managedRepository, String logicalResource )
505 List<ArchivaRepositoryMetadata> metadatas = new ArrayList<ArchivaRepositoryMetadata>();
506 File file = new File( managedRepository.getRepoRoot(), logicalResource );
511 ArchivaRepositoryMetadata existingMetadata = MavenMetadataReader.read( file );
512 if ( existingMetadata != null )
514 metadatas.add( existingMetadata );
517 catch ( XMLException e )
519 log.debug( "Could not read metadata at {}. Metadata will be removed.", file.getAbsolutePath() );
520 FileUtils.deleteQuietly( file );
524 Set<String> proxyIds = proxies.get( managedRepository.getId() );
525 if ( proxyIds != null )
527 for ( String proxyId : proxyIds )
529 ArchivaRepositoryMetadata proxyMetadata =
530 readProxyMetadata( managedRepository, logicalResource, proxyId );
531 if ( proxyMetadata != null )
533 metadatas.add( proxyMetadata );
543 * Update the metadata to represent the all versions/plugins of
544 * the provided groupId:artifactId project or group reference,
545 * based off of information present in the repository,
546 * the maven-metadata.xml files, and the proxy/repository specific
547 * metadata file contents.
549 * We must treat this as a group or a project metadata file as there is no way to know in advance
551 * @param managedRepository the managed repository where the metadata is kept.
552 * @param reference the reference to update.
553 * @throws LayoutException
554 * @throws RepositoryMetadataException
555 * @throws IOException
556 * @throws ContentNotFoundException
559 public void updateMetadata( ManagedRepositoryContent managedRepository, ProjectReference reference )
560 throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
562 File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) );
564 long lastUpdated = getExistingLastUpdated( metadataFile );
566 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
567 metadata.setGroupId( reference.getGroupId() );
568 metadata.setArtifactId( reference.getArtifactId() );
570 // Gather up all versions found in the managed repository.
571 Set<String> allVersions = managedRepository.getVersions( reference );
573 // Gather up all plugins found in the managed repository.
574 // TODO: do we know this information instead?
575 // Set<Plugin> allPlugins = managedRepository.getPlugins( reference );
576 Set<Plugin> allPlugins;
577 if ( metadataFile.exists() )
581 allPlugins = new LinkedHashSet<Plugin>( MavenMetadataReader.read( metadataFile ).getPlugins() );
583 catch ( XMLException e )
585 throw new RepositoryMetadataException( e.getMessage(), e );
590 allPlugins = new LinkedHashSet<Plugin>();
593 // Does this repository have a set of remote proxied repositories?
594 Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
596 if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
598 // Add in the proxied repo version ids too.
599 Iterator<String> it = proxiedRepoIds.iterator();
600 while ( it.hasNext() )
602 String proxyId = it.next();
604 ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
605 if ( proxyMetadata != null )
607 allVersions.addAll( proxyMetadata.getAvailableVersions() );
608 allPlugins.addAll( proxyMetadata.getPlugins() );
609 long proxyLastUpdated = getLastUpdated( proxyMetadata );
611 lastUpdated = Math.max( lastUpdated, proxyLastUpdated );
616 if ( !allVersions.isEmpty() )
618 updateMetadataVersions( allVersions, metadata );
622 // Add the plugins to the metadata model.
623 metadata.setPlugins( new ArrayList<Plugin>( allPlugins ) );
625 // artifact ID was actually the last part of the group
626 metadata.setGroupId( metadata.getGroupId() + "." + metadata.getArtifactId() );
627 metadata.setArtifactId( null );
630 if ( lastUpdated > 0 )
632 metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
635 // Save the metadata model to disk.
636 RepositoryMetadataWriter.write( metadata, metadataFile );
637 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
638 checksum.fixChecksums( algorithms );
641 private void updateMetadataVersions( Collection<String> allVersions, ArchivaRepositoryMetadata metadata )
644 List<String> sortedVersions = new ArrayList<String>( allVersions );
645 Collections.sort( sortedVersions, VersionComparator.getInstance() );
647 // Split the versions into released and snapshots.
648 List<String> releasedVersions = new ArrayList<String>();
649 List<String> snapshotVersions = new ArrayList<String>();
651 for ( String version : sortedVersions )
653 if ( VersionUtil.isSnapshot( version ) )
655 snapshotVersions.add( version );
659 releasedVersions.add( version );
663 Collections.sort( releasedVersions, VersionComparator.getInstance() );
664 Collections.sort( snapshotVersions, VersionComparator.getInstance() );
666 String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
667 String releaseVersion = null;
669 if ( CollectionUtils.isNotEmpty( releasedVersions ) )
671 releaseVersion = releasedVersions.get( releasedVersions.size() - 1 );
674 // Add the versions to the metadata model.
675 metadata.setAvailableVersions( sortedVersions );
677 metadata.setLatestVersion( latestVersion );
678 metadata.setReleasedVersion( releaseVersion );
681 private Date toLastUpdatedDate( long lastUpdated )
683 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
684 cal.setTimeInMillis( lastUpdated );
686 return cal.getTime();
689 private long toLastUpdatedLong( String timestampString )
693 Date date = lastUpdatedFormat.parse( timestampString );
694 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
697 return cal.getTimeInMillis();
699 catch ( ParseException e )
705 private long getLastUpdated( ArchivaRepositoryMetadata metadata )
707 if ( metadata == null )
715 String lastUpdated = metadata.getLastUpdated();
716 if ( StringUtils.isBlank( lastUpdated ) )
722 Date lastUpdatedDate = lastUpdatedFormat.parse( lastUpdated );
723 return lastUpdatedDate.getTime();
725 catch ( ParseException e )
727 // Bad format on the last updated string.
732 private long getExistingLastUpdated( File metadataFile )
734 if ( !metadataFile.exists() )
742 ArchivaRepositoryMetadata metadata = MavenMetadataReader.read( metadataFile );
744 return getLastUpdated( metadata );
746 catch ( XMLException e )
754 * Update the metadata based on the following rules.
756 * 1) If this is a SNAPSHOT reference, then utilize the proxy/repository specific
757 * metadata files to represent the current / latest SNAPSHOT available.
758 * 2) If this is a RELEASE reference, and the metadata file does not exist, then
759 * create the metadata file with contents required of the VersionedReference
761 * @param managedRepository the managed repository where the metadata is kept.
762 * @param reference the versioned reference to update
763 * @throws LayoutException
764 * @throws RepositoryMetadataException
765 * @throws IOException
766 * @throws ContentNotFoundException
769 public void updateMetadata( ManagedRepositoryContent managedRepository, VersionedReference reference )
770 throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
772 File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) );
774 long lastUpdated = getExistingLastUpdated( metadataFile );
776 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
777 metadata.setGroupId( reference.getGroupId() );
778 metadata.setArtifactId( reference.getArtifactId() );
780 if ( VersionUtil.isSnapshot( reference.getVersion() ) )
782 // Do SNAPSHOT handling.
783 metadata.setVersion( VersionUtil.getBaseVersion( reference.getVersion() ) );
785 // Gather up all of the versions found in the reference dir, and any
786 // proxied maven-metadata.xml files.
787 Set<String> snapshotVersions = gatherSnapshotVersions( managedRepository, reference );
789 if ( snapshotVersions.isEmpty() )
791 throw new ContentNotFoundException(
792 "No snapshot versions found on reference [" + VersionedReference.toKey( reference ) + "]." );
795 // sort the list to determine to aide in determining the Latest version.
796 List<String> sortedVersions = new ArrayList<String>();
797 sortedVersions.addAll( snapshotVersions );
798 Collections.sort( sortedVersions, new VersionComparator() );
800 String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
802 if ( VersionUtil.isUniqueSnapshot( latestVersion ) )
804 // The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
805 // This needs to be broken down into ${base}-${timestamp}-${build_number}
807 Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( latestVersion );
810 metadata.setSnapshotVersion( new SnapshotVersion() );
811 int buildNumber = NumberUtils.toInt( m.group( 3 ), -1 );
812 metadata.getSnapshotVersion().setBuildNumber( buildNumber );
814 Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
815 if ( mtimestamp.matches() )
817 String tsDate = mtimestamp.group( 1 );
818 String tsTime = mtimestamp.group( 2 );
820 long snapshotLastUpdated = toLastUpdatedLong( tsDate + tsTime );
822 lastUpdated = Math.max( lastUpdated, snapshotLastUpdated );
824 metadata.getSnapshotVersion().setTimestamp( m.group( 2 ) );
828 else if ( VersionUtil.isGenericSnapshot( latestVersion ) )
830 // The latestVersion ends with the generic version string.
831 // Example: 1.0-alpha-5-SNAPSHOT
833 metadata.setSnapshotVersion( new SnapshotVersion() );
835 /* Disabled due to decision in [MRM-535].
836 * Do not set metadata.lastUpdated to file.lastModified.
838 * Should this be the last updated timestamp of the file, or in the case of an
839 * archive, the most recent timestamp in the archive?
841 ArtifactReference artifact = getFirstArtifact( managedRepository, reference );
843 if ( artifact == null )
845 throw new IOException( "Not snapshot artifact found to reference in " + reference );
848 File artifactFile = managedRepository.toFile( artifact );
850 if ( artifactFile.exists() )
852 Date lastModified = new Date( artifactFile.lastModified() );
853 metadata.setLastUpdatedTimestamp( lastModified );
859 throw new RepositoryMetadataException(
860 "Unable to process snapshot version <" + latestVersion + "> reference <" + reference + ">" );
865 // Do RELEASE handling.
866 metadata.setVersion( reference.getVersion() );
870 if ( lastUpdated > 0 )
872 metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
875 // Save the metadata model to disk.
876 RepositoryMetadataWriter.write( metadata, metadataFile );
877 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
878 checksum.fixChecksums( algorithms );
881 private void initConfigVariables()
883 synchronized ( this.artifactPatterns )
885 this.artifactPatterns.clear();
887 this.artifactPatterns.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
890 synchronized ( proxies )
892 this.proxies.clear();
894 List<ProxyConnectorConfiguration> proxyConfigs = configuration.getConfiguration().getProxyConnectors();
895 for ( ProxyConnectorConfiguration proxyConfig : proxyConfigs )
897 String key = proxyConfig.getSourceRepoId();
899 Set<String> remoteRepoIds = this.proxies.get( key );
901 if ( remoteRepoIds == null )
903 remoteRepoIds = new HashSet<String>();
906 remoteRepoIds.add( proxyConfig.getTargetRepoId() );
908 this.proxies.put( key, remoteRepoIds );
914 * Get the first Artifact found in the provided VersionedReference location.
916 * @param managedRepository the repository to search within.
917 * @param reference the reference to the versioned reference to search within
918 * @return the ArtifactReference to the first artifact located within the versioned reference. or null if
919 * no artifact was found within the versioned reference.
920 * @throws IOException if the versioned reference is invalid (example: doesn't exist, or isn't a directory)
921 * @throws LayoutException
923 public ArtifactReference getFirstArtifact( ManagedRepositoryContent managedRepository,
924 VersionedReference reference )
925 throws LayoutException, IOException
927 String path = toPath( reference );
929 int idx = path.lastIndexOf( '/' );
932 path = path.substring( 0, idx );
935 File repoDir = new File( managedRepository.getRepoRoot(), path );
937 if ( !repoDir.exists() )
939 throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: "
940 + repoDir.getAbsolutePath() );
943 if ( !repoDir.isDirectory() )
945 throw new IOException(
946 "Unable to gather the list of snapshot versions on a non-directory: " + repoDir.getAbsolutePath() );
949 File repoFiles[] = repoDir.listFiles();
950 for ( int i = 0; i < repoFiles.length; i++ )
952 if ( repoFiles[i].isDirectory() )
954 // Skip it. it's a directory.
958 String relativePath = PathUtil.getRelative( managedRepository.getRepoRoot(), repoFiles[i] );
960 if ( filetypes.matchesArtifactPattern( relativePath ) )
962 ArtifactReference artifact = managedRepository.toArtifactReference( relativePath );
968 // No artifact was found.
972 public ArchivaConfiguration getConfiguration()
974 return configuration;
977 public void setConfiguration( ArchivaConfiguration configuration )
979 this.configuration = configuration;
982 public FileTypes getFiletypes()
987 public void setFiletypes( FileTypes filetypes )
989 this.filetypes = filetypes;