Преглед на файлове

simplify location processor, and fix bugs discovered due to swallowing exceptions

git-svn-id: https://svn.apache.org/repos/asf/maven/repository-manager/trunk@359995 13f79535-47bb-0310-9956-ffa450edef68
tags/archiva-0.9-alpha-1
Brett Porter преди 18 години
родител
ревизия
3009cb9d42
променени са 16 файла, в които са добавени 141 реда и са изтрити 220 реда
  1. 67
    97
      maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/LocationArtifactReportProcessor.java
  2. 5
    0
      maven-repository-reports-standard/src/main/resources/META-INF/plexus/components.xml
  3. 69
    123
      maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/LocationArtifactReportProcessorTest.java
  4. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/artifactId/1.0-alpha-3/artifactId-1.0-alpha-3.pom
  5. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-archiver/2.0/maven-archiver-2.0.jar
  6. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-archiver/2.0/maven-archiver-2.0.pom
  7. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-archiver/2.0/note.txt
  8. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-model/2.0/maven-model-2.0.jar
  9. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-model/2.0/maven-model-2.0.pom
  10. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-model/2.0/note.txt
  11. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-monitor/2.1/maven-monitor-2.1.jar
  12. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-monitor/2.1/maven-monitor-2.1.pom
  13. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-monitor/2.1/note.txt
  14. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-project/2.1/maven-project-2.1.jar
  15. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-project/2.1/maven-project-2.1.pom
  16. 0
    0
      maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-project/2.1/note.txt

+ 67
- 97
maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/LocationArtifactReportProcessor.java Целия файл

@@ -17,18 +17,18 @@ package org.apache.maven.repository.reporting;
*/

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

