aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-reporting/archiva-artifact-reports
diff options
context:
space:
mode:
authorJoakim Erdfelt <joakime@apache.org>2007-04-19 12:25:11 +0000
committerJoakim Erdfelt <joakime@apache.org>2007-04-19 12:25:11 +0000
commit8b0319bf628d8ba366d2c12791db67c340dc0076 (patch)
tree06240146f2f875508c60b11908f5d7c4fdc597c4 /archiva-reporting/archiva-artifact-reports
parent346583093493614302e3761b3de1c2d8ff67a806 (diff)
downloadarchiva-8b0319bf628d8ba366d2c12791db67c340dc0076.tar.gz
archiva-8b0319bf628d8ba366d2c12791db67c340dc0076.zip
Refactoring of reporting. One step closer to an end-to-end compile.
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches/archiva-jpox-database-refactor@530395 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-reporting/archiva-artifact-reports')
-rwxr-xr-xarchiva-reporting/archiva-artifact-reports/pom.xml84
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReport.java80
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactsConsumer.java228
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsConsumer.java366
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsReport.java81
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldArtifactReport.java76
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldSnapshotArtifactReport.java76
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/AbstractArtifactReportsTestCase.java126
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReportTest.java168
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/test/resources/META-INF/plexus/components.xml75
-rw-r--r--archiva-reporting/archiva-artifact-reports/src/test/resources/log4j.xml76
11 files changed, 1436 insertions, 0 deletions
diff --git a/archiva-reporting/archiva-artifact-reports/pom.xml b/archiva-reporting/archiva-artifact-reports/pom.xml
new file mode 100755
index 000000000..f2da3aa20
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/pom.xml
@@ -0,0 +1,84 @@
+<?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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.maven.archiva</groupId>
+ <artifactId>archiva-reporting</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>archiva-artifact-reports</artifactId>
+ <name>Archiva Reporting :: Artifact Reports</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.archiva</groupId>
+ <artifactId>archiva-report-manager</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.archiva</groupId>
+ <artifactId>archiva-database</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.archiva</groupId>
+ <artifactId>archiva-repository-layer</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-container-default</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus.registry</groupId>
+ <artifactId>plexus-registry-commons</artifactId>
+ <version>1.0-alpha-2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>1.8.0.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>1.2_Java1.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-slf4j-logging</artifactId>
+ <version>1.1-alpha-1-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReport.java b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReport.java
new file mode 100644
index 000000000..f4e82152d
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReport.java
@@ -0,0 +1,80 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.database.constraints.RepositoryProblemByTypeConstraint;
+import org.apache.maven.archiva.reporting.DataLimits;
+import org.apache.maven.archiva.reporting.DynamicReportSource;
+
+import java.util.List;
+
+/**
+ * DuplicateArtifactReport
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.reporting.DynamicReportSource"
+ * role-hint="duplicate-artifacts"
+ */
+public class DuplicateArtifactReport
+ implements DynamicReportSource
+{
+ public static final String PROBLEM_TYPE_DUPLICATE_ARTIFACTS = "duplicate-artifacts";
+
+ /**
+ * @plexus.configuration default-value="Duplicate Artifact Report"
+ */
+ private String name;
+
+ /**
+ * @plexus.requirement
+ */
+ private ArchivaDAO dao;
+
+ private Constraint constraint;
+
+ public DuplicateArtifactReport()
+ {
+ constraint = new RepositoryProblemByTypeConstraint( PROBLEM_TYPE_DUPLICATE_ARTIFACTS );
+ }
+
+ public List getData()
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ return dao.getRepositoryProblemDAO().queryRepositoryProblems( constraint );
+ }
+
+ public List getData( DataLimits limits )
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ // TODO: implement limits.
+ return dao.getRepositoryProblemDAO().queryRepositoryProblems( constraint );
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactsConsumer.java b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactsConsumer.java
new file mode 100644
index 000000000..ad6bb675f
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactsConsumer.java
@@ -0,0 +1,228 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.commons.collections.CollectionUtils;
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.ConfigurationNames;
+import org.apache.maven.archiva.configuration.FileType;
+import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
+import org.apache.maven.archiva.consumers.ArchivaArtifactConsumer;
+import org.apache.maven.archiva.consumers.ConsumerException;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.database.constraints.ArtifactsBySha1ChecksumConstraint;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.RepositoryProblem;
+import org.apache.maven.archiva.reporting.artifact.DuplicateArtifactReport;
+import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout;
+import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayoutFactory;
+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 java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Search the database of known SHA1 Checksums for potential duplicate artifacts.
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.consumers.ArchivaArtifactConsumer"
+ * role-hint="duplicate-artifacts"
+ */
+public class DuplicateArtifactsConsumer
+ extends AbstractMonitoredConsumer
+ implements ArchivaArtifactConsumer, RegistryListener, Initializable
+{
+ /**
+ * @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 role-hint="jdo"
+ */
+ private ArchivaDAO dao;
+
+ /**
+ * @plexus.requirement
+ */
+ private BidirectionalRepositoryLayoutFactory layoutFactory;
+
+ private List includes = new ArrayList();
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public boolean isPermanent()
+ {
+ return false;
+ }
+
+ public void beginScan()
+ {
+ /* do nothing */
+ }
+
+ public void completeScan()
+ {
+ /* do nothing */
+ }
+
+ public List getIncludedTypes()
+ {
+ return null;
+ }
+
+ public void processArchivaArtifact( ArchivaArtifact artifact )
+ throws ConsumerException
+ {
+ String checksumSha1 = artifact.getModel().getChecksumSHA1();
+
+ List results = null;
+ try
+ {
+ results = dao.getArtifactDAO().queryArtifacts( new ArtifactsBySha1ChecksumConstraint( checksumSha1 ) );
+ }
+ catch ( ObjectNotFoundException e )
+ {
+ getLogger().debug( "No duplicates for artifact: " + artifact );
+ return;
+ }
+ catch ( ArchivaDatabaseException e )
+ {
+ getLogger().warn( "Unable to query DB for potential duplicates with : " + artifact );
+ return;
+ }
+
+ if ( CollectionUtils.isNotEmpty( results ) )
+ {
+ if ( results.size() <= 1 )
+ {
+ // No duplicates detected.
+ getLogger().debug( "Found no duplicate artifact results on: " + artifact );
+ return;
+ }
+
+ Iterator it = results.iterator();
+ while ( it.hasNext() )
+ {
+ ArchivaArtifact dupArtifact = (ArchivaArtifact) it.next();
+
+ if( dupArtifact.equals( artifact ) )
+ {
+ // Skip reference to itself.
+ continue;
+ }
+
+ RepositoryProblem problem = new RepositoryProblem();
+ problem.setRepositoryId( dupArtifact.getModel().getRepositoryId() );
+ problem.setPath( toPath( dupArtifact ) );
+ problem.setGroupId( artifact.getGroupId() );
+ problem.setArtifactId( artifact.getArtifactId() );
+ problem.setVersion( artifact.getVersion() );
+ problem.setType( DuplicateArtifactReport.PROBLEM_TYPE_DUPLICATE_ARTIFACTS );
+ problem.setOrigin( getId() );
+ problem.setMessage( "Duplicate Artifact Detected: " + artifact + " <--> " + dupArtifact );
+
+ try
+ {
+ getLogger().debug( "Found duplicate artifact: " + problem );
+ dao.getRepositoryProblemDAO().saveRepositoryProblem( problem );
+ }
+ catch ( ArchivaDatabaseException e )
+ {
+ String emsg = "Unable to save problem with duplicate artifact to DB: " + e.getMessage();
+ getLogger().warn( emsg, e );
+ throw new ConsumerException( emsg, e );
+ }
+ }
+ }
+ }
+
+ private String toPath( ArchivaArtifact artifact )
+ {
+ try
+ {
+ BidirectionalRepositoryLayout layout = layoutFactory.getLayout( artifact );
+ return layout.toPath( artifact );
+ }
+ catch ( LayoutException e )
+ {
+ getLogger().warn( "Unable to calculate path for artifact: " + artifact );
+ return "";
+ }
+ }
+
+ 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();
+
+ FileType artifactTypes = configuration.getConfiguration().getRepositoryScanning().getFileTypeById( "artifacts" );
+ if ( artifactTypes != null )
+ {
+ includes.addAll( artifactTypes.getPatterns() );
+ }
+ }
+
+ public void initialize()
+ throws InitializationException
+ {
+ initIncludes();
+ configuration.addChangeListener( this );
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsConsumer.java b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsConsumer.java
new file mode 100644
index 000000000..3a350f54f
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsConsumer.java
@@ -0,0 +1,366 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.commons.lang.StringUtils;
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.ConfigurationNames;
+import org.apache.maven.archiva.configuration.FileType;
+import org.apache.maven.archiva.configuration.RepositoryConfiguration;
+import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
+import org.apache.maven.archiva.consumers.ArchivaArtifactConsumer;
+import org.apache.maven.archiva.consumers.ConsumerException;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.ArchivaProjectModel;
+import org.apache.maven.archiva.model.ArchivaRepository;
+import org.apache.maven.archiva.model.RepositoryProblem;
+import org.apache.maven.archiva.repository.ArchivaConfigurationAdaptor;
+import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout;
+import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayoutFactory;
+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.codehaus.plexus.util.SelectorUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Validate the location of the artifact based on the values indicated
+ * in its pom (both the pom packaged with the artifact & the pom in the
+ * file system).
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.consumers.ArchivaArtifactConsumer"
+ * role-hint="validate-artifacts-location"
+ */
+public class LocationArtifactsConsumer
+ extends AbstractMonitoredConsumer
+ implements ArchivaArtifactConsumer, RegistryListener, Initializable
+{
+ /**
+ * @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 role-hint="jdo"
+ */
+ private ArchivaDAO dao;
+
+ /**
+ * @plexus.requirement
+ */
+ private BidirectionalRepositoryLayoutFactory layoutFactory;
+
+ private Map repositoryMap = new HashMap();
+
+ private List includes = new ArrayList();
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public boolean isPermanent()
+ {
+ return false;
+ }
+
+ public void beginScan()
+ {
+ /* do nothing */
+ }
+
+ public void completeScan()
+ {
+ /* do nothing */
+ }
+
+ public List getIncludedTypes()
+ {
+ return null;
+ }
+
+ /**
+ * Check whether the artifact is in its proper location. The location of the artifact
+ * is validated first against the groupId, artifactId and versionId in the specified model
+ * object (pom in the file system). Then unpack the artifact (jar file) and get the model (pom)
+ * included in the package. If a model exists inside the package, then check if the artifact's
+ * location is valid based on the location specified in the pom. Check if the both the location
+ * specified in the file system pom and in the pom included in the package is the same.
+ */
+ public void processArchivaArtifact( ArchivaArtifact artifact )
+ throws ConsumerException
+ {
+ ArchivaRepository repository = findRepository( artifact );
+ if ( !repository.isManaged() )
+ {
+ getLogger().warn( "Artifact Location Validation Cannot operate against a non-managed Repository." );
+ return;
+ }
+
+ File artifactFile = new File( repository.getUrl().toString(), toPath( artifact ) );
+ ArchivaProjectModel fsModel = readFilesystemModel( artifactFile );
+ ArchivaProjectModel embeddedModel = readEmbeddedModel( artifact, artifactFile );
+
+ validateAppropriateModel( "Filesystem", artifact, fsModel );
+ validateAppropriateModel( "Embedded", artifact, embeddedModel );
+ }
+
+ private void validateAppropriateModel( String location, ArchivaArtifact artifact, ArchivaProjectModel model )
+ throws ConsumerException
+ {
+ if ( model != null )
+ {
+ if ( !StringUtils.equals( model.getGroupId(), artifact.getGroupId() ) )
+ {
+ addProblem( artifact, "The groupId of the " + location
+ + " project model doesn't match with the artifact, expected <" + artifact.getGroupId()
+ + ">, but was actually <" + model.getGroupId() + ">" );
+ }
+
+ if ( !StringUtils.equals( model.getArtifactId(), artifact.getArtifactId() ) )
+ {
+ addProblem( artifact, "The artifactId of the " + location
+ + " project model doesn't match with the artifact, expected <" + artifact.getArtifactId()
+ + ">, but was actually <" + model.getArtifactId() + ">" );
+ }
+
+ if ( !StringUtils.equals( model.getVersion(), artifact.getVersion() ) )
+ {
+ addProblem( artifact, "The version of the " + location
+ + " project model doesn't match with the artifact, expected <" + artifact.getVersion()
+ + ">, but was actually <" + model.getVersion() + ">" );
+ }
+ }
+ }
+
+ private ArchivaProjectModel readEmbeddedModel( ArchivaArtifact artifact, File artifactFile )
+ throws ConsumerException
+ {
+ try
+ {
+ JarFile jar = new JarFile( artifactFile );
+
+ // Get the entry and its input stream.
+ JarEntry expectedEntry = jar.getJarEntry( "META-INF/maven/" + artifact.getGroupId() + "/"
+ + artifact.getArtifactId() + "/pom.xml" );
+
+ if ( expectedEntry != null )
+ {
+ // TODO: read and resolve model here.
+ return null;
+ }
+
+ /* Expected Entry not found, look for alternate that might
+ * indicate that the artifact is, indeed located in the wrong place.
+ */
+
+ List actualPomXmls = findJarEntryPattern( jar, "META-INF/maven/**/pom.xml" );
+ if ( actualPomXmls.isEmpty() )
+ {
+ // No check needed.
+
+ }
+
+ // TODO: test for invalid actual pom.xml
+ // TODO: test
+ }
+ catch ( IOException e )
+ {
+ // Not able to read from the file.
+ String emsg = "Unable to read file contents: " + e.getMessage();
+ addProblem( artifact, emsg );
+ }
+
+ return null;
+ }
+
+ private List findJarEntryPattern( JarFile jar, String pattern )
+ {
+ List hits = new ArrayList();
+
+ Enumeration entries = jar.entries();
+ while ( entries.hasMoreElements() )
+ {
+ JarEntry entry = (JarEntry) entries.nextElement();
+ if ( SelectorUtils.match( pattern, entry.getName() ) )
+ {
+ hits.add( entry );
+ }
+ }
+
+ return hits;
+ }
+
+ private void addProblem( ArchivaArtifact artifact, String msg )
+ throws ConsumerException
+ {
+ RepositoryProblem problem = new RepositoryProblem();
+ problem.setRepositoryId( artifact.getModel().getRepositoryId() );
+ problem.setPath( toPath( artifact ) );
+ problem.setGroupId( artifact.getGroupId() );
+ problem.setArtifactId( artifact.getArtifactId() );
+ problem.setVersion( artifact.getVersion() );
+ problem.setType( LocationArtifactsReport.PROBLEM_TYPE_BAD_ARTIFACT_LOCATION );
+ problem.setOrigin( getId() );
+ problem.setMessage( msg );
+
+ try
+ {
+ dao.getRepositoryProblemDAO().saveRepositoryProblem( problem );
+ }
+ catch ( ArchivaDatabaseException e )
+ {
+ String emsg = "Unable to save problem with artifact location to DB: " + e.getMessage();
+ getLogger().warn( emsg, e );
+ throw new ConsumerException( emsg, e );
+ }
+ }
+
+ private ArchivaProjectModel readFilesystemModel( File artifactFile )
+ {
+ File pomFile = createPomFileReference( artifactFile );
+
+ // TODO: read and resolve model here.
+
+ return null;
+ }
+
+ private File createPomFileReference( File artifactFile )
+ {
+ String pomFilename = artifactFile.getAbsolutePath();
+
+ int pos = pomFilename.lastIndexOf( '.' );
+ if ( pos <= 0 )
+ {
+ // Invalid filename.
+ return null;
+ }
+
+ pomFilename = pomFilename.substring( 0, pos ) + ".pom";
+ return new File( pomFilename );
+ }
+
+ private ArchivaRepository findRepository( ArchivaArtifact artifact )
+ {
+ return (ArchivaRepository) this.repositoryMap.get( artifact.getModel().getRepositoryId() );
+ }
+
+ private String toPath( ArchivaArtifact artifact )
+ {
+ try
+ {
+ BidirectionalRepositoryLayout layout = layoutFactory.getLayout( artifact );
+ return layout.toPath( artifact );
+ }
+ catch ( LayoutException e )
+ {
+ getLogger().warn( "Unable to calculate path for artifact: " + artifact );
+ return null;
+ }
+ }
+
+ public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
+ {
+ if ( ConfigurationNames.isRepositories( propertyName ) )
+ {
+ initRepositoryMap();
+ }
+
+ if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
+ {
+ initIncludes();
+ }
+ }
+
+ public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
+ {
+ /* do nothing */
+ }
+
+ private void initIncludes()
+ {
+ includes.clear();
+
+ FileType artifactTypes = configuration.getConfiguration().getRepositoryScanning().getFileTypeById( "artifacts" );
+ if ( artifactTypes != null )
+ {
+ includes.addAll( artifactTypes.getPatterns() );
+ }
+ }
+
+ private void initRepositoryMap()
+ {
+ synchronized ( this.repositoryMap )
+ {
+ this.repositoryMap.clear();
+
+ Iterator it = configuration.getConfiguration().createRepositoryMap().entrySet().iterator();
+ while ( it.hasNext() )
+ {
+ Map.Entry entry = (Entry) it.next();
+ String key = (String) entry.getKey();
+ RepositoryConfiguration repoConfig = (RepositoryConfiguration) entry.getValue();
+ ArchivaRepository repository = ArchivaConfigurationAdaptor.toArchivaRepository( repoConfig );
+ this.repositoryMap.put( key, repository );
+ }
+ }
+ }
+
+ public void initialize()
+ throws InitializationException
+ {
+ initRepositoryMap();
+ initIncludes();
+ configuration.addChangeListener( this );
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsReport.java b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsReport.java
new file mode 100644
index 000000000..3cca3fa13
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/LocationArtifactsReport.java
@@ -0,0 +1,81 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.database.constraints.RepositoryProblemByTypeConstraint;
+import org.apache.maven.archiva.reporting.DataLimits;
+import org.apache.maven.archiva.reporting.DynamicReportSource;
+
+import java.util.List;
+
+/**
+ * LocationArtifactsReport
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.reporting.DynamicReportSource"
+ * role-hint="artifact-location"
+ */
+public class LocationArtifactsReport
+ implements DynamicReportSource
+{
+ public static final String PROBLEM_TYPE_BAD_ARTIFACT_LOCATION = "bad-artifact-location";
+
+ /**
+ * @plexus.configuration default-value="Artifact Locations Report"
+ */
+ private String name;
+
+ /**
+ * @plexus.requirement
+ */
+ private ArchivaDAO dao;
+
+ private Constraint constraint;
+
+ public LocationArtifactsReport()
+ {
+ constraint = new RepositoryProblemByTypeConstraint( PROBLEM_TYPE_BAD_ARTIFACT_LOCATION );
+ }
+
+ public List getData()
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ return dao.getRepositoryProblemDAO().queryRepositoryProblems( constraint );
+ }
+
+ public List getData( DataLimits limits )
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ // TODO: implement limits.
+ return dao.getRepositoryProblemDAO().queryRepositoryProblems( constraint );
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldArtifactReport.java b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldArtifactReport.java
new file mode 100644
index 000000000..6691314e2
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldArtifactReport.java
@@ -0,0 +1,76 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.database.constraints.OlderArtifactsByAgeConstraint;
+import org.apache.maven.archiva.reporting.DataLimits;
+import org.apache.maven.archiva.reporting.DynamicReportSource;
+
+import java.util.List;
+
+/**
+ * OldArtifactReport
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.reporting.DynamicReportSource"
+ * role-hint="old-artifacts"
+ */
+public class OldArtifactReport
+ implements DynamicReportSource
+{
+ /**
+ * @plexus.configuration default-value="Old Artifacts Report"
+ */
+ private String name;
+
+ /**
+ * @plexus.requirement
+ */
+ private ArchivaDAO dao;
+
+ /**
+ * The maximum age of an artifact before it is reported old, specified in days. The default is 1 year.
+ *
+ * @plexus.configuration default-value="365"
+ */
+ private int cutoffDays;
+
+ public List getData()
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ return dao.getArtifactDAO().queryArtifacts( new OlderArtifactsByAgeConstraint( cutoffDays ) );
+ }
+
+ public List getData( DataLimits limits )
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ return dao.getArtifactDAO().queryArtifacts( new OlderArtifactsByAgeConstraint( cutoffDays ) );
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldSnapshotArtifactReport.java b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldSnapshotArtifactReport.java
new file mode 100644
index 000000000..e039f6048
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/main/java/org/apache/maven/archiva/reporting/artifact/OldSnapshotArtifactReport.java
@@ -0,0 +1,76 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.database.constraints.OlderSnapshotArtifactsByAgeConstraint;
+import org.apache.maven.archiva.reporting.DataLimits;
+import org.apache.maven.archiva.reporting.DynamicReportSource;
+
+import java.util.List;
+
+/**
+ * OldSnapshotArtifactReport
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.reporting.DynamicReportSource"
+ * role-hint="old-snapshots"
+ */
+public class OldSnapshotArtifactReport
+ implements DynamicReportSource
+{
+ /**
+ * @plexus.configuration default-value="Old Snapshots Report"
+ */
+ private String name;
+
+ /**
+ * @plexus.requirement
+ */
+ private ArchivaDAO dao;
+
+ /**
+ * The maximum age of a snapshot before it is reported old, specified in days. The default is 1 year.
+ *
+ * @plexus.configuration default-value="365"
+ */
+ private int cutoffDays;
+
+ public List getData()
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ return dao.getArtifactDAO().queryArtifacts( new OlderSnapshotArtifactsByAgeConstraint( cutoffDays ) );
+ }
+
+ public List getData( DataLimits limits )
+ throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ return dao.getArtifactDAO().queryArtifacts( new OlderSnapshotArtifactsByAgeConstraint( cutoffDays ) );
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/AbstractArtifactReportsTestCase.java b/archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/AbstractArtifactReportsTestCase.java
new file mode 100644
index 000000000..a59e84bca
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/AbstractArtifactReportsTestCase.java
@@ -0,0 +1,126 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.maven.archiva.database.ArchivaDAO;
+import org.codehaus.plexus.PlexusTestCase;
+import org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory;
+import org.codehaus.plexus.jdo.JdoFactory;
+import org.jpox.SchemaTool;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+
+/**
+ * AbstractArtifactReportsTestCase
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class AbstractArtifactReportsTestCase
+ extends PlexusTestCase
+{
+ protected ArchivaDAO dao;
+
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ DefaultConfigurableJdoFactory jdoFactory = (DefaultConfigurableJdoFactory) lookup( JdoFactory.ROLE, "archiva" );
+ assertEquals( DefaultConfigurableJdoFactory.class.getName(), jdoFactory.getClass().getName() );
+
+ jdoFactory.setPersistenceManagerFactoryClass( "org.jpox.PersistenceManagerFactoryImpl" );
+
+ /* derby version
+ File derbyDbDir = new File( "target/plexus-home/testdb" );
+ if ( derbyDbDir.exists() )
+ {
+ FileUtils.deleteDirectory( derbyDbDir );
+ }
+
+ jdoFactory.setDriverName( System.getProperty( "jdo.test.driver", "org.apache.derby.jdbc.EmbeddedDriver" ) );
+ jdoFactory.setUrl( System.getProperty( "jdo.test.url", "jdbc:derby:" + derbyDbDir.getAbsolutePath() + ";create=true" ) );
+ */
+
+ jdoFactory.setDriverName( System.getProperty( "jdo.test.driver", "org.hsqldb.jdbcDriver" ) );
+ jdoFactory.setUrl( System.getProperty( "jdo.test.url", "jdbc:hsqldb:mem:" + getName() ) );
+
+ jdoFactory.setUserName( System.getProperty( "jdo.test.user", "sa" ) );
+
+ jdoFactory.setPassword( System.getProperty( "jdo.test.pass", "" ) );
+
+ jdoFactory.setProperty( "org.jpox.transactionIsolation", "READ_COMMITTED" );
+
+ jdoFactory.setProperty( "org.jpox.poid.transactionIsolation", "READ_COMMITTED" );
+
+ jdoFactory.setProperty( "org.jpox.autoCreateSchema", "true" );
+
+ jdoFactory.setProperty( "javax.jdo.option.RetainValues", "true" );
+
+ jdoFactory.setProperty( "javax.jdo.option.RestoreValues", "true" );
+
+ // jdoFactory.setProperty( "org.jpox.autoCreateColumns", "true" );
+
+ jdoFactory.setProperty( "org.jpox.validateTables", "true" );
+
+ jdoFactory.setProperty( "org.jpox.validateColumns", "true" );
+
+ jdoFactory.setProperty( "org.jpox.validateConstraints", "true" );
+
+ Properties properties = jdoFactory.getProperties();
+
+ for ( Iterator it = properties.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+
+ System.setProperty( (String) entry.getKey(), (String) entry.getValue() );
+ }
+
+ URL jdoFileUrls[] = new URL[] { getClass().getResource( "/org/apache/maven/archiva/model/package.jdo" ) };
+
+ if ( ( jdoFileUrls == null ) || ( jdoFileUrls[0] == null ) )
+ {
+ fail( "Unable to process test " + getName() + " - missing package.jdo." );
+ }
+
+ File propsFile = null; // intentional
+ boolean verbose = true;
+
+ SchemaTool.deleteSchemaTables( jdoFileUrls, new URL[] {}, propsFile, verbose );
+ SchemaTool.createSchemaTables( jdoFileUrls, new URL[] {}, propsFile, verbose, null );
+
+ PersistenceManagerFactory pmf = jdoFactory.getPersistenceManagerFactory();
+
+ assertNotNull( pmf );
+
+ PersistenceManager pm = pmf.getPersistenceManager();
+
+ pm.close();
+
+ this.dao = (ArchivaDAO) lookup( ArchivaDAO.class.getName(), "jdo" );
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReportTest.java b/archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReportTest.java
new file mode 100644
index 000000000..e6824de1e
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/test/java/org/apache/maven/archiva/reporting/artifact/DuplicateArtifactReportTest.java
@@ -0,0 +1,168 @@
+package org.apache.maven.archiva.reporting.artifact;
+
+/*
+ * 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.commons.io.FileUtils;
+import org.apache.maven.archiva.common.utils.PathUtil;
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.RepositoryConfiguration;
+import org.apache.maven.archiva.consumers.ArchivaArtifactConsumer;
+import org.apache.maven.archiva.database.ArtifactDAO;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.RepositoryProblem;
+import org.apache.maven.archiva.reporting.DynamicReportSource;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * DuplicateArtifactReportTest
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class DuplicateArtifactReportTest
+ extends AbstractArtifactReportsTestCase
+{
+ private static final String TESTABLE_REPO = "testable";
+
+ private static final String HASH3 = "f3f653289f3217c65324830ab3415bc92feddefa";
+
+ private static final String HASH2 = "a49810ad3eba8651677ab57cd40a0f76fdef9538";
+
+ private static final String HASH1 = "232f01b24b1617c46a3d4b0ab3415bc9237dcdec";
+
+ private ArtifactDAO artifactDao;
+
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ artifactDao = dao.getArtifactDAO();
+
+ ArchivaConfiguration config = (ArchivaConfiguration) lookup( ArchivaConfiguration.class.getName() );
+
+ RepositoryConfiguration repoConfig = new RepositoryConfiguration();
+ repoConfig.setId( TESTABLE_REPO );
+ repoConfig.setLayout( "default" );
+ File testRepoDir = new File( getBasedir(), "target/test-repository" );
+ FileUtils.forceMkdir( testRepoDir );
+ repoConfig.setUrl( PathUtil.toUrl( testRepoDir ) );
+ config.getConfiguration().addRepository( repoConfig );
+ }
+
+ public ArchivaArtifact createArtifact( String artifactId, String version )
+ {
+ ArchivaArtifact artifact = artifactDao.createArtifact( "org.apache.maven.archiva.test", artifactId, version,
+ "", "jar" );
+ artifact.getModel().setLastModified( new Date() );
+ artifact.getModel().setRepositoryId( TESTABLE_REPO );
+ return artifact;
+ }
+
+ public void testSimpleReport()
+ throws Exception
+ {
+ ArchivaArtifact artifact;
+
+ // Setup artifacts in fresh DB.
+ artifact = createArtifact( "test-one", "1.0" );
+ artifact.getModel().setChecksumSHA1( HASH1 );
+ artifactDao.saveArtifact( artifact );
+
+ artifact = createArtifact( "test-one", "1.1" );
+ artifact.getModel().setChecksumSHA1( HASH1 );
+ artifactDao.saveArtifact( artifact );
+
+ artifact = createArtifact( "test-one", "1.2" );
+ artifact.getModel().setChecksumSHA1( HASH1 );
+ artifactDao.saveArtifact( artifact );
+
+ artifact = createArtifact( "test-two", "1.0" );
+ artifact.getModel().setChecksumSHA1( HASH1 );
+ artifactDao.saveArtifact( artifact );
+
+ artifact = createArtifact( "test-two", "2.0" );
+ artifact.getModel().setChecksumSHA1( HASH3 );
+ artifactDao.saveArtifact( artifact );
+
+ artifact = createArtifact( "test-two", "2.1" );
+ artifact.getModel().setChecksumSHA1( HASH2 );
+ artifactDao.saveArtifact( artifact );
+
+ artifact = createArtifact( "test-two", "3.0" );
+ artifact.getModel().setChecksumSHA1( HASH2 );
+ artifactDao.saveArtifact( artifact );
+
+ // Setup entries for bad/duplicate in problem DB.
+ pretendToRunDuplicateArtifactsConsumer();
+
+ List allArtifacts = artifactDao.queryArtifacts( null );
+ assertEquals( "Total Artifact Count", 7, allArtifacts.size() );
+
+ DuplicateArtifactReport report = (DuplicateArtifactReport) lookup( DynamicReportSource.class.getName(),
+ "duplicate-artifacts" );
+
+ List results = report.getData();
+
+ System.out.println( "Results.size: " + results.size() );
+ int i = 0;
+ Iterator it = results.iterator();
+ while ( it.hasNext() )
+ {
+ RepositoryProblem problem = (RepositoryProblem) it.next();
+ System.out.println( "[" + ( i++ ) + "] " + problem.getMessage() );
+ }
+
+ int hash1Count = 4;
+ int hash2Count = 2;
+ int hash3Count = 1;
+
+ int totals = ( ( hash1Count * hash1Count ) - hash1Count ) +
+ ( ( hash2Count * hash2Count ) - hash2Count ) +
+ ( ( hash3Count * hash3Count ) - hash3Count );
+ assertEquals( "Total report hits.", totals, results.size() );
+ }
+
+ private void pretendToRunDuplicateArtifactsConsumer()
+ throws Exception
+ {
+ List artifacts = dao.getArtifactDAO().queryArtifacts( null );
+ ArchivaArtifactConsumer consumer = (ArchivaArtifactConsumer) lookup( ArchivaArtifactConsumer.class.getName(),
+ "duplicate-artifacts" );
+ consumer.beginScan();
+ try
+ {
+ Iterator it = artifacts.iterator();
+ while ( it.hasNext() )
+ {
+ ArchivaArtifact artifact = (ArchivaArtifact) it.next();
+ consumer.processArchivaArtifact( artifact );
+ }
+ }
+ finally
+ {
+ consumer.completeScan();
+ }
+ }
+}
diff --git a/archiva-reporting/archiva-artifact-reports/src/test/resources/META-INF/plexus/components.xml b/archiva-reporting/archiva-artifact-reports/src/test/resources/META-INF/plexus/components.xml
new file mode 100644
index 000000000..d9d54741b
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/test/resources/META-INF/plexus/components.xml
@@ -0,0 +1,75 @@
+<component-set>
+ <components>
+ <component>
+ <role>org.codehaus.plexus.jdo.JdoFactory</role>
+ <role-hint>archiva</role-hint>
+ <implementation>org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory</implementation>
+ <configuration>
+ <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
+ <otherProperties>
+ <property>
+ <name>javax.jdo.PersistenceManagerFactoryClass</name>
+ <value>org.jpox.PersistenceManagerFactoryImpl</value>
+ </property>
+ </otherProperties>
+ </configuration>
+ </component>
+
+ <component>
+ <role>org.codehaus.plexus.registry.Registry</role>
+ <implementation>org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry</implementation>
+ <role-hint>commons-configuration</role-hint>
+ <configuration>
+ <properties>
+ <system />
+ <xml fileName="${appserver.base}/conf/archiva.xml" config-optional="true"
+ config-name="org.apache.maven.archiva.base" config-at="org.apache.maven.archiva" />
+ <xml fileName="${appserver.home}/conf/archiva.xml" config-optional="true"
+ config-at="org.apache.maven.archiva" />
+ <xml fileName="${user.home}/.m2/archiva.xml" config-optional="true"
+ config-name="org.apache.maven.archiva.user" config-at="org.apache.maven.archiva" />
+ <xml fileName="org/apache/maven/archiva/configuration/default-archiva.xml" config-optional="true"
+ config-at="org.apache.maven.archiva" />
+ </properties>
+ </configuration>
+ </component>
+
+ <component>
+ <role>org.codehaus.plexus.logging.LoggerManager</role>
+ <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
+ </component>
+ </components>
+
+ <lifecycle-handler-manager implementation="org.codehaus.plexus.lifecycle.DefaultLifecycleHandlerManager">
+ <default-lifecycle-handler-id>plexus</default-lifecycle-handler-id>
+ <lifecycle-handlers>
+ <lifecycle-handler implementation="org.codehaus.plexus.personality.plexus.PlexusLifecycleHandler">
+ <id>plexus</id>
+ <name>Plexus Lifecycle Handler</name>
+ <begin-segment>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogEnablePhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.CompositionPhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ContextualizePhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.AutoConfigurePhase"/>
+ <phase implementation="org.codehaus.plexus.registry.RegistryConfigurePhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ServiceablePhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializePhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StartPhase"/>
+ </begin-segment>
+ <suspend-segment>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.SuspendPhase"/>
+ </suspend-segment>
+ <resume-segment>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ResumePhase"/>
+ </resume-segment>
+ <end-segment>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StopPhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.DisposePhase"/>
+ <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogDisablePhase"/>
+ </end-segment>
+ </lifecycle-handler>
+ </lifecycle-handlers>
+ </lifecycle-handler-manager>
+
+</component-set>
+
diff --git a/archiva-reporting/archiva-artifact-reports/src/test/resources/log4j.xml b/archiva-reporting/archiva-artifact-reports/src/test/resources/log4j.xml
new file mode 100644
index 000000000..395941ac3
--- /dev/null
+++ b/archiva-reporting/archiva-artifact-reports/src/test/resources/log4j.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d [%t] %-5p %-30c{1} - %m%n"/>
+ </layout>
+ </appender>
+
+ <!-- Help identify bugs during testing -->
+ <logger name="org.apache.maven">
+ <level value="info"/>
+ </logger>
+
+ <logger name="org.codehaus.plexus.security">
+ <level value="info"/>
+ </logger>
+
+ <!-- squelch noisy objects (for now) -->
+ <logger name="org.codehaus.plexus.mailsender.MailSender">
+ <level value="info"/>
+ </logger>
+
+ <logger name="org.quartz">
+ <level value="info"/>
+ </logger>
+
+ <logger name="org.apache.jasper">
+ <level value="info"/>
+ </logger>
+
+ <logger name="com.opensymphony.xwork">
+ <level value="info"/>
+ </logger>
+
+ <logger name="com.opensymphony.webwork">
+ <level value="info"/>
+ </logger>
+
+ <logger name="org.codehaus.plexus.PlexusContainer">
+ <level value="info"/>
+ </logger>
+
+ <logger name="JPOX">
+ <level value="warn"/>
+ </logger>
+
+ <logger name="JPOX.MetaData">
+ <level value="error"/>
+ </logger>
+
+ <logger name="JPOX.RDBMS.SQL">
+ <level value="error"/>
+ </logger>
+
+ <logger name="SQL">
+ <level value="error"/>
+ </logger>
+
+ <logger name="freemarker">
+ <level value="warn"/>
+ </logger>
+
+ <logger name="org.codehaus.plexus.component.manager.ClassicSingletonComponentManager">
+ <level value="error"/>
+ </logger>
+
+ <root>
+ <priority value ="info" />
+ <appender-ref ref="console" />
+ </root>
+
+</log4j:configuration>