Parcourir la source

Adding additional tests

pull/60/head
Martin Stockhammer il y a 4 ans
Parent
révision
729da5803c

+ 46
- 30
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven/content/ManagedDefaultRepositoryContent.java Voir le fichier

@@ -112,6 +112,7 @@ public class ManagedDefaultRepositoryContent

public static final Pattern UNIQUE_SNAPSHOT_PATTERN = Pattern.compile( "^(SNAPSHOT|[0-9]{8}\\.[0-9]{6}-[0-9]+)(.*)" );
public static final Pattern CLASSIFIER_PATTERN = Pattern.compile( "^-([^.]+)(\\..*)" );
public static final Pattern COMMON_EXTENSIONS = Pattern.compile( "^(jar|war|ear|dar|tar|zip|pom|xml)$" );

public static final Pattern TIMESTAMP_PATTERN = Pattern.compile( "^([0-9]{8})\\.([0-9]{6})$" );

@@ -292,6 +293,23 @@ public class ManagedDefaultRepositoryContent
.build( ) );
}

public Namespace getNamespaceFromPath( final StorageAsset namespacePath) {
final String namespace = MavenContentHelper.getNamespaceFromNamespacePath( namespacePath );
return namespaceMap.computeIfAbsent( namespace,
myNamespace -> ArchivaNamespace.withRepository( this )
.withAsset( namespacePath )
.withNamespace( namespace )
.build( ) );
}

private Project getProjectFromPath( final StorageAsset projectPath) {
return projectMap.computeIfAbsent( projectPath,
myProjectPath -> ArchivaProject.withAsset( projectPath )
.withNamespace( getNamespaceFromPath( projectPath.getParent() ) )
.withId( projectPath.getName( ) ).build( )
);
}

private Project getProjectFromArtifactPath( final StorageAsset artifactPath) {
final StorageAsset projectPath = artifactPath.getParent( ).getParent( );
return projectMap.computeIfAbsent( projectPath,
@@ -344,7 +362,6 @@ public class ManagedDefaultRepositoryContent
// Check for version directory (contains at least a pom or metadata file)
if (itemPath.list( ).stream( ).map(a -> a.getName().toLowerCase()).anyMatch( n ->
n.endsWith( ".pom" )
|| n.startsWith( "maven-metadata" )
)) {
return versionMap.computeIfAbsent( itemPath,
myVersionPath -> ArchivaVersion.withAsset( itemPath )
@@ -437,8 +454,15 @@ public class ManagedDefaultRepositoryContent
}
} else {
log.debug( "Artifact does not match the snapshot version pattern {}", path );

info.artifactType = BaseArtifactTypes.UNKNOWN;
info.version = "";
// This is just a guess. No guarantee to the get a usable version.
info.version = StringUtils.removeStart( fileName, info.id + '-' );
String postfix = StringUtils.substringAfterLast( info.version, "." ).toLowerCase();
while (COMMON_EXTENSIONS.matcher(postfix).matches()) {
info.version = StringUtils.substringBeforeLast( info.version, "." );
postfix = StringUtils.substringAfterLast( info.version, "." ).toLowerCase();
}
info.classifier = "";
info.remainder = StringUtils.substringAfter( fileName, prefix );
}
@@ -515,7 +539,7 @@ public class ManagedDefaultRepositoryContent
throw new IllegalArgumentException( "Version must be set" );
}
if (!selector.hasArtifactId( )) {
throw new IllegalArgumentException( "Artifact Id must be set" );
throw new IllegalArgumentException( "Artifact id must be set" );
}
final StorageAsset artifactDir = getAsset(selector.getNamespace(), selector.getProjectId(),
selector.getVersion());
@@ -529,21 +553,6 @@ public class ManagedDefaultRepositoryContent
return artifactMap.computeIfAbsent( path, artifactPath -> createArtifact( path, selector, classifier, extension ) );
}

private StorageAsset getBasePathFromSelector(ItemSelector selector) {
StringBuilder path = new StringBuilder( );
if (selector.hasNamespace()) {
path.append(String.join( "/", getNamespace( selector ).getNamespacePath( ) ));
}
if (selector.hasProjectId()) {
path.append( "/" ).append( selector.getProjectId( ) );
}
if (selector.hasVersion()) {
path.append( "/" ).append( selector.getVersion( ) );
}
return getStorage( ).getAsset( path.toString( ) );
}


