Index: archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/RepositoryProblemReport.java
===================================================================
--- archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/RepositoryProblemReport.java	(revision 0)
+++ archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/RepositoryProblemReport.java	(revision 0)
@@ -0,0 +1,39 @@
+package org.apache.maven.archiva.model;
+
+public class RepositoryProblemReport extends RepositoryProblem
+{
+    protected String groupURL;
+
+    protected String artifactURL;
+
+    public RepositoryProblemReport( RepositoryProblem repositoryProblem )
+    {
+        setGroupId( repositoryProblem.getGroupId() );
+        setArtifactId( repositoryProblem.getArtifactId() );
+        setVersion( repositoryProblem.getVersion() );
+        setMessage( repositoryProblem.getMessage() );
+        setOrigin( repositoryProblem.getOrigin() );
+        setPath( repositoryProblem.getPath() );
+        setType( repositoryProblem.getType() );
+    }
+
+    public void setGroupURL( String groupURL )
+    {
+        this.groupURL = groupURL;
+    }
+
+    public String getGroupURL()
+    {
+        return groupURL; 
+    }
+
+    public void setArtifactURL( String artifactURL )
+    {
+        this.artifactURL = artifactURL;
+    }
+
+    public String getArtifactURL()
+    {
+        return artifactURL; 
+    }
+}

Property changes on: archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/RepositoryProblemReport.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java	(revision 558600)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java	(working copy)
@@ -39,6 +39,8 @@
 
     protected Object[] params;
 
+    protected int[] range;
+
     public String getFilter()
     {
         return null;
@@ -73,4 +75,9 @@
     {
         return variables;
     }
+
+    public int[] getRange()
+    {
+    	return range;
+    }
 }
Index: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RangeConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RangeConstraint.java	(revision 0)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RangeConstraint.java	(revision 0)
@@ -0,0 +1,48 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.Constraint;
+
+/**
+ * RangeConstraint
+ */
+public class RangeConstraint extends AbstractDeclarativeConstraint implements Constraint
+{
+    public RangeConstraint()
+    {
+        this.range = null;
+    }
+
+    public RangeConstraint( int[] range )
+    {
+        this.range = range;
+    }
+
+    public String getSortColumn()
+    {
+        return null;
+    }
+
+    public String getWhereCondition()
+    {
+        return null;
+    }
+}

Property changes on: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RangeConstraint.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraint.java	(revision 0)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraint.java	(revision 0)
@@ -0,0 +1,59 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.Constraint;
+
+/**
+ * RepositoryProblemByGroupIdConstraint
+ */
+public class RepositoryProblemByGroupIdConstraint extends RangeConstraint implements Constraint
+{
+    private String whereClause;
+
+    private void createWhereClause( String desiredGroupId )
+    {
+        whereClause = "groupId == desiredGroupId";
+        declParams = new String[] { "String desiredGroupId" };
+        params = new Object[] { desiredGroupId };
+    }
+
+    public RepositoryProblemByGroupIdConstraint( String desiredGroupId )
+    {
+        super();
+        createWhereClause( desiredGroupId );
+    }
+
+    public RepositoryProblemByGroupIdConstraint( int[] range, String desiredGroupId )
+    {
+        super( range );
+        createWhereClause( desiredGroupId );
+    }
+
+    public String getSortColumn()
+    {
+        return "artifactId";
+    }
+
+    public String getWhereCondition()
+    {
+        return whereClause;
+    }
+}

Property changes on: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraint.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraint.java	(revision 0)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraint.java	(revision 0)
@@ -0,0 +1,59 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.Constraint;
+
+/**
+ * RepositoryProblemByRepositoryIdConstraint
+ */
+public class RepositoryProblemByRepositoryIdConstraint extends RangeConstraint implements Constraint
+{
+    private String whereClause;
+
+    private void createWhereClause( String desiredRepositoryId )
+    {
+        whereClause = "repositoryId == desiredRepositoryId";
+        declParams = new String[] { "String desiredRepositoryId" };
+        params = new Object[] { desiredRepositoryId };
+    }
+
+    public RepositoryProblemByRepositoryIdConstraint( String desiredRepositoryId )
+    {
+        super();
+        createWhereClause( desiredRepositoryId );
+    }
+
+    public RepositoryProblemByRepositoryIdConstraint( int[] range, String desiredRepositoryId )
+    {
+        super( range );
+        createWhereClause( desiredRepositoryId );
+    }
+
+    public String getSortColumn()
+    {
+        return "groupId";
+    }
+
+    public String getWhereCondition()
+    {
+        return whereClause;
+    }
+}

Property changes on: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraint.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraint.java	(revision 0)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraint.java	(revision 0)
@@ -0,0 +1,59 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.Constraint;
+
+/**
+ * RepositoryProblemConstraint
+ */
+public class RepositoryProblemConstraint extends RangeConstraint implements Constraint
+{
+    private String whereClause;
+
+    private void createWhereClause( String desiredGroupId, String desiredRepositoryId )
+    {
+        whereClause = "groupId == desiredGroupId && repositoryId == desiredRepositoryId";
+        declParams = new String[] { "String desiredGroupId", "String desiredRepositoryId" };
+        params = new Object[] { desiredGroupId, desiredRepositoryId };
+    }
+
+    public RepositoryProblemConstraint( String desiredGroupId, String desiredRepositoryId )
+    {
+        super();
+        createWhereClause( desiredGroupId, desiredRepositoryId );
+    }
+
+    public RepositoryProblemConstraint( int[] range, String desiredGroupId, String desiredRepositoryId )
+    {
+        super( range );
+        createWhereClause( desiredGroupId, desiredRepositoryId );
+    }
+
+    public String getSortColumn()
+    {
+        return "artifactId";
+    }
+
+    public String getWhereCondition()
+    {
+        return whereClause;
+    }
+}

