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 @Service( "metadataTools#default" )
79 public class MetadataTools
80 implements RegistryListener
82 private Logger log = LoggerFactory.getLogger( getClass() );
84 public static final String MAVEN_METADATA = "maven-metadata.xml";
86 private static final char PATH_SEPARATOR = '/';
88 private static final char GROUP_SEPARATOR = '.';
94 @Named( value = "archivaConfiguration#default" )
95 private ArchivaConfiguration configuration;
101 @Named(value = "fileTypes")
102 private FileTypes filetypes;
104 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
106 private List<String> artifactPatterns;
108 private Map<String, Set<String>> proxies;
110 private static final char NUMS[] = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
112 private SimpleDateFormat lastUpdatedFormat;
114 public MetadataTools()
116 lastUpdatedFormat = new SimpleDateFormat( "yyyyMMddHHmmss" );
117 lastUpdatedFormat.setTimeZone( DateUtils.UTC_TIME_ZONE );
120 public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
122 if ( ConfigurationNames.isProxyConnector( propertyName ) )
124 initConfigVariables();
128 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
134 * Gather the set of snapshot versions found in a particular versioned reference.
136 * @return the Set of snapshot artifact versions found.
137 * @throws LayoutException
138 * @throws ContentNotFoundException
140 public Set<String> gatherSnapshotVersions( ManagedRepositoryContent managedRepository,
141 VersionedReference reference )
142 throws LayoutException, IOException, ContentNotFoundException
144 Set<String> foundVersions = managedRepository.getVersions( reference );
146 // Next gather up the referenced 'latest' versions found in any proxied repositories
147 // maven-metadata-${proxyId}.xml files that may be present.
149 // Does this repository have a set of remote proxied repositories?
150 Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
152 if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
154 String baseVersion = VersionUtil.getBaseVersion( reference.getVersion() );
155 baseVersion = baseVersion.substring( 0, baseVersion.indexOf( VersionUtil.SNAPSHOT ) - 1 );
157 // Add in the proxied repo version ids too.
158 Iterator<String> it = proxiedRepoIds.iterator();
159 while ( it.hasNext() )
161 String proxyId = it.next();
163 ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
164 if ( proxyMetadata == null )
166 // There is no proxy metadata, skip it.
170 // Is there some snapshot info?
171 SnapshotVersion snapshot = proxyMetadata.getSnapshotVersion();
172 if ( snapshot != null )
174 String timestamp = snapshot.getTimestamp();
175 int buildNumber = snapshot.getBuildNumber();
177 // Only interested in the timestamp + buildnumber.
178 if ( StringUtils.isNotBlank( timestamp ) && ( buildNumber > 0 ) )
180 foundVersions.add( baseVersion + "-" + timestamp + "-" + buildNumber );
186 return foundVersions;
190 * Take a path to a maven-metadata.xml, and attempt to translate it to a VersionedReference.
195 public VersionedReference toVersionedReference( String path )
196 throws RepositoryMetadataException
198 if ( !path.endsWith( "/" + MAVEN_METADATA ) )
200 throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " );
203 VersionedReference reference = new VersionedReference();
205 String normalizedPath = StringUtils.replace( path, "\\", "/" );
206 String pathParts[] = StringUtils.split( normalizedPath, '/' );
208 int versionOffset = pathParts.length - 2;
209 int artifactIdOffset = versionOffset - 1;
210 int groupIdEnd = artifactIdOffset - 1;
212 reference.setVersion( pathParts[versionOffset] );
214 if ( !hasNumberAnywhere( reference.getVersion() ) )
216 // Scary check, but without it, all paths are version references;
217 throw new RepositoryMetadataException(
218 "Not a versioned reference, as version id on path has no number in it." );
221 reference.setArtifactId( pathParts[artifactIdOffset] );
223 StringBuilder gid = new StringBuilder();
224 for ( int i = 0; i <= groupIdEnd; i++ )
230 gid.append( pathParts[i] );
233 reference.setGroupId( gid.toString() );
238 private boolean hasNumberAnywhere( String version )
240 return StringUtils.indexOfAny( version, NUMS ) != ( -1 );
243 public ProjectReference toProjectReference( String path )
244 throws RepositoryMetadataException
246 if ( !path.endsWith( "/" + MAVEN_METADATA ) )
248 throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " );
251 ProjectReference reference = new ProjectReference();
253 String normalizedPath = StringUtils.replace( path, "\\", "/" );
254 String pathParts[] = StringUtils.split( normalizedPath, '/' );
256 // Assume last part of the path is the version.
258 int artifactIdOffset = pathParts.length - 2;
259 int groupIdEnd = artifactIdOffset - 1;
261 reference.setArtifactId( pathParts[artifactIdOffset] );
263 StringBuilder gid = new StringBuilder();
264 for ( int i = 0; i <= groupIdEnd; i++ )
270 gid.append( pathParts[i] );
273 reference.setGroupId( gid.toString() );
278 public String toPath( ProjectReference reference )
280 StringBuilder path = new StringBuilder();
282 path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR );
283 path.append( reference.getArtifactId() ).append( PATH_SEPARATOR );
284 path.append( MAVEN_METADATA );
286 return path.toString();
289 public String toPath( VersionedReference reference )
291 StringBuilder path = new StringBuilder();
293 path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR );
294 path.append( reference.getArtifactId() ).append( PATH_SEPARATOR );
295 if ( reference.getVersion() != null )
297 // add the version only if it is present
298 path.append( VersionUtil.getBaseVersion( reference.getVersion() ) ).append( PATH_SEPARATOR );
300 path.append( MAVEN_METADATA );
302 return path.toString();
305 private String formatAsDirectory( String directory )
307 return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
311 * Adjusts a path for a metadata.xml file to its repository specific path.
313 * @param repository the repository to base new path off of.
314 * @param path the path to the metadata.xml file to adjust the name of.
315 * @return the newly adjusted path reference to the repository specific metadata path.
317 public String getRepositorySpecificName( RemoteRepositoryContent repository, String path )
319 return getRepositorySpecificName( repository.getId(), path );
323 * Adjusts a path for a metadata.xml file to its repository specific path.
325 * @param proxyId the repository id to base new path off of.
326 * @param path the path to the metadata.xml file to adjust the name of.
327 * @return the newly adjusted path reference to the repository specific metadata path.
329 public String getRepositorySpecificName( String proxyId, String path )
331 StringBuilder ret = new StringBuilder();
333 int idx = path.lastIndexOf( "/" );
336 ret.append( path.substring( 0, idx + 1 ) );
339 // TODO: need to filter out 'bad' characters from the proxy id.
340 ret.append( "maven-metadata-" ).append( proxyId ).append( ".xml" );
342 return ret.toString();
346 public void initialize()
348 this.artifactPatterns = new ArrayList<String>();
349 this.proxies = new HashMap<String, Set<String>>();
350 initConfigVariables();
352 configuration.addChangeListener( this );
355 public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
356 ProjectReference reference, String proxyId )
358 String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) );
359 File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
361 if ( !metadataFile.exists() || !metadataFile.isFile() )
363 // Nothing to do. return null.
369 return RepositoryMetadataReader.read( metadataFile );
371 catch ( RepositoryMetadataException e )
373 // TODO: [monitor] consider a monitor for this event.
374 // TODO: consider a read-redo on monitor return code?
375 log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
380 public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
381 String logicalResource, String proxyId )
383 String metadataPath = getRepositorySpecificName( proxyId, logicalResource );
384 File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
386 if ( !metadataFile.exists() || !metadataFile.isFile() )
388 // Nothing to do. return null.
394 return RepositoryMetadataReader.read( metadataFile );
396 catch ( RepositoryMetadataException e )
398 // TODO: [monitor] consider a monitor for this event.
399 // TODO: consider a read-redo on monitor return code?
400 log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
405 public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
406 VersionedReference reference, String proxyId )
408 String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) );
409 File metadataFile = new File( managedRepository.getRepoRoot(), metadataPath );
411 if ( !metadataFile.exists() || !metadataFile.isFile() )
413 // Nothing to do. return null.
419 return RepositoryMetadataReader.read( metadataFile );
421 catch ( RepositoryMetadataException e )
423 // TODO: [monitor] consider a monitor for this event.
424 // TODO: consider a read-redo on monitor return code?
425 log.warn( "Unable to read metadata: " + metadataFile.getAbsolutePath(), e );
430 public void updateMetadata( ManagedRepositoryContent managedRepository, String logicalResource )
431 throws RepositoryMetadataException
433 final File metadataFile = new File( managedRepository.getRepoRoot(), logicalResource );
434 ArchivaRepositoryMetadata metadata = null;
436 //Gather and merge all metadata available
437 List<ArchivaRepositoryMetadata> metadatas =
438 getMetadatasForManagedRepository( managedRepository, logicalResource );
439 for ( ArchivaRepositoryMetadata proxiedMetadata : metadatas )
441 if ( metadata == null )
443 metadata = proxiedMetadata;
446 metadata = RepositoryMetadataMerge.merge( metadata, proxiedMetadata );
449 if ( metadata == null )
451 log.debug( "No metadata to update for {}", logicalResource );
455 Set<String> availableVersions = new HashSet<String>();
456 List<String> metadataAvailableVersions = metadata.getAvailableVersions();
457 if ( metadataAvailableVersions != null )
459 availableVersions.addAll( metadataAvailableVersions );
461 availableVersions = findPossibleVersions( availableVersions, metadataFile.getParentFile() );
463 if ( availableVersions.size() > 0 )
465 updateMetadataVersions( availableVersions, metadata );
468 RepositoryMetadataWriter.write( metadata, metadataFile );
470 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
471 checksum.fixChecksums( algorithms );
475 * Skims the parent directory of a metadata in vain hope of finding
476 * subdirectories that contain poms.
478 * @param metadataParentDirectory
479 * @return origional set plus newley found versions
481 private Set<String> findPossibleVersions( Set<String> versions, File metadataParentDirectory )
483 Set<String> result = new HashSet<String>( versions );
484 for ( File directory : metadataParentDirectory.listFiles() )
486 if ( directory.isDirectory() )
488 for ( File possiblePom : directory.listFiles() )
490 if ( possiblePom.getName().endsWith( ".pom" ) )
492 result.add( directory.getName() );
500 private List<ArchivaRepositoryMetadata> getMetadatasForManagedRepository(
501 ManagedRepositoryContent managedRepository, String logicalResource )
503 List<ArchivaRepositoryMetadata> metadatas = new ArrayList<ArchivaRepositoryMetadata>();
504 File file = new File( managedRepository.getRepoRoot(), logicalResource );
509 ArchivaRepositoryMetadata existingMetadata = RepositoryMetadataReader.read( file );
510 if ( existingMetadata != null )
512 metadatas.add( existingMetadata );
515 catch ( RepositoryMetadataException e )
517 log.debug( "Could not read metadata at {}. Metadata will be removed.", file.getAbsolutePath() );
518 FileUtils.deleteQuietly( file );
522 Set<String> proxyIds = proxies.get( managedRepository.getId() );
523 if ( proxyIds != null )
525 for ( String proxyId : proxyIds )
527 ArchivaRepositoryMetadata proxyMetadata =
528 readProxyMetadata( managedRepository, logicalResource, proxyId );
529 if ( proxyMetadata != null )
531 metadatas.add( proxyMetadata );
541 * Update the metadata to represent the all versions/plugins of
542 * the provided groupId:artifactId project or group reference,
543 * based off of information present in the repository,
544 * the maven-metadata.xml files, and the proxy/repository specific
545 * metadata file contents.
547 * We must treat this as a group or a project metadata file as there is no way to know in advance
549 * @param managedRepository the managed repository where the metadata is kept.
550 * @param reference the reference to update.
551 * @throws LayoutException
552 * @throws RepositoryMetadataException
553 * @throws IOException
554 * @throws ContentNotFoundException
557 public void updateMetadata( ManagedRepositoryContent managedRepository, ProjectReference reference )
558 throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
560 File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) );
562 long lastUpdated = getExistingLastUpdated( metadataFile );
564 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
565 metadata.setGroupId( reference.getGroupId() );
566 metadata.setArtifactId( reference.getArtifactId() );
568 // Gather up all versions found in the managed repository.
569 Set<String> allVersions = managedRepository.getVersions( reference );
571 // Gather up all plugins found in the managed repository.
572 // TODO: do we know this information instead?
573 // Set<Plugin> allPlugins = managedRepository.getPlugins( reference );
574 Set<Plugin> allPlugins;
575 if ( metadataFile.exists() )
577 allPlugins = new LinkedHashSet<Plugin>( RepositoryMetadataReader.read( metadataFile ).getPlugins() );
581 allPlugins = new LinkedHashSet<Plugin>();
584 // Does this repository have a set of remote proxied repositories?
585 Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
587 if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
589 // Add in the proxied repo version ids too.
590 Iterator<String> it = proxiedRepoIds.iterator();
591 while ( it.hasNext() )
593 String proxyId = it.next();
595 ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
596 if ( proxyMetadata != null )
598 allVersions.addAll( proxyMetadata.getAvailableVersions() );
599 allPlugins.addAll( proxyMetadata.getPlugins() );
600 long proxyLastUpdated = getLastUpdated( proxyMetadata );
602 lastUpdated = Math.max( lastUpdated, proxyLastUpdated );
607 if ( !allVersions.isEmpty() )
609 updateMetadataVersions( allVersions, metadata );
613 // Add the plugins to the metadata model.
614 metadata.setPlugins( new ArrayList<Plugin>( allPlugins ) );
616 // artifact ID was actually the last part of the group
617 metadata.setGroupId( metadata.getGroupId() + "." + metadata.getArtifactId() );
618 metadata.setArtifactId( null );
621 if ( lastUpdated > 0 )
623 metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
626 // Save the metadata model to disk.
627 RepositoryMetadataWriter.write( metadata, metadataFile );
628 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
629 checksum.fixChecksums( algorithms );
632 private void updateMetadataVersions( Collection<String> allVersions, ArchivaRepositoryMetadata metadata )
635 List<String> sortedVersions = new ArrayList<String>( allVersions );
636 Collections.sort( sortedVersions, VersionComparator.getInstance() );
638 // Split the versions into released and snapshots.
639 List<String> releasedVersions = new ArrayList<String>();
640 List<String> snapshotVersions = new ArrayList<String>();
642 for ( String version : sortedVersions )
644 if ( VersionUtil.isSnapshot( version ) )
646 snapshotVersions.add( version );
650 releasedVersions.add( version );
654 Collections.sort( releasedVersions, VersionComparator.getInstance() );
655 Collections.sort( snapshotVersions, VersionComparator.getInstance() );
657 String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
658 String releaseVersion = null;
660 if ( CollectionUtils.isNotEmpty( releasedVersions ) )
662 releaseVersion = releasedVersions.get( releasedVersions.size() - 1 );
665 // Add the versions to the metadata model.
666 metadata.setAvailableVersions( sortedVersions );
668 metadata.setLatestVersion( latestVersion );
669 metadata.setReleasedVersion( releaseVersion );
672 private Date toLastUpdatedDate( long lastUpdated )
674 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
675 cal.setTimeInMillis( lastUpdated );
677 return cal.getTime();
680 private long toLastUpdatedLong( String timestampString )
684 Date date = lastUpdatedFormat.parse( timestampString );
685 Calendar cal = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
688 return cal.getTimeInMillis();
690 catch ( ParseException e )
696 private long getLastUpdated( ArchivaRepositoryMetadata metadata )
698 if ( metadata == null )
706 String lastUpdated = metadata.getLastUpdated();
707 if ( StringUtils.isBlank( lastUpdated ) )
713 Date lastUpdatedDate = lastUpdatedFormat.parse( lastUpdated );
714 return lastUpdatedDate.getTime();
716 catch ( ParseException e )
718 // Bad format on the last updated string.
723 private long getExistingLastUpdated( File metadataFile )
725 if ( !metadataFile.exists() )
733 ArchivaRepositoryMetadata metadata = RepositoryMetadataReader.read( metadataFile );
735 return getLastUpdated( metadata );
737 catch ( RepositoryMetadataException e )
745 * Update the metadata based on the following rules.
747 * 1) If this is a SNAPSHOT reference, then utilize the proxy/repository specific
748 * metadata files to represent the current / latest SNAPSHOT available.
749 * 2) If this is a RELEASE reference, and the metadata file does not exist, then
750 * create the metadata file with contents required of the VersionedReference
752 * @param managedRepository the managed repository where the metadata is kept.
753 * @param reference the versioned reference to update
754 * @throws LayoutException
755 * @throws RepositoryMetadataException
756 * @throws IOException
757 * @throws ContentNotFoundException
760 public void updateMetadata( ManagedRepositoryContent managedRepository, VersionedReference reference )
761 throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
763 File metadataFile = new File( managedRepository.getRepoRoot(), toPath( reference ) );
765 long lastUpdated = getExistingLastUpdated( metadataFile );
767 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
768 metadata.setGroupId( reference.getGroupId() );
769 metadata.setArtifactId( reference.getArtifactId() );
771 if ( VersionUtil.isSnapshot( reference.getVersion() ) )
773 // Do SNAPSHOT handling.
774 metadata.setVersion( VersionUtil.getBaseVersion( reference.getVersion() ) );
776 // Gather up all of the versions found in the reference dir, and any
777 // proxied maven-metadata.xml files.
778 Set<String> snapshotVersions = gatherSnapshotVersions( managedRepository, reference );
780 if ( snapshotVersions.isEmpty() )
782 throw new ContentNotFoundException(
783 "No snapshot versions found on reference [" + VersionedReference.toKey( reference ) + "]." );
786 // sort the list to determine to aide in determining the Latest version.
787 List<String> sortedVersions = new ArrayList<String>();
788 sortedVersions.addAll( snapshotVersions );
789 Collections.sort( sortedVersions, new VersionComparator() );
791 String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
793 if ( VersionUtil.isUniqueSnapshot( latestVersion ) )
795 // The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
796 // This needs to be broken down into ${base}-${timestamp}-${build_number}
798 Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( latestVersion );
801 metadata.setSnapshotVersion( new SnapshotVersion() );
802 int buildNumber = NumberUtils.toInt( m.group( 3 ), -1 );
803 metadata.getSnapshotVersion().setBuildNumber( buildNumber );
805 Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
806 if ( mtimestamp.matches() )
808 String tsDate = mtimestamp.group( 1 );
809 String tsTime = mtimestamp.group( 2 );
811 long snapshotLastUpdated = toLastUpdatedLong( tsDate + tsTime );
813 lastUpdated = Math.max( lastUpdated, snapshotLastUpdated );
815 metadata.getSnapshotVersion().setTimestamp( m.group( 2 ) );
819 else if ( VersionUtil.isGenericSnapshot( latestVersion ) )
821 // The latestVersion ends with the generic version string.
822 // Example: 1.0-alpha-5-SNAPSHOT
824 metadata.setSnapshotVersion( new SnapshotVersion() );
826 /* Disabled due to decision in [MRM-535].
827 * Do not set metadata.lastUpdated to file.lastModified.
829 * Should this be the last updated timestamp of the file, or in the case of an
830 * archive, the most recent timestamp in the archive?
832 ArtifactReference artifact = getFirstArtifact( managedRepository, reference );
834 if ( artifact == null )
836 throw new IOException( "Not snapshot artifact found to reference in " + reference );
839 File artifactFile = managedRepository.toFile( artifact );
841 if ( artifactFile.exists() )
843 Date lastModified = new Date( artifactFile.lastModified() );
844 metadata.setLastUpdatedTimestamp( lastModified );
850 throw new RepositoryMetadataException(
851 "Unable to process snapshot version <" + latestVersion + "> reference <" + reference + ">" );
856 // Do RELEASE handling.
857 metadata.setVersion( reference.getVersion() );
861 if ( lastUpdated > 0 )
863 metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
866 // Save the metadata model to disk.
867 RepositoryMetadataWriter.write( metadata, metadataFile );
868 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
869 checksum.fixChecksums( algorithms );
872 private void initConfigVariables()
874 synchronized ( this.artifactPatterns )
876 this.artifactPatterns.clear();
878 this.artifactPatterns.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
881 synchronized ( proxies )
883 this.proxies.clear();
885 List<ProxyConnectorConfiguration> proxyConfigs = configuration.getConfiguration().getProxyConnectors();
886 for ( ProxyConnectorConfiguration proxyConfig : proxyConfigs )
888 String key = proxyConfig.getSourceRepoId();
890 Set<String> remoteRepoIds = this.proxies.get( key );
892 if ( remoteRepoIds == null )
894 remoteRepoIds = new HashSet<String>();
897 remoteRepoIds.add( proxyConfig.getTargetRepoId() );
899 this.proxies.put( key, remoteRepoIds );
905 * Get the first Artifact found in the provided VersionedReference location.
907 * @param managedRepository the repository to search within.
908 * @param reference the reference to the versioned reference to search within
909 * @return the ArtifactReference to the first artifact located within the versioned reference. or null if
910 * no artifact was found within the versioned reference.
911 * @throws IOException if the versioned reference is invalid (example: doesn't exist, or isn't a directory)
912 * @throws LayoutException
914 public ArtifactReference getFirstArtifact( ManagedRepositoryContent managedRepository,
915 VersionedReference reference )
916 throws LayoutException, IOException
918 String path = toPath( reference );
920 int idx = path.lastIndexOf( '/' );
923 path = path.substring( 0, idx );
926 File repoDir = new File( managedRepository.getRepoRoot(), path );
928 if ( !repoDir.exists() )
930 throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: "
931 + repoDir.getAbsolutePath() );
934 if ( !repoDir.isDirectory() )
936 throw new IOException(
937 "Unable to gather the list of snapshot versions on a non-directory: " + repoDir.getAbsolutePath() );
940 File repoFiles[] = repoDir.listFiles();
941 for ( int i = 0; i < repoFiles.length; i++ )
943 if ( repoFiles[i].isDirectory() )
945 // Skip it. it's a directory.
949 String relativePath = PathUtil.getRelative( managedRepository.getRepoRoot(), repoFiles[i] );
951 if ( filetypes.matchesArtifactPattern( relativePath ) )
953 ArtifactReference artifact = managedRepository.toArtifactReference( relativePath );
959 // No artifact was found.
963 public ArchivaConfiguration getConfiguration()
965 return configuration;
968 public void setConfiguration( ArchivaConfiguration configuration )
970 this.configuration = configuration;
973 public FileTypes getFiletypes()
978 public void setFiletypes( FileTypes filetypes )
980 this.filetypes = filetypes;