/**
* Returns all the subdirectories of the given namespace directory as project.
*/
@@ -552,7 +561,7 @@ public class ManagedDefaultRepositoryContent
{
return namespace.getAsset( ).list( ).stream( )
.filter( a -> a.isContainer( ) )
.map( a -> getProjectFromArtifactPath( a ) )
.map( a -> getProjectFromPath( a ) )
.collect( Collectors.toList());
}

@@ -590,9 +599,9 @@ public class ManagedDefaultRepositoryContent
@Override
public List<? extends Version> getVersions( final ItemSelector selector ) throws ContentAccessException, IllegalArgumentException
{
if (StringUtils.isEmpty( selector.getProjectId() )) {
if (!selector.hasProjectId()) {
log.error( "Bad item selector for version list: {}", selector );
throw new IllegalArgumentException( "Project ID not set, while retrieving versions." );
throw new IllegalArgumentException( "Project id not set, while retrieving versions." );
}
final Project project = getProject( selector );
if (selector.hasVersion()) {
@@ -639,15 +648,17 @@ public class ManagedDefaultRepositoryContent
}
if (selector.hasArtifactVersion()) {
if ( selector.getArtifactVersion( ).contains("*")) {
String[] tokens = StringUtils.splitPreserveAllTokens( selector.getArtifactVersion( ), "*" );
String[] tokens = StringUtils.splitByWholeSeparator( selector.getArtifactVersion( ), "*" );
for (String currentToken : tokens) {
if (!currentToken.equals("")) {
fileNamePattern.append( Pattern.quote( currentToken ) );
}
fileNamePattern.append( "[A-Za-z0-9_\\-.]*" );
}
} else
{
fileNamePattern.append( Pattern.quote( selector.getArtifactVersion( ) ) );
}
fileNamePattern.append( Pattern.quote(selector.getArtifactVersion( )) );
} else {
fileNamePattern.append( "[A-Za-z0-9_\\-.]+" );
}
@@ -738,15 +749,14 @@ public class ManagedDefaultRepositoryContent
.map( this::getArtifactFromPath );

} else {
// We descend into 2 subdirectories (project and version)
return namespaceDir.list( ).stream( )
.filter( StorageAsset::isContainer )
.map( StorageAsset::list )
.map( a -> a.isContainer( ) ? a.list( ) : Arrays.asList( a ) )
.flatMap( List::stream )
.filter( StorageAsset::isContainer )
.map( StorageAsset::list )
.map( a -> a.isContainer( ) ? a.list( ) : Arrays.asList( a ) )
.flatMap( List::stream )
.filter( filter )
.map(this::getArtifactFromPath);
.map( this::getArtifactFromPath );
}
}
}
@@ -857,8 +867,14 @@ public class ManagedDefaultRepositoryContent
@Override
public ContentItem toItem( String path ) throws LayoutException
{
ItemSelector selector = getPathParser( ).toItemSelector( path );
return getItem( selector );
StorageAsset asset = getRepository( ).getAsset( path );
if (asset.isLeaf())
{
ItemSelector selector = getPathParser( ).toItemSelector( path );
return getItem( selector );
} else {
return getItemFromPath( asset );
}
}

@Override

+ 443
- 0
archiva-modules/archiva-maven/archiva-maven-repository/src/test/java/org/apache/archiva/repository/maven/content/ManagedDefaultRepositoryContentTest.java Voir le fichier

@@ -32,17 +32,22 @@ import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.RepositoryContent;
import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.content.BaseArtifactTypes;
import org.apache.archiva.repository.content.ContentItem;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.content.Namespace;
import org.apache.archiva.repository.content.Project;
import org.apache.archiva.repository.content.Version;
import org.apache.archiva.repository.content.base.ArchivaItemSelector;
import org.apache.archiva.repository.maven.MavenManagedRepository;
import org.apache.archiva.repository.maven.metadata.storage.ArtifactMappingProvider;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;

import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.Name;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
@@ -51,6 +56,7 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -281,6 +287,156 @@ public class ManagedDefaultRepositoryContentTest

}