@@ -40,9 +40,7 @@ import java.util.jar.JarFile;
public class LocationArtifactReportProcessor
implements ArtifactReportProcessor
{
private boolean isLocal = true;

private InputStream is;
private ArtifactFactory artifactFactory;

/**
* Check whether the artifact is in its proper location. The location of the artifact
@@ -61,79 +59,63 @@ public class LocationArtifactReportProcessor
ArtifactRepository repository )
throws ReportProcessorException
{
boolean fsPomLocation = false, pkgPomLocation = false;
String repositoryUrl = "", modelArtifactLocation = "";

if ( !repository.getProtocol().equals( "file" ) )
if ( !"file".equals( repository.getProtocol() ) )
{
isLocal = false;
repositoryUrl = repository.getUrl();
}
else
{
repositoryUrl = repository.getBasedir();
// We can't check other types of URLs yet. Need to use Wagon, with an exists() method.
throw new UnsupportedOperationException(
"Can't process repository '" + repository.getUrl() + "'. Only file based repositories are supported" );
}

//check if the artifact is located in its proper location based on the info
//specified in the model object/pom
modelArtifactLocation = repositoryUrl + model.getGroupId() + "/" + model.getArtifactId() + "/" +
model.getVersion() + "/" + model.getArtifactId() + "-" + model.getVersion() + "." + model.getPackaging();
fsPomLocation = validateArtifactLocation( modelArtifactLocation );

//get the location of the artifact itself
String artifactLocation = repositoryUrl + artifact.getGroupId() + "/" + artifact.getArtifactId() + "/" +
artifact.getVersion() + "/" + artifact.getArtifactId() + "-" + artifact.getVersion() + "." +
artifact.getType();

//unpack the artifact (using the groupId, artifactId & version specified in the artifact object itself
//check if the pom is included in the package
Model extractedModel = readArtifactModel( artifactLocation, artifact.getGroupId(), artifact.getArtifactId() );
Artifact modelArtifact = artifactFactory.createBuildArtifact( model.getGroupId(), model.getArtifactId(),
model.getVersion(), model.getPackaging() );

if ( extractedModel != null )
boolean failed = false;
String modelPath = repository.pathOf( modelArtifact );
String artifactPath = repository.pathOf( artifact );
if ( modelPath.equals( artifactPath ) )
{
//get the location of the artifact itself
File file = new File( repository.getBasedir(), artifactPath );

String pkgPomArtifactLocation = repositoryUrl + extractedModel.getGroupId() + "/" +
extractedModel.getArtifactId() + "/" + extractedModel.getVersion() + "/" +
extractedModel.getArtifactId() + "-" + extractedModel.getVersion() + "." +
extractedModel.getPackaging();
pkgPomLocation = validateArtifactLocation( pkgPomArtifactLocation );

//check the conditions
if ( fsPomLocation == true && pkgPomLocation == true )
if ( file.exists() )
{
reporter.addSuccess( artifact );

}
else if ( fsPomLocation == false && pkgPomLocation == true )
{
reporter.addFailure( artifact,
"The artifact is out of place. It does not match the specified location in the file system pom." );
//unpack the artifact (using the groupId, artifactId & version specified in the artifact object itself
//check if the pom is included in the package
Model extractedModel = readArtifactModel( file, artifact.getGroupId(), artifact.getArtifactId() );

if ( extractedModel != null )
{
Artifact extractedArtifact = artifactFactory.createBuildArtifact( extractedModel.getGroupId(),
extractedModel.getArtifactId(),
extractedModel.getVersion(),
extractedModel.getPackaging() );
if ( !repository.pathOf( extractedArtifact ).equals( artifactPath ) )
{
reporter.addFailure( artifact,
"The artifact is out of place. It does not match the specified location in the packaged pom." );
failed = true;
}
}
}
else if ( fsPomLocation == true && pkgPomLocation == false )
else
{
reporter.addFailure( artifact,
"The artifact is out of place. It does not match the specified location in the packaged pom." );

}
else if ( fsPomLocation == false && pkgPomLocation == false )
{
reporter.addFailure( artifact, "The artifact is out of place." );
"The artifact is out of place. It does not exist at the specified location in the repository pom." );
failed = true;
}

}
else
{
reporter.addFailure( artifact,
"The artifact is out of place. It does not match the specified location in the repository pom." );
failed = true;
}

if ( fsPomLocation )
{
reporter.addSuccess( artifact );

}
else
{
reporter.addFailure( artifact, "The artifact is out of place." );
}
if ( !failed )
{
reporter.addSuccess( artifact );
}
}

@@ -144,43 +126,25 @@ public class LocationArtifactReportProcessor
*/
private boolean validateArtifactLocation( String filename )
{
try
{
if ( isLocal )
{
is = new FileInputStream( filename );
}
else
{
URL url = new URL( filename );
is = url.openStream();
}

is.close();
}
catch ( Exception e )
{
return false;
}
return true;
return new File( filename ).exists();
}

/**
* Extract the contents of the artifact/jar file.
*
* @param filename
* @param file
* @param groupId
* @param artifactId
*/
private Model readArtifactModel( String filename, String groupId, String artifactId )
private Model readArtifactModel( File file, String groupId, String artifactId )
throws ReportProcessorException
{
Model modelObj = null;
Model model = null;

JarFile jar = null;
try
{
jar = new JarFile( filename );
jar = new JarFile( file );

//Get the entry and its input stream.
JarEntry entry = jar.getJarEntry( "META-INF/maven/" + groupId + "/" + artifactId + "/pom.xml" );
@@ -188,19 +152,7 @@ public class LocationArtifactReportProcessor
// If the entry is not null, extract it.
if ( entry != null )
{
InputStream entryStream = jar.getInputStream( entry );

Reader isReader = new InputStreamReader( entryStream );

try
{
MavenXpp3Reader pomReader = new MavenXpp3Reader();
modelObj = pomReader.read( isReader );
}
finally
{
IOUtil.close( isReader );
}
model = readModel( jar.getInputStream( entry ) );
}
}
catch ( IOException e )
@@ -228,7 +180,25 @@ public class LocationArtifactReportProcessor
}
}
}
return modelObj;
return model;
}

private Model readModel( InputStream entryStream )
throws IOException, XmlPullParserException
{
Reader isReader = new InputStreamReader( entryStream );

Model model;
try
{
MavenXpp3Reader pomReader = new MavenXpp3Reader();
model = pomReader.read( isReader );
}
finally
{
IOUtil.close( isReader );
}
return model;
}

}

+ 5
- 0
maven-repository-reports-standard/src/main/resources/META-INF/plexus/components.xml Целия файл

@@ -50,6 +50,11 @@
<role-hint>artifact-location</role-hint>
<implementation>org.apache.maven.repository.reporting.LocationArtifactReportProcessor</implementation>
<instantiation-strategy>per-lookup</instantiation-strategy>
<requirements>
<requirement>
<role>org.apache.maven.artifact.factory.ArtifactFactory</role>
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.repository.reporting.ArtifactReportProcessor</role>

+ 69
- 123
maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/LocationArtifactReportProcessorTest.java Целия файл

@@ -23,10 +23,11 @@ import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
@@ -62,29 +63,18 @@ public class LocationArtifactReportProcessorTest
* both in the file system pom and in the pom included in the package.
*/
public void testPackagedPomLocationArtifactReporterSuccess()
throws ReportProcessorException, IOException, XmlPullParserException
{
//System.out.println("");
//System.out.println("====================== PACKAGED POM TEST [SUCCESS] ========================");
try
{
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.0" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-model", version, "compile", "jar", "", handler );
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.0" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-model", version, "compile", "jar", "", handler );