Property changes on: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraint.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraint.java	(revision 0)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraint.java	(revision 0)
@@ -0,0 +1,57 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.Constraint;
+
+/**
+ * UniqueFieldConstraint
+ */
+public class UniqueFieldConstraint extends AbstractSimpleConstraint implements Constraint
+{
+    private String sql;
+
+    public UniqueFieldConstraint( String className, String fieldName )
+    {
+        sql =
+            "SELECT " + fieldName + " FROM " + className + " GROUP BY " + fieldName + " ORDER BY " + fieldName
+                            + " ASCENDING";
+    }
+
+    public UniqueFieldConstraint( String className, String fieldName, String fieldNamePrefix )
+    {
+        sql =
+            "SELECT " + fieldName + " FROM " + className + " WHERE " + fieldName
+                            + ".startsWith( fieldPrefix ) PARAMETERS String fieldPrefix GROUP BY " + fieldName
+                            + " ORDER BY " + fieldName + " ASCENDING";
+
+        super.params = new Object[] { fieldNamePrefix };
+    }
+
+    public Class getResultClass()
+    {
+        return String.class;
+    }
+
+    public String getSelectSql()
+    {
+        return sql;
+    }
+}

Property changes on: archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraint.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/main/java/org/apache/maven/archiva/database/DeclarativeConstraint.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/DeclarativeConstraint.java	(revision 558600)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/DeclarativeConstraint.java	(working copy)
@@ -92,4 +92,13 @@
      * @return the equivalent of the SELECT WHERE (condition) value for this constraint. (can be null)
      */
     public abstract String getWhereCondition();
+
+    /**
+     * Get the declared range used for this query. (optional)
+     * 
+     * NOTE: This is DAO implementation specific.
+     * 
+     * @return the range. (can be null)
+     */
+    public abstract int[] getRange();
 }
\ No newline at end of file
Index: archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoAccess.java
===================================================================
--- archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoAccess.java	(revision 558600)
+++ archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoAccess.java	(working copy)
@@ -357,6 +357,11 @@
             query.declareImports( StringUtils.join( constraint.getDeclaredImports(), ", " ) );
         }
 
+        if ( constraint.getRange() != null )
+        {
+        	query.setRange( constraint.getRange()[0], constraint.getRange()[1] );
+        }
+
         if ( constraint.getDeclaredParameters() != null )
         {
             if ( constraint.getParameters() == null )
Index: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RangeConstraintTest.java
===================================================================
--- archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RangeConstraintTest.java	(revision 0)
+++ archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RangeConstraintTest.java	(revision 0)
@@ -0,0 +1,84 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.List;
+
+import org.apache.maven.archiva.database.AbstractArchivaDatabaseTestCase;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.RepositoryProblemDAO;
+import org.apache.maven.archiva.model.RepositoryProblem;
+
+/**
+ * RangeConstraintTest
+ */
+public class RangeConstraintTest extends AbstractArchivaDatabaseTestCase
+{
+    private RepositoryProblemDAO repoProblemDao;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" );
+        repoProblemDao = dao.getRepositoryProblemDAO();
+    }
+
+    public RepositoryProblem createRepoProblem()
+    {
+        RepositoryProblem repoProblem = new RepositoryProblem();
+
+        repoProblem.setGroupId( "groupId" );
+        repoProblem.setArtifactId( "artifactId" );
+        repoProblem.setMessage( "message" );
+        repoProblem.setOrigin( "origin" );
+        repoProblem.setPath( "path" );
+        repoProblem.setRepositoryId( "repositoryId" );
+        repoProblem.setType( "type" );
+        repoProblem.setVersion( "version" );
+
+        return repoProblem;
+    }
+
+    public void testConstraint() throws Exception
+    {
+        repoProblemDao.saveRepositoryProblem( createRepoProblem() );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem() );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem() );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem() );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem() );
+
+        assertConstraint( 0, new RangeConstraint( new int[]{ 5, 10 } ) );
+        assertConstraint( 1, new RangeConstraint( new int[]{ 0, 1 } ) );
+        assertConstraint( 2, new RangeConstraint( new int[]{ 0, 2 } ) );
+        assertConstraint( 3, new RangeConstraint( new int[]{ 0, 3 } ) );
+        assertConstraint( 4, new RangeConstraint( new int[]{ 0, 4 } ) );
+        assertConstraint( 5, new RangeConstraint( new int[]{ 0, 5 } ) );
+        assertConstraint( 5, new RangeConstraint() );
+    }
+
+    private void assertConstraint( int expectedHits, Constraint constraint ) throws Exception
+    {
+        List results = repoProblemDao.queryRepositoryProblems( constraint );
+        assertNotNull( "Range Constraint: Not Null", results );
+        assertEquals( "Range Constraint: Results.size", expectedHits, results.size() );
+    }
+}