@Test
public void getTestGetProjectWithIllegalArgs() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache" )
.withVersion( "1.0" )
.build();
try
{
repoContent.getProject( selector );
assertFalse( "Should throw IllegalArgumentException if no project id is given", true );
} catch (IllegalArgumentException e) {
// Everything fine
assertTrue( e.getMessage( ).contains( "Project id must be set" ) );
}
}

@Test
public void getTestGetVersionWithIllegalArgs() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withVersion( "1.0" )
.build();
try
{
repoContent.getVersion( selector );
assertFalse( "Should throw IllegalArgumentException if no project id is given", true );
} catch (IllegalArgumentException e) {
// Everything fine
assertTrue( e.getMessage( ).contains( "Project id must be set" ) );
}


selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "shared" )
.build();
try
{
repoContent.getVersion( selector );
assertFalse( "Should throw IllegalArgumentException if no version is given", true );
} catch (IllegalArgumentException e) {
// Everything fine
assertTrue( e.getMessage( ).contains( "Version must be set" ) );
}
}

@Test
public void getTestGetArtifactWithIllegalArgs() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withVersion( "1.0" )
.withArtifactId( "shared" )
.withArtifactVersion("1.0")
.build();
try
{
repoContent.getArtifact( selector );
assertFalse( "Should throw IllegalArgumentException if no project id is given", true );
} catch (IllegalArgumentException e) {
// Everything fine
assertTrue( e.getMessage( ).contains( "Project id must be set" ) );
}


selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "shared" )
.withArtifactId( "shared" )
.withArtifactVersion("1.0")
.build();
try
{
repoContent.getArtifact( selector );
assertFalse( "Should throw IllegalArgumentException if no version is given", true );
} catch (IllegalArgumentException e) {
// Everything fine
assertTrue( e.getMessage( ).contains( "Version must be set" ) );
}

selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "shared" )
.withVersion("1.0")
.withArtifactVersion("1.0")
.build();
try
{
repoContent.getArtifact( selector );
assertFalse( "Should throw IllegalArgumentException if no artifact id is given", true );
} catch (IllegalArgumentException e) {
// Everything fine
assertTrue( e.getMessage( ).contains( "Artifact id must be set" ) );
}


}

@Test
public void testGetProjects() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" ).build();
Namespace ns = repoContent.getNamespace( selector );
assertNotNull( ns );
List<? extends Project> projects = repoContent.getProjects( ns );
assertEquals( 12, projects.size( ) );
String[] expected = new String[]{
"A", "B", "C", "archiva", "discovery", "maven-parent", "samplejar", "shared", "some-ejb", "test",
"testing", "update"
};
Object[] actual = projects.stream( ).map( p -> p.getId( ) ).sorted( ).toArray( );
assertArrayEquals( expected, actual);
}

@Test
public void testGetProjectsWithSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" ).build();
List<? extends Project> projects = repoContent.getProjects( selector );
assertEquals( 12, projects.size( ) );
String[] expected = new String[]{
"A", "B", "C", "archiva", "discovery", "maven-parent", "samplejar", "shared", "some-ejb", "test",
"testing", "update"
};
Object[] actual = projects.stream( ).map( p -> p.getId( ) ).sorted( ).toArray( );
assertArrayEquals( expected, actual);
}

@Test
public void testGetVersionsWithIllegalSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" ).build();
try
{
List<? extends Version> versions = repoContent.getVersions( selector );
assertFalse( "IllegalArgumentException expected, when project id not set", true );
} catch (IllegalArgumentException e) {
assertEquals( "Project id not set, while retrieving versions.", e.getMessage( ) );
}
}

@Test
public void testGetVersionsWithSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "samplejar" ).build();
List<? extends Version> versions = repoContent.getVersions( selector );
assertNotNull( versions );
assertEquals( 2, versions.size( ) );
}


@Override
protected ArtifactReference toArtifactReference( String path )
@@ -816,6 +972,293 @@ public class ManagedDefaultRepositoryContentTest
assertEquals( "wrong-artifactId", artifact.getId( ) );
}

@Test
public void testArtifactListWithArtifactSelector4() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "test" )
.withVersion( "1.0-SNAPSHOT" )
.withClassifier( "" )
.build( );

List<? extends Artifact> results = repoContent.getArtifacts( selector );

