blob: b875be6aeb90a9363db866d22d06f0485e9ca365 [file] [log] [blame]
package org.apache.archiva.repository.metadata.base;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.common.utils.PathUtil;
import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.configuration.ConfigurationEvent;
import org.apache.archiva.configuration.ConfigurationListener;
import org.apache.archiva.configuration.ConfigurationNames;
import org.apache.archiva.configuration.FileTypes;
import org.apache.archiva.configuration.ProxyConnectorConfiguration;
// import org.apache.archiva.maven2.metadata.MavenMetadataReader;
import org.apache.archiva.model.ArchivaRepositoryMetadata;
import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.model.Plugin;
import org.apache.archiva.model.ProjectReference;
import org.apache.archiva.model.SnapshotVersion;
import org.apache.archiva.model.VersionedReference;
import org.apache.archiva.components.registry.Registry;
import org.apache.archiva.components.registry.RegistryListener;
import org.apache.archiva.repository.ContentNotFoundException;
import org.apache.archiva.repository.LayoutException;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.RemoteRepositoryContent;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.metadata.MetadataReader;
import org.apache.archiva.repository.metadata.RepositoryMetadataException;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.stream.Stream;
/**
* MetadataTools
*
*
*/
@Service( "metadataTools#default" )
public class MetadataTools
implements RegistryListener, ConfigurationListener
{
private static final Logger log = LoggerFactory.getLogger( MetadataTools.class );
public static final String MAVEN_METADATA = "maven-metadata.xml";
public static final String MAVEN_ARCHETYPE_CATALOG ="archetype-catalog.xml";
private static final char PATH_SEPARATOR = '/';
private static final char GROUP_SEPARATOR = '.';
@Inject
private RepositoryRegistry repositoryRegistry;
/**
*
*/
@Inject
@Named( value = "archivaConfiguration#default" )
private ArchivaConfiguration configuration;
/**
*
*/
@Inject
@Named( value = "fileTypes" )
private FileTypes filetypes;
private List<ChecksumAlgorithm> algorithms = Arrays.asList(ChecksumAlgorithm.SHA256, ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 );
private List<String> artifactPatterns;
private Map<String, Set<String>> proxies;
private static final char NUMS[] = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
private SimpleDateFormat lastUpdatedFormat;
public MetadataTools()
{
lastUpdatedFormat = new SimpleDateFormat( "yyyyMMddHHmmss" );
lastUpdatedFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Override
public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
{
if ( ConfigurationNames.isProxyConnector( propertyName ) )
{
initConfigVariables();
}
}
@Override
public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
{
/* nothing to do */
}
/**
* Gather the set of snapshot versions found in a particular versioned reference.
*
* @return the Set of snapshot artifact versions found.
* @throws LayoutException
* @throws ContentNotFoundException
*/
public Set<String> gatherSnapshotVersions( ManagedRepositoryContent managedRepository,
VersionedReference reference )
throws LayoutException, IOException, ContentNotFoundException
{
Set<String> foundVersions = null;
try
{
foundVersions = managedRepository.getVersions( reference );
}
catch ( org.apache.archiva.repository.ContentAccessException e )
{
e.printStackTrace( );
}
// Next gather up the referenced 'latest' versions found in any proxied repositories
// maven-metadata-${proxyId}.xml files that may be present.
// Does this repository have a set of remote proxied repositories?
Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
{
String baseVersion = VersionUtil.getBaseVersion( reference.getVersion() );
baseVersion = baseVersion.substring( 0, baseVersion.indexOf( VersionUtil.SNAPSHOT ) - 1 );
// Add in the proxied repo version ids too.
Iterator<String> it = proxiedRepoIds.iterator();
while ( it.hasNext() )
{
String proxyId = it.next();
ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
if ( proxyMetadata == null )
{
// There is no proxy metadata, skip it.
continue;
}
// Is there some snapshot info?
SnapshotVersion snapshot = proxyMetadata.getSnapshotVersion();
if ( snapshot != null )
{
String timestamp = snapshot.getTimestamp();
int buildNumber = snapshot.getBuildNumber();
// Only interested in the timestamp + buildnumber.
if ( StringUtils.isNotBlank( timestamp ) && ( buildNumber > 0 ) )
{
foundVersions.add( baseVersion + "-" + timestamp + "-" + buildNumber );
}
}
}
}
return foundVersions;
}
/**
* Take a path to a maven-metadata.xml, and attempt to translate it to a VersionedReference.
*
* @param path
* @return
*/
public VersionedReference toVersionedReference( String path )
throws RepositoryMetadataException
{
if ( !path.endsWith( "/" + MAVEN_METADATA ) )
{
throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " );
}
VersionedReference reference = new VersionedReference();
String normalizedPath = StringUtils.replace( path, "\\", "/" );
String pathParts[] = StringUtils.split( normalizedPath, '/' );
int versionOffset = pathParts.length - 2;
int artifactIdOffset = versionOffset - 1;
int groupIdEnd = artifactIdOffset - 1;
reference.setVersion( pathParts[versionOffset] );
if ( !hasNumberAnywhere( reference.getVersion() ) )
{
// Scary check, but without it, all paths are version references;
throw new RepositoryMetadataException(
"Not a versioned reference, as version id on path has no number in it." );
}
reference.setArtifactId( pathParts[artifactIdOffset] );
StringBuilder gid = new StringBuilder();
for ( int i = 0; i <= groupIdEnd; i++ )
{
if ( i > 0 )
{
gid.append( "." );
}
gid.append( pathParts[i] );
}
reference.setGroupId( gid.toString() );
return reference;
}
private boolean hasNumberAnywhere( String version )
{
return StringUtils.indexOfAny( version, NUMS ) != ( -1 );
}
public ProjectReference toProjectReference( String path )
throws RepositoryMetadataException
{
if ( !path.endsWith( "/" + MAVEN_METADATA ) )
{
throw new RepositoryMetadataException( "Cannot convert to versioned reference, not a metadata file. " );
}
ProjectReference reference = new ProjectReference();
String normalizedPath = StringUtils.replace( path, "\\", "/" );
String pathParts[] = StringUtils.split( normalizedPath, '/' );
// Assume last part of the path is the version.
int artifactIdOffset = pathParts.length - 2;
int groupIdEnd = artifactIdOffset - 1;
reference.setArtifactId( pathParts[artifactIdOffset] );
StringBuilder gid = new StringBuilder();
for ( int i = 0; i <= groupIdEnd; i++ )
{
if ( i > 0 )
{
gid.append( "." );
}
gid.append( pathParts[i] );
}
reference.setGroupId( gid.toString() );
return reference;
}
public String toPath( ProjectReference reference )
{
StringBuilder path = new StringBuilder();
path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR );
path.append( reference.getArtifactId() ).append( PATH_SEPARATOR );
path.append( MAVEN_METADATA );
return path.toString();
}
public String toPath( VersionedReference reference )
{
StringBuilder path = new StringBuilder();
path.append( formatAsDirectory( reference.getGroupId() ) ).append( PATH_SEPARATOR );
path.append( reference.getArtifactId() ).append( PATH_SEPARATOR );
if ( reference.getVersion() != null )
{
// add the version only if it is present
path.append( VersionUtil.getBaseVersion( reference.getVersion() ) ).append( PATH_SEPARATOR );
}
path.append( MAVEN_METADATA );
return path.toString();
}
private String formatAsDirectory( String directory )
{
return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
}
/**
* Adjusts a path for a metadata.xml file to its repository specific path.
*
* @param repository the repository to base new path off of.
* @param path the path to the metadata.xml file to adjust the name of.
* @return the newly adjusted path reference to the repository specific metadata path.
*/
public String getRepositorySpecificName( RemoteRepositoryContent repository, String path )
{
return getRepositorySpecificName( repository.getId(), path );
}
/**
* Adjusts a path for a metadata.xml file to its repository specific path.
*
* @param proxyId the repository id to base new path off of.
* @param path the path to the metadata.xml file to adjust the name of.
* @return the newly adjusted path reference to the repository specific metadata path.
*/
public String getRepositorySpecificName( String proxyId, String path )
{
StringBuilder ret = new StringBuilder();
int idx = path.lastIndexOf( '/' );
if ( idx > 0 )
{
ret.append( path.substring( 0, idx + 1 ) );
}
// TODO: need to filter out 'bad' characters from the proxy id.
ret.append( "maven-metadata-" ).append( proxyId ).append( ".xml" );
return ret.toString();
}
@PostConstruct
public void initialize()
{
assert(configuration != null);
this.artifactPatterns = new ArrayList<>();
this.proxies = new HashMap<>();
initConfigVariables();
configuration.addChangeListener( this );
configuration.addListener( this );
}
public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
ProjectReference reference, String proxyId )
{
MetadataReader reader = getMetadataReader( managedRepository );
String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) );
StorageAsset metadataFile = managedRepository.getRepository().getAsset( metadataPath );
return readMetadataFile( managedRepository, metadataFile );
}
public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
String logicalResource, String proxyId )
{
String metadataPath = getRepositorySpecificName( proxyId, logicalResource );
StorageAsset metadataFile = managedRepository.getRepository().getAsset( metadataPath );
return readMetadataFile( managedRepository, metadataFile );
}
public ArchivaRepositoryMetadata readProxyMetadata( ManagedRepositoryContent managedRepository,
VersionedReference reference, String proxyId )
{
String metadataPath = getRepositorySpecificName( proxyId, toPath( reference ) );
StorageAsset metadataFile = managedRepository.getRepository().getAsset( metadataPath );
return readMetadataFile( managedRepository, metadataFile );
}
public void updateMetadata( ManagedRepositoryContent managedRepository, String logicalResource )
throws RepositoryMetadataException
{
final StorageAsset metadataFile = managedRepository.getRepository().getAsset( logicalResource );
ArchivaRepositoryMetadata metadata = null;
//Gather and merge all metadata available
List<ArchivaRepositoryMetadata> metadatas =
getMetadatasForManagedRepository( managedRepository, logicalResource );
for ( ArchivaRepositoryMetadata proxiedMetadata : metadatas )
{
if ( metadata == null )
{
metadata = proxiedMetadata;
continue;
}
metadata = RepositoryMetadataMerge.merge( metadata, proxiedMetadata );
}
if ( metadata == null )
{
log.debug( "No metadata to update for {}", logicalResource );
return;
}
Set<String> availableVersions = new HashSet<String>();
List<String> metadataAvailableVersions = metadata.getAvailableVersions();
if ( metadataAvailableVersions != null )
{
availableVersions.addAll( metadataAvailableVersions );
}
availableVersions = findPossibleVersions( availableVersions, metadataFile.getParent() );
if ( availableVersions.size() > 0 )
{
updateMetadataVersions( availableVersions, metadata );
}
RepositoryMetadataWriter.write( metadata, metadataFile );
ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() );
checksum.fixChecksums( algorithms );
}
/**
* Skims the parent directory of a metadata in vain hope of finding
* subdirectories that contain poms.
*
* @param metadataParentDirectory
* @return origional set plus newly found versions
*/
private Set<String> findPossibleVersions( Set<String> versions, StorageAsset metadataParentDirectory )
{
Set<String> result = new HashSet<String>( versions );
metadataParentDirectory.list().stream().filter(asset ->
asset.isContainer()).filter(asset -> {
return asset.list().stream().anyMatch(f -> !f.isContainer() && f.getName().endsWith(".pom"));
}
).forEach( p -> result.add(p.getName()));
return result;
}
private List<ArchivaRepositoryMetadata> getMetadatasForManagedRepository(
ManagedRepositoryContent managedRepository, String logicalResource )
{
List<ArchivaRepositoryMetadata> metadatas = new ArrayList<>();
StorageAsset file = managedRepository.getRepository().getAsset( logicalResource );
if ( file.exists() )
{
ArchivaRepositoryMetadata existingMetadata = readMetadataFile( managedRepository, file );
if ( existingMetadata != null )
{
metadatas.add( existingMetadata );
}
}
Set<String> proxyIds = proxies.get( managedRepository.getId() );
if ( proxyIds != null )
{
for ( String proxyId : proxyIds )
{
ArchivaRepositoryMetadata proxyMetadata =
readProxyMetadata( managedRepository, logicalResource, proxyId );
if ( proxyMetadata != null )
{
metadatas.add( proxyMetadata );
}
}
}
return metadatas;
}
/**
* Update the metadata to represent the all versions/plugins of
* the provided groupId:artifactId project or group reference,
* based off of information present in the repository,
* the maven-metadata.xml files, and the proxy/repository specific
* metadata file contents.
* <p>
* We must treat this as a group or a project metadata file as there is no way to know in advance
*
* @param managedRepository the managed repository where the metadata is kept.
* @param reference the reference to update.
* @throws LayoutException
* @throws RepositoryMetadataException
* @throws IOException
* @throws ContentNotFoundException
* @deprecated
*/
public void updateMetadata( ManagedRepositoryContent managedRepository, ProjectReference reference )
throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
{
StorageAsset metadataFile = managedRepository.getRepository().getAsset( toPath( reference ) );
ArchivaRepositoryMetadata existingMetadata = readMetadataFile( managedRepository, metadataFile );
long lastUpdated = getExistingLastUpdated( existingMetadata );
ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
metadata.setGroupId( reference.getGroupId() );
metadata.setArtifactId( reference.getArtifactId() );
// Gather up all versions found in the managed repository.
Set<String> allVersions = null;
try
{
allVersions = managedRepository.getVersions( reference );
}
catch ( org.apache.archiva.repository.ContentAccessException e )
{
e.printStackTrace( );
}
// Gather up all plugins found in the managed repository.
// TODO: do we know this information instead?
// Set<Plugin> allPlugins = managedRepository.getPlugins( reference );
Set<Plugin> allPlugins;
if ( existingMetadata!=null)
{
allPlugins = new LinkedHashSet<Plugin>( existingMetadata.getPlugins() );
}
else
{
allPlugins = new LinkedHashSet<Plugin>();
}
// Does this repository have a set of remote proxied repositories?
Set<String> proxiedRepoIds = this.proxies.get( managedRepository.getId() );
if ( CollectionUtils.isNotEmpty( proxiedRepoIds ) )
{
// Add in the proxied repo version ids too.
Iterator<String> it = proxiedRepoIds.iterator();
while ( it.hasNext() )
{
String proxyId = it.next();
ArchivaRepositoryMetadata proxyMetadata = readProxyMetadata( managedRepository, reference, proxyId );
if ( proxyMetadata != null )
{
allVersions.addAll( proxyMetadata.getAvailableVersions() );
allPlugins.addAll( proxyMetadata.getPlugins() );
long proxyLastUpdated = getLastUpdated( proxyMetadata );
lastUpdated = Math.max( lastUpdated, proxyLastUpdated );
}
}
}
if ( !allVersions.isEmpty() )
{
updateMetadataVersions( allVersions, metadata );
}
else
{
// Add the plugins to the metadata model.
metadata.setPlugins( new ArrayList<>( allPlugins ) );
// artifact ID was actually the last part of the group
metadata.setGroupId( metadata.getGroupId() + "." + metadata.getArtifactId() );
metadata.setArtifactId( null );
}
if ( lastUpdated > 0 )
{
metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
}
// Save the metadata model to disk.
RepositoryMetadataWriter.write( metadata, metadataFile );
ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() );
checksum.fixChecksums( algorithms );
}
public MetadataReader getMetadataReader( ManagedRepositoryContent managedRepository )
{
if (managedRepository!=null)
{
return repositoryRegistry.getMetadataReader( managedRepository.getRepository( ).getType( ) );
} else {
return repositoryRegistry.getMetadataReader( RepositoryType.MAVEN );
}
}
private void updateMetadataVersions( Collection<String> allVersions, ArchivaRepositoryMetadata metadata )
{
// Sort the versions
List<String> sortedVersions = new ArrayList<>( allVersions );
Collections.sort( sortedVersions, VersionComparator.getInstance() );
// Split the versions into released and snapshots.
List<String> releasedVersions = new ArrayList<>();
List<String> snapshotVersions = new ArrayList<>();
for ( String version : sortedVersions )
{
if ( VersionUtil.isSnapshot( version ) )
{
snapshotVersions.add( version );
}
else
{
releasedVersions.add( version );
}
}
Collections.sort( releasedVersions, VersionComparator.getInstance() );
Collections.sort( snapshotVersions, VersionComparator.getInstance() );
String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
String releaseVersion = null;
if ( CollectionUtils.isNotEmpty( releasedVersions ) )
{
releaseVersion = releasedVersions.get( releasedVersions.size() - 1 );
}
// Add the versions to the metadata model.
metadata.setAvailableVersions( sortedVersions );
metadata.setLatestVersion( latestVersion );
metadata.setReleasedVersion( releaseVersion );
}
private Date toLastUpdatedDate( long lastUpdated )
{
Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("UTC") );
cal.setTimeInMillis( lastUpdated );
return cal.getTime();
}
private long toLastUpdatedLong( String timestampString )
{
try
{
Date date = lastUpdatedFormat.parse( timestampString );
Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("UTC"));
cal.setTime( date );
return cal.getTimeInMillis();
}
catch ( ParseException e )
{
return 0;
}
}
private long getLastUpdated( ArchivaRepositoryMetadata metadata )
{
if ( metadata == null )
{
// Doesn't exist.
return 0;
}
try
{
String lastUpdated = metadata.getLastUpdated();
if ( StringUtils.isBlank( lastUpdated ) )
{
// Not set.
return 0;
}
Date lastUpdatedDate = lastUpdatedFormat.parse( lastUpdated );
return lastUpdatedDate.getTime();
}
catch ( ParseException e )
{
// Bad format on the last updated string.
return 0;
}
}
ArchivaRepositoryMetadata readMetadataFile( ManagedRepositoryContent repository, StorageAsset asset) {
MetadataReader reader = getMetadataReader( repository );
try
{
if (asset.exists() && !asset.isContainer())
{
return reader.read( asset );
} else {
log.error( "Trying to read metadata from container: {}", asset.getPath( ) );
return null;
}
}
catch ( RepositoryMetadataException e )
{
log.error( "Could not read metadata file {}", asset, e );
return null;
}
}
private long getExistingLastUpdated( ArchivaRepositoryMetadata metadata )
{
if ( metadata==null )
{
// Doesn't exist.
return 0;
}
return getLastUpdated( metadata );
}
/**
* Update the metadata based on the following rules.
* <p>
* 1) If this is a SNAPSHOT reference, then utilize the proxy/repository specific
* metadata files to represent the current / latest SNAPSHOT available.
* 2) If this is a RELEASE reference, and the metadata file does not exist, then
* create the metadata file with contents required of the VersionedReference
*
* @param managedRepository the managed repository where the metadata is kept.
* @param reference the versioned reference to update
* @throws LayoutException
* @throws RepositoryMetadataException
* @throws IOException
* @throws ContentNotFoundException
* @deprecated
*/
public void updateMetadata( ManagedRepositoryContent managedRepository, VersionedReference reference )
throws LayoutException, RepositoryMetadataException, IOException, ContentNotFoundException
{
StorageAsset metadataFile = managedRepository.getRepository().getAsset( toPath( reference ) );
ArchivaRepositoryMetadata existingMetadata = readMetadataFile(managedRepository, metadataFile );
long lastUpdated = getExistingLastUpdated( existingMetadata );
ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
metadata.setGroupId( reference.getGroupId() );
metadata.setArtifactId( reference.getArtifactId() );
if ( VersionUtil.isSnapshot( reference.getVersion() ) )
{
// Do SNAPSHOT handling.
metadata.setVersion( VersionUtil.getBaseVersion( reference.getVersion() ) );
// Gather up all of the versions found in the reference dir, and any
// proxied maven-metadata.xml files.
Set<String> snapshotVersions = gatherSnapshotVersions( managedRepository, reference );
if ( snapshotVersions.isEmpty() )
{
throw new ContentNotFoundException(
"No snapshot versions found on reference [" + VersionedReference.toKey( reference ) + "]." );
}
// sort the list to determine to aide in determining the Latest version.
List<String> sortedVersions = new ArrayList<>();
sortedVersions.addAll( snapshotVersions );
Collections.sort( sortedVersions, new VersionComparator() );
String latestVersion = sortedVersions.get( sortedVersions.size() - 1 );
if ( VersionUtil.isUniqueSnapshot( latestVersion ) )
{
// The latestVersion will contain the full version string "1.0-alpha-5-20070821.213044-8"
// This needs to be broken down into ${base}-${timestamp}-${build_number}
Matcher m = VersionUtil.UNIQUE_SNAPSHOT_PATTERN.matcher( latestVersion );
if ( m.matches() )
{
metadata.setSnapshotVersion( new SnapshotVersion() );
int buildNumber = NumberUtils.toInt( m.group( 3 ), -1 );
metadata.getSnapshotVersion().setBuildNumber( buildNumber );
Matcher mtimestamp = VersionUtil.TIMESTAMP_PATTERN.matcher( m.group( 2 ) );
if ( mtimestamp.matches() )
{
String tsDate = mtimestamp.group( 1 );
String tsTime = mtimestamp.group( 2 );
long snapshotLastUpdated = toLastUpdatedLong( tsDate + tsTime );
lastUpdated = Math.max( lastUpdated, snapshotLastUpdated );
metadata.getSnapshotVersion().setTimestamp( m.group( 2 ) );
}
}
}
else if ( VersionUtil.isGenericSnapshot( latestVersion ) )
{
// The latestVersion ends with the generic version string.
// Example: 1.0-alpha-5-SNAPSHOT
metadata.setSnapshotVersion( new SnapshotVersion() );
/* Disabled due to decision in [MRM-535].
* Do not set metadata.lastUpdated to file.lastModified.
*
* Should this be the last updated timestamp of the file, or in the case of an
* archive, the most recent timestamp in the archive?
*
ArtifactReference artifact = getFirstArtifact( managedRepository, reference );
if ( artifact == null )
{
throw new IOException( "Not snapshot artifact found to reference in " + reference );
}
File artifactFile = managedRepository.toFile( artifact );
if ( artifactFile.exists() )
{
Date lastModified = new Date( artifactFile.lastModified() );
metadata.setLastUpdatedTimestamp( lastModified );
}
*/
}
else
{
throw new RepositoryMetadataException(
"Unable to process snapshot version <" + latestVersion + "> reference <" + reference + ">" );
}
}
else
{
// Do RELEASE handling.
metadata.setVersion( reference.getVersion() );
}
// Set last updated
if ( lastUpdated > 0 )
{
metadata.setLastUpdatedTimestamp( toLastUpdatedDate( lastUpdated ) );
}
// Save the metadata model to disk.
RepositoryMetadataWriter.write( metadata, metadataFile );
ChecksummedFile checksum = new ChecksummedFile( metadataFile.getFilePath() );
checksum.fixChecksums( algorithms );
}
private void initConfigVariables()
{
assert(this.artifactPatterns!=null);
assert(proxies!=null);
synchronized ( this.artifactPatterns )
{
this.artifactPatterns.clear();
this.artifactPatterns.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
}
synchronized ( proxies )
{
this.proxies.clear();
List<ProxyConnectorConfiguration> proxyConfigs = configuration.getConfiguration().getProxyConnectors();
for ( ProxyConnectorConfiguration proxyConfig : proxyConfigs )
{
String key = proxyConfig.getSourceRepoId();
Set<String> remoteRepoIds = this.proxies.get( key );
if ( remoteRepoIds == null )
{
remoteRepoIds = new HashSet<String>();
}
remoteRepoIds.add( proxyConfig.getTargetRepoId() );
this.proxies.put( key, remoteRepoIds );
}
}
}
/**
* Get the first Artifact found in the provided VersionedReference location.
*
* @param managedRepository the repository to search within.
* @param reference the reference to the versioned reference to search within
* @return the ArtifactReference to the first artifact located within the versioned reference. or null if
* no artifact was found within the versioned reference.
* @throws IOException if the versioned reference is invalid (example: doesn't exist, or isn't a directory)
* @throws LayoutException
*/
public ArtifactReference getFirstArtifact( ManagedRepositoryContent managedRepository,
VersionedReference reference )
throws LayoutException, IOException
{
String path = toPath( reference );
int idx = path.lastIndexOf( '/' );
if ( idx > 0 )
{
path = path.substring( 0, idx );
}
Path repoDir = Paths.get( managedRepository.getRepoRoot(), path );
if ( !Files.exists(repoDir))
{
throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: "
+ repoDir.toAbsolutePath() );
}
if ( !Files.isDirectory( repoDir ))
{
throw new IOException(
"Unable to gather the list of snapshot versions on a non-directory: " + repoDir.toAbsolutePath() );
}
try(Stream<Path> stream = Files.list(repoDir)) {
String result = stream.filter( Files::isRegularFile ).map( path1 ->
PathUtil.getRelative( managedRepository.getRepoRoot(), path1 )
).filter( filetypes::matchesArtifactPattern ).findFirst().orElse( null );
if (result!=null) {
return managedRepository.toArtifactReference( result );
}
}
// No artifact was found.
return null;
}
public ArchivaConfiguration getConfiguration()
{
return configuration;
}
public void setConfiguration( ArchivaConfiguration configuration )
{
this.configuration = configuration;
}
public FileTypes getFiletypes()
{
return filetypes;
}
public void setFiletypes( FileTypes filetypes )
{
this.filetypes = filetypes;
}
@Override
public void configurationEvent( ConfigurationEvent event )
{
log.debug( "Configuration event {}", event );
}
}