Property changes on: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RangeConstraintTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraintTest.java
===================================================================
--- archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraintTest.java	(revision 0)
+++ archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraintTest.java	(revision 0)
@@ -0,0 +1,89 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.List;
+
+import org.apache.maven.archiva.database.AbstractArchivaDatabaseTestCase;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.RepositoryProblemDAO;
+import org.apache.maven.archiva.model.RepositoryProblem;
+
+/**
+ * RepositoryProblemByGroupIdConstraintTest
+ */
+public class RepositoryProblemByGroupIdConstraintTest extends AbstractArchivaDatabaseTestCase
+{
+    private static final String GROUP_ID_1 = "org.apache.maven.archiva.test.1";
+
+    private static final String GROUP_ID_2 = "org.apache.maven.archiva.test.2";
+
+    private static final String GROUP_ID_3 = "org.apache.maven.archiva.test.3";
+
+    private RepositoryProblemDAO repoProblemDao;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" );
+        repoProblemDao = dao.getRepositoryProblemDAO();
+    }
+
+    public RepositoryProblem createRepoProblem( String groupId )
+    {
+        RepositoryProblem repoProblem = new RepositoryProblem();
+
+        repoProblem.setGroupId( groupId );
+        repoProblem.setArtifactId( "artifactId" );
+        repoProblem.setMessage( "message" );
+        repoProblem.setOrigin( "origin" );
+        repoProblem.setPath( "path" );
+        repoProblem.setRepositoryId( "repositoryId" );
+        repoProblem.setType( "type" );
+        repoProblem.setVersion( "version" );
+
+        return repoProblem;
+    }
+
+    public void testConstraint() throws Exception
+    {
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_2 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_2 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3 ) );
+
+        assertConstraint( 1, new RepositoryProblemByGroupIdConstraint( GROUP_ID_1 ) );
+        assertConstraint( 2, new RepositoryProblemByGroupIdConstraint( GROUP_ID_2 ) );
+        assertConstraint( 3, new RepositoryProblemByGroupIdConstraint( GROUP_ID_3 ) );
+    }
+
+    private void assertConstraint( int expectedHits, Constraint constraint ) throws Exception
+    {
+        List results = repoProblemDao.queryRepositoryProblems( constraint );
+        assertNotNull( "Repository Problems by Group Id: Not Null", results );
+        assertEquals( "Repository Problems by Group Id: Results.size", expectedHits, results.size() );
+    }
+}