assertNotNull( results );
assertEquals( 5, results.size( ) );

Artifact artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "test-1.0-20050611.112233-1-javadoc.jar" ) )
.findFirst().get();
assertNotNull( artifact );
assertEquals( "javadoc", artifact.getClassifier( ) );
assertEquals( "javadoc", artifact.getType( ) );

artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "wrong-artifactId-1.0-20050611.112233-1.jar" ) )
.findFirst().get();
assertNotNull( artifact );
assertEquals( "", artifact.getClassifier( ) );
assertEquals( "wrong-artifactId", artifact.getId( ) );

artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "wrong-artifactId-1.0-20050611.1122x-1.jar" ) )
.findFirst().get();
assertNotNull( artifact );
assertEquals( "", artifact.getClassifier( ) );
assertEquals( "wrong-artifactId", artifact.getId( ) );
assertEquals( "", artifact.getArtifactVersion( ) );

artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "test-1.0-20050611.1122x-1.jar" ) )
.findFirst().get();
assertNotNull( artifact );
assertEquals( "", artifact.getClassifier( ) );
assertEquals( "test", artifact.getId( ) );
assertEquals( "1.0-20050611.1122x-1", artifact.getArtifactVersion( ) );

}

@Test
public void testArtifactListWithArtifactSelectorWithClassifier() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "test" )
.withVersion( "1.0-SNAPSHOT" )
.withArtifactId( "test" )
.withClassifier( "javadoc" )
.withArtifactVersion( "1.0-20050611.112233-1" )
.build( );

List<? extends Artifact> results = repoContent.getArtifacts( selector );

assertNotNull( results );
assertEquals( 1, results.size( ) );

Artifact artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "test-1.0-20050611.112233-1-javadoc.jar" ) )
.findFirst().get();
assertNotNull( artifact );
assertEquals( "javadoc", artifact.getClassifier( ) );
assertEquals( "javadoc", artifact.getType( ) );
}

@Test
public void testArtifactListWithArtifactSelectorWrongArtifact() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "test" )
.withVersion( "1.0-SNAPSHOT" )
.withArtifactId( "wrong-artifactId" )
.withArtifactVersion( "1.0-20050611.112233-1" )
.build( );

List<? extends Artifact> results = repoContent.getArtifacts( selector );

assertNotNull( results );
assertEquals( 1, results.size( ) );

Artifact artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "wrong-artifactId-1.0-20050611.112233-1.jar" ) )
.findFirst().get();
assertNotNull( artifact );
}

@Test
public void testArtifactListWithArtifactSelectorVersionPattern() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "test" )
.withVersion( "1.0-SNAPSHOT" )
.withArtifactVersion( "1.0-*" )
.build( );

List<? extends Artifact> results = repoContent.getArtifacts( selector );

assertNotNull( results );
assertEquals( 5, results.size( ) );

Artifact artifact = results.stream( ).filter( a -> a.getFileName( ).equalsIgnoreCase( "wrong-artifactId-1.0-20050611.112233-1.jar" ) )
.findFirst().get();
assertNotNull( artifact );
}

@Test
public void testGetArtifactFromContentItem() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" ).build();
Namespace ns = repoContent.getNamespace( selector );
List<? extends Artifact> artifacts = repoContent.getArtifacts( ns );
assertNotNull( artifacts );
assertEquals( 39, artifacts.size( ) );
List<? extends Artifact> artifacts2 = repoContent.getArtifacts( (ContentItem)ns );
assertArrayEquals( artifacts.toArray(), artifacts2.toArray() );

selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven.shared" )
.withProjectId( "maven-downloader" )
.build();
Project project = repoContent.getProject( selector );
artifacts = repoContent.getArtifacts( project );
assertNotNull( artifacts );
assertEquals( 27, artifacts.size( ) );
artifacts2 = repoContent.getArtifacts( (ContentItem)project );
assertArrayEquals( artifacts.toArray(), artifacts2.toArray() );

selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven.shared" )
.withProjectId( "maven-downloader" )
.withVersion( "1.1" )
.build( );
Version version = repoContent.getVersion( selector );
artifacts = repoContent.getArtifacts( version );
assertNotNull( artifacts );
assertEquals( 12, artifacts.size( ) );
artifacts2 = repoContent.getArtifacts( (ContentItem)version );
assertArrayEquals( artifacts.toArray(), artifacts2.toArray() );

}

