diff options
author | Brett Porter <brett@apache.org> | 2009-12-15 23:07:36 +0000 |
---|---|---|
committer | Brett Porter <brett@apache.org> | 2009-12-15 23:07:36 +0000 |
commit | 4331620db667226493479efa67b44ae27e890582 (patch) | |
tree | 76eb805c6a301589e441abce751f233ff24fe89c /archiva-modules/plugins | |
parent | 7da14962fa313809e961ffd1d248260b146b1045 (diff) | |
download | archiva-4331620db667226493479efa67b44ae27e890582.tar.gz archiva-4331620db667226493479efa67b44ae27e890582.zip |
[MRM-1301] migrate reports to metadata repository
git-svn-id: https://svn.apache.org/repos/asf/archiva/branches/MRM-1025@891064 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-modules/plugins')
12 files changed, 654 insertions, 46 deletions
diff --git a/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/MavenProjectFacet.java b/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/MavenProjectFacet.java index bd306e774..0145b9482 100644 --- a/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/MavenProjectFacet.java +++ b/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/MavenProjectFacet.java @@ -82,6 +82,12 @@ public class MavenProjectFacet return FACET_ID; } + public String getName() + { + // TODO: not needed, perhaps version metadata facet should be separate interface? + return null; + } + public Map<String, String> toProperties() { HashMap<String, String> properties = new HashMap<String, String>(); diff --git a/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java b/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java index 24c54e4c6..cb27a3afb 100644 --- a/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java +++ b/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java @@ -246,8 +246,28 @@ public class FileMetadataRepository public List<String> getMetadataFacets( String repoId, String facetId ) { File directory = getMetadataDirectory( repoId, facetId ); - String[] list = directory.list(); - return list != null ? Arrays.asList( list ) : Collections.<String>emptyList(); + List<String> facets = new ArrayList<String>(); + recurse( facets, "", directory ); + return facets; + } + + private void recurse( List<String> facets, String prefix, File directory ) + { + File[] list = directory.listFiles(); + if ( list != null ) + { + for ( File dir : list ) + { + if ( dir.isDirectory() ) + { + recurse( facets, prefix + "/" + dir.getName(), dir ); + } + else if ( dir.getName().equals( METADATA_KEY + ".properties" ) ) + { + facets.add( prefix.substring( 1 ) ); + } + } + } } public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name ) @@ -283,14 +303,15 @@ public class FileMetadataRepository return metadataFacet; } - public void addMetadataFacet( String repositoryId, String facetId, String name, MetadataFacet metadataFacet ) + public void addMetadataFacet( String repositoryId, String facetId, MetadataFacet metadataFacet ) { Properties properties = new Properties(); properties.putAll( metadataFacet.toProperties() ); try { - writeProperties( properties, new File( getMetadataDirectory( repositoryId, facetId ), name ), + writeProperties( properties, + new File( getMetadataDirectory( repositoryId, facetId ), metadataFacet.getName() ), METADATA_KEY ); } catch ( IOException e ) @@ -313,6 +334,20 @@ public class FileMetadataRepository } } + public void removeMetadataFacet( String repoId, String facetId, String name ) + { + File dir = new File( getMetadataDirectory( repoId, facetId ), name ); + try + { + FileUtils.deleteDirectory( dir ); + } + catch ( IOException e ) + { + // TODO + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime ) { // TODO: this is quite slow - if we are to persist with this repository implementation we should build an index diff --git a/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java b/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java index 35d595ff8..f8d22d5f7 100644 --- a/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java +++ b/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java @@ -53,7 +53,7 @@ public class FileMetadataRepositoryTest private static final String TEST_FACET_ID = "test-facet-id"; - private static final String TEST_NAME = "test-name"; + private static final String TEST_NAME = "test/name"; private static final String TEST_VALUE = "test-value"; @@ -125,7 +125,7 @@ public class FileMetadataRepositoryTest public void testGetMetadataFacet() { - repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, new TestMetadataFacet( TEST_VALUE ) ); assertEquals( new TestMetadataFacet( TEST_VALUE ), repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ) ); @@ -138,14 +138,14 @@ public class FileMetadataRepositoryTest public void testGetMetadataFacetWhenUnknownName() { - repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, new TestMetadataFacet( TEST_VALUE ) ); assertNull( repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, UNKNOWN ) ); } public void testGetMetadataFacetWhenDefaultValue() { - repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( null ) ); + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, new TestMetadataFacet( null ) ); assertEquals( new TestMetadataFacet( "test-metadata" ), repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ) ); @@ -153,14 +153,14 @@ public class FileMetadataRepositoryTest public void testGetMetadataFacetWhenUnknownFacetId() { - repository.addMetadataFacet( TEST_REPO_ID, UNKNOWN, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); + repository.addMetadataFacet( TEST_REPO_ID, UNKNOWN, new TestMetadataFacet( TEST_VALUE ) ); assertNull( repository.getMetadataFacet( TEST_REPO_ID, UNKNOWN, TEST_NAME ) ); } public void testGetMetadataFacets() { - repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, new TestMetadataFacet( TEST_VALUE ) ); assertEquals( Collections.singletonList( TEST_NAME ), repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ) ); @@ -174,8 +174,10 @@ public class FileMetadataRepositoryTest public void testRemoveFacets() { + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, new TestMetadataFacet( TEST_VALUE ) ); + List<String> facets = repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); - assertTrue( facets.isEmpty() ); + assertFalse( facets.isEmpty() ); repository.removeMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); @@ -185,10 +187,8 @@ public class FileMetadataRepositoryTest public void testRemoveFacetsWhenEmpty() { - repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); - List<String> facets = repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); - assertFalse( facets.isEmpty() ); + assertTrue( facets.isEmpty() ); repository.removeMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); @@ -201,6 +201,40 @@ public class FileMetadataRepositoryTest repository.removeMetadataFacets( TEST_REPO_ID, UNKNOWN ); } + public void testRemoveFacet() + { + TestMetadataFacet metadataFacet = new TestMetadataFacet( TEST_VALUE ); + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, metadataFacet ); + + assertEquals( metadataFacet, repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ) ); + List<String> facets = repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); + assertFalse( facets.isEmpty() ); + + repository.removeMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ); + + assertNull( repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ) ); + facets = repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); + assertTrue( facets.isEmpty() ); + } + + public void testRemoveFacetWhenEmpty() + { + List<String> facets = repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); + assertTrue( facets.isEmpty() ); + assertNull( repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ) ); + + repository.removeMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ); + + facets = repository.getMetadataFacets( TEST_REPO_ID, TEST_FACET_ID ); + assertTrue( facets.isEmpty() ); + assertNull( repository.getMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME ) ); + } + + public void testRemoveFacetWhenUnknown() + { + repository.removeMetadataFacet( TEST_REPO_ID, UNKNOWN, TEST_NAME ); + } + public void testGetArtifacts() { ArtifactMetadata artifact1 = createArtifact(); @@ -246,8 +280,8 @@ public class FileMetadataRepositoryTest public void testRepositories() { - repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); - repository.addMetadataFacet( OTHER_REPO, TEST_FACET_ID, TEST_NAME, new TestMetadataFacet( TEST_VALUE ) ); + repository.addMetadataFacet( TEST_REPO_ID, TEST_FACET_ID, new TestMetadataFacet( TEST_VALUE ) ); + repository.addMetadataFacet( OTHER_REPO, TEST_FACET_ID, new TestMetadataFacet( TEST_VALUE ) ); assertEquals( Arrays.asList( OTHER_REPO, TEST_REPO_ID ), repository.getRepositories() ); } @@ -452,6 +486,11 @@ public class FileMetadataRepositoryTest return TEST_FACET_ID; } + public String getName() + { + return TEST_NAME; + } + public Map<String, String> toProperties() { if ( value != null ) diff --git a/archiva-modules/plugins/pom.xml b/archiva-modules/plugins/pom.xml index ab617b085..19878499a 100644 --- a/archiva-modules/plugins/pom.xml +++ b/archiva-modules/plugins/pom.xml @@ -30,5 +30,6 @@ <module>metadata-repository-file</module> <module>maven2-repository</module> <module>repository-statistics</module> + <module>problem-reports</module> </modules> </project>
\ No newline at end of file diff --git a/archiva-modules/plugins/problem-reports/pom.xml b/archiva-modules/plugins/problem-reports/pom.xml new file mode 100644 index 000000000..955cfdf62 --- /dev/null +++ b/archiva-modules/plugins/problem-reports/pom.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. +--> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>plugins</artifactId> + <groupId>org.apache.archiva</groupId> + <version>1.3-SNAPSHOT</version> + </parent> + <artifactId>problem-reports</artifactId> + <name>Archiva Problem Reporting Plugin</name> + <dependencies> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>metadata-repository-api</artifactId> + </dependency> + <!-- TODO: we want to move the event handling, or perhaps centralise under deleteArtifact() in the metadata repository itself --> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository-layer</artifactId> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-checksum</artifactId> + </dependency> + </dependencies> +</project> diff --git a/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemEventListener.java b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemEventListener.java new file mode 100644 index 000000000..5a9dd9855 --- /dev/null +++ b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemEventListener.java @@ -0,0 +1,48 @@ +package org.apache.archiva.reports; + +/* + * 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.metadata.repository.MetadataRepository; +import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; + +/** + * Process repository management events and respond appropriately. + * + * @plexus.component role="org.apache.maven.archiva.repository.events.RepositoryListener" role-hint="problem-reports" + */ +public class RepositoryProblemEventListener + implements RepositoryListener +{ + /** + * @plexus.requirement + */ + private MetadataRepository metadataRepository; + + public void deleteArtifact( ManagedRepositoryContent repository, ArchivaArtifact artifact ) + { + String name = + RepositoryProblemFacet.createName( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), + repository.toFile( artifact ).getName() ); + + metadataRepository.removeMetadataFacet( repository.getId(), RepositoryProblemFacet.FACET_ID, name ); + } +}
\ No newline at end of file diff --git a/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemFacet.java b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemFacet.java new file mode 100644 index 000000000..33694c032 --- /dev/null +++ b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemFacet.java @@ -0,0 +1,154 @@ +package org.apache.archiva.reports; + +/* + * 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 java.util.HashMap; +import java.util.Map; + +import org.apache.archiva.metadata.model.MetadataFacet; + +public class RepositoryProblemFacet + implements MetadataFacet +{ + public static final String FACET_ID = "org.apache.archiva.reports"; + + private String repositoryId; + + private String namespace; + + private String project; + + private String version; + + private String id; + + private String message; + + private String problem; + + public String getFacetId() + { + return FACET_ID; + } + + public String getName() + { + return createName( namespace, project, version, id ); + } + + public Map<String, String> toProperties() + { + Map<String, String> map = new HashMap<String, String>(); + map.put( "repositoryId", repositoryId ); + map.put( "namespace", namespace ); + map.put( "project", project ); + map.put( "version", version ); + map.put( "id", id ); + map.put( "message", message ); + map.put( "problem", problem ); + return map; + } + + public void fromProperties( Map<String, String> properties ) + { + repositoryId = properties.get( "repositoryId" ); + namespace = properties.get( "namespace" ); + project = properties.get( "project" ); + version = properties.get( "version" ); + id = properties.get( "id" ); + message = properties.get( "message" ); + problem = properties.get( "problem" ); + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + } + + public void setNamespace( String namespace ) + { + this.namespace = namespace; + } + + public String getRepositoryId() + { + return repositoryId; + } + + public String getNamespace() + { + return namespace; + } + + public void setProject( String project ) + { + this.project = project; + } + + public String getProject() + { + return project; + } + + public void setVersion( String version ) + { + this.version = version; + } + + public String getVersion() + { + return version; + } + + public void setId( String id ) + { + this.id = id; + } + + public String getId() + { + return id; + } + + public void setMessage( String message ) + { + this.message = message; + } + + public String getMessage() + { + return message; + } + + public void setProblem( String problem ) + { + this.problem = problem; + } + + public String getProblem() + { + return problem; + } + + static String createName( String namespace, String project, String projectVersion, String id ) + { + return namespace + "/" + project + "/" + projectVersion + "/" + id; + } +} diff --git a/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemFacetFactory.java b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemFacetFactory.java new file mode 100644 index 000000000..aeb602b59 --- /dev/null +++ b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/RepositoryProblemFacetFactory.java @@ -0,0 +1,35 @@ +package org.apache.archiva.reports; + +/* + * 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.metadata.model.MetadataFacet; +import org.apache.archiva.metadata.model.MetadataFacetFactory; + +/** + * @plexus.component role="org.apache.archiva.metadata.model.MetadataFacetFactory" role-hint="org.apache.archiva.reports" + */ +public class RepositoryProblemFacetFactory + implements MetadataFacetFactory +{ + public MetadataFacet createMetadataFacet() + { + return new RepositoryProblemFacet(); + } +} diff --git a/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/consumers/DuplicateArtifactsConsumer.java b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/consumers/DuplicateArtifactsConsumer.java new file mode 100644 index 000000000..c6c5d837f --- /dev/null +++ b/archiva-modules/plugins/problem-reports/src/main/java/org/apache/archiva/reports/consumers/DuplicateArtifactsConsumer.java @@ -0,0 +1,248 @@ +package org.apache.archiva.reports.consumers; + +/* + * 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 java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.apache.archiva.checksum.ChecksumAlgorithm; +import org.apache.archiva.checksum.ChecksummedFile; +import org.apache.archiva.metadata.model.ArtifactMetadata; +import org.apache.archiva.metadata.repository.MetadataRepository; +import org.apache.archiva.reports.RepositoryProblemFacet; +import org.apache.commons.collections.CollectionUtils; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; +import org.apache.maven.archiva.configuration.FileTypes; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; +import org.apache.maven.archiva.consumers.ConsumerException; +import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer; +import org.apache.maven.archiva.model.ArtifactReference; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.RepositoryContentFactory; +import org.apache.maven.archiva.repository.RepositoryException; +import org.apache.maven.archiva.repository.layout.LayoutException; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; +import org.codehaus.plexus.registry.Registry; +import org.codehaus.plexus.registry.RegistryListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Search the database of known SHA1 Checksums for potential duplicate artifacts. + * + * TODO: no need for this to be a scanner - we can just query the database / content repository to get a full list + * + * @version $Id$ + * @plexus.component role="org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer" + * role-hint="duplicate-artifacts" + * instantiation-strategy="per-lookup" + */ +public class DuplicateArtifactsConsumer + extends AbstractMonitoredConsumer + implements KnownRepositoryContentConsumer, RegistryListener, Initializable +{ + private Logger log = LoggerFactory.getLogger( DuplicateArtifactsConsumer.class ); + + /** + * @plexus.configuration default-value="duplicate-artifacts" + */ + private String id; + + /** + * @plexus.configuration default-value="Check for Duplicate Artifacts via SHA1 Checksums" + */ + private String description; + + /** + * @plexus.requirement + */ + private ArchivaConfiguration configuration; + + /** + * @plexus.requirement + */ + private FileTypes filetypes; + + /** + * @plexus.requirement + */ + private RepositoryContentFactory repositoryFactory; + + private List<String> includes = new ArrayList<String>(); + + private File repositoryDir; + + private String repoId; + + private ManagedRepositoryContent repository; + + /** + * @plexus.requirement + */ + private MetadataRepository metadataRepository; + + public String getId() + { + return id; + } + + public String getDescription() + { + return description; + } + + public boolean isPermanent() + { + return false; + } + + public List<String> getIncludes() + { + return includes; + } + + public List<String> getExcludes() + { + return Collections.emptyList(); + } + + public void beginScan( ManagedRepositoryConfiguration repo, Date whenGathered ) + throws ConsumerException + { + try + { + repoId = repo.getId(); + repository = repositoryFactory.getManagedRepositoryContent( repoId ); + this.repositoryDir = new File( repository.getRepoRoot() ); + } + catch ( RepositoryException e ) + { + throw new ConsumerException( e.getMessage(), e ); + } + } + + public void processFile( String path ) + throws ConsumerException + { + File artifactFile = new File( this.repositoryDir, path ); + + // TODO: would be quicker to somehow make sure it ran after the update database consumer, or as a part of that + // perhaps could use an artifact context that is retained for all consumers? First in can set the SHA-1 + String checksumSha1; + ChecksummedFile checksummedFile = new ChecksummedFile( artifactFile ); + try + { + checksumSha1 = checksummedFile.calculateChecksum( ChecksumAlgorithm.SHA1 ); + } + catch ( IOException e ) + { + throw new ConsumerException( e.getMessage(), e ); + } + + List<ArtifactMetadata> results = metadataRepository.getArtifactsByChecksum( repoId, checksumSha1 ); + + if ( CollectionUtils.isNotEmpty( results ) ) + { + if ( results.size() <= 1 ) + { + // No duplicates detected. + log.debug( "Found no duplicate artifact results on: " + path + " (repository " + repoId + ")" ); + return; + } + + ArtifactReference artifactReference; + try + { + artifactReference = repository.toArtifactReference( path ); + } + catch ( LayoutException e ) + { + log.warn( "Unable to report problem for path: " + path ); + return; + } + + for ( ArtifactMetadata dupArtifact : results ) + { + String id = path.substring( path.lastIndexOf( "/" ) + 1 ); + if ( dupArtifact.getId().equals( id ) && + dupArtifact.getNamespace().equals( artifactReference.getGroupId() ) && + dupArtifact.getProject().equals( artifactReference.getArtifactId() ) && + dupArtifact.getVersion().equals( artifactReference.getVersion() ) ) + { + // Skip reference to itself. + continue; + } + + RepositoryProblemFacet problem = new RepositoryProblemFacet(); + problem.setRepositoryId( repoId ); + problem.setNamespace( artifactReference.getGroupId() ); + problem.setProject( artifactReference.getArtifactId() ); + problem.setVersion( artifactReference.getVersion() ); + problem.setId( id ); + // TODO: proper path conversion for new metadata + problem.setMessage( + "Duplicate Artifact Detected: " + path + " <--> " + dupArtifact.getNamespace().replace( '.', '/' ) + + "/" + dupArtifact.getProject() + "/" + dupArtifact.getVersion() + "/" + dupArtifact.getId() ); + problem.setProblem( "duplicate-artifact" ); + + metadataRepository.addMetadataFacet( repoId, RepositoryProblemFacet.FACET_ID, problem ); + } + } + } + + public void completeScan() + { + // nothing to do + } + + public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + if ( ConfigurationNames.isRepositoryScanning( propertyName ) ) + { + initIncludes(); + } + } + + public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + /* do nothing */ + } + + private void initIncludes() + { + includes.clear(); + + includes.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) ); + } + + public void initialize() + throws InitializationException + { + initIncludes(); + configuration.addChangeListener( this ); + } +} diff --git a/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java b/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java index b47e1166f..561cf3c8c 100644 --- a/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java +++ b/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java @@ -19,9 +19,7 @@ package org.apache.archiva.metadata.repository.stats; * under the License. */ -import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -44,8 +42,6 @@ public class DefaultRepositoryStatisticsManager */ private MetadataRepository metadataRepository; - static final DateFormat SCAN_TIMESTAMP = new SimpleDateFormat( "yyyyMMdd.HHmmss.SSS" ); - public RepositoryStatistics getLastStatistics( String repositoryId ) { // TODO: consider a more efficient implementation that directly gets the last one from the content repository @@ -81,9 +77,7 @@ public class DefaultRepositoryStatisticsManager // populate total project count from content repository // repositoryStatistics.setTotalProjectCount( ); - metadataRepository.addMetadataFacet( repositoryId, RepositoryStatistics.FACET_ID, - SCAN_TIMESTAMP.format( repositoryStatistics.getScanStartTime() ), - repositoryStatistics ); + metadataRepository.addMetadataFacet( repositoryId, RepositoryStatistics.FACET_ID, repositoryStatistics ); } public void deleteStatistics( String repositoryId ) @@ -100,7 +94,7 @@ public class DefaultRepositoryStatisticsManager { try { - Date date = SCAN_TIMESTAMP.parse( name ); + Date date = RepositoryStatistics.SCAN_TIMESTAMP.parse( name ); if ( ( startTime == null || !date.before( startTime ) ) && ( endTime == null || !date.after( endTime ) ) ) { diff --git a/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/RepositoryStatistics.java b/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/RepositoryStatistics.java index efc26bf85..272d524dd 100644 --- a/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/RepositoryStatistics.java +++ b/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/RepositoryStatistics.java @@ -19,6 +19,8 @@ package org.apache.archiva.metadata.repository.stats; * under the License. */ +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -46,6 +48,8 @@ public class RepositoryStatistics public static String FACET_ID = "org.apache.archiva.metadata.repository.stats"; + static final DateFormat SCAN_TIMESTAMP = new SimpleDateFormat( "yyyyMMdd.HHmmss.SSS" ); + public Date getScanEndTime() { return scanEndTime; @@ -136,6 +140,11 @@ public class RepositoryStatistics return FACET_ID; } + public String getName() + { + return SCAN_TIMESTAMP.format( scanStartTime ); + } + public Map<String, String> toProperties() { Map<String, String> properties = new HashMap<String, String>(); diff --git a/archiva-modules/plugins/repository-statistics/src/test/java/org/apache/archiva/metadata/repository/stats/RepositoryStatisticsManagerTest.java b/archiva-modules/plugins/repository-statistics/src/test/java/org/apache/archiva/metadata/repository/stats/RepositoryStatisticsManagerTest.java index d561b77f3..d75e68330 100644 --- a/archiva-modules/plugins/repository-statistics/src/test/java/org/apache/archiva/metadata/repository/stats/RepositoryStatisticsManagerTest.java +++ b/archiva-modules/plugins/repository-statistics/src/test/java/org/apache/archiva/metadata/repository/stats/RepositoryStatisticsManagerTest.java @@ -65,11 +65,10 @@ public class RepositoryStatisticsManagerTest public void testGetLatestStats() throws ParseException { - Date endTime = - new Date( DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.parse( SECOND_TEST_SCAN ).getTime() + 60000 ); + Date endTime = new Date( RepositoryStatistics.SCAN_TIMESTAMP.parse( SECOND_TEST_SCAN ).getTime() + 60000 ); RepositoryStatistics stats = new RepositoryStatistics(); - stats.setScanStartTime( DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.parse( SECOND_TEST_SCAN ) ); + stats.setScanStartTime( RepositoryStatistics.SCAN_TIMESTAMP.parse( SECOND_TEST_SCAN ) ); stats.setScanEndTime( endTime ); stats.setTotalArtifactFileSize( 1314527915L ); stats.setNewFileCount( 123 ); @@ -94,8 +93,8 @@ public class RepositoryStatisticsManagerTest assertEquals( 2031, stats.getTotalProjectCount() ); assertEquals( 529, stats.getTotalGroupCount() ); assertEquals( 56229, stats.getTotalFileCount() ); - assertEquals( SECOND_TEST_SCAN, - DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.format( stats.getScanStartTime() ) ); + assertEquals( SECOND_TEST_SCAN, RepositoryStatistics.SCAN_TIMESTAMP.format( stats.getScanStartTime() ) ); + assertEquals( SECOND_TEST_SCAN, stats.getName() ); assertEquals( endTime, stats.getScanEndTime() ); metadataRepositoryControl.verify(); @@ -119,17 +118,15 @@ public class RepositoryStatisticsManagerTest Date current = new Date(); Date startTime = new Date( current.getTime() - 12345 ); - RepositoryStatistics stats1 = createTestStats( startTime, current ); + RepositoryStatistics stats = createTestStats( startTime, current ); - String startTimeAsString = DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.format( startTime ); - metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, startTimeAsString, stats1 ); + metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, stats ); metadataRepositoryControl.expectAndReturn( metadataRepository.getMetadataFacets( TEST_REPO_ID, RepositoryStatistics.FACET_ID ), - Arrays.asList( startTimeAsString ) ); + Arrays.asList( stats.getName() ) ); metadataRepositoryControl.expectAndReturn( - metadataRepository.getMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, startTimeAsString ), - stats1 ); - RepositoryStatistics stats = stats1; + metadataRepository.getMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, stats.getName() ), + stats ); metadataRepositoryControl.replay(); @@ -155,19 +152,17 @@ public class RepositoryStatisticsManagerTest Date startTime1 = new Date( current.getTime() - 12345 ); RepositoryStatistics stats1 = createTestStats( startTime1, new Date( current.getTime() - 6000 ) ); - String startTimeAsString1 = DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.format( startTime1 ); - metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, startTimeAsString1, stats1 ); + metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, stats1 ); Date startTime2 = new Date( current.getTime() - 3000 ); RepositoryStatistics stats2 = createTestStats( startTime2, current ); - String startTimeAsString2 = DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.format( startTime2 ); - metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, startTimeAsString2, stats2 ); + metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, stats2 ); metadataRepositoryControl.expectAndReturn( metadataRepository.getMetadataFacets( TEST_REPO_ID, RepositoryStatistics.FACET_ID ), - Arrays.asList( startTimeAsString1, startTimeAsString2 ) ); + Arrays.asList( stats1.getName(), stats2.getName() ) ); metadataRepositoryControl.expectAndReturn( - metadataRepository.getMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, startTimeAsString2 ), + metadataRepository.getMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, stats2.getName() ), stats2 ); metadataRepository.removeMetadataFacets( TEST_REPO_ID, RepositoryStatistics.FACET_ID ); @@ -230,7 +225,7 @@ public class RepositoryStatisticsManagerTest for ( RepositoryStatistics stats : statsCreated.values() ) { - repositoryStatisticsManager.addStatisticsAfterScan( TEST_REPO_ID, stats ); + repositoryStatisticsManager.addStatisticsAfterScan( TEST_REPO_ID, stats ); } List<RepositoryStatistics> list = @@ -396,9 +391,8 @@ public class RepositoryStatisticsManagerTest private void addStats( Date startTime, Date endTime ) { RepositoryStatistics stats = createTestStats( startTime, endTime ); - String startTimeAsString = DefaultRepositoryStatisticsManager.SCAN_TIMESTAMP.format( startTime ); - metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, startTimeAsString, stats ); - statsCreated.put( startTimeAsString, stats ); + metadataRepository.addMetadataFacet( TEST_REPO_ID, RepositoryStatistics.FACET_ID, stats ); + statsCreated.put( stats.getName(), stats ); } private RepositoryStatistics createTestStats( Date startTime, Date endTime ) |