Property changes on: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByGroupIdConstraintTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraintTest.java
===================================================================
--- archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraintTest.java	(revision 0)
+++ archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraintTest.java	(revision 0)
@@ -0,0 +1,89 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.List;
+
+import org.apache.maven.archiva.database.AbstractArchivaDatabaseTestCase;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.RepositoryProblemDAO;
+import org.apache.maven.archiva.model.RepositoryProblem;
+
+/**
+ * RepositoryProblemByRepositoryIdConstraintTest
+ */
+public class RepositoryProblemByRepositoryIdConstraintTest extends AbstractArchivaDatabaseTestCase
+{
+    private static final String REPO_ID_1 = "test-repo-1";
+
+    private static final String REPO_ID_2 = "test-repo-2";
+
+    private static final String REPO_ID_3 = "test-repo-3";
+
+    private RepositoryProblemDAO repoProblemDao;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" );
+        repoProblemDao = dao.getRepositoryProblemDAO();
+    }
+
+    public RepositoryProblem createRepoProblem( String repoId )
+    {
+        RepositoryProblem repoProblem = new RepositoryProblem();
+
+        repoProblem.setGroupId( "groupId" );
+        repoProblem.setArtifactId( "artifactId" );
+        repoProblem.setMessage( "message" );
+        repoProblem.setOrigin( "origin" );
+        repoProblem.setPath( "path" );
+        repoProblem.setRepositoryId( repoId );
+        repoProblem.setType( "type" );
+        repoProblem.setVersion( "version" );
+
+        return repoProblem;
+    }
+
+    public void testConstraint() throws Exception
+    {
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( REPO_ID_1 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( REPO_ID_2 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( REPO_ID_2 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( REPO_ID_3 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( REPO_ID_3 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( REPO_ID_3 ) );
+
+        assertConstraint( 1, new RepositoryProblemByRepositoryIdConstraint( REPO_ID_1 ) );
+        assertConstraint( 2, new RepositoryProblemByRepositoryIdConstraint( REPO_ID_2 ) );
+        assertConstraint( 3, new RepositoryProblemByRepositoryIdConstraint( REPO_ID_3 ) );
+    }
+
+    private void assertConstraint( int expectedHits, Constraint constraint ) throws Exception
+    {
+        List results = repoProblemDao.queryRepositoryProblems( constraint );
+        assertNotNull( "Repository Problems by Repository Id: Not Null", results );
+        assertEquals( "Repository Problems by Repository Id: Results.size", expectedHits, results.size() );
+    }
+}

Property changes on: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemByRepositoryIdConstraintTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraintTest.java
===================================================================
--- archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraintTest.java	(revision 0)
+++ archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraintTest.java	(revision 0)
@@ -0,0 +1,117 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.List;
+
+import org.apache.maven.archiva.database.AbstractArchivaDatabaseTestCase;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.RepositoryProblemDAO;
+import org.apache.maven.archiva.model.RepositoryProblem;
+
+/**
+ * RepositoryProblemConstraintTest
+ */
+public class RepositoryProblemConstraintTest extends AbstractArchivaDatabaseTestCase
+{
+    private static final String GROUP_ID_1 = "org.apache.maven.archiva.test.1";
+
+    private static final String GROUP_ID_2 = "org.apache.maven.archiva.test.2";
+
+    private static final String GROUP_ID_3 = "org.apache.maven.archiva.test.3";
+
+    private static final String GROUP_ID_4 = "org.apache.maven.archiva.test.4";
+
+    private static final String REPO_ID_1 = "test-repo-1";
+
+    private static final String REPO_ID_2 = "test-repo-2";
+
+    private static final String REPO_ID_3 = "test-repo-3";
+
+    private static final String REPO_ID_4 = "test-repo-4";
+
+    private RepositoryProblemDAO repoProblemDao;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" );
+        repoProblemDao = dao.getRepositoryProblemDAO();
+    }
+
+    public RepositoryProblem createRepoProblem( String groupId, String repoId )
+    {
+        RepositoryProblem repoProblem = new RepositoryProblem();
+
+        repoProblem.setGroupId( groupId );
+        repoProblem.setArtifactId( "artifactId" );
+        repoProblem.setMessage( "message" );
+        repoProblem.setOrigin( "origin" );
+        repoProblem.setPath( "path" );
+        repoProblem.setRepositoryId( repoId );
+        repoProblem.setType( "type" );
+        repoProblem.setVersion( "version" );
+
+        return repoProblem;
+    }
+
+    public void testGroupIdConstraint() throws Exception
+    {
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_1 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_2, REPO_ID_1 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_2, REPO_ID_1 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3, REPO_ID_1 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3, REPO_ID_1 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3, REPO_ID_1 ) );
+
+        assertConstraint( 1, new RepositoryProblemConstraint( GROUP_ID_1, REPO_ID_1 ) );
+        assertConstraint( 2, new RepositoryProblemConstraint( GROUP_ID_2, REPO_ID_1 ) );
+        assertConstraint( 3, new RepositoryProblemConstraint( GROUP_ID_3, REPO_ID_1 ) );
+        assertConstraint( 0, new RepositoryProblemConstraint( GROUP_ID_4, REPO_ID_1 ) );
+    }
+
+    public void testRepoIdConstraint() throws Exception
+    {
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_1 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_2 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_2 ) );
+
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_3 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_3 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1, REPO_ID_3 ) );
+
+        assertConstraint( 1, new RepositoryProblemConstraint( GROUP_ID_1, REPO_ID_1 ) );
+        assertConstraint( 2, new RepositoryProblemConstraint( GROUP_ID_1, REPO_ID_2 ) );
+        assertConstraint( 3, new RepositoryProblemConstraint( GROUP_ID_1, REPO_ID_3 ) );
+        assertConstraint( 0, new RepositoryProblemConstraint( GROUP_ID_1, REPO_ID_4 ) );
+    }
+
+    private void assertConstraint( int expectedHits, Constraint constraint ) throws Exception
+    {
+        List results = repoProblemDao.queryRepositoryProblems( constraint );
+        assertNotNull( "Repository Problems: Not Null", results );
+        assertEquals( "Repository Problems: Results.size", expectedHits, results.size() );
+    }
+}

Property changes on: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryProblemConstraintTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraintTest.java
===================================================================
--- archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraintTest.java	(revision 0)
+++ archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraintTest.java	(revision 0)
@@ -0,0 +1,112 @@
+package org.apache.maven.archiva.database.constraints;
+
+/*
+ * 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.Date;
+import java.util.List;
+
+import org.apache.maven.archiva.database.AbstractArchivaDatabaseTestCase;
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArtifactDAO;
+import org.apache.maven.archiva.database.RepositoryProblemDAO;
+import org.apache.maven.archiva.database.SimpleConstraint;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.ArchivaArtifactModel;
+import org.apache.maven.archiva.model.RepositoryProblem;
+
+/**
+ * UniqueFieldConstraintTest
+ */
+public class UniqueFieldConstraintTest extends AbstractArchivaDatabaseTestCase
+{
+    private static final String GROUP_ID_1 = "org.apache.maven.archiva.test.1";
+
+    private static final String GROUP_ID_2 = "org.apache.maven.archiva.test.2";
+
+    private static final String GROUP_ID_3 = "org.apache.maven.archiva.test.3";
+
+    private ArchivaDAO archivaDao;
+
+    private ArtifactDAO artifactDao;
+
+    private RepositoryProblemDAO repoProblemDao;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        archivaDao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" );
+        artifactDao = archivaDao.getArtifactDAO();
+        repoProblemDao = archivaDao.getRepositoryProblemDAO();
+    }
+
+    public ArchivaArtifact createArtifact( String groupId )
+    {
+        ArchivaArtifact artifact = artifactDao.createArtifact( groupId, "artifactId", "version", "classifier", "jar" );
+
+        artifact.getModel().setLastModified( new Date() );
+        artifact.getModel().setRepositoryId( "repoId" );
+
+        return artifact;
+    }
+
+    public RepositoryProblem createRepoProblem( String groupId )
+    {
+        RepositoryProblem repoProblem = new RepositoryProblem();
+
+        repoProblem.setGroupId( groupId );
+        repoProblem.setArtifactId( "artifactId" );
+        repoProblem.setMessage( "message" );
+        repoProblem.setOrigin( "origin" );
+        repoProblem.setPath( "path" );
+        repoProblem.setRepositoryId( "repoId" );
+        repoProblem.setType( "type" );
+        repoProblem.setVersion( "version" );
+
+        return repoProblem;
+    }
+
+    public void testArtifact() throws Exception
+    {
+        artifactDao.saveArtifact( createArtifact( GROUP_ID_1 ) );
+        artifactDao.saveArtifact( createArtifact( GROUP_ID_2 ) );
+        artifactDao.saveArtifact( createArtifact( GROUP_ID_3 ) );
+
+        assertConstraint( 1, new UniqueFieldConstraint( ArchivaArtifactModel.class.getName(), "artifactId" ) );
+        assertConstraint( 3, new UniqueFieldConstraint( ArchivaArtifactModel.class.getName(), "groupId" ) );
+    }
+
+    public void testRepoProblem() throws Exception
+    {
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_1 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_2 ) );
+        repoProblemDao.saveRepositoryProblem( createRepoProblem( GROUP_ID_3 ) );
+
+        assertConstraint( 1, new UniqueFieldConstraint( RepositoryProblem.class.getName(), "artifactId" ) );
+        assertConstraint( 3, new UniqueFieldConstraint( RepositoryProblem.class.getName(), "groupId" ) );
+    }
+
+    private void assertConstraint( int expectedHits, SimpleConstraint constraint ) throws Exception
+    {
+        List results = archivaDao.query( constraint );
+        assertNotNull( "Repository Problems: Not Null", results );
+        assertEquals( "Repository Problems: Results.size", expectedHits, results.size() );
+    }
+}