InputStream is =
new FileInputStream( repository.getBasedir() + "org.apache.maven/maven-model/2.0/maven-model-2.0.pom" );
Reader reader = new InputStreamReader( is );
Model model = pomReader.read( reader );
String path = "org/apache/maven/maven-model/2.0/maven-model-2.0.pom";
Model model = readPom( path );

artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
//System.out.println("PACKAGED POM SUCCESSES ---> " + reporter.getSuccesses());
assertTrue( reporter.getSuccesses() == 1 );
}
catch ( Exception e )
{
e.printStackTrace();
}
artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertEquals( 1, reporter.getSuccesses() );
}

/**
@@ -92,29 +82,17 @@ public class LocationArtifactReportProcessorTest
* file system pom (but the jar file does not have a pom included in its package).
*/
public void testLocationArtifactReporterSuccess()
throws ReportProcessorException, IOException, XmlPullParserException
{
// System.out.println("");
// System.out.println("====================== FILE SYSTEM POM TEST [SUCCESS] ========================");

try
{
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "1.0-alpha-1" );
Artifact artifact = new DefaultArtifact( "groupId", "artifactId", version, "compile", "jar", "", handler );
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "1.0-alpha-1" );
Artifact artifact = new DefaultArtifact( "groupId", "artifactId", version, "compile", "jar", "", handler );

InputStream is = new FileInputStream(
repository.getBasedir() + "groupId/artifactId/1.0-alpha-1/artifactId-1.0-alpha-1.pom" );
Reader reader = new InputStreamReader( is );
Model model = pomReader.read( reader );
String path = "groupId/artifactId/1.0-alpha-1/artifactId-1.0-alpha-1.pom";
Model model = readPom( path );

artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertTrue( reporter.getSuccesses() == 1 );
// System.out.println("FILE SYSTEM POM SUCCESSES ---> " + reporter.getSuccesses());
}
catch ( Exception e )
{
e.printStackTrace();
}
artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertEquals( 1, reporter.getSuccesses() );
}

/**
@@ -122,29 +100,17 @@ public class LocationArtifactReportProcessorTest
* in the file system pom.
*/
public void testLocationArtifactReporterFailure()
throws IOException, XmlPullParserException, ReportProcessorException
{
// System.out.println("");
// System.out.println("====================== FILE SYSTEM POM TEST [FAILURE] ========================");

try
{
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "1.0-alpha-2" );
Artifact artifact = new DefaultArtifact( "groupId", "artifactId", version, "compile", "jar", "", handler );
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "1.0-alpha-2" );
Artifact artifact = new DefaultArtifact( "groupId", "artifactId", version, "compile", "jar", "", handler );

InputStream is = new FileInputStream(
repository.getBasedir() + "groupId/artifactId/1.0-alpha-2/artifactId-1.0-alpha-2.pom" );
Reader reader = new InputStreamReader( is );
Model model = pomReader.read( reader );
String path = "groupId/artifactId/1.0-alpha-2/artifactId-1.0-alpha-2.pom";
Model model = readPom( path );

artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertTrue( reporter.getFailures() == 1 );
// System.out.println("FILE SYSTEM POM FAILURES ---> " + reporter.getFailures());
}
catch ( Exception e )
{
e.printStackTrace();
}
artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertEquals( 1, reporter.getFailures() );
}

/**
@@ -152,31 +118,35 @@ public class LocationArtifactReportProcessorTest
* location in the file system pom but instead matches the specified location in the packaged pom.
*/
public void testFsPomArtifactMatchFailure()
throws IOException, ReportProcessorException, XmlPullParserException
{
// System.out.println("");
// System.out.println("====================== FILE SYSTEM POM MATCH TEST [FAILURE] ========================");
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.0" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-archiver", version, "compile", "jar", "", handler );

try
{
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.0" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-archiver", version, "compile", "jar", "", handler );
String path = "org/apache/maven/maven-archiver/2.0/maven-archiver-2.0.pom";
Model model = readPom( path );

InputStream is = new FileInputStream(
repository.getBasedir() + "org.apache.maven/maven-archiver/2.0/maven-archiver-2.0.pom" );
Reader reader = new InputStreamReader( is );
Model model = pomReader.read( reader );
artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertEquals( 1, reporter.getFailures() );
}

artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertTrue( reporter.getFailures() == 1 );
// System.out.println("FILE SYSTEM POM MATCH FAILURES ---> " + reporter.getFailures());
//System.out.println("FILE SYSTEM POM MATCH SUCCESS ---> " + reporter.getSuccesses());
private Model readPom( String path )
throws IOException, XmlPullParserException
{
Reader reader = new FileReader( new File( repository.getBasedir(), path ) );
Model model = pomReader.read( reader );
// hokey inheritence to avoid some errors right now
if ( model.getGroupId() == null )
{
model.setGroupId( model.getParent().getGroupId() );
}
catch ( Exception e )
if ( model.getVersion() == null )
{
e.printStackTrace();
model.setVersion( model.getParent().getVersion() );
}
return model;
}

/**
@@ -184,30 +154,18 @@ public class LocationArtifactReportProcessorTest
* location specified in the packaged pom but matches the location specified in the file system pom.
*/
public void testPkgPomArtifactMatchFailure()
throws IOException, XmlPullParserException, ReportProcessorException
{
// System.out.println("");
// System.out.println("====================== PACKAGED POM MATCH TEST [FAILURE] ========================");

try
{
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.1" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-monitor", version, "compile", "jar", "", handler );
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.1" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-monitor", version, "compile", "jar", "", handler );

InputStream is = new FileInputStream(
repository.getBasedir() + "org.apache.maven/maven-monitor/2.1/maven-monitor-2.1.pom" );
Reader reader = new InputStreamReader( is );
Model model = pomReader.read( reader );
String path = "org/apache/maven/maven-monitor/2.1/maven-monitor-2.1.pom";
Model model = readPom( path );

artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertTrue( reporter.getFailures() == 1 );
// System.out.println("PACKAGED POM MATCH FAILURES ---> " + reporter.getFailures());
}
catch ( Exception e )
{
e.printStackTrace();
}
artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertEquals( 1, reporter.getFailures() );
}

/**
@@ -215,30 +173,18 @@ public class LocationArtifactReportProcessorTest
* location specified in the packaged pom and the location specified in the file system pom.
*/
public void testBothPomArtifactMatchFailure()
throws IOException, XmlPullParserException, ReportProcessorException
{
// System.out.println("");
// System.out.println("====================== BOTH POMS MATCH TEST [FAILURE] ========================");

try
{
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.1" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-project", version, "compile", "jar", "", handler );
ArtifactHandler handler = new DefaultArtifactHandler( "jar" );
VersionRange version = VersionRange.createFromVersion( "2.1" );
Artifact artifact =
new DefaultArtifact( "org.apache.maven", "maven-project", version, "compile", "jar", "", handler );

InputStream is = new FileInputStream(
repository.getBasedir() + "org.apache.maven/maven-project/2.1/maven-project-2.1.pom" );
Reader reader = new InputStreamReader( is );
Model model = pomReader.read( reader );
String path = "org/apache/maven/maven-project/2.1/maven-project-2.1.pom";
Model model = readPom( path );

artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertTrue( reporter.getFailures() == 1 );
// System.out.println("BOTH POMS MATCH FAILURES ---> " + reporter.getFailures());
}
catch ( Exception e )
{
e.printStackTrace();
}
artifactReportProcessor.processArtifact( model, artifact, reporter, repository );
assertEquals( 1, reporter.getFailures() );
}

/**

maven-repository-reports-standard/src/test/repository/org.apache.maven/artifactId/1.0-alpha-3/artifactId-1.0-alpha-3.pom → maven-repository-reports-standard/src/test/repository/org/apache/maven/artifactId/1.0-alpha-3/artifactId-1.0-alpha-3.pom Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-archiver/2.0/maven-archiver-2.0.jar → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-archiver/2.0/maven-archiver-2.0.jar Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-archiver/2.0/maven-archiver-2.0.pom → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-archiver/2.0/maven-archiver-2.0.pom Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-archiver/2.0/note.txt → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-archiver/2.0/note.txt Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-model/2.0/maven-model-2.0.jar → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-model/2.0/maven-model-2.0.jar Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-model/2.0/maven-model-2.0.pom → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-model/2.0/maven-model-2.0.pom Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-model/2.0/note.txt → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-model/2.0/note.txt Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-monitor/2.1/maven-monitor-2.1.jar → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-monitor/2.1/maven-monitor-2.1.jar Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-monitor/2.1/maven-monitor-2.1.pom → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-monitor/2.1/maven-monitor-2.1.pom Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-monitor/2.1/note.txt → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-monitor/2.1/note.txt Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-project/2.1/maven-project-2.1.jar → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-project/2.1/maven-project-2.1.jar Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-project/2.1/maven-project-2.1.pom → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-project/2.1/maven-project-2.1.pom Целия файл


maven-repository-reports-standard/src/test/repository/org.apache.maven/maven-project/2.1/note.txt → maven-repository-reports-standard/src/test/repository/org/apache/maven/maven-project/2.1/note.txt Целия файл


Loading…
Отказ
Запис