1 package org.apache.maven.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.commons.collections.CollectionUtils;
25 import org.apache.commons.io.FileUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.lang.math.NumberUtils;
28 import org.apache.commons.lang.time.DateUtils;
29 import org.apache.maven.archiva.common.utils.PathUtil;
30 import org.apache.maven.archiva.common.utils.VersionComparator;
31 import org.apache.maven.archiva.common.utils.VersionUtil;
32 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
33 import org.apache.maven.archiva.configuration.ConfigurationNames;
34 import org.apache.maven.archiva.configuration.FileTypes;
35 import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration;
36 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
37 import org.apache.maven.archiva.model.ArtifactReference;
38 import org.apache.maven.archiva.model.Plugin;
39 import org.apache.maven.archiva.model.ProjectReference;
40 import org.apache.maven.archiva.model.SnapshotVersion;
41 import org.apache.maven.archiva.model.VersionedReference;
42 import org.apache.maven.archiva.repository.ContentNotFoundException;
43 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
44 import org.apache.maven.archiva.repository.RemoteRepositoryContent;
45 import org.apache.maven.archiva.repository.layout.LayoutException;
46 import org.codehaus.plexus.registry.Registry;
47 import org.codehaus.plexus.registry.RegistryListener;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50 import org.springframework.stereotype.Service;
52 import javax.annotation.PostConstruct;
53 import javax.inject.Inject;
54 import javax.inject.Named;
56 import java.io.IOException;
57 import java.text.ParseException;
58 import java.text.SimpleDateFormat;
59 import java.util.ArrayList;
60 import java.util.Calendar;
61 import java.util.Collection;
62 import java.util.Collections;
63 import java.util.Date;
64 import java.util.HashMap;
65 import java.util.HashSet;
66 import java.util.Iterator;
67 import java.util.LinkedHashSet;
68 import java.util.List;
71 import java.util.regex.Matcher;
78 * plexus.component role="org.apache.maven.archiva.repository.metadata.MetadataTools"
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 RepositoryMetadataReader.read( metadataFile );
373 catch ( RepositoryMetadataException 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 RepositoryMetadataReader.read( metadataFile );
398 catch ( RepositoryMetadataException 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 RepositoryMetadataReader.read( metadataFile );
423 catch ( RepositoryMetadataException 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 = RepositoryMetadataReader.read( file );
512 if ( existingMetadata != null )
514 metadatas.add( existingMetadata );
517 catch ( RepositoryMetadataException 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() )
579 allPlugins = new LinkedHashSet<Plugin>( RepositoryMetadataReader.read( metadataFile ).getPlugins() );
583 allPlugins = new LinkedHashSet<Plugin>();
586 // Does this repository have a set of remote proxied repositories?
587 Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
589 if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
591 // Add in the proxied repo version ids too.
592 Iterator<String> it = proxiedRepoIds.iterator();
593 while ( it.hasNext() )
595 String proxyId = it.next();
597 ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
598 if ( proxyMetadata != null )
600 allVersions.addAll( proxyMetadata.getAvailableVersions() );
601 allPlugins.addAll( proxyMetadata.getPlugins() );
602 long proxyLastUpdated = getLastUpdated( proxyMetadata );
604 lastUpdated = Math.max( lastUpdated, proxyLastUpdated );
609 if ( !allVersions.isEmpty() )
611 updateMetadataVersions( allVersions, metadata );
615 // Add the plugins to the metadata model.
616 metadata.setPlugins( new ArrayList<Plugin>( allPlugins ) );
618 // artifact ID was actually the last part of the group
619 metadata.setGroupId( metadata.getGroupId() + "." + metadata.getArtifactId() );
620 metadata.setArtifactId( null );
623 if ( lastUpdated > 0 )
625 metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
628 // Save the metadata model to disk.
629 RepositoryMetadataWriter.write( metadata, metadataFile );
630 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
631 checksum.fixChecksums( algorithms );
634 private void updateMetadataVersions( Collection<String> allVersions, ArchivaRepositoryMetadata metadata )
637 List<String> sortedVersions = new ArrayList<String>( allVersions );
638 Collections.sort( sortedVersions, VersionComparator.getInstance() );
640 // Split the versions into released and snapshots.
641 List<String> releasedVersions = new ArrayList<String>();
642 List<String> snapshotVersions = new ArrayList<String>();
644 for ( String version : sortedVersions )
646 if ( VersionUtil.isSnapshot( version ) )
648 snapshotVersions.add( version );
652 releasedVersions.add( version );
656 Collections.sort( releasedVersions, VersionComparator.getInstance() );
657 Collections.sort( snapshotVersions, VersionComparator.getInstance() );
659 String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
660 String releaseVersion = null;
662 if ( CollectionUtils.isNotEmpty( releasedVersions ) )
664 releaseVersion = releasedVersions.get( releasedVersions.size() - 1 );
667 // Add the versions to the metadata model.
668 metadata.setAvailableVersions( sortedVersions );
670 metadata.setLatestVersion( latestVersion );
671 metadata.setReleasedVersion( releaseVersion );
674 private Date toLastUpdatedDate( long lastUpdated )
676 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
677 cal.setTimeInMillis( lastUpdated );
679 return cal.getTime();
682 private long toLastUpdatedLong( String timestampString )
686 Date date = lastUpdatedFormat.parse( timestampString );
687 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
690 return cal.getTimeInMillis();
692 catch ( ParseException e )
698 private long getLastUpdated( ArchivaRepositoryMetadata metadata )
700 if ( metadata == null )
708 String lastUpdated = metadata.getLastUpdated();
709 if ( StringUtils.isBlank( lastUpdated ) )
715 Date lastUpdatedDate = lastUpdatedFormat.parse( lastUpdated );
716 return lastUpdatedDate.getTime();
718 catch ( ParseException e )
720 // Bad format on the last updated string.
725 private long getExistingLastUpdated( File metadataFile )
727 if ( !metadataFile.exists() )
735 ArchivaRepositoryMetadata metadata = RepositoryMetadataReader.read( metadataFile );
737 return getLastUpdated( metadata );
739 catch ( RepositoryMetadataException e )
747 * Update the metadata based on the following rules.
749 * 1) If this is a SNAPSHOT reference, then utilize the proxy/repository specific
750 * metadata files to represent the current / latest SNAPSHOT available.
751 * 2) If this is a RELEASE reference, and the metadata file does not exist, then
752 * create the metadata file with contents required of the VersionedReference
754 * @param managedRepository the managed repository where the metadata is kept.
755 * @param reference the versioned reference to update
756 * @throws LayoutException
757 * @throws RepositoryMetadataException
758 * @throws IOException
759 * @throws ContentNotFoundException
762 public void updateMetadata( ManagedRepositoryContent managedRepository, VersionedReference reference )
763 throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
765 File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) );
767 long lastUpdated = getExistingLastUpdated( metadataFile );
769 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
770 metadata.setGroupId( reference.getGroupId() );
771 metadata.setArtifactId( reference.getArtifactId() );
773 if ( VersionUtil.isSnapshot( reference.getVersion() ) )
775 // Do SNAPSHOT handling.
776 metadata.setVersion( VersionUtil.getBaseVersion( reference.getVersion() ) );
778 // Gather up all of the versions found in the reference dir, and any
779 // proxied maven-metadata.xml files.
780 Set<String> snapshotVersions = gatherSnapshotVersions( managedRepository, reference );
782 if ( snapshotVersions.isEmpty() )
784 throw new ContentNotFoundException(
785 "No snapshot versions found on reference [" + VersionedReference.toKey( reference ) + "]." );
788 // sort the list to determine to aide in determining the Latest version.
789 List<String> sortedVersions = new ArrayList<String>();
790 sortedVersions.addAll( snapshotVersions );
791 Collections.sort( sortedVersions, new VersionComparator() );
793 String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
795 if ( VersionUtil.isUniqueSnapshot( latestVersion ) )
797 // The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
798 // This needs to be broken down into ${base}-${timestamp}-${build_number}
800 Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( latestVersion );
803 metadata.setSnapshotVersion( new SnapshotVersion() );
804 int buildNumber = NumberUtils.toInt( m.group( 3 ), -1 );
805 metadata.getSnapshotVersion().setBuildNumber( buildNumber );
807 Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
808 if ( mtimestamp.matches() )
810 String tsDate = mtimestamp.group( 1 );
811 String tsTime = mtimestamp.group( 2 );
813 long snapshotLastUpdated = toLastUpdatedLong( tsDate + tsTime );
815 lastUpdated = Math.max( lastUpdated, snapshotLastUpdated );
817 metadata.getSnapshotVersion().setTimestamp( m.group( 2 ) );
821 else if ( VersionUtil.isGenericSnapshot( latestVersion ) )
823 // The latestVersion ends with the generic version string.
824 // Example: 1.0-alpha-5-SNAPSHOT
826 metadata.setSnapshotVersion( new SnapshotVersion() );
828 /* Disabled due to decision in [MRM-535].
829 * Do not set metadata.lastUpdated to file.lastModified.
831 * Should this be the last updated timestamp of the file, or in the case of an
832 * archive, the most recent timestamp in the archive?
834 ArtifactReference artifact = getFirstArtifact( managedRepository, reference );
836 if ( artifact == null )
838 throw new IOException( "Not snapshot artifact found to reference in " + reference );
841 File artifactFile = managedRepository.toFile( artifact );
843 if ( artifactFile.exists() )
845 Date lastModified = new Date( artifactFile.lastModified() );
846 metadata.setLastUpdatedTimestamp( lastModified );
852 throw new RepositoryMetadataException(
853 "Unable to process snapshot version <" + latestVersion + "> reference <" + reference + ">" );
858 // Do RELEASE handling.
859 metadata.setVersion( reference.getVersion() );
863 if ( lastUpdated > 0 )
865 metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
868 // Save the metadata model to disk.
869 RepositoryMetadataWriter.write( metadata, metadataFile );
870 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
871 checksum.fixChecksums( algorithms );
874 private void initConfigVariables()
876 synchronized ( this.artifactPatterns )
878 this.artifactPatterns.clear();
880 this.artifactPatterns.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
883 synchronized ( proxies )
885 this.proxies.clear();
887 List<ProxyConnectorConfiguration> proxyConfigs = configuration.getConfiguration().getProxyConnectors();
888 for ( ProxyConnectorConfiguration proxyConfig : proxyConfigs )
890 String key = proxyConfig.getSourceRepoId();
892 Set<String> remoteRepoIds = this.proxies.get( key );
894 if ( remoteRepoIds == null )
896 remoteRepoIds = new HashSet<String>();
899 remoteRepoIds.add( proxyConfig.getTargetRepoId() );
901 this.proxies.put( key, remoteRepoIds );
907 * Get the first Artifact found in the provided VersionedReference location.
909 * @param managedRepository the repository to search within.
910 * @param reference the reference to the versioned reference to search within
911 * @return the ArtifactReference to the first artifact located within the versioned reference. or null if
912 * no artifact was found within the versioned reference.
913 * @throws IOException if the versioned reference is invalid (example: doesn't exist, or isn't a directory)
914 * @throws LayoutException
916 public ArtifactReference getFirstArtifact( ManagedRepositoryContent managedRepository,
917 VersionedReference reference )
918 throws LayoutException, IOException
920 String path = toPath( reference );
922 int idx = path.lastIndexOf( '/' );
925 path = path.substring( 0, idx );
928 File repoDir = new File( managedRepository.getRepoRoot(), path );
930 if ( !repoDir.exists() )
932 throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: "
933 + repoDir.getAbsolutePath() );
936 if ( !repoDir.isDirectory() )
938 throw new IOException(
939 "Unable to gather the list of snapshot versions on a non-directory: " + repoDir.getAbsolutePath() );
942 File repoFiles[] = repoDir.listFiles();
943 for ( int i = 0; i < repoFiles.length; i++ )
945 if ( repoFiles[i].isDirectory() )
947 // Skip it. it's a directory.
951 String relativePath = PathUtil.getRelative( managedRepository.getRepoRoot(), repoFiles[i] );
953 if ( filetypes.matchesArtifactPattern( relativePath ) )
955 ArtifactReference artifact = managedRepository.toArtifactReference( relativePath );
961 // No artifact was found.
965 public ArchivaConfiguration getConfiguration()
967 return configuration;
970 public void setConfiguration( ArchivaConfiguration configuration )
972 this.configuration = configuration;
975 public FileTypes getFiletypes()
980 public void setFiletypes( FileTypes filetypes )
982 this.filetypes = filetypes;