Property changes on: archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueFieldConstraintTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-web/archiva-webapp/pom.xml
===================================================================
--- archiva-web/archiva-webapp/pom.xml	(revision 558600)
+++ archiva-web/archiva-webapp/pom.xml	(working copy)
@@ -211,6 +211,11 @@
       <artifactId>activation</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>jasperreports</groupId>
+      <artifactId>jasperreports</artifactId>
+      <version>1.2.0</version>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -249,6 +254,8 @@
                 <!-- Directory created by jetty:run -->
                 <include>WEB-INF/temp</include>
                 <!-- Directory created by jetty:run -->
+                <include>WEB-INF/jasperreports</include>
+                <!-- Directory created by jasperreports-maven-plugin -->
               </includes>
             </fileset>
           </filesets>
@@ -397,6 +404,22 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>jasperreports-maven-plugin</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <executions>
+          <execution>
+            <phase>compile</phase>
+            <goals>
+              <goal>compile-reports</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <targetDirectory>src/main/webapp/WEB-INF/jasperreports</targetDirectory>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
   <profiles>
@@ -443,4 +466,16 @@
       </build>
     </profile>
    </profiles>
+  <pluginRepositories>
+    <pluginRepository>
+      <id>Codehaus Snapshots</id>
+      <url>http://snapshots.repository.codehaus.org/</url>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+    </pluginRepository>
+  </pluginRepositories>
 </project>