@Test
public void testGetRelatedArtifactsFromArtifact() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven.shared" )
.withProjectId( "maven-downloader" )
.withVersion( "1.1" )
.withExtension( "jar" )
.withArtifactId( "maven-downloader" ).build( );

Artifact artifact = repoContent.getArtifact( selector );
assertNotNull( artifact );
List<? extends Artifact> artifacts = repoContent.getArtifacts( artifact );
assertNotNull( artifacts );
assertEquals( 2, artifacts.size( ) );

}

@Test
public void testToItemFromPath() throws LayoutException
{
String path = "/org/apache/maven/shared";
ContentItem item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Namespace );

path = "/org/apache/maven/shared/maven-downloader";
item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Project );

path = "/org/apache/maven/shared/maven-downloader/1.1";
item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Version );

path = "/org/apache/maven/shared/maven-downloader/1.1/maven-downloader-1.1.jar";
item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Artifact );

}

@Test
public void testToItemFromAssetPath() throws LayoutException
{
StorageAsset path = repoContent.getRepository().getAsset("/org/apache/maven/shared");
ContentItem item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Namespace );

path = repoContent.getRepository( ).getAsset( "/org/apache/maven/shared/maven-downloader" );
item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Project );

path = repoContent.getRepository( ).getAsset( "/org/apache/maven/shared/maven-downloader/1.1" );
item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Version );

path = repoContent.getRepository( ).getAsset( "/org/apache/maven/shared/maven-downloader/1.1/maven-downloader-1.1.jar" );
item = repoContent.toItem( path );
assertNotNull( item );
assertTrue( item instanceof Artifact );

}

@Test
public void testHasContent() throws LayoutException
{
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven.shared" )
.withProjectId( "maven-downloader" )
.withVersion( "1.1" )
.withArtifactId( "maven-downloader" )
.withExtension( "jar" )
.build();

assertTrue( repoContent.hasContent( selector ) );

selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven.shared" )
.withProjectId( "maven-downloader" )
.withVersion( "1.1" )
.withArtifactId( "maven-downloader" )
.withExtension( "zip" )
.build();

assertFalse( repoContent.hasContent( selector ) );

}

@Test
public void testGetItemWithNamespaceSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.build( );
ContentItem item = repoContent.getItem( selector );
assertNotNull( item );
assertTrue( item instanceof Namespace );
}

@Test
public void testGetItemWithProjectSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "shared" )
.build( );
ContentItem item = repoContent.getItem( selector );
assertNotNull( item );
assertTrue( item instanceof Project );
}

@Test
public void testGetItemWithVersionSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "samplejar" )
.withVersion("2.0")
.build( );
ContentItem item = repoContent.getItem( selector );
assertNotNull( item );
assertTrue( item instanceof Version );
}

@Test
public void testGetItemWithArtifactSelector() {
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( "org.apache.maven" )
.withProjectId( "samplejar" )
.withVersion("2.0")
.withArtifactId( "samplejar" )
.build( );
ContentItem item = repoContent.getItem( selector );
assertNotNull( item );
assertTrue( item instanceof Artifact );
}

@Test
public void testGetNamespaceFromPath() {
StorageAsset path = repoContent.getRepository( ).getAsset( "/org/apache/axis2" );
Namespace ns = repoContent.getNamespaceFromPath( path );
assertNotNull( ns );
assertEquals( "org.apache.axis2", ns.getNamespace( ) );

}

@Test
public void testArtifactListWithArtifactSelectorAndRelated() {
ItemSelector selector = ArchivaItemSelector.builder( )

+ 0
- 0
archiva-modules/archiva-maven/archiva-maven-repository/src/test/resources/repositories/default-repository/org/apache/maven/test/1.0-SNAPSHOT/test-1.0-20050611.1122x-1.jar Voir le fichier


+ 0
- 0
archiva-modules/archiva-maven/archiva-maven-repository/src/test/resources/repositories/default-repository/org/apache/maven/test/1.0-SNAPSHOT/wrong-artifactId-1.0-20050611.1122x-1.jar Voir le fichier


Chargement…
Annuler
Enregistrer