Index: archiva-web/archiva-webapp/src/main/jasperreports/report.jrxml
===================================================================
--- archiva-web/archiva-webapp/src/main/jasperreports/report.jrxml	(revision 0)
+++ archiva-web/archiva-webapp/src/main/jasperreports/report.jrxml	(revision 0)
@@ -0,0 +1,170 @@
+<?xml version="1.0"?>
+<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
+<jasperReport name="ArchivaReport"
+              pageWidth="1040">
+  <field name="groupId" class="java.lang.String"/>
+  <field name="artifactId" class="java.lang.String"/>
+  <field name="version" class="java.lang.String"/>
+  <field name="message" class="java.lang.String"/>
+  <field name="origin" class="java.lang.String"/>
+  <field name="path" class="java.lang.String"/>
+  <field name="type" class="java.lang.String"/>
+  <field name="groupURL" class="java.lang.String"/>
+  <field name="artifactURL" class="java.lang.String"/>
+  <field name="prev" class="java.lang.String"/>
+  <field name="next" class="java.lang.String"/>
+  <field name="page" class="java.lang.Integer"/>
+  <field name="isLastPage" class="java.lang.Boolean"/>
+  <title>
+    <band height="50">
+      <staticText>
+        <reportElement x="0" y="0" width="1040" height="50"/>
+        <textElement textAlignment="Center">
+          <font size="14" isBold="true"/>
+        </textElement>
+        <text><![CDATA[Archiva Report]]></text>
+      </staticText>
+    </band>
+  </title>
+  <pageHeader>
+    <band></band>
+  </pageHeader>
+  <columnHeader>
+    <band height="20">
+      <staticText>
+        <reportElement x="0" y="0" width="200" height="20"/>
+        <box leftBorder="Thin"
+             leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             topBorder="Thin"
+             bottomBorder="Thin"/>
+        <textElement textAlignment="Center">
+          <font size="12"/>
+        </textElement>
+        <text><![CDATA[Group Id]]></text>
+      </staticText>
+      <staticText>
+        <reportElement x="200" y="0" width="200" height="20"/>
+        <box leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             topBorder="Thin"
+             bottomBorder="Thin"/>
+        <textElement textAlignment="Center">
+          <font size="12"/>
+        </textElement>
+        <text><![CDATA[Artifact Id]]></text>
+      </staticText>
+      <staticText>
+        <reportElement x="400" y="0" width="200" height="20"/>
+        <box leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             topBorder="Thin"
+             bottomBorder="Thin"/>
+        <textElement textAlignment="Center">
+          <font size="12"/>
+        </textElement>
+        <text><![CDATA[Version]]></text>
+      </staticText>
+      <staticText>
+        <reportElement x="600" y="0" width="300" height="20"/>
+        <box leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             topBorder="Thin"
+             bottomBorder="Thin"/>
+        <textElement textAlignment="Center">
+          <font size="12"/>
+        </textElement>
+        <text><![CDATA[Message]]></text>
+      </staticText>
+    </band>
+  </columnHeader>
+  <detail>
+    <band height="20">
+      <textField isBlankWhenNull="true" hyperlinkType="Reference" hyperlinkTarget="Self">
+        <reportElement x="0" y="0" width="200" height="15"/>
+        <box leftBorder="Thin"
+             leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             bottomBorder="Thin"/>
+        <textFieldExpression>
+          <![CDATA[$F{groupId}]]>
+        </textFieldExpression>
+        <hyperlinkReferenceExpression><![CDATA[$F{groupURL}]]></hyperlinkReferenceExpression>
+      </textField>
+      <textField isBlankWhenNull="true" hyperlinkType="Reference" hyperlinkTarget="Self">
+        <reportElement x="200" y="0" width="200" height="15"/>
+        <box leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             bottomBorder="Thin"/>
+        <textFieldExpression>
+          <![CDATA[$F{artifactId}]]>
+        </textFieldExpression>
+        <hyperlinkReferenceExpression><![CDATA[$F{artifactURL}]]></hyperlinkReferenceExpression>
+      </textField>
+      <textField isBlankWhenNull="true">
+        <reportElement x="400" y="0" width="200" height="15"/>
+        <box leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             bottomBorder="Thin"/>
+        <textFieldExpression>
+          <![CDATA[$F{version}]]>
+        </textFieldExpression>
+      </textField>
+      <textField isBlankWhenNull="true" isStretchWithOverflow="true">
+        <reportElement x="600" y="0" width="300" height="15"/>
+        <box leftPadding="10"
+             rightBorder="Thin"
+             rightPadding="10"
+             bottomBorder="Thin"/>
+        <textFieldExpression>
+          <![CDATA[$F{message}]]>
+        </textFieldExpression>
+      </textField>
+    </band>
+  </detail>
+  <columnFooter>
+    <band></band>
+  </columnFooter>
+  <pageFooter>
+    <band height="15">
+      <textField>
+        <reportElement x="0" y="0" width="50" height="15"/>
+        <textFieldExpression>
+          <![CDATA["Page: " + $F{page}]]>
+        </textFieldExpression>
+      </textField>
+      <textField hyperlinkType="Reference" hyperlinkTarget="Self">
+        <reportElement x="50" y="0" width="50" height="15">
+          <printWhenExpression>
+            <![CDATA[$F{page}.intValue() != 1]]>
+          </printWhenExpression>
+        </reportElement>
+        <textFieldExpression>
+          <![CDATA["prev"]]>
+        </textFieldExpression>
+        <hyperlinkReferenceExpression><![CDATA[$F{prev}]]></hyperlinkReferenceExpression>
+      </textField>
+      <textField hyperlinkType="Reference" hyperlinkTarget="Self">
+        <reportElement x="100" y="0" width="50" height="15">
+          <printWhenExpression>
+            <![CDATA[$F{isLastPage} != true]]>
+          </printWhenExpression>
+        </reportElement>
+        <textFieldExpression>
+          <![CDATA["next"]]>
+        </textFieldExpression>
+        <hyperlinkReferenceExpression><![CDATA[$F{next}]]></hyperlinkReferenceExpression>
+      </textField>
+    </band>
+  </pageFooter>
+  <summary>
+    <band></band>
+  </summary>
+</jasperReport>

Property changes on: archiva-web/archiva-webapp/src/main/jasperreports/report.jrxml
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java
===================================================================
--- archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java	(revision 0)
+++ archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java	(revision 0)
@@ -0,0 +1,228 @@
+package org.apache.maven.archiva.web.action.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.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.Constraint;
+import org.apache.maven.archiva.database.constraints.RangeConstraint;
+import org.apache.maven.archiva.database.constraints.RepositoryProblemByGroupIdConstraint;
+import org.apache.maven.archiva.database.constraints.RepositoryProblemByRepositoryIdConstraint;
+import org.apache.maven.archiva.database.constraints.RepositoryProblemConstraint;
+import org.apache.maven.archiva.model.RepositoryProblem;
+import org.apache.maven.archiva.model.RepositoryProblemReport;
+import org.apache.maven.archiva.security.ArchivaRoleConstants;
+import org.codehaus.plexus.redback.rbac.Resource;
+import org.codehaus.plexus.redback.xwork.interceptor.SecureAction;
+import org.codehaus.plexus.redback.xwork.interceptor.SecureActionBundle;
+import org.codehaus.plexus.redback.xwork.interceptor.SecureActionException;
+import org.codehaus.plexus.xwork.action.PlexusActionSupport;
+
+import com.opensymphony.webwork.interceptor.ServletRequestAware;
+
+/**
+ * @plexus.component role="com.opensymphony.xwork.Action" role-hint="generateReportAction"
+ */
+public class GenerateReportAction extends PlexusActionSupport implements SecureAction, ServletRequestAware
+{
+    /**
+     * @plexus.requirement role-hint="jdo"
+     */
+    protected ArchivaDAO dao;
+
+    protected Constraint constraint;
+
+    protected HttpServletRequest request;
+
+    protected List reports = new ArrayList();
+
+    protected String groupId;
+
+    protected String repositoryId;
+
+    protected String prev;
+
+    protected String next;
+
+    protected int[] range = new int[2];
+
+    protected int page = 1;
+
+    protected int rowCount = 100;
+
+    protected boolean isLastPage = false;
+
+    public static final String BLANK = "blank";
+
+    public String execute() throws Exception
+    {
+        List problemArtifacts = dao.getRepositoryProblemDAO().queryRepositoryProblems( configureConstraint() );
+
+        String contextPath =
+            request.getRequestURL().substring( 0, request.getRequestURL().indexOf( request.getRequestURI() ) );
+        RepositoryProblem problemArtifact;
+        RepositoryProblemReport problemArtifactReport;
+        for ( int i = 0; i < problemArtifacts.size(); i++ )
+        {
+            problemArtifact = (RepositoryProblem) problemArtifacts.get( i );
+            problemArtifactReport = new RepositoryProblemReport( problemArtifact );
+
+            problemArtifactReport.setGroupURL( contextPath + "/browse/" + problemArtifact.getGroupId() );
+            problemArtifactReport.setArtifactURL( contextPath + "/browse/" + problemArtifact.getGroupId() + "/"
+                            + problemArtifact.getArtifactId() );
+
+            reports.add( problemArtifactReport );
+        }
+
+        if ( reports.size() <= rowCount )
+        {
+            isLastPage = true;
+        }
+        else
+        {
+            reports.remove( rowCount );
+        }
+
+        prev =
+            request.getRequestURL() + "?page=" + ( page - 1 ) + "&rowCount=" + rowCount + "&groupId=" + groupId
+                            + "&repositoryId=" + repositoryId;
+        next =
+            request.getRequestURL() + "?page=" + ( page + 1 ) + "&rowCount=" + rowCount + "&groupId=" + groupId
+                            + "&repositoryId=" + repositoryId;
+
+        if ( reports.size() == 0 && page == 1 )
+        {
+            return BLANK;
+        }
+        else
+        {
+            return SUCCESS;
+        }
+    }
+
+    private Constraint configureConstraint()
+    {
+        Constraint constraint;
+
+        range[0] = ( page - 1 ) * rowCount;
+        range[1] = ( page * rowCount ) + 1; // Add 1 to check if it's the last page or not.
+
+        if ( groupId != null && ( !groupId.equals( "" ) ) )
+        {
+            if ( repositoryId != null && ( !repositoryId.equals( "" ) ) )
+            {
+                constraint = new RepositoryProblemConstraint( range, groupId, repositoryId );
+            }
+            else
+            {
+                constraint = new RepositoryProblemByGroupIdConstraint( range, groupId );
+            }
+        }
+        else if ( repositoryId != null && ( !repositoryId.equals( "" ) ) )
+        {
+            constraint = new RepositoryProblemByRepositoryIdConstraint( range, repositoryId );
+        }
+        else
+        {
+            constraint = new RangeConstraint( range );
+        }
+
+        return constraint;
+    }
+
+    public void setServletRequest( HttpServletRequest request )
+    {
+        this.request = request;
+    }
+
+    public List getReports()
+    {
+        return reports;
+    }
+
+    public String getGroupId()
+    {
+        return groupId;
+    }
+
+    public void setGroupId( String groupId )
+    {
+        this.groupId = groupId;
+    }
+
+    public String getRepositoryId()
+    {
+        return repositoryId;
+    }
+
+    public void setRepositoryId( String repositoryId )
+    {
+        this.repositoryId = repositoryId;
+    }
+
+    public String getPrev()
+    {
+        return prev;
+    }
+
+    public String getNext()
+    {
+        return next;
+    }
+
+    public int getPage()
+    {
+        return page;
+    }
+
+    public void setPage( int page )
+    {
+        this.page = page;
+    }
+
+    public int getRowCount()
+    {
+        return rowCount;
+    }
+
+    public void setRowCount( int rowCount )
+    {
+        this.rowCount = rowCount;
+    }
+
+    public boolean getIsLastPage()
+    {
+        return isLastPage;
+    }
+
+    public SecureActionBundle getSecureActionBundle() throws SecureActionException
+    {
+        SecureActionBundle bundle = new SecureActionBundle();
+
+        bundle.setRequiresAuthentication( true );
+        bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL );
+
+        return bundle;
+    }
+}

Property changes on: archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/ShowReportsAction.java
===================================================================
--- archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/ShowReportsAction.java	(revision 0)
+++ archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/ShowReportsAction.java	(revision 0)
@@ -0,0 +1,58 @@
+package org.apache.maven.archiva.web.action.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.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.constraints.UniqueGroupIdConstraint;
+import org.apache.maven.archiva.database.constraints.UniqueFieldConstraint;
+import org.apache.maven.archiva.model.RepositoryProblem;
+import org.codehaus.plexus.xwork.action.PlexusActionSupport;
+
+/**
+ * Show reports.
+ * 
+ * @plexus.component role="com.opensymphony.xwork.Action" role-hint="showReportsAction"
+ */
+public class ShowReportsAction extends PlexusActionSupport
+{
+    /**
+     * @plexus.requirement role-hint="jdo"
+     */
+    protected ArchivaDAO dao;
+
+    private Collection repositoryIds = new ArrayList();
+
+    public String execute() throws Exception
+    {
+        repositoryIds.add( "" );
+        repositoryIds.addAll( dao.query( new UniqueFieldConstraint( RepositoryProblem.class.getName(), "repositoryId" ) ) );
+
+        return SUCCESS;
+    }
+
+    public Collection getRepositoryIds()
+    {
+        return repositoryIds;
+    }
+}

Property changes on: archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/ShowReportsAction.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-web/archiva-webapp/src/main/resources/xwork.xml
===================================================================
--- archiva-web/archiva-webapp/src/main/resources/xwork.xml	(revision 558600)
+++ archiva-web/archiva-webapp/src/main/resources/xwork.xml	(working copy)
@@ -368,17 +368,6 @@
       <interceptor-ref name="unconfiguredArchivaStack"/>
     </action>
 
-    <action name="reports" class="reportsAction">
-      <result>/WEB-INF/jsp/reports/reports.jsp</result>
-    </action>
-
-    <action name="runReport" class="reportsAction" method="runReport">
-      <interceptor-ref name="configuredArchivaStack"/>
-      <interceptor-ref name="execAndWait"/>
-      <result name="wait" type="redirect">/admin/reports.action?reportGroup=${reportGroup}&amp;repositoryId=${repositoryId}&amp;filter=${filter}</result>
-      <result name="success" type="redirect">/admin/reports.action?reportGroup=${reportGroup}&amp;repositoryId=${repositoryId}&amp;filter=${filter}</result>
-    </action>
-    
     <!-- The following are needed by the maven-app-configuration-web artifact -->
 
     <action name="configureAppearance" class="configureAppearance" method="input">
@@ -409,5 +398,20 @@
       </result>
     </action>
   </package>
+
+  <package name="report" namespace="/report" extends="base">
+    <action name="showReports" class="showReportsAction">
+      <result>/WEB-INF/jsp/reports/showReports.jsp</result>
+    </action>
+
+    <action name="generateReportAction" class="generateReportAction">
+      <result name="success" type="jasper">
+        <param name="location">/WEB-INF/jasperreports/report.jasper</param>
+        <param name="dataSource">reports</param>
+        <param name="format">HTML</param>
+      </result>
+      <result name="blank">/WEB-INF/jsp/reports/blankReport.jsp</result>
+    </action>
+  </package>
 </xwork>
 
Index: archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp
===================================================================
--- archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp	(revision 558600)
+++ archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp	(working copy)
@@ -98,13 +98,11 @@
     <redback:ifAnyAuthorized permissions="archiva-manage-users,archiva-access-reports,archiva-manage-configuration">
       <h5>Manage</h5>
       <ul>
-         <%-- POSTPONED to 1.0-alpha-2 
         <redback:ifAuthorized permission="archiva-access-reports">
           <li class="none">
-            <my:currentWWUrl action="reports" namespace="/admin">Reports</my:currentWWUrl>
+            <my:currentWWUrl action="showReports" namespace="/report">Show Reports</my:currentWWUrl>
           </li>
         </redback:ifAuthorized>
-          --%>
           <%-- POSTPONED to 1.1 series
                 <li class="none">
                   <a href="#">Synchronisation</a>
Index: archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/blankReport.jsp
===================================================================
--- archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/blankReport.jsp	(revision 0)
+++ archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/blankReport.jsp	(revision 0)
@@ -0,0 +1,36 @@
+<%--
+  ~ 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.
+  --%>
+
+<%@ taglib prefix="ww" uri="/webwork" %>
+
+<html>
+<head>
+  <title>Reports</title>
+  <ww:head/>
+</head>
+
+<body>
+<h1>Reports</h1>
+<div id="contentArea">
+
+  <ww:text name="The operation generated an empty report."/>
+
+</div>
+</body>
+</html>

Property changes on: archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/blankReport.jsp
___________________________________________________________________
Name: svn:eol-style
   + native

Index: archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/showReports.jsp
===================================================================
--- archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/showReports.jsp	(revision 0)
+++ archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/showReports.jsp	(revision 0)
@@ -0,0 +1,42 @@
+<%--
+  ~ 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.
+  --%>
+
+<%@ taglib prefix="ww" uri="/webwork" %>
+
+<html>
+<head>
+  <title>Reports</title>
+  <ww:head/>
+</head>
+
+<body>
+<h1>Reports</h1>
+<div id="contentArea">
+
+  <ww:form action="generateReportAction" namespace="/report">
+    <ww:textfield label="Row Count" name="rowCount" value="100"/>
+    <ww:textfield label="Group ID" name="groupId"/>
+    <ww:select label="Repository ID" name="repositoryId" list="repositoryIds"/>
+    <ww:submit value="Show Report"/>
+  </ww:form>
+
+</div>
+
+</body>
+</html>

Property changes on: archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/showReports.jsp
___________________________________________________________________
Name: svn:eol-style
   + native

