]> source.dussan.org Git - archiva.git/commitdiff
Merging from trunk
authorJames William Dumay <jdumay@apache.org>
Sat, 18 Oct 2008 06:45:02 +0000 (06:45 +0000)
committerJames William Dumay <jdumay@apache.org>
Sat, 18 Oct 2008 06:45:02 +0000 (06:45 +0000)
git-svn-id: https://svn.apache.org/repos/asf/archiva/branches@705848 13f79535-47bb-0310-9956-ffa450edef68

75 files changed:
archiva-struts2/archiva-docs/pom.xml
archiva-struts2/archiva-docs/src/site/apt/release-notes.apt
archiva-struts2/archiva-docs/src/site/site.xml
archiva-struts2/archiva-jetty/pom.xml
archiva-struts2/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/VersionUtil.java
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/main/java/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumer.java
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/java/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumerTest.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumerTest.xml [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-api/2.4.4/test-project-api-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-broker-ejb/2.4.4/test-project-broker-ejb-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-broker-pom/2.4.4/test-project-broker-pom-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-common/2.4.4/test-project-common-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-endpoint-pom/2.4.4/test-project-endpoint-pom-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project/2.4.4/test-project-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-model/src/main/mdo/archiva-base.xml
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/content/FilenameParser.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/project/ProjectModelMerge.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/project/filters/EffectiveProjectModelFilter.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/project/filters/ProjectModelExpressionFilter.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/project/readers/ProjectModel300Reader.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/project/readers/ProjectModel400Reader.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/expected-poms/archiva-model-effective.pom
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/expected-poms/test-project-model-effective.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/content/DefaultPathParserTest.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/content/FilenameParserTest.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/project/filters/EffectiveProjectModelFilterTest.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/project/readers/ProjectModel400ReaderTest.java
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/org/apache/maven/archiva/archiva-model/1.0-SNAPSHOT/archiva-model-1.0-SNAPSHOT.pom
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-api/2.4.4/test-project-api-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-broker-ejb/2.4.4/test-project-broker-ejb-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-broker-pom/2.4.4/test-project-broker-pom-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-common/2.4.4/test-project-common-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-endpoint-pom/2.4.4/test-project-endpoint-pom-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project/2.4.4/test-project-2.4.4.pom [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java
archiva-struts2/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraint.java
archiva-struts2/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraint.java
archiva-struts2/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java
archiva-struts2/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/project/ProjectModelToDatabaseListener.java
archiva-struts2/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraintTest.java
archiva-struts2/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraintTest.java
archiva-struts2/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraintTest.java
archiva-struts2/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java
archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/pom.xml
archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaRepositoryScanningTaskExecutor.java
archiva-struts2/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaXworkUser.java
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java
archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/reports/GenerateReportAction-validation.xml [deleted file]
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryGroups.jsp
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css
archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/archiva-splat-32.gif
archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java
archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java
archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java
archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml [new file with mode: 0644]
archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml
archiva-struts2/pom.xml

index bd38f139e223dafd9b4f5921ed00522ad529c24c..fe78803d507432a6bb09478d92fec2709acdf579 100644 (file)
               </execution>
             </executions>
           </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-enforcer-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>enforce-beanshell</id>
+                <goals>
+                  <goal>enforce</goal>
+                </goals>
+                <configuration>
+                  <rules>
+                    <evaluateBeanshell>
+                      <message>Site descriptor needs to be updated for the current release version</message>
+                      <condition>
+                        <![CDATA[
+                          javax.xml.xpath.XPath xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
+                          org.xml.sax.InputSource is = new org.xml.sax.InputSource( new java.io.FileInputStream( "${basedir}/src/site/site.xml" ) );
+                          xpath.evaluate( "//project/body/breadcrumbs/item[@name='${project.version}']/@href", is ).equals( "/docs/${project.version}" )
+                        ]]>
+                      </condition>
+                    </evaluateBeanshell>
+                    <evaluateBeanshell>
+                      <message>Release notes need to be updated for the current release version</message>
+                      <condition>
+                        <![CDATA[
+                          org.codehaus.plexus.util.FileUtils.fileRead( "${basedir}/src/site/apt/release-notes.apt" ).indexOf( "Release Notes for Archiva ${project.version}" ) >= 0
+                        ]]>
+                      </condition>
+                    </evaluateBeanshell>
+                  </rules>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
         </plugins>
       </build>
     </profile>
   </profiles>
-
 </project>
index 5431145a2d99c590ab8e0d8eada40819f34206e1..f8e8db067b921dfb75adaed0a494cece0abe6f60 100644 (file)
@@ -1,12 +1,11 @@
  -----
- Release Notes for Archiva 1.1.1
+ Release Notes for Archiva 1.2-SNAPSHOT
  -----
 
-Release Notes for Archiva 1.1.1
+Release Notes for Archiva 1.2-SNAPSHOT
 
-  The Apache Archiva team would like to announce the release of Archiva 1.1.1.
-
-  Archiva 1.1.1 is {{{http://archiva.apache.org/download.html} available for download from the web site}}.
+  The Apache Archiva team would like to announce the release of Archiva 1.2.  Archiva is {{{http://archiva.apache.org/download.html} 
+  available for download from the web site}}.
 
   Archiva is an application for managing one or more remote repositories, including administration, artifact handling, browsing and searching.
 
@@ -16,46 +15,77 @@ Release Notes for Archiva 1.1.1
 
     * the archiva-user mailing list: {{http://archiva.apache.org/mail-lists.html}}
 
-* New in Archiva 1.1
+* New in Archiva 1.2
 
-** Artifact Uploads
+~~TODO
 
-   To simplify adding artifacts to a repository, an upload form has been put in place that allows you to put an artifact and POM into
-   the repository without the need for the Maven <<<deploy-file>>> command.
+* Release Notes
 
-** RSS
+  The Archiva 1.2 feature set can be seen in the {{{tour/index.html} feature tour}}.
 
-   RSS is now available for getting a feed of new artifacts being added to a given repository. Two types of feeds are generated by Archiva:
-   new artifacts in a repository and new versions of a specific artifact. Details are available in {{{userguide/rss.html}Rss Feeds}}.
+* Changes in Archiva 1.2
 
-** Virtual Repositories
+~~TODO
 
-   Virtual repositories or repository groups allows downloading from a group of repositories via one url. For more details of this feature,
-   see {{{userguide/virtual-repositories.html}Virtual Repositories}}.
+* Changes in Archiva 1.1.3
 
-** Timeouts
+** Bug
 
-   Connections to remote repositories can now have a configurable timeout value
+    * [MRM-967] - Security Issue: If repository observer role is enabled for the 'guest' user, an invalid user is able to deploy to that repository
 
-** New Runtime Bundle
+    * [MRM-397] - background of the Archiva logo is not transparent in repositories page
 
-   The application is now distributed using Jetty 6.1 and it's documented configuration, rather than the previous
-   Plexus application server bundle. It continues to use the Java Service Wrapper (v3.2.3) for application monitoring,
-   though the configuration has been improved, particularly with regard to separating the application configuration from the installation.
+    * [MRM-580] - does not give error message when one defines an illegal directory for a managed repository
 
-** Using Spring
+    * [MRM-954] - Footer doesn't stretch across repositoryGroups page
 
-   Archiva now uses the Spring Framework as it's underlying container instead of Plexus. This results in a boost in performance and
-   stability for the web application in particular.
+* Changes in Archiva 1.1.2
 
-** Using Apache Jackrabbit WebDAV Servlet
+** Bug
 
-   Archiva now uses Apache Jackrabbit's WebDAV servlet for serving repository content instead of plexus-webdav. The change results in reduced
-   codebase complexity, increased standards compliance, better webdav client support and a small peformance boost.
+    * [MRM-765] - should not be possible to create a proxy connector if there are no remote repositories
 
-* Release Notes
+    * [MRM-807] - Deployed dll won't be indexed
+
+    * [MRM-834] - Wrong repository url when archiva is used behind Apache with mof_proxy
+
+    * [MRM-841] - Introducing a new scannable artifact file type requires restart in order for some consumers to work
+
+    * [MRM-880] - Archiva does not start up on Solaris 64-Bit
+
+    * [MRM-881] - Failing to startup due to invalid bean definition
+
+    * [MRM-893] - Illegal browse operation allow
+
+    * [MRM-902] - If path has leading slash when being checked againts whitelists and blacklists causes matching failure
+
+    * [MRM-903] - Repository scanning should not stop when encounters error
+
+    * [MRM-905] - EL Expression failed with empty/not functions
+
+    * [MRM-911] - Archiva checks user's credentials before guest's rights on the repository
+
+    * [MRM-912] - rss urls seem to use fixed webcontext "archiva" instead of actual webcontext
+
+    * [MRM-915] - NPE with rss links
+
+    * [MRM-926] - NPE with search page
+
+    * [MRM-932] - Error 500 when clicking the Next or Previous icon of the results of a search, if user is trying to search for java classes, packages or methods.
+
+    * [MRM-934] - For bytecode search, only 1 version of the artifact is returned even if there are more than 1 version of that artifact which matched the search
+
+    * [MRM-943] - results search option should only be available on results page
+
+** Improvement
+
+    * [MRM-839] - change RSS URLs
+
+    * [MRM-848] - Pre-configured repositories initially appear to be empty
+
+    * [MRM-874] - POM snippet for plugins should be <plugin> not <dependency>
 
-  The Archiva 1.1 feature set can be seen in the {{{tour/index.html} feature tour}}.
+  The full list of changes can be found {{{http://jira.codehaus.org/secure/ReleaseNote.jspa?version=14491&styleName=Text&projectId=10980} in JIRA}}.
 
 * Changes in Archiva 1.1.1
 
index 08c18d35cefdd2113c8a42020f752916582374d5..14c1f9b1b360e3e77f9008431573287cb864e249 100644 (file)
@@ -21,7 +21,7 @@
 <project>
   <body>
     <breadcrumbs>
-      <item name="1.1.1" href="/docs/1.1.1" />
+      <item name="1.2-SNAPSHOT" href="/docs/1.2-SNAPSHOT" />
     </breadcrumbs>
 
     <menu name="Introduction">
index 5c88febb98a0a4dc0de3bfd1e9a7f6d6789d49a1..09928b1d851ec88e45682cbbbaf2d9438d973874 100644 (file)
       </plugin>
     </plugins>
   </build>
-  <pluginRepositories>
-    <pluginRepository>
-      <id>codehaus.snapshots</id>
-      <url>http://snapshots.repository.codehaus.org/</url>
-    </pluginRepository>
-  </pluginRepositories>
 </project>
index 2e3831d4a05053a65c66298865f7ea387757fa98..1ae5831f043fe9cb030e6dd2cac57700985d7f95 100644 (file)
@@ -137,7 +137,7 @@ public class VersionUtil
         }
         else
         {
-            return version.endsWith( SNAPSHOT );
+            return isGenericSnapshot(version);
         }
     }
 
index 58e1dd9cce52df003d212f223406ca07ddd0240f..6bc21386a8f0f8dc99d2a066c2e976743552972c 100644 (file)
@@ -32,6 +32,7 @@ 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.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.ArchivaModelCloner;
 import org.apache.maven.archiva.model.ArchivaProjectModel;
 import org.apache.maven.archiva.model.Keys;
 import org.apache.maven.archiva.model.RepositoryProblem;
@@ -41,7 +42,6 @@ import org.apache.maven.archiva.repository.RepositoryContentFactory;
 import org.apache.maven.archiva.repository.RepositoryException;
 import org.apache.maven.archiva.repository.content.ManagedLegacyRepositoryContent;
 import org.apache.maven.archiva.repository.project.ProjectModelException;
-import org.apache.maven.archiva.repository.project.ProjectModelFilter;
 import org.apache.maven.archiva.repository.project.ProjectModelReader;
 import org.apache.maven.archiva.repository.project.filters.EffectiveProjectModelFilter;
 import org.apache.maven.archiva.repository.project.readers.ProjectModel300Reader;
@@ -85,11 +85,6 @@ public class ProjectModelToDatabaseConsumer
      */
     private RepositoryContentFactory repositoryFactory;
 
-    /**
-     * @plexus.requirement role-hint="expression"
-     */
-    private ProjectModelFilter expressionModelFilter;
-
     /**
      * @plexus.requirement role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
      * role-hint="effective"
@@ -160,23 +155,22 @@ public class ProjectModelToDatabaseConsumer
         {
             model = reader.read( artifactFile );
 
-            model.setOrigin( "filesystem" );
-
             // The version should be updated to the artifact/filename version if it is a unique snapshot
             if ( VersionUtil.isUniqueSnapshot( artifact.getVersion() ) )
             {
                 model.setVersion( artifact.getVersion() );
             }
 
-            // Filter the model
-            model = expressionModelFilter.filter( model );
-
-            // Resolve the project model
+            // Resolve the project model (build effective model, resolve expressions)
             model = effectiveModelFilter.filter( model );
 
             if ( isValidModel( model, repo, artifact ) )
             {
                 log.debug( "Adding project model to database - " + Keys.toKey( model ) );
+                
+                // Clone model, since DAO while detachingCopy resets its contents
+                // This changes contents of the cache in EffectiveProjectModelFilter
+                model = ArchivaModelCloner.clone( model );
                 dao.getProjectModelDAO().saveProjectModel( model );
             }
             else
@@ -356,5 +350,4 @@ public class ProjectModelToDatabaseConsumer
             }
         }
     }
-    
 }
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/java/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumerTest.java b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/java/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumerTest.java
new file mode 100644 (file)
index 0000000..955d221
--- /dev/null
@@ -0,0 +1,125 @@
+package org.apache.maven.archiva.consumers.database;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.Iterator;
+
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.Configuration;
+import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.maven.archiva.consumers.ConsumerException;
+import org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.ObjectNotFoundException;
+import org.apache.maven.archiva.database.ProjectModelDAO;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.ArchivaArtifactModel;
+import org.apache.maven.archiva.model.ArchivaProjectModel;
+import org.apache.maven.archiva.model.Dependency;
+import org.apache.maven.archiva.model.Keys;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
+/**
+ * Test for ProjectModelToDatabaseConsumerTest
+ * 
+ * @author <a href="mailto:michal.stochmialek@eurobank.pl">Michal Stochmialek</a>
+ */
+public class ProjectModelToDatabaseConsumerTest
+    extends PlexusInSpringTestCase
+{
+    private ProjectModelToDatabaseConsumer consumer;
+
+    private ProjectModelDAO modelDao;
+
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        ArchivaConfiguration archivaConfig = (ArchivaConfiguration) lookup( ArchivaConfiguration.class );
+
+        Configuration configuration = archivaConfig.getConfiguration();
+        ManagedRepositoryConfiguration repo = configuration.findManagedRepositoryById( "internal" );
+        repo.setLocation( new File( getBasedir(), "src/test/resources/test-repo" ).toString() );
+
+        consumer =
+            (ProjectModelToDatabaseConsumer) lookup( DatabaseUnprocessedArtifactConsumer.class, "update-db-project" );
+        modelDao = (ProjectModelDAO) lookup( ProjectModelDAO.class, "jdo" );
+    }
+
+    public void testProcess()
+        throws Exception
+    {
+        ArchivaProjectModel model = processAndGetModel( "test-project", "test-project-endpoint-pom", "2.4.4" );
+        assertNotNull( model.getParentProject() );
+        assertEquals( "test-project:test-project:2.4.4", Keys.toKey( model.getParentProject() ) );
+
+        assertFalse( model.getDependencyManagement().isEmpty() );
+
+        model = processAndGetModel( "test-project", "test-project-endpoint-ejb", "2.4.4" );
+        assertNotNull( model.getParentProject() );
+        assertEquals( "test-project:test-project-endpoint-pom:2.4.4", Keys.toKey( model.getParentProject() ) );
+        assertTrue( hasDependency( model, "test-project:test-project-api:2.4.4" ) );
+        assertTrue( hasDependency( model, "commons-id:commons-id:0.1-dev" ) );
+
+        model = processAndGetModel( "test-project", "test-project", "2.4.4" );
+        assertFalse( model.getDependencyManagement().isEmpty() );
+    }
+
+    private boolean hasDependency( ArchivaProjectModel model, String key )
+    {
+        for ( Iterator i = model.getDependencies().iterator(); i.hasNext(); )
+        {
+            Dependency dependency = (Dependency) i.next();
+            if ( key.equals( Keys.toKey( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ) ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private ArchivaProjectModel processAndGetModel( String group, String artifactId, String version )
+        throws ConsumerException, ObjectNotFoundException, ArchivaDatabaseException
+    {
+        ArchivaArtifact artifact = createArtifact( group, artifactId, version, "pom" );
+        consumer.processArchivaArtifact( artifact );
+
+        ArchivaProjectModel model = modelDao.getProjectModel( group, artifactId, version );
+        assertEquals( group, model.getGroupId() );
+        assertEquals( artifactId, model.getArtifactId() );
+        assertEquals( version, model.getVersion() );
+        return model;
+    }
+
+    protected ArchivaArtifact createArtifact( String group, String artifactId, String version, String type )
+    {
+        ArchivaArtifactModel model = new ArchivaArtifactModel();
+        model.setGroupId( group );
+        model.setArtifactId( artifactId );
+        model.setVersion( version );
+        model.setType( type );
+        model.setRepositoryId( "internal" );
+
+        return new ArchivaArtifact( model );
+    }
+
+}
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumerTest.xml b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/org/apache/maven/archiva/consumers/database/ProjectModelToDatabaseConsumerTest.xml
new file mode 100644 (file)
index 0000000..3766646
--- /dev/null
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+-->
+
+<component-set>
+    <components>
+        <!-- JdoAccess -->
+        <component>
+            <role>org.apache.maven.archiva.database.jdo.JdoAccess</role>
+            <role-hint>archiva</role-hint>
+            <implementation>org.apache.maven.archiva.database.jdo.JdoAccess</implementation>
+            <requirements>
+                <requirement>
+                    <role>org.codehaus.plexus.jdo.JdoFactory</role>
+                    <role-hint>archiva</role-hint>
+                </requirement>
+            </requirements>
+        </component>
+
+        <!-- JDO Factory -->
+        <component>
+            <role>org.codehaus.plexus.jdo.JdoFactory</role>
+            <role-hint>archiva</role-hint>
+            <implementation>org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory</implementation>
+
+            <configuration>
+                <!-- Database Configuration -->
+                <driverName>org.hsqldb.jdbcDriver</driverName>
+                <url>jdbc:hsqldb:mem:TESTDB</url>
+                <userName>sa</userName>
+                <password></password>
+
+                <!-- JPOX and JDO configuration -->
+                <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
+                <otherProperties>
+                    <property>
+                        <name>javax.jdo.PersistenceManagerFactoryClass</name>
+                        <value>org.jpox.PersistenceManagerFactoryImpl</value>
+                    </property>
+                    <property>
+                        <name>org.jpox.autoCreateSchema</name>
+                        <value>true</value>
+                    </property>
+                </otherProperties>
+            </configuration>
+        </component>
+
+        <component>
+            <role>org.codehaus.plexus.cache.Cache</role>
+            <role-hint>effective-project-cache</role-hint>
+            <implementation>org.codehaus.plexus.cache.ehcache.EhcacheCache</implementation>
+            <description>Effective Project Cache</description>
+            <configuration>
+                <disk-expiry-thread-interval-seconds>600</disk-expiry-thread-interval-seconds>
+                <disk-persistent>true</disk-persistent>
+                <disk-store-path>${java.io.tmpdir}/archiva/effectiveproject</disk-store-path>
+                <eternal>true</eternal>
+                <max-elements-in-memory>1000</max-elements-in-memory>
+                <memory-eviction-policy>LRU</memory-eviction-policy>
+                <name>effective-project-cache</name>
+                <overflow-to-disk>false</overflow-to-disk>
+                <!-- TODO: Adjust the time to live to be more sane (ie: huge 4+ hours) -->
+                <!-- 45 minutes = 2700 seconds -->
+                <time-to-idle-seconds>2700</time-to-idle-seconds>
+                <!-- 30 minutes = 1800 seconds  -->
+                <time-to-live-seconds>1800</time-to-live-seconds>
+            </configuration>
+        </component>
+    </components>
+</component-set>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-api/2.4.4/test-project-api-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-api/2.4.4/test-project-api-2.4.4.pom
new file mode 100644 (file)
index 0000000..fa0c87e
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <groupId>test-project</groupId>
+    <artifactId>test-project-api</artifactId>
+    <name>Test Project API</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>stax</groupId>
+            <artifactId>stax-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-broker-ejb/2.4.4/test-project-broker-ejb-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-broker-ejb/2.4.4/test-project-broker-ejb-2.4.4.pom
new file mode 100644 (file)
index 0000000..b333a52
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project-broker-pom</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <artifactId>test-project-broker-ejb</artifactId>
+    <name>Test Project Broker EJB</name>
+    <packaging>ejb</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <type>test-jar</type>
+            <version>${pom.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-api</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-id</groupId>
+            <artifactId>commons-id</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-discovery</groupId>
+            <artifactId>commons-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-mock</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jms</groupId>
+            <artifactId>jms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.management</groupId>
+            <artifactId>jmxri</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-broker-pom/2.4.4/test-project-broker-pom-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-broker-pom/2.4.4/test-project-broker-pom-2.4.4.pom
new file mode 100644 (file)
index 0000000..fd54736
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <artifactId>test-project-broker-pom</artifactId>
+    <name>Test Project Broker POM</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>broker-ejb</module>
+    </modules>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-common/2.4.4/test-project-common-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-common/2.4.4/test-project-common-2.4.4.pom
new file mode 100644 (file)
index 0000000..d47958b
--- /dev/null
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <groupId>test-project</groupId>
+    <artifactId>test-project-common</artifactId>
+    <name>Test Project Commons</name>
+    <dependencies>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-api</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-id</groupId>
+            <artifactId>commons-id</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-discovery</groupId>
+            <artifactId>commons-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>stax</groupId>
+            <artifactId>stax-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>wstx-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.castor</groupId>
+            <artifactId>castor</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xerces</groupId>
+            <artifactId>xerces</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jms</groupId>
+            <artifactId>jms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.ejb</groupId>
+            <artifactId>ejb</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.management</groupId>
+            <artifactId>jmxri</artifactId>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom
new file mode 100644 (file)
index 0000000..582f1e5
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project-endpoint-pom</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <groupId>test-project</groupId>
+    <artifactId>test-project-endpoint-ejb</artifactId>
+    <name>Test Project Endpoint EJB</name>
+    <packaging>ejb</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-api</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <!-- for tests only -->
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <version>${pom.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-id</groupId>
+            <artifactId>commons-id</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-discovery</groupId>
+            <artifactId>commons-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jms</groupId>
+            <artifactId>jms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.management</groupId>
+            <artifactId>jmxri</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-endpoint-pom/2.4.4/test-project-endpoint-pom-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project-endpoint-pom/2.4.4/test-project-endpoint-pom-2.4.4.pom
new file mode 100644 (file)
index 0000000..ea4d637
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <artifactId>test-project-endpoint-pom</artifactId>
+    <name>Test Project Endpoint POM</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>endpoint-ejb</module>
+    </modules>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project/2.4.4/test-project-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-consumers/archiva-database-consumers/src/test/resources/test-repo/test-project/test-project/2.4.4/test-project-2.4.4.pom
new file mode 100644 (file)
index 0000000..6dc4719
--- /dev/null
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>test-project</groupId>
+    <artifactId>test-project</artifactId>
+    <name>Test Project</name>
+    <version>2.4.4</version>
+    <packaging>pom</packaging>
+
+    <organization>
+        <name>Company</name>
+        <url>http://www.company.com/</url>
+    </organization>
+    <inceptionYear>2002</inceptionYear>
+
+    <modules>
+        <module>api</module>
+        <module>common</module>
+        <module>broker</module>
+        <module>endpoint</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <!-- common version strategy -->
+            <dependency>
+                <groupId>javax.activation</groupId>
+                <artifactId>activation</artifactId>
+                <version>1.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.jms</groupId>
+                <artifactId>jms</artifactId>
+                <version>1.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.ejb</groupId>
+                <artifactId>ejb</artifactId>
+                <version>2.0</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.servlet</groupId>
+                <artifactId>servlet-api</artifactId>
+                <version>2.4</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.mail</groupId>
+                <artifactId>mail</artifactId>
+                <version>1.4</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>xml-apis</groupId>
+                <artifactId>xml-apis</artifactId>
+                <version>2.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>commons-logging</groupId>
+                <artifactId>commons-logging</artifactId>
+                <version>1.0.4</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-lang</groupId>
+                <artifactId>commons-lang</artifactId>
+                <version>2.1</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>3.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring</artifactId>
+                <version>2.0.7</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-mock</artifactId>
+                <version>2.0.7</version>
+                <scope>test</scope>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.springframework</groupId>
+                        <artifactId>spring-jdbc</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>org.springframework</groupId>
+                        <artifactId>spring-web</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>log4j</groupId>
+                <artifactId>log4j</artifactId>
+                <version>1.2.8</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-discovery</groupId>
+                <artifactId>commons-discovery</artifactId>
+                <version>0.2</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-id</groupId>
+                <artifactId>commons-id</artifactId>
+                <version>0.1-dev</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.castor</groupId>
+                <artifactId>castor</artifactId>
+                <version>1.0.5-xml</version>
+            </dependency>
+            <dependency>
+                <groupId>xerces</groupId>
+                <artifactId>xerces</artifactId>
+                <version>2.4.0</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-httpclient</groupId>
+                <artifactId>commons-httpclient</artifactId>
+                <version>3.1</version>
+            </dependency>
+            <dependency>
+                <groupId>stax</groupId>
+                <artifactId>stax-api</artifactId>
+                <version>1.0.1</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.woodstox</groupId>
+                <artifactId>wstx-asl</artifactId>
+                <version>3.2.1</version>
+            </dependency>
+            <dependency>
+                <groupId>com.thoughtworks.xstream</groupId>
+                <artifactId>xstream</artifactId>
+                <version>1.2.2</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.management</groupId>
+                <artifactId>jmxri</artifactId>
+                <version>1.2.1</version>
+                <scope>provided</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>
index 9bf4c20170bd598218e079f3f981e2441958ebe8..93912f68817ab94e19e2f9c962c7ddc1abc81868 100644 (file)
         StringBuffer key = new StringBuffer();
 
         key.append( defaultString( reference.getGroupId() ) ).append( ":" );
-        key.append( defaultString( reference.getArtifactId() ) ).append( ":" );
+        key.append( defaultString( reference.getArtifactId() ) );
 
         return key.toString();
     }
 
         key.append( defaultString( reference.getGroupId() ) ).append( ":" );
         key.append( defaultString( reference.getArtifactId() ) ).append( ":" );
-        key.append( defaultString( reference.getVersion() ) ).append( ":" );
+        key.append( defaultString( reference.getVersion() ) );
 
         return key.toString();
     }
             The number of new files discovered.
           </description>
         </field>
+        <field>
+          <name>totalProjectCount</name>
+          <version>1.0.0+</version>
+          <identifier>false</identifier>
+          <required>true</required>
+          <type>long</type>
+          <description>
+            The total number of unique projects in the repository.
+          </description>
+        </field>
+        <field>
+          <name>totalGroupCount</name>
+          <version>1.0.0+</version>
+          <identifier>false</identifier>
+          <required>true</required>
+          <type>long</type>
+          <description>
+            The total number of unique groups in the repository.
+          </description>
+        </field>
+        <field>
+          <name>totalArtifactCount</name>
+          <version>1.0.0+</version>
+          <identifier>false</identifier>
+          <required>true</required>
+          <type>long</type>
+          <description>
+            The total number of artifacts in the repository. 
+          </description>
+        </field>
+        <field>
+          <name>totalSize</name>
+          <version>1.0.0+</version>
+          <identifier>false</identifier>
+          <required>true</required>
+          <type>long</type>
+          <description>
+            The total size in bytes of the repository.
+          </description>
+        </field>
       </fields>
       <codeSegments>
         <codeSegment>
index fa49e5d1403acac0f1102263a44be192c5883f72..08228a5e7bca4ec353c7049e49964d202e2759ed 100644 (file)
@@ -104,7 +104,8 @@ public class FilenameParser
 
             // check it starts with the same version up to the snapshot part
             int leadingLength = expected.length() - 9;
-            if ( version.startsWith( expected.substring( 0, leadingLength ) ) && version.length() > leadingLength )
+            if ( leadingLength > 0 && version.startsWith( expected.substring( 0, leadingLength ) ) &&
+                version.length() > leadingLength )
             {
                 // If we expect a non-generic snapshot - look for the timestamp
                 Matcher m = SNAPSHOT_PATTERN.matcher( version.substring( leadingLength + 1 ) );
index b14b52a04b88218c851b4923869e9d053a7e0c34..6470eaa564417ee9794654c86d19e9d7d8524120 100644 (file)
@@ -77,6 +77,7 @@ public class ProjectModelMerge
         ArchivaProjectModel merged = new ArchivaProjectModel();
 
         // Unmerged.
+        merged.setParentProject(mainProject.getParentProject());
         merged.setArtifactId( mainProject.getArtifactId() );
         merged.setPackaging( StringUtils.defaultIfEmpty( mainProject.getPackaging(), "jar" ) );
         merged.setRelocation( mainProject.getRelocation() );
@@ -334,6 +335,7 @@ public class ProjectModelMerge
         }
 
         Properties merged = new Properties();
+        merged.putAll(mainProperties);
 
         Enumeration keys = parentProperties.propertyNames();
         while ( keys.hasMoreElements() )
index 24a22f90c00667bf20a5fa1ace38677eb1cc560f..d1860e8c8e3a867a9d2a41839ed550dae85beb75 100644 (file)
@@ -100,20 +100,23 @@ public class EffectiveProjectModelFilter
         // Clone submitted project (so that we don't mess with it) 
         effectiveProject = ArchivaModelCloner.clone( project );
 
-        // Setup Expression Evaluation pieces.
-        effectiveProject = expressionFilter.filter( effectiveProject );
-
         DEBUG( "Starting build of effective with: " + effectiveProject );
 
         // Merge in all the parent poms.
         effectiveProject = mergeParent( effectiveProject );
 
+        // Setup Expression Evaluation pieces.
+        effectiveProject = expressionFilter.filter( effectiveProject );
+
         // Resolve dependency versions from dependency management.
         applyDependencyManagement( effectiveProject );
 
+        // groupId or version could be updated by parent or expressions
+        projectKey = toProjectKey( effectiveProject );
+        
         // Do not add project into cache if it contains no groupId and
         // version information
-        if ( project.getGroupId() != null && project.getVersion() != null )
+        if ( effectiveProject.getGroupId() != null && effectiveProject.getVersion() != null )
         {
             synchronized ( effectiveProjectCache )
             {
@@ -191,8 +194,8 @@ public class EffectiveProjectModelFilter
             if ( parentProject != null )
             {
                 // Merge the pom with the parent pom.
-                parentProject = expressionFilter.filter( parentProject );
                 parentProject = mergeParent( parentProject );
+                parentProject = expressionFilter.filter( parentProject );
 
                 // Cache the pre-merged parent.
                 synchronized ( effectiveProjectCache )
index 1c2f989ba4271cd2898ab5bc4d7143517d56f9db..6c39cd3e66a2e246940d7d666768abbecdf32728 100644 (file)
@@ -104,11 +104,24 @@ public class ProjectModelExpressionFilter
             try
             {
                 // Setup some common properties.
+                VersionedReference parent = model.getParentProject();
+                if ( parent != null )
+                {
+                    String parentGroupId = StringUtils.defaultString( evaluator.expand( parent.getGroupId() ) );
+                    String parentArtifactId = StringUtils.defaultString( evaluator.expand( parent.getArtifactId() ) );
+                    String parentVersion = StringUtils.defaultString( evaluator.expand( parent.getVersion() ) );
+
+                    props.setProperty( "parent.groupId", parentGroupId );
+                    props.setProperty( "parent.artifactId", parentArtifactId );
+                    props.setProperty( "parent.version", parentVersion );
+                }
+
                 String groupId = StringUtils.defaultString( evaluator.expand( model.getGroupId() ) );
                 String artifactId = StringUtils.defaultString( evaluator.expand( model.getArtifactId() ) );
                 String version = StringUtils.defaultString( evaluator.expand( model.getVersion() ) );
                 String name = StringUtils.defaultString( evaluator.expand( model.getName() ) );
                 
+
                 /* Archiva doesn't need to handle a full expression language with object tree walking
                  * as the requirements within Archiva are much smaller, a quick replacement of the
                  * important fields (groupId, artifactId, version, name) are handled specifically. 
index 95aa27c6c8a830e961b9c1adcc18317796d45c9d..a46d85f4c919bee347deca3e4473f8fbbee9def7 100644 (file)
@@ -94,6 +94,8 @@ public class ProjectModel300Reader
             model.setProperties( getProperties( xml.getElement( "//project/properties" ) ) );
             model.setDependencies( getDependencies( xml ) );
             
+            model.setOrigin("filesystem");
+
             /* Following are not valid for <pomVersion>3</pomVersion> / Maven 1 pom files.
              * 
              * model.setDependencyManagement()
index 38509be26623b47e607a4c1c8ecbc65c5b603526..441f63f6fac8b89413bcb9c3d39a492b3eed132c 100644 (file)
@@ -104,6 +104,8 @@ public class ProjectModel400Reader
             model.setBuildExtensions( getBuildExtensions( xml ) );
 
             model.setRelocation( getRelocation( xml ) );
+            
+            model.setOrigin("filesystem");
 
             return model;
         }
index 9129a9db4c153248436ceb521cefa70e3edcf9a5..37d9d112c36160d848eb4031f8175f73c2ece20e 100644 (file)
       <artifactId>archiva-common</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven.archiva</groupId>
+      <artifactId>archiva-test-A</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.archiva</groupId>
+      <artifactId>archiva-test-B</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/expected-poms/test-project-model-effective.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/expected-poms/test-project-model-effective.pom
new file mode 100644 (file)
index 0000000..3057af9
--- /dev/null
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ====================================================================== -->
+<!--                                                                        -->
+<!-- Generated by Maven Help Plugin on 9/17/08 5:36 PM                      -->
+<!-- See: http://maven.apache.org/plugins/maven-help-plugin/                -->
+<!--                                                                        -->
+<!-- ====================================================================== -->
+
+<!-- ====================================================================== -->
+<!--                                                                        -->
+<!-- Effective POM for project                                              -->
+<!-- 'test-project:test-project-endpoint-ejb:ejb:2.4.4'                     -->
+<!--                                                                        -->
+<!-- ====================================================================== -->
+
+<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>
+    <artifactId>test-project-endpoint-pom</artifactId>
+    <groupId>test-project</groupId>
+    <version>2.4.4</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>test-project</groupId>
+  <artifactId>test-project-endpoint-ejb</artifactId>
+  <packaging>ejb</packaging>
+  <name>Test Project Endpoint EJB</name>
+  <version>2.4.4</version>
+  <inceptionYear>2002</inceptionYear>
+  <organization>
+    <name>Company</name>
+    <url>http://www.company.com/</url>
+  </organization>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>test-project</groupId>
+      <artifactId>test-project-common</artifactId>
+      <version>2.4.4</version>
+    </dependency>
+    <dependency>
+      <groupId>test-project</groupId>
+      <artifactId>test-project-api</artifactId>
+      <version>2.4.4</version>
+    </dependency>
+    <dependency>
+      <groupId>test-project</groupId>
+      <artifactId>test-project-common</artifactId>
+      <version>2.4.4</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-id</groupId>
+      <artifactId>commons-id</artifactId>
+      <version>0.1-dev</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-discovery</groupId>
+      <artifactId>commons-discovery</artifactId>
+      <version>0.2</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.4</version>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <version>1.2.8</version>
+    </dependency>
+    <dependency>
+      <groupId>javax.jms</groupId>
+      <artifactId>jms</artifactId>
+      <version>1.0.2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.activation</groupId>
+      <artifactId>activation</artifactId>
+      <version>1.0.2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <version>1.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>xml-apis</groupId>
+      <artifactId>xml-apis</artifactId>
+      <version>2.0.2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.management</groupId>
+      <artifactId>jmxri</artifactId>
+      <version>1.2.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>javax.activation</groupId>
+        <artifactId>activation</artifactId>
+        <version>1.0.2</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>javax.jms</groupId>
+        <artifactId>jms</artifactId>
+        <version>1.0.2</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>javax.ejb</groupId>
+        <artifactId>ejb</artifactId>
+        <version>2.0</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>javax.servlet</groupId>
+        <artifactId>servlet-api</artifactId>
+        <version>2.4</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>javax.mail</groupId>
+        <artifactId>mail</artifactId>
+        <version>1.4</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>xml-apis</groupId>
+        <artifactId>xml-apis</artifactId>
+        <version>2.0.2</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>commons-logging</groupId>
+        <artifactId>commons-logging</artifactId>
+        <version>1.0.4</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-lang</groupId>
+        <artifactId>commons-lang</artifactId>
+        <version>2.1</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-collections</groupId>
+        <artifactId>commons-collections</artifactId>
+        <version>3.2</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring</artifactId>
+        <version>2.0.7</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-mock</artifactId>
+        <version>2.0.7</version>
+        <scope>test</scope>
+        <exclusions>
+          <exclusion>
+            <artifactId>spring-jdbc</artifactId>
+            <groupId>org.springframework</groupId>
+          </exclusion>
+          <exclusion>
+            <artifactId>spring-web</artifactId>
+            <groupId>org.springframework</groupId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>log4j</groupId>
+        <artifactId>log4j</artifactId>
+        <version>1.2.8</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-discovery</groupId>
+        <artifactId>commons-discovery</artifactId>
+        <version>0.2</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-id</groupId>
+        <artifactId>commons-id</artifactId>
+        <version>0.1-dev</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.castor</groupId>
+        <artifactId>castor</artifactId>
+        <version>1.0.5-xml</version>
+      </dependency>
+      <dependency>
+        <groupId>xerces</groupId>
+        <artifactId>xerces</artifactId>
+        <version>2.4.0</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-httpclient</groupId>
+        <artifactId>commons-httpclient</artifactId>
+        <version>3.1</version>
+      </dependency>
+      <dependency>
+        <groupId>stax</groupId>
+        <artifactId>stax-api</artifactId>
+        <version>1.0.1</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.woodstox</groupId>
+        <artifactId>wstx-asl</artifactId>
+        <version>3.2.1</version>
+      </dependency>
+      <dependency>
+        <groupId>com.thoughtworks.xstream</groupId>
+        <artifactId>xstream</artifactId>
+        <version>1.2.2</version>
+      </dependency>
+      <dependency>
+        <groupId>javax.management</groupId>
+        <artifactId>jmxri</artifactId>
+        <version>1.2.1</version>
+        <scope>provided</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
\ No newline at end of file
index 6da1ce21e05be07eefb4f4da39d356344ca725c5..e1a0394feaedf79d643a4cc9fc74e274ffd4407b 100644 (file)
@@ -295,6 +295,15 @@ public class DefaultPathParserTest
         assertLayout( path, groupId, artifactId, version, classifier, type );
     }
 
+    /**
+     * A timestamped versioned artifact but without release version part. Like on axiom trunk. 
+     */
+    public void testBadSnapshotWithoutReleasePart()
+    {
+        assertBadPath( "org/apache/ws/commons/axiom/axiom/SNAPSHOT/axiom-20070912.093446-2.pom", 
+             "snapshot version without release part");
+    }
+
     /**
      * A timestamped versioned artifact, should reside in a SNAPSHOT baseversion directory.
      * @throws LayoutException
index 9b31da6317935ead363a20647b1d95f903daddc8..7f8238462ee30045bf02d1fc63692140b12d2ca2 100644 (file)
@@ -169,6 +169,15 @@ public class FilenameParserTest
         assertNull( parser.expect( "2.0-SNAPSHOT" ) );
     }
 
+    public void testExpectWrongSnapshot2()
+    {
+        // tests parsing axiom snapshots without exceptions
+        FilenameParser parser = new FilenameParser( "axiom-20080221.062205-9.pom" );
+
+        assertEquals( "axiom", parser.nextNonVersion() );
+        assertNull( parser.expect( "SNAPSHOT" ) );
+    }
+
     public void testClassifier()
     {
         FilenameParser parser = new FilenameParser( "artifact-id-1.0-20070219.171202-34-test-sources.jar" );
index c4f04182b8ec614069f2726bcdcfbfe89df1ba83..c65a73772df0aa648fcab2ed5bee2a414b374ee4 100644 (file)
@@ -81,20 +81,29 @@ public class EffectiveProjectModelFilterTest
     public void testBuildEffectiveProject()
         throws Exception
     {
+        assertEffectiveProject(
+                "/org/apache/maven/archiva/archiva-model/1.0-SNAPSHOT/archiva-model-1.0-SNAPSHOT.pom",
+        "/archiva-model-effective.pom");
+        assertEffectiveProject(
+                "/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom",
+        "/test-project-model-effective.pom");
+    }
+
+    private void assertEffectiveProject(String pomFile, String effectivePomFile) throws Exception,
+            ProjectModelException {
         initTestResolverFactory();
         EffectiveProjectModelFilter filter = lookupEffective();
 
-        ArchivaProjectModel startModel = createArchivaProjectModel( DEFAULT_REPOSITORY
-            + "/org/apache/maven/archiva/archiva-model/1.0-SNAPSHOT/archiva-model-1.0-SNAPSHOT.pom" );
+        ArchivaProjectModel startModel = createArchivaProjectModel( DEFAULT_REPOSITORY + pomFile );
 
         ArchivaProjectModel effectiveModel = filter.filter( startModel );
 
-        ArchivaProjectModel expectedModel = createArchivaProjectModel( "src/test/expected-poms/"
-            + "/archiva-model-effective.pom" );
+        ArchivaProjectModel expectedModel = createArchivaProjectModel( "src/test/expected-poms/" + effectivePomFile);
 
         assertModel( expectedModel, effectiveModel );
     }
 
+
     /**
      * [MRM-510] In Repository Browse, the first unique snapshot version clicked is getting persisted in the 
      * request resulting to 'version does not match' error
@@ -272,7 +281,7 @@ public class EffectiveProjectModelFilterTest
         while ( it.hasNext() )
         {
             Dependency dep = it.next();
-            String key = Dependency.toVersionlessKey( dep );
+            String key = Dependency.toKey( dep );
             map.put( key, dep );
         }
         return map;
index 5d6d0c3b7815811946b19a1abf1dc6225a84b3ac..735bf9b3161d876b48041fd5a164dcee783da499 100644 (file)
@@ -92,6 +92,6 @@ public class ProjectModel400ReaderTest
         assertEquals( "Parent Version", "1.0-SNAPSHOT", parentRef.getVersion() );
         
         assertNotNull( "Dependencies", project.getDependencies() );
-        assertEquals( "Dependencies.size", 6, project.getDependencies().size() );
+        assertEquals( "Dependencies.size", 8, project.getDependencies().size() );
     }
 }
index 52c185ea706a5855acec976d039618057c7db7f9..9c9053a3c984acb140096013ac884563f4c6258d 100644 (file)
       <groupId>org.apache.maven.archiva</groupId>
       <artifactId>archiva-common</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven.archiva</groupId>
+      <artifactId>archiva-test-A</artifactId>
+      <version>${pom.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.archiva</groupId>
+      <artifactId>archiva-test-B</artifactId>
+      <version>${parent.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-api/2.4.4/test-project-api-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-api/2.4.4/test-project-api-2.4.4.pom
new file mode 100644 (file)
index 0000000..fa0c87e
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <groupId>test-project</groupId>
+    <artifactId>test-project-api</artifactId>
+    <name>Test Project API</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>stax</groupId>
+            <artifactId>stax-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-broker-ejb/2.4.4/test-project-broker-ejb-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-broker-ejb/2.4.4/test-project-broker-ejb-2.4.4.pom
new file mode 100644 (file)
index 0000000..b333a52
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project-broker-pom</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <artifactId>test-project-broker-ejb</artifactId>
+    <name>Test Project Broker EJB</name>
+    <packaging>ejb</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <type>test-jar</type>
+            <version>${pom.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-api</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-id</groupId>
+            <artifactId>commons-id</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-discovery</groupId>
+            <artifactId>commons-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-mock</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jms</groupId>
+            <artifactId>jms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.management</groupId>
+            <artifactId>jmxri</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-broker-pom/2.4.4/test-project-broker-pom-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-broker-pom/2.4.4/test-project-broker-pom-2.4.4.pom
new file mode 100644 (file)
index 0000000..fd54736
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <artifactId>test-project-broker-pom</artifactId>
+    <name>Test Project Broker POM</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>broker-ejb</module>
+    </modules>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-common/2.4.4/test-project-common-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-common/2.4.4/test-project-common-2.4.4.pom
new file mode 100644 (file)
index 0000000..d47958b
--- /dev/null
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <groupId>test-project</groupId>
+    <artifactId>test-project-common</artifactId>
+    <name>Test Project Commons</name>
+    <dependencies>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-api</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-id</groupId>
+            <artifactId>commons-id</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-discovery</groupId>
+            <artifactId>commons-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>stax</groupId>
+            <artifactId>stax-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>wstx-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.castor</groupId>
+            <artifactId>castor</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xerces</groupId>
+            <artifactId>xerces</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jms</groupId>
+            <artifactId>jms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.ejb</groupId>
+            <artifactId>ejb</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.management</groupId>
+            <artifactId>jmxri</artifactId>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-endpoint-ejb/2.4.4/test-project-endpoint-ejb-2.4.4.pom
new file mode 100644 (file)
index 0000000..582f1e5
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project-endpoint-pom</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <groupId>test-project</groupId>
+    <artifactId>test-project-endpoint-ejb</artifactId>
+    <name>Test Project Endpoint EJB</name>
+    <packaging>ejb</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>test-project</groupId>
+            <artifactId>test-project-api</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+        <dependency>
+            <!-- for tests only -->
+            <groupId>test-project</groupId>
+            <artifactId>test-project-common</artifactId>
+            <version>${pom.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-id</groupId>
+            <artifactId>commons-id</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-discovery</groupId>
+            <artifactId>commons-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jms</groupId>
+            <artifactId>jms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.management</groupId>
+            <artifactId>jmxri</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-endpoint-pom/2.4.4/test-project-endpoint-pom-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project-endpoint-pom/2.4.4/test-project-endpoint-pom-2.4.4.pom
new file mode 100644 (file)
index 0000000..ea4d637
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>test-project</groupId>
+        <artifactId>test-project</artifactId>
+        <version>2.4.4</version>
+    </parent>
+    <artifactId>test-project-endpoint-pom</artifactId>
+    <name>Test Project Endpoint POM</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>endpoint-ejb</module>
+    </modules>
+</project>
diff --git a/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project/2.4.4/test-project-2.4.4.pom b/archiva-struts2/archiva-modules/archiva-base/archiva-repository-layer/src/test/repositories/default-repository/test-project/test-project/2.4.4/test-project-2.4.4.pom
new file mode 100644 (file)
index 0000000..6dc4719
--- /dev/null
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>test-project</groupId>
+    <artifactId>test-project</artifactId>
+    <name>Test Project</name>
+    <version>2.4.4</version>
+    <packaging>pom</packaging>
+
+    <organization>
+        <name>Company</name>
+        <url>http://www.company.com/</url>
+    </organization>
+    <inceptionYear>2002</inceptionYear>
+
+    <modules>
+        <module>api</module>
+        <module>common</module>
+        <module>broker</module>
+        <module>endpoint</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <!-- common version strategy -->
+            <dependency>
+                <groupId>javax.activation</groupId>
+                <artifactId>activation</artifactId>
+                <version>1.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.jms</groupId>
+                <artifactId>jms</artifactId>
+                <version>1.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.ejb</groupId>
+                <artifactId>ejb</artifactId>
+                <version>2.0</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.servlet</groupId>
+                <artifactId>servlet-api</artifactId>
+                <version>2.4</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.mail</groupId>
+                <artifactId>mail</artifactId>
+                <version>1.4</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>xml-apis</groupId>
+                <artifactId>xml-apis</artifactId>
+                <version>2.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>commons-logging</groupId>
+                <artifactId>commons-logging</artifactId>
+                <version>1.0.4</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-lang</groupId>
+                <artifactId>commons-lang</artifactId>
+                <version>2.1</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>3.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring</artifactId>
+                <version>2.0.7</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-mock</artifactId>
+                <version>2.0.7</version>
+                <scope>test</scope>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.springframework</groupId>
+                        <artifactId>spring-jdbc</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>org.springframework</groupId>
+                        <artifactId>spring-web</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>log4j</groupId>
+                <artifactId>log4j</artifactId>
+                <version>1.2.8</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-discovery</groupId>
+                <artifactId>commons-discovery</artifactId>
+                <version>0.2</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-id</groupId>
+                <artifactId>commons-id</artifactId>
+                <version>0.1-dev</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.castor</groupId>
+                <artifactId>castor</artifactId>
+                <version>1.0.5-xml</version>
+            </dependency>
+            <dependency>
+                <groupId>xerces</groupId>
+                <artifactId>xerces</artifactId>
+                <version>2.4.0</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-httpclient</groupId>
+                <artifactId>commons-httpclient</artifactId>
+                <version>3.1</version>
+            </dependency>
+            <dependency>
+                <groupId>stax</groupId>
+                <artifactId>stax-api</artifactId>
+                <version>1.0.1</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.woodstox</groupId>
+                <artifactId>wstx-asl</artifactId>
+                <version>3.2.1</version>
+            </dependency>
+            <dependency>
+                <groupId>com.thoughtworks.xstream</groupId>
+                <artifactId>xstream</artifactId>
+                <version>1.2.2</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.management</groupId>
+                <artifactId>jmxri</artifactId>
+                <version>1.2.1</version>
+                <scope>provided</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>
index fe3985a020d5ef34a3c4898495ee0c16b166dccf..8559e035c12c73bf8e56e0de077af1bec04662fa 100644 (file)
@@ -40,6 +40,8 @@ public abstract class AbstractDeclarativeConstraint
     protected Object[] params;
 
     protected int[] range;
+    
+    protected String sortDirection = Constraint.ASCENDING;
 
     public String getFilter()
     {
@@ -68,7 +70,7 @@ public abstract class AbstractDeclarativeConstraint
 
     public String getSortDirection()
     {
-        return Constraint.ASCENDING;
+        return sortDirection;
     }
     
     public String[] getVariables()
index 4506123a2b9f993d5dc49723446fbc7572cb5969..9b3afab0a5fa005bf51e2561aa5ac96c37a8a2a8 100644 (file)
@@ -44,14 +44,26 @@ public class ArtifactsByRepositoryConstraint
         params = new Object[] { repoId };
        }
                
-       public ArtifactsByRepositoryConstraint( String repoId, Date targetWhenGathered, String sortColumn )
+       public ArtifactsByRepositoryConstraint( String repoId, Date targetWhenGathered, String sortColumn, boolean isBefore )
     {
+           String condition = isBefore ? "<=" : ">=";
+           
            declImports = new String[] { "import java.util.Date" };
-           whereClause = "this.repositoryId == repoId && this.whenGathered >= targetWhenGathered";        
+           whereClause = "this.repositoryId == repoId && this.whenGathered " + condition + " targetWhenGathered";        
         declParams = new String[] { "String repoId", "Date targetWhenGathered" };
         params = new Object[] { repoId, targetWhenGathered };        
         this.sortColumn = sortColumn;
     }
+       
+       public ArtifactsByRepositoryConstraint( String repoId, String type, Date before, String sortColumn )
+       {
+           declImports = new String[] { "import java.util.Date" };
+        whereClause =
+            "this.repositoryId == repoId && this.type == type && this.whenGathered <= before";        
+        declParams = new String[] { "String repoId", "String type", "Date before" };
+        params = new Object[] { repoId, type, before };        
+        this.sortColumn = sortColumn;
+       }
                
        public String getSortColumn() 
        {               
index dc39909802e9ff2bd4630fd371d9154a29bedc6a..ac3aad06102183512d002cd4a3204da62b8cb9f9 100644 (file)
@@ -1,5 +1,9 @@
 package org.apache.maven.archiva.database.constraints;
 
+import java.util.Date;
+
+import org.apache.maven.archiva.database.Constraint;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -36,6 +40,16 @@ public class RepositoryContentStatisticsByRepositoryConstraint
         declParams = new String[] { "String repoId" };
         params = new Object[] { repoId };
     }
+    
+    public RepositoryContentStatisticsByRepositoryConstraint( String repoId, Date startDate, Date endDate )
+    {    
+        declImports = new String[] { "import java.util.Date" };
+        whereClause = "repositoryId == repoId && whenGathered >= startDate && whenGathered <= endDate";
+        declParams = new String[] { "String repoId", "Date startDate", "Date endDate" };
+        params = new Object[] { repoId, startDate, endDate };
+        
+        sortDirection = Constraint.DESCENDING;
+    }
 
     public String getSortColumn()
     {
index 47766b94e8692ccc80061109063bb3b76ec21f85..d64382c7dfb6d648ba07d05d3400e5bddc213026 100644 (file)
@@ -35,7 +35,9 @@ public class UniqueArtifactIdConstraint
     implements Constraint
 {
     private StringBuffer sql = new StringBuffer();
-
+    
+    private Class resultClass;
+    
     /**
      * Obtain a set of unique ArtifactIds for the specified groupId.
      * 
@@ -43,7 +45,7 @@ public class UniqueArtifactIdConstraint
      */
     public UniqueArtifactIdConstraint( List<String> selectedRepositoryIds, String groupId )
     {
-        appendSelect( sql );
+        appendSelect( sql, false );
         sql.append( " WHERE " );
         SqlBuilder.appendWhereSelectedRepositories( sql, "repositoryId", selectedRepositoryIds );
         sql.append( " && " );
@@ -60,17 +62,36 @@ public class UniqueArtifactIdConstraint
      */
     public UniqueArtifactIdConstraint( String groupId )
     {
-        appendSelect( sql );
+        appendSelect( sql, false );
         sql.append( " WHERE " );
         appendWhereSelectedGroupId( sql );
         appendGroupBy( sql );
 
         super.params = new Object[] { groupId };
     }
+    
+    /**
+     * Obtain a set of unique artifactIds with respect to their groups from the specified repository.
+     * 
+     * @param repoId
+     * @param isUnique
+     */
+    public UniqueArtifactIdConstraint( String repoId, boolean isUnique )
+    {
+        appendSelect( sql, isUnique );
+        sql.append( " WHERE repositoryId == \"" + repoId + "\"" );
+        
+        resultClass = Object[].class;
+    }
 
     @SuppressWarnings("unchecked")
     public Class getResultClass()
     {
+        if( resultClass != null )
+        {
+            return resultClass;
+        }
+        
         return String.class;
     }
 
@@ -84,9 +105,16 @@ public class UniqueArtifactIdConstraint
         buf.append( " GROUP BY artifactId ORDER BY artifactId ASCENDING" );
     }
 
-    private void appendSelect( StringBuffer buf )
+    private void appendSelect( StringBuffer buf, boolean isUnique )
     {
-        buf.append( "SELECT artifactId FROM " ).append( ArchivaArtifactModel.class.getName() );
+        if( isUnique )
+        {
+            buf.append( "SELECT DISTINCT groupId, artifactId FROM " ).append( ArchivaArtifactModel.class.getName() );
+        }
+        else
+        {
+            buf.append( "SELECT artifactId FROM " ).append( ArchivaArtifactModel.class.getName() );
+        }
     }
 
     private void appendWhereSelectedGroupId( StringBuffer buf )
index 04f3a23c70d99ef99562142b45287f9f3a07a67c..2e636197e2679f16e448e2592d1bb91c1ec75629 100644 (file)
@@ -24,6 +24,7 @@ import java.util.List;
 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.model.ArchivaModelCloner;
 import org.apache.maven.archiva.model.ArchivaProjectModel;
 import org.apache.maven.archiva.model.VersionedReference;
 import org.apache.maven.archiva.repository.project.ProjectModelException;
@@ -135,7 +136,9 @@ public class ProjectModelToDatabaseListener
             return;
         }
 
-        model.setOrigin( "filesystem" );
+        // Clone model, since DAO while detachingCopy resets contents of the model
+        // this changes behaviour of EffectiveProjectModelFilter
+        model = ArchivaModelCloner.clone( model );
 
         try
         {
index c503ffcfa147b50cb55310c56f693cbcb0680a09..41516e7d58a93300107f0389dbbaa9b1774bfd33 100644 (file)
@@ -37,20 +37,20 @@ import org.apache.maven.archiva.model.ArchivaArtifact;
 public class ArtifactsByRepositoryConstraintTest
     extends AbstractArchivaDatabaseTestCase
 {
-    private ArtifactDAO artifactDao;
+    private ArtifactDAO artifactDao; 
 
     public void setUp()
         throws Exception
     {
-        super.setUp();
+        super.setUp(); 
 
         ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" );
         artifactDao = dao.getArtifactDAO();
     }
 
-    private ArchivaArtifact createArtifact( String groupId, String artifactId, String version )
+    private ArchivaArtifact createArtifact( String groupId, String artifactId, String version, String type )
     {
-        ArchivaArtifact artifact = artifactDao.createArtifact( groupId, artifactId, version, null, "jar" );
+        ArchivaArtifact artifact = artifactDao.createArtifact( groupId, artifactId, version, null, type );
         artifact.getModel().setLastModified( new Date() );
         artifact.getModel().setRepositoryId( "test-repo" );
 
@@ -63,19 +63,19 @@ public class ArtifactsByRepositoryConstraintTest
         Date whenGathered = Calendar.getInstance().getTime();
         whenGathered.setTime( 123456789 );
 
-        ArchivaArtifact artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0" );
+        ArchivaArtifact artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.1" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.1", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-two", "1.0.2" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-two", "1.0.2", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-one", "2.0" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "2.0", "jar" );
         artifact.getModel().setRepositoryId( "different-repo" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
@@ -88,19 +88,19 @@ public class ArtifactsByRepositoryConstraintTest
     {
         Date whenGathered = Calendar.getInstance().getTime();
 
-        ArchivaArtifact artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0" );
+        ArchivaArtifact artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.1" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.1", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.2" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.2", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-one", "2.0" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "2.0", "jar" );
         artifact.getModel().setRepositoryId( "different-repo" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
@@ -108,18 +108,63 @@ public class ArtifactsByRepositoryConstraintTest
         Date olderWhenGathered = Calendar.getInstance().getTime();
         olderWhenGathered.setTime( 123456789 );
         
-        artifact = createArtifact( "org.apache.archiva", "artifact-two", "1.1-SNAPSHOT" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-two", "1.1-SNAPSHOT", "jar" );
         artifact.getModel().setWhenGathered( olderWhenGathered );
         artifactDao.saveArtifact( artifact );
 
-        artifact = createArtifact( "org.apache.archiva", "artifact-three", "2.0-beta-1" );
+        artifact = createArtifact( "org.apache.archiva", "artifact-three", "2.0-beta-1", "jar" );
         artifact.getModel().setWhenGathered( whenGathered );
         artifactDao.saveArtifact( artifact );
 
         assertConstraint( "Artifacts By Repository and When Gathered", 4,
-                          new ArtifactsByRepositoryConstraint( "test-repo", whenGathered, "repositoryId" ) );
+                          new ArtifactsByRepositoryConstraint( "test-repo", whenGathered, "repositoryId", false ) );
     }
+    
+    public void testQueryArtifactsInRepoByType()
+        throws Exception
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.set( 2008, 9, 1 );
+        Date whenGathered = cal.getTime();
+
+        ArchivaArtifact artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0", "jar" );
+        artifact.getModel().setWhenGathered( whenGathered );
+        artifactDao.saveArtifact( artifact );
+
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.1", "jar" );
+        artifact.getModel().setWhenGathered( whenGathered );
+        artifactDao.saveArtifact( artifact );
+
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "1.0.2", "jar" );
+        artifact.getModel().setWhenGathered( whenGathered );
+        artifactDao.saveArtifact( artifact );
+        
+        artifact = createArtifact( "org.apache.archiva", "artifact-two", "1.1-SNAPSHOT", "war" );
+        artifact.getModel().setWhenGathered( whenGathered );
+        artifactDao.saveArtifact( artifact );
+
+        artifact = createArtifact( "org.apache.archiva", "artifact-three", "2.0-beta-1", "war" );
+        artifact.getModel().setWhenGathered( whenGathered );
+        artifactDao.saveArtifact( artifact );
 
+        Calendar cal2 = Calendar.getInstance();
+        cal2.set( 2008, 12, 12 );
+        Date diffWhenGathered = cal2.getTime();
+        
+        artifact = createArtifact( "org.apache.archiva", "artifact-one", "2.0", "jar" );
+        artifact.getModel().setWhenGathered( diffWhenGathered );
+        artifactDao.saveArtifact( artifact );
+        
+        cal2 = Calendar.getInstance();
+        cal2.set( 2008, 10, 30 );
+        Date before = cal2.getTime();
+        
+        assertConstraint( "Artifacts of Type 'jar' By Repository and When Gathered", 3,
+                          new ArtifactsByRepositoryConstraint( "test-repo", "jar", before, "whenGathered" ) );
+        assertConstraint( "Artifacts of Type 'war' By Repository and When Gathered", 2,
+                          new ArtifactsByRepositoryConstraint( "test-repo", "war", before, "whenGathered" ) );
+    }
+    
     private void assertConstraint( String msg, int count, ArtifactsByRepositoryConstraint constraint )
         throws Exception
     {
index 3e036b554e8b9e790c3619fab63e48f3d4d08544..4a6b4555cad36bb87dd540b9e70fd4ffaa960e35 100644 (file)
@@ -32,7 +32,7 @@ import org.apache.maven.archiva.model.RepositoryContentStatistics;
  * @version
  */
 public class RepositoryContentStatisticsByRepositoryConstraintTest
-    extends AbstractArchivaDatabaseTestCase
+    extends AbstractArchivaDatabaseTestCase 
 {
     private RepositoryContentStatistics createStats( String repoId, String timestamp, long duration, long totalfiles,
                                                      long newfiles )
@@ -76,4 +76,27 @@ public class RepositoryContentStatisticsByRepositoryConstraintTest
         assertEquals( "internal", ( (RepositoryContentStatistics) results.get( 2 ) ).getRepositoryId() );
         assertEquals( "internal", ( (RepositoryContentStatistics) results.get( 3 ) ).getRepositoryId() );
     }
+    
+    public void testStatsWithDateRange()
+        throws Exception
+    {
+        Constraint constraint =
+            new RepositoryContentStatisticsByRepositoryConstraint( "internal", toDate( "2007/10/18 8:00:00" ),
+                                                                   toDate( "2007/10/20 8:00:00" ) );
+        List results = dao.getRepositoryContentStatisticsDAO().queryRepositoryContentStatistics( constraint );
+        assertNotNull( "Stats: results (not null)", results );
+        assertEquals( "Stats: results.size", 3, results.size() );
+
+        assertEquals( "internal", ( (RepositoryContentStatistics) results.get( 0 ) ).getRepositoryId() );
+        assertEquals( toDate( "2007/10/20 8:00:00" ),
+                      ( (RepositoryContentStatistics) results.get( 0 ) ).getWhenGathered() );
+
+        assertEquals( "internal", ( (RepositoryContentStatistics) results.get( 1 ) ).getRepositoryId() );
+        assertEquals( toDate( "2007/10/19 8:00:00" ),
+                      ( (RepositoryContentStatistics) results.get( 1 ) ).getWhenGathered() );
+
+        assertEquals( "internal", ( (RepositoryContentStatistics) results.get( 2 ) ).getRepositoryId() );
+        assertEquals( toDate( "2007/10/18 8:00:00" ),
+                      ( (RepositoryContentStatistics) results.get( 2 ) ).getWhenGathered() );
+    }
 }
index 45191ec3aed92130f8783588246c59787d344cb4..db9fc81bb5eff69ec2a0854b2ea4a22215c167ff 100644 (file)
@@ -22,6 +22,7 @@ package org.apache.maven.archiva.database.constraints;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.archiva.database.AbstractArchivaDatabaseTestCase;
 import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
 import org.apache.maven.archiva.database.ArtifactDAO;
 import org.apache.maven.archiva.database.SimpleConstraint;
 import org.apache.maven.archiva.model.ArchivaArtifact;
@@ -62,9 +63,31 @@ public class UniqueArtifactIdConstraintTest
     public void testConstraint()
         throws Exception
     {
-        ArchivaArtifact artifact;
+        setUpArtifacts();
 
-        // Setup artifacts in fresh DB.
+        assertConstraint( new String[] {}, new UniqueArtifactIdConstraint( "org.apache" ) );
+        assertConstraint( new String[] { "commons-lang" }, new UniqueArtifactIdConstraint( "commons-lang" ) );
+        assertConstraint( new String[] { "test-one" }, new UniqueArtifactIdConstraint( "org.apache.maven.test" ) );
+        assertConstraint( new String[] { "test-two", "test-bar" },
+                          new UniqueArtifactIdConstraint( "org.apache.maven.shared" ) );
+        assertConstraint( new String[] { "modellong" }, new UniqueArtifactIdConstraint( "org.codehaus.modello" ) );
+    }
+    
+    public void testConstraintDisregardGroupId()
+        throws Exception
+    {
+        setUpArtifacts();
+        
+        assertConstraintWithMultipleResultTypes( new String[] { "commons-lang", "test-one", "test-two", "test-two", "test-bar", "modellong" },
+                          new UniqueArtifactIdConstraint( "testable_repo", true ) );
+    }
+
+    private void setUpArtifacts()
+        throws ArchivaDatabaseException
+    {
+        ArchivaArtifact artifact;
+        
+     // Setup artifacts in fresh DB.
         artifact = createArtifact( "commons-lang", "commons-lang", "2.0" );
         artifactDao.saveArtifact( artifact );
 
@@ -88,26 +111,41 @@ public class UniqueArtifactIdConstraintTest
 
         artifact = createArtifact( "org.codehaus.modello", "modellong", "3.0" );
         artifactDao.saveArtifact( artifact );
-
-        assertConstraint( new String[] {}, new UniqueArtifactIdConstraint( "org.apache" ) );
-        assertConstraint( new String[] { "commons-lang" }, new UniqueArtifactIdConstraint( "commons-lang" ) );
-        assertConstraint( new String[] { "test-one" }, new UniqueArtifactIdConstraint( "org.apache.maven.test" ) );
-        assertConstraint( new String[] { "test-two", "test-bar" },
-                          new UniqueArtifactIdConstraint( "org.apache.maven.shared" ) );
-        assertConstraint( new String[] { "modellong" }, new UniqueArtifactIdConstraint( "org.codehaus.modello" ) );
     }
-
+    
+    private void assertConstraintWithMultipleResultTypes( String[] artifactIds, SimpleConstraint constraint )
+        throws Exception
+    {
+        String prefix = "Unique Artifact IDs: ";
+    
+        List<Object[]> results = dao.query( constraint );
+        assertNotNull( prefix + "Not Null", results );
+        assertEquals( prefix + "Results.size", artifactIds.length, results.size() );
+    
+        List<String> expectedArtifactIds = Arrays.asList( artifactIds );
+    
+        Iterator<Object[]> it = results.iterator();
+        while ( it.hasNext() )
+        {
+            Object[] actualArtifactIds = (Object[]) it.next();            
+            String actualArtifactId = ( String ) actualArtifactIds[1];
+            assertTrue( prefix + "artifactId result should not be blank.", StringUtils.isNotBlank( actualArtifactId ) );
+            assertTrue( prefix + " artifactId result <" + actualArtifactId + "> exists in expected artifactIds.",
+                        expectedArtifactIds.contains( actualArtifactId ) );            
+        }
+    }
+    
     private void assertConstraint( String[] artifactIds, SimpleConstraint constraint )
     {
         String prefix = "Unique Artifact IDs: ";
 
-        List results = dao.query( constraint );
+        List<String> results = dao.query( constraint );
         assertNotNull( prefix + "Not Null", results );
         assertEquals( prefix + "Results.size", artifactIds.length, results.size() );
 
-        List expectedArtifactIds = Arrays.asList( artifactIds );
+        List<String> expectedArtifactIds = Arrays.asList( artifactIds );
 
-        Iterator it = results.iterator();
+        Iterator<String> it = results.iterator();
         while ( it.hasNext() )
         {
             String actualArtifactId = (String) it.next();
index b32ea06cf1c5be2c815f2682cf885f53a1bb957a..eef212eb2bf054131b3861a129e12ae4da6ef36f 100644 (file)
@@ -230,8 +230,8 @@ public class UniqueGroupIdConstraintTest
 
         assertConstraint( new String[] { "org.codehaus.modello", "org.codehaus.mojo", "org.apache.archiva" },
                           new UniqueGroupIdConstraint( observableRepositories ) );
-    }
-
+    }   
+    
     private void assertConstraint( String[] expectedGroupIds, SimpleConstraint constraint )
         throws Exception
     {
index 2220a81f1f02c980d9ec0ff203906fbf8e370f7a..cf94e84b8c28c559fb2f24b6f3df98404144642c 100755 (executable)
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
   </build>
diff --git a/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java b/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java
new file mode 100644 (file)
index 0000000..3eca9bf
--- /dev/null
@@ -0,0 +1,40 @@
+package org.apache.maven.archiva.reporting;
+
+/*
+ * 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.
+ */
+
+/**
+ * ArchivaReportException
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id: ArchivaReportException.java
+ */
+public class ArchivaReportException
+    extends Exception
+{
+    public ArchivaReportException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public ArchivaReportException( String message )
+    {
+        super( message );
+    }
+}
diff --git a/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java b/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java
new file mode 100644 (file)
index 0000000..44d6d4a
--- /dev/null
@@ -0,0 +1,234 @@
+package org.apache.maven.archiva.reporting;
+
+import java.util.Date;
+
+/*
+ * 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.
+ */
+
+/**
+ * RepositoryStatistics
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class RepositoryStatistics
+{
+    private String repositoryId;
+    
+    private long fileCount = 0;
+    
+    private long totalSize = 0;
+    
+    private long projectCount = 0;
+    
+    private long groupCount = 0;
+    
+    private long artifactCount = 0;
+    
+    private long pluginCount = 0;
+    
+    private long archetypeCount = 0;
+    
+    private long jarCount = 0;
+    
+    private long warCount = 0;
+    
+    private long earCount = 0;
+    
+    private long dllCount = 0;
+    
+    private long exeCount = 0;
+    
+    private long pomCount = 0;
+    
+    private long deploymentCount = 0;
+    
+    private long downloadCount = 0;
+    
+    private Date dateOfScan;
+
+    public String getRepositoryId()
+    {
+        return repositoryId;
+    }
+
+    public void setRepositoryId( String repositoryId )
+    {
+        this.repositoryId = repositoryId;
+    }
+
+    public long getFileCount()
+    {
+        return fileCount;
+    }
+
+    public void setFileCount( long fileCount )
+    {
+        this.fileCount = fileCount;
+    }
+
+    public long getTotalSize()
+    {
+        return totalSize;
+    }
+
+    public void setTotalSize( long totalSize )
+    {
+        this.totalSize = totalSize;
+    }
+
+    public long getProjectCount()
+    {
+        return projectCount;
+    }
+
+    public void setProjectCount( long projectCount )
+    {
+        this.projectCount = projectCount;
+    }
+
+    public long getGroupCount()
+    {
+        return groupCount;
+    }
+
+    public void setGroupCount( long groupCount )
+    {
+        this.groupCount = groupCount;
+    }
+
+    public long getArtifactCount()
+    {
+        return artifactCount;
+    }
+
+    public void setArtifactCount( long artifactCount )
+    {
+        this.artifactCount = artifactCount;
+    }
+
+    public long getPluginCount()
+    {
+        return pluginCount;
+    }
+
+    public void setPluginCount( long pluginCount )
+    {
+        this.pluginCount = pluginCount;
+    }
+
+    public long getArchetypeCount()
+    {
+        return archetypeCount;
+    }
+
+    public void setArchetypeCount( long archetypeCount )
+    {
+        this.archetypeCount = archetypeCount;
+    }
+
+    public long getJarCount()
+    {
+        return jarCount;
+    }
+
+    public void setJarCount( long jarCount )
+    {
+        this.jarCount = jarCount;
+    }
+
+    public long getWarCount()
+    {
+        return warCount;
+    }
+
+    public void setWarCount( long warCount )
+    {
+        this.warCount = warCount;
+    }
+
+    public long getEarCount()
+    {
+        return earCount;
+    }
+
+    public void setEarCount( long earCount )
+    {
+        this.earCount = earCount;
+    }
+
+    public long getDllCount()
+    {
+        return dllCount;
+    }
+
+    public void setDllCount( long dllCount )
+    {
+        this.dllCount = dllCount;
+    }
+
+    public long getExeCount()
+    {
+        return exeCount;
+    }
+
+    public void setExeCount( long exeCount )
+    {
+        this.exeCount = exeCount;
+    }
+
+    public long getPomCount()
+    {
+        return pomCount;
+    }
+
+    public void setPomCount( long pomCount )
+    {
+        this.pomCount = pomCount;
+    }
+
+    public long getDeploymentCount()
+    {
+        return deploymentCount;
+    }
+
+    public void setDeploymentCount( long deploymentCount )
+    {
+        this.deploymentCount = deploymentCount;
+    }
+
+    public long getDownloadCount()
+    {
+        return downloadCount;
+    }
+
+    public void setDownloadCount( long downloadCount )
+    {
+        this.downloadCount = downloadCount;
+    }
+
+    public Date getDateOfScan()
+    {
+        return dateOfScan;
+    }
+
+    public void setDateOfScan( Date dateOfScan )
+    {
+        this.dateOfScan = dateOfScan;
+    }
+}
diff --git a/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java b/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java
new file mode 100644 (file)
index 0000000..1b1e0aa
--- /dev/null
@@ -0,0 +1,50 @@
+package org.apache.maven.archiva.reporting;
+
+/*
+ * 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.model.RepositoryContentStatistics;
+
+/**
+ * RepositoryStatisticsReportGenerator
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id: RepositoryStatisticsReportGenerator.java
+ */
+public interface RepositoryStatisticsReportGenerator
+{
+    public static final String JAR_TYPE = "jar";
+    
+    public static final String WAR_TYPE = "war";
+    
+    public static final String POM_TYPE = "pom";
+    
+    public static final String MAVEN_PLUGIN = "maven-plugin";
+    
+    public static final String ARCHETYPE = "archetype";
+    
+    public List<RepositoryStatistics> generateReport( List<RepositoryContentStatistics> repoContentStats, String repository, Date startDate, Date endDate, DataLimits limits )
+        throws ArchivaReportException;
+    
+    public List<RepositoryStatistics> generateReport( List<RepositoryContentStatistics> repoContentStats, String repository, Date startDate, Date endDate )
+        throws ArchivaReportException;
+}
diff --git a/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java b/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java
new file mode 100644 (file)
index 0000000..8eb7586
--- /dev/null
@@ -0,0 +1,147 @@
+package org.apache.maven.archiva.reporting;
+
+/*
+ * 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.Date;
+import java.util.List;
+
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArchivaDatabaseException;
+import org.apache.maven.archiva.database.ArtifactDAO;
+import org.apache.maven.archiva.database.constraints.ArtifactsByRepositoryConstraint;
+import org.apache.maven.archiva.model.RepositoryContentStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SimpleRepositoryStatisticsReportGenerator
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id: SimpleRepositoryStatisticsReportGenerator.java
+ * 
+ * @plexus.component role="org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator" role-hint="simple"
+ */
+public class SimpleRepositoryStatisticsReportGenerator
+    implements RepositoryStatisticsReportGenerator
+{   
+    private Logger log = LoggerFactory.getLogger( SimpleRepositoryStatisticsReportGenerator.class );
+    
+    /**
+     * @plexus.requirement role-hint="jdo"
+     */
+    private ArchivaDAO dao;
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator#generateReport(java.util.List
+     *      repoContentStats, java.util.String repository, java.util.Date startDate, java.util.Date endDate,
+     *      org.apache.maven.archiva.reporting.DataLimits limits )
+     */
+    public List<RepositoryStatistics> generateReport( List<RepositoryContentStatistics> repoContentStats,
+                                                      String repository, Date startDate, Date endDate, DataLimits limits )
+        throws ArchivaReportException
+    {   
+        if( limits.getCurrentPage() > limits.getCountOfPages() )
+        {
+            throw new ArchivaReportException( "The requested page exceeds the total number of pages." );
+        }
+         
+        int start = ( limits.getPerPageCount() * limits.getCurrentPage() ) - limits.getPerPageCount();
+        int end = ( start + limits.getPerPageCount() ) - 1;
+        
+        if( end > repoContentStats.size() )
+        {
+            end = repoContentStats.size() - 1;
+        }
+        
+        return constructRepositoryStatistics( repoContentStats, repository, endDate, start, end );
+    }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator#generateReport(java.util.List
+     *      repoContentStats, java.util.String repository, java.util.Date startDate, java.util.Date endDate)
+     */
+    public List<RepositoryStatistics> generateReport( List<RepositoryContentStatistics> repoContentStats, String repository, Date startDate, Date endDate )
+        throws ArchivaReportException
+    {
+        return constructRepositoryStatistics( repoContentStats, repository, endDate, 0, repoContentStats.size() - 1 );
+    }
+
+    private List<RepositoryStatistics> constructRepositoryStatistics(
+                                                                      List<RepositoryContentStatistics> repoContentStats,
+                                                                      String repository, Date endDate,
+                                                                      int start, int end )
+    {
+        ArtifactDAO artifactDao = dao.getArtifactDAO();    
+        
+        List<RepositoryStatistics> repoStatisticsList = new ArrayList<RepositoryStatistics>();
+        for( int i = start; i <= end; i++ )
+        {   
+            RepositoryContentStatistics repoContentStat = (RepositoryContentStatistics) repoContentStats.get( i );
+            RepositoryStatistics repoStatistics = new RepositoryStatistics();
+            repoStatistics.setRepositoryId( repository );
+            
+            // get only the latest                
+            repoStatistics.setArtifactCount( repoContentStat.getTotalArtifactCount() );
+            repoStatistics.setGroupCount( repoContentStat.getTotalGroupCount() );
+            repoStatistics.setProjectCount( repoContentStat.getTotalProjectCount() );
+            repoStatistics.setTotalSize( repoContentStat.getTotalSize() );
+            repoStatistics.setFileCount( repoContentStat.getTotalFileCount() );
+            repoStatistics.setDateOfScan( repoContentStat.getWhenGathered() );
+                
+            try
+            {
+                //TODO use the repo content stats whenGathered date instead of endDate for single repo reports
+                List types = artifactDao.queryArtifacts( 
+                         new ArtifactsByRepositoryConstraint( repository, JAR_TYPE, endDate, "whenGathered" ) );
+                repoStatistics.setJarCount( types.size() );
+                
+                types = artifactDao.queryArtifacts( 
+                        new ArtifactsByRepositoryConstraint( repository, WAR_TYPE, endDate, "whenGathered" ) );
+                repoStatistics.setWarCount( types.size() );
+                
+                types = artifactDao.queryArtifacts( 
+                        new ArtifactsByRepositoryConstraint( repository, MAVEN_PLUGIN, endDate, "whenGathered" ) );
+                repoStatistics.setPluginCount( types.size() );
+                
+                // TODO: must need to be able to track archetypes. possible way of identifying an 
+                //      archetype is by checking if archetype.xml exists in src/main/resources/META-INF/
+                
+            }
+            catch( ArchivaDatabaseException e )
+            {
+                log.error( "Error occurred while querying artifacts from the database.", e.getMessage() );                 
+            }            
+                            
+            repoStatisticsList.add( repoStatistics );  
+        }
+        
+        return repoStatisticsList;
+    }
+        
+    public void setDao( ArchivaDAO dao )
+    {
+        this.dao = dao;
+    }
+}
diff --git a/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java b/archiva-struts2/archiva-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java
new file mode 100644 (file)
index 0000000..49828e0
--- /dev/null
@@ -0,0 +1,356 @@
+package org.apache.maven.archiva.reporting;
+
+/*
+ * 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.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.maven.archiva.database.ArchivaDAO;
+import org.apache.maven.archiva.database.ArtifactDAO;
+import org.apache.maven.archiva.database.constraints.ArtifactsByRepositoryConstraint;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.RepositoryContentStatistics;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.easymock.MockControl;
+import org.easymock.internal.AlwaysMatcher;
+
+/**
+ * SimpleRepositoryStatisticsReportGeneratorTest
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id: SimpleRepositoryStatisticsReportGenerator.java
+ * 
+ * @plexus.component role="org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator" role-hint="simple"
+ */
+public class SimpleRepositoryStatisticsReportGeneratorTest 
+    extends PlexusInSpringTestCase
+{    
+    private MockControl daoControl;
+    
+    private ArchivaDAO dao;
+    
+    private MockControl artifactDaoControl;
+    
+    private ArtifactDAO artifactDao;
+    
+    private SimpleRepositoryStatisticsReportGenerator generator;
+    
+    private static final String REPO = "test-repo";
+    
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        
+        daoControl = MockControl.createControl( ArchivaDAO.class );        
+        dao = ( ArchivaDAO ) daoControl.getMock();
+        
+        generator = new SimpleRepositoryStatisticsReportGenerator();
+        generator.setDao( dao );
+        
+        artifactDaoControl = MockControl.createControl( ArtifactDAO.class );
+        artifactDaoControl.setDefaultMatcher( new AlwaysMatcher() );
+        artifactDao = ( ArtifactDAO ) artifactDaoControl.getMock();       
+    }
+    
+    private Date toDate( int year, int month, int date, int hour, int min, int sec )
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set( year, month, date, hour, min, sec );        
+        
+        return cal.getTime();        
+    }
+    
+    private List<ArchivaArtifact> createArtifacts( String type )
+    {
+        List<ArchivaArtifact> artifacts = new ArrayList<ArchivaArtifact>();
+        artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "1.0", type ) );
+        artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "1.1", type ) );
+        artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "1.2", type ) );
+        artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "2.0", type ) );
+        artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "3.0", type ) );
+
+        return artifacts;
+    }    
+
+    private ArchivaArtifact createArtifact( String repoId, String groupId, String artifactId, String version, String type )
+    {
+        ArchivaArtifact artifact = new ArchivaArtifact( groupId, artifactId, version, null, type );
+        artifact.getModel().setLastModified( new Date() );
+        artifact.getModel().setRepositoryId( repoId );
+
+        return artifact;
+    }
+    
+    private RepositoryContentStatistics createRepositoryContentStatistics( Date startDate, String repositoryId )
+    {
+        RepositoryContentStatistics repoContentStats = new RepositoryContentStatistics();
+        repoContentStats.setRepositoryId( repositoryId );
+        repoContentStats.setDuration( 10000 );
+        repoContentStats.setNewFileCount( 100 );
+        repoContentStats.setTotalArtifactCount( 200 );
+        repoContentStats.setTotalFileCount( 250 );
+        repoContentStats.setTotalGroupCount( 100 );
+        repoContentStats.setTotalProjectCount( 180 );
+        repoContentStats.setTotalSize( 200000 );
+        repoContentStats.setWhenGathered( startDate );
+        
+        return repoContentStats;
+    }
+    
+    private List<RepositoryContentStatistics> createStatisticsHistoryForSingleRepositoryTest( String repoId )
+    {
+        List<RepositoryContentStatistics> repoContentStatsList = new ArrayList<RepositoryContentStatistics>();
+        
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 11, 1, 0, 0, 0 ), repoId ) );        
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 10, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 10, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 9, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 9, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 8, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 8, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 7, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 7, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 6, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 6, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 5, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 5, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 4, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 4, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 3, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 3, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 2, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 2, 1, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 1, 16, 0, 0, 0 ), repoId ) );
+        repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 1, 1, 0, 0, 0 ), repoId ) );
+        
+        return repoContentStatsList;
+    }   
+    
+    public void testSimpleReportWithPagination()
+        throws Exception
+    {   
+        Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
+        Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
+                
+        DataLimits limits = new DataLimits();
+        limits.setPerPageCount( 5 );
+        limits.setCurrentPage( 1 );
+        limits.setCountOfPages( 5 );
+        limits.setTotalCount( 21 );      
+                
+        List<ArchivaArtifact> jarArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.JAR_TYPE );        
+        List<ArchivaArtifact> warArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.WAR_TYPE );
+        List<ArchivaArtifact> mavenPlugins = createArtifacts( RepositoryStatisticsReportGenerator.MAVEN_PLUGIN );
+        
+        List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
+        
+        // get first page
+        daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts, 5 );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts, 5 );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins, 5 );
+        
+        daoControl.replay(); 
+        artifactDaoControl.replay();
+        
+        List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
+        
+        daoControl.verify();
+        artifactDaoControl.verify();
+        
+        assertEquals( 5, data.size() );
+        
+        RepositoryStatistics stats = (RepositoryStatistics) data.get( 0 );        
+        assertEquals( REPO, stats.getRepositoryId() );
+        assertEquals( 200, stats.getArtifactCount() );
+        assertEquals( 5, stats.getJarCount() );
+        assertEquals( 5, stats.getWarCount() );
+        assertEquals( 5, stats.getPluginCount() );
+        assertEquals( toDate( 2008, 11, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
+        assertEquals( toDate( 2008, 9, 1, 0, 0, 0 ).getTime(), ( (RepositoryStatistics) data.get( 4 ) ).getDateOfScan().getTime() );
+        
+        // get last page
+        limits.setCurrentPage( 5 );
+        
+        daoControl.reset();
+        artifactDaoControl.reset();
+        
+        artifactDaoControl.setDefaultMatcher( new AlwaysMatcher() );
+        
+        daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins );
+        
+        daoControl.replay(); 
+        artifactDaoControl.replay();
+        
+        data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
+        
+        daoControl.verify();
+        artifactDaoControl.verify();
+        
+        assertEquals( 1, data.size() );
+        
+        stats = (RepositoryStatistics) data.get( 0 );        
+        assertEquals( REPO, stats.getRepositoryId() );
+        assertEquals( 200, stats.getArtifactCount() );
+        assertEquals( 5, stats.getJarCount() );
+        assertEquals( 5, stats.getWarCount() );
+        assertEquals( 5, stats.getPluginCount() );
+        assertEquals( toDate( 2008, 1, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );  
+    }
+    
+    public void testSimpleReportWithoutPagination()
+        throws Exception
+    {
+        Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
+        Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
+                        
+        List<ArchivaArtifact> jarArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.JAR_TYPE );        
+        List<ArchivaArtifact> warArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.WAR_TYPE );
+        List<ArchivaArtifact> mavenPlugins = createArtifacts( RepositoryStatisticsReportGenerator.MAVEN_PLUGIN );
+        
+        List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
+        
+        // get first page
+        daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts, 21 );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts, 21 );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins, 21 );
+        
+        daoControl.replay(); 
+        artifactDaoControl.replay();
+        
+        List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate );
+        
+        daoControl.verify();
+        artifactDaoControl.verify();
+        
+        assertEquals( 21, data.size() );
+        
+        RepositoryStatistics stats = (RepositoryStatistics) data.get( 0 );        
+        assertEquals( REPO, stats.getRepositoryId() );
+        assertEquals( 200, stats.getArtifactCount() );
+        assertEquals( 5, stats.getJarCount() );
+        assertEquals( 5, stats.getWarCount() );
+        assertEquals( 5, stats.getPluginCount() );
+        assertEquals( toDate( 2008, 11, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
+        assertEquals( toDate( 2008, 1, 1, 0, 0, 0 ).getTime(), ( (RepositoryStatistics) data.get( 20 ) ).getDateOfScan().getTime() );
+    }
+    
+    public void testSimpleReportNoArtifactCountStatisticsAvailable()
+        throws Exception
+    {
+        Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
+        Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
+                
+        DataLimits limits = new DataLimits();
+        limits.setPerPageCount( 5 );
+        limits.setCurrentPage( 1 );
+        limits.setCountOfPages( 5 );
+        limits.setTotalCount( 21 );      
+                
+        List<ArchivaArtifact> jarArtifacts = new ArrayList<ArchivaArtifact>();        
+        List<ArchivaArtifact> warArtifacts = new ArrayList<ArchivaArtifact>();
+        List<ArchivaArtifact> mavenPlugins = new ArrayList<ArchivaArtifact>();
+        
+        List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
+                
+        daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts, 5 );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts, 5 );
+        
+        artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts( 
+                new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins, 5 );
+        
+        daoControl.replay(); 
+        artifactDaoControl.replay();
+        
+        List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
+        
+        daoControl.verify();
+        artifactDaoControl.verify();
+        
+        assertEquals( 5, data.size() );
+        
+        RepositoryStatistics stats = (RepositoryStatistics) data.get( 0 );        
+        assertEquals( REPO, stats.getRepositoryId() );
+        assertEquals( 200, stats.getArtifactCount() );
+        assertEquals( 0, stats.getJarCount() );
+        assertEquals( 0, stats.getWarCount() );
+        assertEquals( 0, stats.getPluginCount() );
+        assertEquals( toDate( 2008, 11, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
+        assertEquals( toDate( 2008, 9, 1, 0, 0, 0 ).getTime(), ( (RepositoryStatistics) data.get( 4 ) ).getDateOfScan().getTime() );
+        // no results found when ArtifactDAO was queried
+    }
+    
+    public void testSimpleReportWithPaginationInvalidRequestedPage()
+        throws Exception
+    {
+        Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
+        Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
+                
+        DataLimits limits = new DataLimits();
+        limits.setPerPageCount( 5 );
+        limits.setCurrentPage( 10 );
+        limits.setCountOfPages( 5 );
+        limits.setTotalCount( 21 );      
+        
+        List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
+        
+        try
+        {
+            List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
+            fail( "An ArchivaReportException should have been thrown." );
+        }
+        catch ( ArchivaReportException a )
+        {
+            
+        }
+        // requested page exceeds total number of pages
+    }
+}
index 527ee34fc7aca27c540aa4037fb56f344df0983a..b07388b044fa2ef2491cb1b9894d7287ad35cf98 100644 (file)
@@ -20,11 +20,17 @@ package org.apache.maven.archiva.scheduled.executors;
  */
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
 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.ArtifactsByRepositoryConstraint;
 import org.apache.maven.archiva.database.constraints.MostRecentRepositoryScanStatistics;
+import org.apache.maven.archiva.database.constraints.UniqueArtifactIdConstraint;
+import org.apache.maven.archiva.database.constraints.UniqueGroupIdConstraint;
 import org.apache.maven.archiva.model.RepositoryContentStatistics;
 import org.apache.maven.archiva.repository.RepositoryException;
 import org.apache.maven.archiva.repository.scanner.RepositoryScanStatistics;
@@ -38,6 +44,8 @@ import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -112,19 +120,59 @@ public class ArchivaRepositoryScanningTaskExecutor
 
             log.info( "Finished repository task: " + stats.toDump( arepo ) );
             
-            // I hate jpox and modello
-            RepositoryContentStatistics dbstats = new RepositoryContentStatistics();
-            dbstats.setDuration( stats.getDuration() );
-            dbstats.setNewFileCount( stats.getNewFileCount() );
-            dbstats.setRepositoryId( stats.getRepositoryId() );
-            dbstats.setTotalFileCount( stats.getTotalFileCount() );
-            dbstats.setWhenGathered( stats.getWhenGathered() );
+            RepositoryContentStatistics dbstats = constructRepositoryStatistics( arepo, sinceWhen, results, stats );
             
-            dao.getRepositoryContentStatisticsDAO().saveRepositoryContentStatistics( dbstats );
+            dao.getRepositoryContentStatisticsDAO().saveRepositoryContentStatistics( dbstats );            
         }
         catch ( RepositoryException e )
-        {
+        {   
             throw new TaskExecutionException( "Repository error when executing repository job.", e );
-        }        
+        }    
     }
+
+    private RepositoryContentStatistics constructRepositoryStatistics( ManagedRepositoryConfiguration arepo,
+                                                                       long sinceWhen,
+                                                                       List<RepositoryContentStatistics> results,
+                                                                       RepositoryScanStatistics stats )        
+    {
+        // I hate jpox and modello <-- and so do I
+        RepositoryContentStatistics dbstats = new RepositoryContentStatistics();
+        dbstats.setDuration( stats.getDuration() );
+        dbstats.setNewFileCount( stats.getNewFileCount() );
+        dbstats.setRepositoryId( stats.getRepositoryId() );
+        dbstats.setTotalFileCount( stats.getTotalFileCount() );
+        dbstats.setWhenGathered( stats.getWhenGathered() );
+                
+        // total artifact count
+        try
+        {
+            List artifacts = dao.getArtifactDAO().queryArtifacts( 
+                      new ArtifactsByRepositoryConstraint( arepo.getId(), stats.getWhenGathered(), "groupId", true ) );            
+            dbstats.setTotalArtifactCount( artifacts.size() );
+        }
+        catch ( ObjectNotFoundException oe )
+        {
+            log.error( "Object not found in the database : " + oe.getMessage() );
+        }
+        catch ( ArchivaDatabaseException ae )
+        {   
+            log.error( "Error occurred while querying artifacts for artifact count : " + ae.getMessage() );
+        }
+        
+        // total repo size
+        long size = FileUtils.sizeOfDirectory( new File( arepo.getLocation() ) );
+        dbstats.setTotalSize( size );
+          
+          // total unique groups
+        List<String> repos = new ArrayList<String>();
+        repos.add( arepo.getId() ); 
+        
+        List<String> groupIds = dao.query( new UniqueGroupIdConstraint( repos ) );
+        dbstats.setTotalGroupCount( groupIds.size() );
+                
+        List<Object[]> artifactIds = dao.query( new UniqueArtifactIdConstraint( arepo.getId(), true ) );
+        dbstats.setTotalProjectCount( artifactIds.size() );
+                        
+        return dbstats;
+    }    
 }
index 3ef5c91829789aadd9797985d5c10d2bccec7f41..031fc11d4f6a7644801a8bab1ec72328076ad630 100644 (file)
@@ -89,7 +89,7 @@ public class NewArtifactsRssFeedProcessor
         Calendar greaterThanThisDate = Calendar.getInstance( DateUtils.UTC_TIME_ZONE );
         greaterThanThisDate.add( Calendar.DATE, -( getNumberOfDaysBeforeNow() ) );
         
-        Constraint artifactsByRepo = new ArtifactsByRepositoryConstraint( repoId, greaterThanThisDate.getTime(), "whenGathered" );
+        Constraint artifactsByRepo = new ArtifactsByRepositoryConstraint( repoId, greaterThanThisDate.getTime(), "whenGathered", false );
         List<ArchivaArtifact> artifacts = artifactDAO.queryArtifacts( artifactsByRepo );
 
         List<RssFeedEntry> entries = processData( artifacts, true );
index 31d1245c93f175d7925b778cca6b575807558322..7059598df3ea3edeb5f348ea58142b3859223cc2 100644 (file)
@@ -93,11 +93,18 @@ public class ArchivaServletAuthenticator
         return true;
     }
 
-    public boolean isAuthorized( String principal, String repoId )
+    public boolean isAuthorized( String principal, String repoId, boolean isWriteRequest )
         throws UnauthorizedException
     {
         try
         {
+            String permission = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS;
+
+            if ( isWriteRequest )
+            {
+                permission = ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD;
+            }
+            
             User user = securitySystem.getUserManager().findUser( principal );
             if ( user.isLocked() )
             {
@@ -107,8 +114,7 @@ public class ArchivaServletAuthenticator
             AuthenticationResult authn = new AuthenticationResult( true, principal, null );
             SecuritySession securitySession = new DefaultSecuritySession( authn, user );
 
-            return securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
-                                                repoId );
+            return securitySystem.isAuthorized( securitySession, permission, repoId );
         }
         catch ( UserNotFoundException e )
         {
index 4c07a0cf489ccdc6fa7b062b7c4c5574181aede3..c03405425d52391145991c3126c59a6128cea5c9 100644 (file)
@@ -85,4 +85,9 @@ public class ArchivaXworkUser
         
         return guest;
     }
+    
+    public void setGuest( String guesT )
+    {
+        guest = guesT;
+    }
 }
index 2edda81208bb230af14a9066d363abf4ff985b86..adc6ad1ab3df4009eb7add091f639fd569941c14 100644 (file)
@@ -35,12 +35,46 @@ import org.codehaus.plexus.redback.system.SecuritySession;
  */
 public interface ServletAuthenticator
 {
+    /**
+     * Authentication check for users.
+     * 
+     * @param request
+     * @param result
+     * @return
+     * @throws AuthenticationException
+     * @throws AccountLockedException
+     * @throws MustChangePasswordException
+     */
     public boolean isAuthenticated( HttpServletRequest request, AuthenticationResult result )
         throws AuthenticationException, AccountLockedException, MustChangePasswordException;
 
+    /**
+     * Authorization check for valid users.
+     * 
+     * @param request
+     * @param securitySession
+     * @param repositoryId
+     * @param isWriteRequest
+     * @return
+     * @throws AuthorizationException
+     * @throws UnauthorizedException
+     */
     public boolean isAuthorized( HttpServletRequest request, SecuritySession securitySession, String repositoryId,
         boolean isWriteRequest ) throws AuthorizationException, UnauthorizedException;
     
-    public boolean isAuthorized( String principal, String repoId )
+    /**
+     * Authorization check specific for user guest, which doesn't go through 
+     * HttpBasicAuthentication#getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
+     * since no credentials are attached to the request. 
+     * 
+     * See also MRM-911
+     * 
+     * @param principal
+     * @param repoId
+     * @param isWriteRequest
+     * @return
+     * @throws UnauthorizedException
+     */
+    public boolean isAuthorized( String principal, String repoId, boolean isWriteRequest )
         throws UnauthorizedException;
 }
diff --git a/archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java b/archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java
new file mode 100644 (file)
index 0000000..399c87e
--- /dev/null
@@ -0,0 +1,126 @@
+package org.apache.maven.archiva.security;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
+import org.codehaus.plexus.redback.rbac.RBACManager;
+import org.codehaus.plexus.redback.role.RoleManager;
+import org.codehaus.plexus.redback.system.SecuritySystem;
+import org.codehaus.plexus.redback.users.User;
+import org.codehaus.plexus.redback.users.UserManager;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
+/**
+ * AbstractSecurityTest 
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id: AbstractSecurityTest
+ */
+public abstract class AbstractSecurityTest
+    extends PlexusInSpringTestCase
+{
+    protected static final String USER_GUEST = "guest";
+
+    protected static final String USER_ADMIN = "admin";
+
+    protected static final String USER_ALPACA = "alpaca";
+
+    protected SecuritySystem securitySystem;
+
+    private RBACManager rbacManager;
+
+    protected RoleManager roleManager;
+
+    private ArchivaConfiguration archivaConfiguration;
+
+    protected UserRepositories userRepos;
+
+    protected void setupRepository( String repoId )
+        throws Exception
+    {
+        // Add repo to configuration.
+        ManagedRepositoryConfiguration repoConfig = new ManagedRepositoryConfiguration();
+        repoConfig.setId( repoId );
+        repoConfig.setName( "Testable repo <" + repoId + ">" );
+        repoConfig.setLocation( getTestPath( "target/test-repo/" + repoId ) );
+        archivaConfiguration.getConfiguration().addManagedRepository( repoConfig );
+
+        // Add repo roles to security.
+        userRepos.createMissingRepositoryRoles( repoId );
+    }
+
+    protected void assignRepositoryObserverRole( String principal, String repoId )
+        throws Exception
+    {
+        roleManager.assignTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId, principal );
+    }
+
+    protected User createUser( String principal, String fullname )
+    {
+        UserManager userManager = securitySystem.getUserManager();
+
+        User user = userManager.createUser( principal, fullname, principal + "@testable.archiva.apache.org" );
+        securitySystem.getPolicy().setEnabled( false );
+        userManager.addUser( user );
+        securitySystem.getPolicy().setEnabled( true );
+
+        return user;
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        File srcConfig = getTestFile( "src/test/resources/repository-archiva.xml" );
+        File destConfig = getTestFile( "target/test-conf/archiva.xml" );
+
+        destConfig.getParentFile().mkdirs();
+        destConfig.delete();
+
+        FileUtils.copyFile( srcConfig, destConfig );
+
+        securitySystem = (SecuritySystem) lookup( SecuritySystem.class, "testable" );
+        rbacManager = (RBACManager) lookup( RBACManager.class, "memory" );
+        roleManager = (RoleManager) lookup( RoleManager.class, "default" );
+        userRepos = (UserRepositories) lookup( UserRepositories.class, "default" );
+        archivaConfiguration = (ArchivaConfiguration) lookup( ArchivaConfiguration.class );
+
+        // Some basic asserts.
+        assertNotNull( securitySystem );
+        assertNotNull( rbacManager );
+        assertNotNull( roleManager );
+        assertNotNull( userRepos );
+        assertNotNull( archivaConfiguration );
+
+        // Setup Admin User.
+        User adminUser = createUser( USER_ADMIN, "Admin User" );
+        roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_SYSTEM_ADMIN, adminUser.getPrincipal().toString() );
+
+        // Setup Guest User.
+        User guestUser = createUser( USER_GUEST, "Guest User" );
+        roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_GUEST, guestUser.getPrincipal().toString() );
+    }
+}
diff --git a/archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java b/archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java
new file mode 100644 (file)
index 0000000..d100b88
--- /dev/null
@@ -0,0 +1,224 @@
+package org.apache.maven.archiva.security;
+
+/*
+ * 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 javax.servlet.http.HttpServletRequest;
+
+import org.codehaus.plexus.redback.authentication.AuthenticationException;
+import org.codehaus.plexus.redback.authentication.AuthenticationResult;
+import org.codehaus.plexus.redback.authorization.UnauthorizedException;
+import org.codehaus.plexus.redback.system.DefaultSecuritySession;
+import org.codehaus.plexus.redback.system.SecuritySession;
+import org.codehaus.plexus.redback.users.User;
+import org.codehaus.plexus.redback.users.UserManager; 
+
+import org.easymock.MockControl;
+
+/**
+ * ArchivaServletAuthenticatorTest
+ * 
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version
+ */
+public class ArchivaServletAuthenticatorTest
+    extends AbstractSecurityTest
+{    
+    private ServletAuthenticator servletAuth;
+    
+    private MockControl httpServletRequestControl;
+    
+    private HttpServletRequest request;
+    
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        
+        servletAuth = ( ServletAuthenticator ) lookup( ServletAuthenticator.class, "default" );
+        
+        httpServletRequestControl = MockControl.createControl( HttpServletRequest.class );
+        request = ( HttpServletRequest ) httpServletRequestControl.getMock();
+        
+        setupRepository( "corporate" );
+    }
+    
+    @Override
+    protected String getPlexusConfigLocation()
+    {
+        return "org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml";
+    }
+    
+    protected void assignRepositoryManagerRole( String principal, String repoId )
+        throws Exception
+    {
+        roleManager.assignTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, repoId, principal );
+    }
+    
+    public void testIsAuthenticatedUserExists()
+        throws Exception
+    {
+        AuthenticationResult result = new AuthenticationResult( true, "user", null );
+        boolean isAuthenticated = servletAuth.isAuthenticated( request, result );
+        
+        assertTrue( isAuthenticated );
+    }
+    
+    public void testIsAuthenticatedUserDoesNotExist()
+        throws Exception
+    {
+        AuthenticationResult result = new AuthenticationResult( false, "non-existing-user", null );
+        try
+        {
+            servletAuth.isAuthenticated( request, result );
+            fail( "Authentication exception should have been thrown." );
+        }
+        catch ( AuthenticationException e )
+        {
+            assertEquals( "User Credentials Invalid", e.getMessage() );
+        }        
+    }
+    
+    public void testIsAuthorizedUserHasWriteAccess()
+        throws Exception
+    {   
+        createUser( USER_ALPACA, "Al 'Archiva' Paca" );
+        
+        assignRepositoryManagerRole( USER_ALPACA, "corporate" );
+
+        UserManager userManager = securitySystem.getUserManager();
+        User user = userManager.findUser( USER_ALPACA );
+        
+        AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null );
+        
+        SecuritySession session = new DefaultSecuritySession( result, user );
+        boolean isAuthorized = servletAuth.isAuthorized( request, session, "corporate", true );
+                
+        assertTrue( isAuthorized );
+    }
+    
+    public void testIsAuthorizedUserHasNoWriteAccess()
+        throws Exception
+    {
+        createUser( USER_ALPACA, "Al 'Archiva' Paca" );
+        
+        assignRepositoryObserverRole( USER_ALPACA, "corporate" );
+    
+        httpServletRequestControl.expectAndReturn( request.getRemoteAddr(), "192.168.111.111" );
+        
+        UserManager userManager = securitySystem.getUserManager();
+        User user = userManager.findUser( USER_ALPACA );
+        
+        AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null );
+        
+        SecuritySession session = new DefaultSecuritySession( result, user );
+        
+        httpServletRequestControl.replay();
+        
+        try
+        {
+            servletAuth.isAuthorized( request, session, "corporate", true );
+            fail( "UnauthorizedException should have been thrown." ); 
+        }
+        catch ( UnauthorizedException e )
+        {
+            assertEquals( "Access denied for repository corporate", e.getMessage() );
+        }
+    
+        httpServletRequestControl.verify();
+    }
+    
+    
+    public void testIsAuthorizedUserHasReadAccess()
+        throws Exception
+    { 
+        createUser( USER_ALPACA, "Al 'Archiva' Paca" );
+        
+        assignRepositoryObserverRole( USER_ALPACA, "corporate" );
+        
+        UserManager userManager = securitySystem.getUserManager();
+        User user = userManager.findUser( USER_ALPACA );
+        
+        AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null );
+        
+        SecuritySession session = new DefaultSecuritySession( result, user );
+        boolean isAuthorized = servletAuth.isAuthorized( request, session, "corporate", false );
+                
+        assertTrue( isAuthorized );        
+    }
+    
+    public void testIsAuthorizedUserHasNoReadAccess()
+        throws Exception
+    {
+        createUser( USER_ALPACA, "Al 'Archiva' Paca" );
+        
+        UserManager userManager = securitySystem.getUserManager();
+        User user = userManager.findUser( USER_ALPACA );
+        
+        AuthenticationResult result = new AuthenticationResult( true, USER_ALPACA, null );
+        
+        SecuritySession session = new DefaultSecuritySession( result, user );
+        try
+        {
+            servletAuth.isAuthorized( request, session, "corporate", false );
+            fail( "UnauthorizedException should have been thrown." );
+        }
+        catch ( UnauthorizedException e )
+        {
+            assertEquals( "Access denied for repository corporate", e.getMessage() );
+        }       
+    }
+    
+    public void testIsAuthorizedGuestUserHasWriteAccess()
+        throws Exception
+    {   
+        assignRepositoryManagerRole( USER_GUEST, "corporate" );        
+        boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", true );
+        
+        assertTrue( isAuthorized );
+    }
+    
+    public void testIsAuthorizedGuestUserHasNoWriteAccess()
+        throws Exception
+    {   
+        assignRepositoryObserverRole( USER_GUEST, "corporate" );
+        
+        boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", true );
+        assertFalse( isAuthorized );
+    }
+    
+    public void testIsAuthorizedGuestUserHasReadAccess()
+        throws Exception
+    {
+        assignRepositoryObserverRole( USER_GUEST, "corporate" );
+        
+        boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", false );
+        
+        assertTrue( isAuthorized );        
+    }
+    
+    public void testIsAuthorizedGuestUserHasNoReadAccess()
+        throws Exception
+    {                   
+        boolean isAuthorized = servletAuth.isAuthorized( USER_GUEST, "corporate", false );
+            
+        assertFalse( isAuthorized );
+    }
+}
index ceb0a357c6c10a2bfc40052ae9a426aef09d6424..a9f8c1897f1f3224a25b9c807b72bf10b7c0dfe0 100644 (file)
@@ -19,19 +19,9 @@ package org.apache.maven.archiva.security;
  * under the License.
  */
 
-import java.io.File;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
-import org.apache.maven.archiva.configuration.ArchivaConfiguration;
-import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
-import org.codehaus.plexus.spring.PlexusInSpringTestCase;
-import org.codehaus.plexus.redback.rbac.RBACManager;
-import org.codehaus.plexus.redback.role.RoleManager;
-import org.codehaus.plexus.redback.system.SecuritySystem;
-import org.codehaus.plexus.redback.users.User;
-import org.codehaus.plexus.redback.users.UserManager;
 
 /**
  * DefaultUserRepositoriesTest 
@@ -40,24 +30,14 @@ import org.codehaus.plexus.redback.users.UserManager;
  * @version $Id$
  */
 public class DefaultUserRepositoriesTest
-    extends PlexusInSpringTestCase
-{
-    private static final String USER_GUEST = "guest";
-
-    private static final String USER_ADMIN = "admin";
-
-    private static final String USER_ALPACA = "alpaca";
-
-    private SecuritySystem securitySystem;
-
-    private RBACManager rbacManager;
-
-    private RoleManager roleManager;
-
-    private ArchivaConfiguration archivaConfiguration;
-
-    private UserRepositories userRepos;
-
+    extends AbstractSecurityTest
+{   
+    @Override
+    protected String getPlexusConfigLocation()
+    {
+        return "org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml";
+    }
+    
     public void testGetObservableRepositoryIds()
         throws Exception
     {
@@ -98,78 +78,9 @@ public class DefaultUserRepositoriesTest
         }
     }
 
-    private void setupRepository( String repoId )
-        throws Exception
-    {
-        // Add repo to configuration.
-        ManagedRepositoryConfiguration repoConfig = new ManagedRepositoryConfiguration();
-        repoConfig.setId( repoId );
-        repoConfig.setName( "Testable repo <" + repoId + ">" );
-        repoConfig.setLocation( getTestPath( "target/test-repo/" + repoId ) );
-        archivaConfiguration.getConfiguration().addManagedRepository( repoConfig );
-
-        // Add repo roles to security.
-        userRepos.createMissingRepositoryRoles( repoId );
-    }
-
     private void assignGlobalRepositoryObserverRole( String principal )
         throws Exception
     {
         roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_GLOBAL_REPOSITORY_OBSERVER, principal );
     }
-
-    private void assignRepositoryObserverRole( String principal, String repoId )
-        throws Exception
-    {
-        roleManager.assignTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId, principal );
-    }
-
-    private User createUser( String principal, String fullname )
-    {
-        UserManager userManager = securitySystem.getUserManager();
-
-        User user = userManager.createUser( principal, fullname, principal + "@testable.archiva.apache.org" );
-        securitySystem.getPolicy().setEnabled( false );
-        userManager.addUser( user );
-        securitySystem.getPolicy().setEnabled( true );
-
-        return user;
-    }
-
-    @Override
-    protected void setUp()
-        throws Exception
-    {
-        super.setUp();
-
-        File srcConfig = getTestFile( "src/test/resources/repository-archiva.xml" );
-        File destConfig = getTestFile( "target/test-conf/archiva.xml" );
-
-        destConfig.getParentFile().mkdirs();
-        destConfig.delete();
-
-        FileUtils.copyFile( srcConfig, destConfig );
-
-        securitySystem = (SecuritySystem) lookup( SecuritySystem.class, "testable" );
-        rbacManager = (RBACManager) lookup( RBACManager.class, "memory" );
-        roleManager = (RoleManager) lookup( RoleManager.class, "default" );
-        userRepos = (UserRepositories) lookup( UserRepositories.class, "default" );
-        archivaConfiguration = (ArchivaConfiguration) lookup( ArchivaConfiguration.class );
-
-        // Some basic asserts.
-        assertNotNull( securitySystem );
-        assertNotNull( rbacManager );
-        assertNotNull( roleManager );
-        assertNotNull( userRepos );
-        assertNotNull( archivaConfiguration );
-
-        // Setup Admin User.
-        User adminUser = createUser( USER_ADMIN, "Admin User" );
-        roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_SYSTEM_ADMIN, adminUser.getPrincipal().toString() );
-
-        // Setup Guest User.
-        User guestUser = createUser( USER_GUEST, "Guest User" );
-        roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_GUEST, guestUser.getPrincipal().toString() );
-
-    }
 }
diff --git a/archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml b/archiva-struts2/archiva-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml
new file mode 100644 (file)
index 0000000..adfb9b2
--- /dev/null
@@ -0,0 +1,202 @@
+<?xml version="1.0" ?>
+<component-set>
+  <components>
+  
+       <component>
+      <role>org.apache.maven.archiva.security.ServletAuthenticator</role>
+      <role-hint>default</role-hint>
+      <implementation>org.apache.maven.archiva.security.ArchivaServletAuthenticator</implementation>
+      <description>ArchivaServletAuthenticator</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.system.SecuritySystem</role>
+          <role-hint>testable</role-hint>
+          <field-name>securitySystem</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.apache.maven.archiva.security.UserRepositories</role>
+      <role-hint>default</role-hint>
+      <implementation>org.apache.maven.archiva.security.DefaultUserRepositories</implementation>
+      <description>DefaultUserRepositories</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.system.SecuritySystem</role>
+          <role-hint>testable</role-hint>
+          <field-name>securitySystem</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>rbacManager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.role.RoleManager</role>
+          <role-hint>default</role-hint>
+          <field-name>roleManager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
+          <field-name>archivaConfiguration</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.codehaus.plexus.redback.system.SecuritySystem</role>
+      <role-hint>testable</role-hint>
+      <implementation>org.codehaus.plexus.redback.system.DefaultSecuritySystem</implementation>
+      <description>DefaultSecuritySystem:</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.authentication.AuthenticationManager</role>
+          <field-name>authnManager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.authorization.Authorizer</role>
+          <role-hint>rbac</role-hint>
+          <field-name>authorizer</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.users.UserManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>userManager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.keys.KeyManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>keyManager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.policy.UserSecurityPolicy</role>
+          <field-name>policy</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.codehaus.plexus.redback.authorization.Authorizer</role>
+      <role-hint>rbac</role-hint>
+      <implementation>org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer</implementation>
+      <description>RbacAuthorizer:</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>manager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.users.UserManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>userManager</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator</role>
+          <role-hint>default</role-hint>
+          <field-name>evaluator</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.configuration.UserConfiguration</role>
+          <role-hint>default</role-hint>
+          <field-name>config</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator</role>
+      <role-hint>default</role-hint>
+      <implementation>org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator</implementation>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.users.UserManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>userManager</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.codehaus.plexus.redback.role.RoleManager</role>
+      <role-hint>default</role-hint>
+      <implementation>org.codehaus.plexus.redback.role.DefaultRoleManager</implementation>
+      <description>RoleProfileManager:</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.role.validator.RoleModelValidator</role>
+          <role-hint>default</role-hint>
+          <field-name>modelValidator</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.role.processor.RoleModelProcessor</role>
+          <role-hint>default</role-hint>
+          <field-name>modelProcessor</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.role.template.RoleTemplateProcessor</role>
+          <role-hint>default</role-hint>
+          <field-name>templateProcessor</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>rbacManager</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.codehaus.plexus.redback.role.processor.RoleModelProcessor</role>
+      <role-hint>default</role-hint>
+      <implementation>org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor</implementation>
+      <description>DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>rbacManager</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.codehaus.plexus.redback.role.template.RoleTemplateProcessor</role>
+      <role-hint>default</role-hint>
+      <implementation>org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor</implementation>
+      <description>DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager</description>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
+          <role-hint>memory</role-hint>
+          <field-name>rbacManager</field-name>
+        </requirement>
+      </requirements>
+    </component>
+    
+    <component>
+      <role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
+      <implementation>org.apache.maven.archiva.configuration.DefaultArchivaConfiguration</implementation>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.registry.Registry</role>
+          <role-hint>configured</role-hint>
+        </requirement>
+      </requirements>
+    </component>
+    <component>
+      <role>org.codehaus.plexus.registry.Registry</role>
+      <role-hint>configured</role-hint>
+      <implementation>org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry</implementation>
+      <configuration>
+        <properties>
+          <system/>
+          <xml fileName="${basedir}/target/test-conf/archiva.xml"
+               config-name="org.apache.maven.archiva.base" config-at="org.apache.maven.archiva"/>
+        </properties>
+      </configuration>
+    </component>
+    
+  </components>
+</component-set>
index cb90bc185e97346e6460a68fbfaacde901e79c73..e33004110d255d6c3cb31417c1af53215cb15d73 100644 (file)
@@ -19,30 +19,48 @@ package org.apache.maven.archiva.web.action.reports;
  * under the License.
  */
 
-import org.apache.struts2.interceptor.ServletRequestAware;
 import com.opensymphony.xwork2.Preparable;
+import org.apache.commons.lang.time.DateFormatUtils;
+import org.apache.commons.lang.time.DateUtils;
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
 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.RepositoryContentStatisticsDAO;
 import org.apache.maven.archiva.database.constraints.RangeConstraint;
+import org.apache.maven.archiva.database.constraints.RepositoryContentStatisticsByRepositoryConstraint;
 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.database.constraints.UniqueFieldConstraint;
+import org.apache.maven.archiva.model.RepositoryContentStatistics;
 import org.apache.maven.archiva.model.RepositoryProblem;
 import org.apache.maven.archiva.model.RepositoryProblemReport;
+import org.apache.maven.archiva.reporting.ArchivaReportException;
+import org.apache.maven.archiva.reporting.DataLimits;
+import org.apache.maven.archiva.reporting.RepositoryStatistics;
+import org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator;
 import org.apache.maven.archiva.security.ArchivaRoleConstants;
-import org.apache.maven.archiva.web.action.PlexusActionSupport;
 import org.codehaus.plexus.redback.rbac.Resource;
-import org.codehaus.plexus.redback.struts2.interceptor.SecureAction;
-import org.codehaus.plexus.redback.struts2.interceptor.SecureActionBundle;
-import org.codehaus.plexus.redback.struts2.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.servlet.http.HttpServletRequest;
+
+import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
+import org.apache.maven.archiva.web.action.PlexusActionSupport;
+import org.apache.struts2.interceptor.ServletRequestAware;
+import org.codehaus.plexus.redback.struts2.interceptor.SecureAction;
+import org.codehaus.plexus.redback.struts2.interceptor.SecureActionBundle;
+import org.codehaus.plexus.redback.struts2.interceptor.SecureActionException;
 
 /**
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="generateReport"
@@ -51,10 +69,17 @@ public class GenerateReportAction
     extends PlexusActionSupport
     implements SecureAction, ServletRequestAware, Preparable
 {
+    private Logger log = LoggerFactory.getLogger( GenerateReportAction.class );
+    
     /**
      * @plexus.requirement role-hint="jdo"
      */
     protected ArchivaDAO dao;
+    
+    /**
+     * @plexus.requirement
+     */
+    private ArchivaConfiguration archivaConfiguration;
 
     protected Constraint constraint;
 
@@ -90,13 +115,50 @@ public class GenerateReportAction
     
     protected Map<String, List<RepositoryProblemReport>> repositoriesMap = 
                new TreeMap<String, List<RepositoryProblemReport>>();
-
+    
+    // for statistics report
+    /**
+     * @plexus.requirement role-hint="simple"
+     */
+    private RepositoryStatisticsReportGenerator generator;
+    
+    private List<String> selectedRepositories = new ArrayList<String>();
+    
+    private List<String> availableRepositories;  
+    
+    private String startDate;
+    
+    private String endDate;
+    
+    private int reposSize;
+    
+    private String selectedRepo;
+    
+    private List<RepositoryStatistics> repositoryStatistics = new ArrayList<RepositoryStatistics>();
+    
+    private DataLimits limits = new DataLimits();
+    
+    private String[] datePatterns = new String[] { "MM/dd/yy", "MM/dd/yyyy", "MMMMM/dd/yyyy", "MMMMM/dd/yy", 
+        "dd MMMMM yyyy", "dd/MM/yy", "dd/MM/yyyy", "yyyy/MM/dd" };
+    
     public void prepare()
     {
         repositoryIds = new ArrayList<String>();
         repositoryIds.add( ALL_REPOSITORIES ); // comes first to be first in the list
         repositoryIds.addAll(
             dao.query( new UniqueFieldConstraint( RepositoryProblem.class.getName(), "repositoryId" ) ) );
+        
+        availableRepositories = new ArrayList<String>();
+     
+        // remove selected repositories in the option for the statistics report
+        availableRepositories.addAll( archivaConfiguration.getConfiguration().getManagedRepositoriesAsMap().keySet() );        
+        for( String repo : selectedRepositories )
+        {
+            if( availableRepositories.contains( repo ) )
+            {
+                availableRepositories.remove( repo );
+            }
+        }
     }
 
     public Collection<String> getRepositoryIds()
@@ -104,10 +166,202 @@ public class GenerateReportAction
         return repositoryIds;
     }
 
-    @Override
+    /**
+     * Generate the statistics report.
+     * 
+     * check whether single repo report or comparison report
+     * 1. if it is a single repository, get all the statistics for the repository on the specified date
+     *    - if no date is specified, get only the latest 
+     *          (total page = 1 --> no pagination since only the most recent stats will be displayed)
+     *    - otherwise, get everything within the date range (total pages = repo stats / rows per page)
+     *       - required params: repository, startDate, endDate
+     *       
+     * 2. if multiple repositories, get the latest statistics on each repository on the specified date
+     *    - if no date is specified, use the current date endDate
+     *       - required params: repositories, endDate
+     *    - total pages = repositories / rows per page
+     * 
+     * @return
+     */
+    public String generateStatistics()
+    {   
+        if( rowCount < 10 )
+        {
+            addFieldError( "rowCount", "Row count must be larger than 10." );
+            return INPUT;
+        }
+        reposSize = selectedRepositories.size();
+        Date startDateInDateFormat = null;
+        Date endDateInDateFormat = null;
+        
+        if( startDate == null || "".equals( startDate ) )
+        {
+            startDateInDateFormat = getDefaultStartDate();
+        }
+        else
+        {
+            try
+            {
+                startDateInDateFormat = DateUtils.parseDate( startDate, datePatterns );
+            }
+            catch ( ParseException e )
+            {
+                addFieldError( "startDate", "Invalid date format.");
+                return INPUT;
+            }
+        }
+        
+        if( endDate == null || "".equals( endDate ) )
+        {
+            endDateInDateFormat = getDefaultEndDate();
+        }
+        else
+        {
+            try
+            {
+                endDateInDateFormat = DateUtils.parseDate( endDate, datePatterns );                
+            }
+            catch ( ParseException e )
+            {
+                addFieldError( "endDate", "Invalid date format.");
+                return INPUT;
+            }
+        }
+        
+        try
+        {
+            RepositoryContentStatisticsDAO repoContentStatsDao = dao.getRepositoryContentStatisticsDAO();            
+            if( selectedRepositories.size() > 1 )
+            {
+                limits.setTotalCount( selectedRepositories.size() );            
+                limits.setCurrentPage( 1 );
+                limits.setPerPageCount( 1 );
+                limits.setCountOfPages( 1 );
+                
+                // multiple repos
+                for( String repo : selectedRepositories )
+                {  
+                    try
+                    {
+                        List contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
+                           new RepositoryContentStatisticsByRepositoryConstraint( repo, startDateInDateFormat, endDateInDateFormat ) );
+                        
+                        if( contentStats == null || contentStats.isEmpty() )
+                        {
+                            log.info( "No statistics available for repository '" + repo + "'." );
+                            // TODO set repo's stats to 0
+                            
+                            continue;
+                        }                        
+                        repositoryStatistics.addAll( generator.generateReport( contentStats, repo, startDateInDateFormat, endDateInDateFormat, limits ) );
+                    }
+                    catch ( ObjectNotFoundException oe )
+                    {
+                        log.error( "No statistics available for repository '" + repo + "'." );
+                        // TODO set repo's stats to 0
+                    }
+                    catch ( ArchivaDatabaseException ae )
+                    {
+                        log.error( "Error encountered while querying statistics of repository '" + repo + "'." );
+                        // TODO set repo's stats to 0
+                    }
+                }
+            }
+            else if ( selectedRepositories.size() == 1 )
+            {   
+                limits.setCurrentPage( getPage() );
+                limits.setPerPageCount( getRowCount() );
+                
+                selectedRepo = selectedRepositories.get( 0 );
+                try
+                {
+                    List<RepositoryContentStatistics> contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
+                           new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDateInDateFormat, endDateInDateFormat ) );
+                    
+                    if( contentStats == null || contentStats.isEmpty() )
+                    {   
+                        addActionError( "No statistics available for repository. Repository might not have been scanned." );
+                        return ERROR;
+                    }   
+                    
+                    limits.setTotalCount( contentStats.size() );                    
+                    int extraPage = ( limits.getTotalCount() % limits.getPerPageCount() ) != 0 ? 1 : 0;
+                    int totalPages = ( limits.getTotalCount() / limits.getPerPageCount() ) + extraPage;                    
+                    limits.setCountOfPages( totalPages );
+                    
+                    repositoryStatistics = generator.generateReport( contentStats, selectedRepo, startDateInDateFormat, endDateInDateFormat, limits );
+                }
+                catch ( ObjectNotFoundException oe )
+                {
+                    addActionError( oe.getMessage() );
+                    return ERROR;
+                }
+                catch ( ArchivaDatabaseException de )
+                {
+                    addActionError( de.getMessage() );
+                    return ERROR;
+                }
+            }
+            else
+            {
+                addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." );
+                return INPUT;
+            } 
+            
+            if( repositoryStatistics.isEmpty() )
+            {
+                return BLANK;
+            }
+            
+            if( startDate.equals( getDefaultStartDate() ) )
+            {
+                startDate = null;
+            }
+            else
+            {   
+                startDate = DateFormatUtils.format( startDateInDateFormat, "MM/dd/yyyy" );                
+            }
+            
+            endDate = DateFormatUtils.format( endDateInDateFormat, "MM/dd/yyyy" );
+        }
+        catch ( ArchivaReportException e )
+        {
+            addActionError( "Error encountered while generating report :: " + e.getMessage() );
+            return ERROR;
+        }
+        
+        return SUCCESS;
+    }
+    
+    private Date getDefaultStartDate()
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set( 1900, 1, 1, 0, 0, 0 );
+        
+        return cal.getTime();
+    }
+    
+    private Date getDefaultEndDate()
+    {
+        return Calendar.getInstance().getTime();
+    }
+    
     public String execute()
         throws Exception
-    {
+    {   
+        if( repositoryId == null )
+        {
+            addFieldError( "repositoryId", "You must provide a repository id.");            
+            return INPUT;
+        }
+        
+        if( rowCount < 10 )
+        {
+            addFieldError( "rowCount", "Row count must be larger than 10." );
+            return INPUT;
+        }
+        
         List<RepositoryProblem> problemArtifacts =
             dao.getRepositoryProblemDAO().queryRepositoryProblems( configureConstraint() );
 
@@ -157,7 +411,7 @@ public class GenerateReportAction
             return SUCCESS;
         }
     }
-
+    
     private static boolean isJasperPresent()
     {
         if ( jasperPresent == null )
@@ -208,6 +462,34 @@ public class GenerateReportAction
 
         return constraint;
     }
+    
+    public SecureActionBundle getSecureActionBundle()
+        throws SecureActionException
+    {
+        SecureActionBundle bundle = new SecureActionBundle();
+    
+        bundle.setRequiresAuthentication( true );
+        bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL );
+    
+        return bundle;
+    }
+    
+    private void addToList( RepositoryProblemReport repoProblemReport )
+    {
+        List<RepositoryProblemReport> problemsList = null;
+        
+        if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) )
+        {
+            problemsList = ( List<RepositoryProblemReport> ) repositoriesMap.get( repoProblemReport.getRepositoryId() );
+        }
+        else
+        {
+            problemsList = new ArrayList<RepositoryProblemReport>();
+            repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList );
+        }
+        
+        problemsList.add( repoProblemReport );
+    }
 
     public void setServletRequest( HttpServletRequest request )
     {
@@ -284,31 +566,83 @@ public class GenerateReportAction
        return repositoriesMap;
     }
     
-    public SecureActionBundle getSecureActionBundle()
-        throws SecureActionException
+    public List<String> getSelectedRepositories()
     {
-        SecureActionBundle bundle = new SecureActionBundle();
+        return selectedRepositories;
+    }
 
-        bundle.setRequiresAuthentication( true );
-        bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL );
+    public void setSelectedRepositories( List<String> selectedRepositories )
+    {
+        this.selectedRepositories = selectedRepositories;
+    }
 
-        return bundle;
+    public List<String> getAvailableRepositories()
+    {
+        return availableRepositories;
+    }
+
+    public void setAvailableRepositories( List<String> availableRepositories )
+    {
+        this.availableRepositories = availableRepositories;
+    }
+
+    public String getStartDate()
+    {
+        return startDate;
+    }
+
+    public void setStartDate( String startDate )
+    {
+        this.startDate = startDate;
+    }
+
+    public String getEndDate()
+    {
+        return endDate;
+    }
+
+    public void setEndDate( String endDate )
+    {
+        this.endDate = endDate;
+    }
+
+    public List<RepositoryStatistics> getRepositoryStatistics()
+    {
+        return repositoryStatistics;
+    }
+
+    public void setRepositoryStatistics( List<RepositoryStatistics> repositoryStatistics )
+    {
+        this.repositoryStatistics = repositoryStatistics;
     }
     
-    private void addToList( RepositoryProblemReport repoProblemReport )
+    public int getReposSize()
+    {
+        return reposSize;
+    }
+
+    public void setReposSize( int reposSize )
+    {
+        this.reposSize = reposSize;
+    }
+
+    public String getSelectedRepo()
+    {
+        return selectedRepo;
+    }
+
+    public void setSelectedRepo( String selectedRepo )
+    {
+        this.selectedRepo = selectedRepo;
+    }
+
+    public DataLimits getLimits()
+    {
+        return limits;
+    }
+
+    public void setLimits( DataLimits limits )
     {
-       List<RepositoryProblemReport> problemsList = null;
-       
-       if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) )
-       {
-               problemsList = ( List<RepositoryProblemReport> ) repositoriesMap.get( repoProblemReport.getRepositoryId() );
-       }
-       else
-       {
-               problemsList = new ArrayList<RepositoryProblemReport>();
-               repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList );
-       }
-       
-       problemsList.add( repoProblemReport );
+        this.limits = limits;
     }
 }
diff --git a/archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/reports/GenerateReportAction-validation.xml b/archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/reports/GenerateReportAction-validation.xml
deleted file mode 100644 (file)
index a31c065..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-
-<validators>
-  <field name="rowCount">
-    <field-validator type="int">
-      <param name="min">10</param>
-      <message>Row count must be larger than ${min}.</message>
-    </field-validator>
-  </field>
-  <!-- 
-  <field name="groupId">
-    <field-validator type="regex">
-      <param name="expression"><![CDATA[([a-zA-Z0-9]+[a-zA-Z0-9.]*)]]></param>
-      <message>You must provide a valid group id.</message>
-    </field-validator>
-  </field>
-     -->
-  <field name="repositoryId">
-    <field-validator type="requiredstring">
-      <message>You must provide a repository id.</message>
-    </field-validator>
-  </field>
-</validators>
index 095841dbe00575d84770839c9491c89a5ec3dd74..f4dc821cd960ec730892a68df51d463b14a49073 100644 (file)
             <my:currentWWUrl action="userlist" namespace="/security">User Management</my:currentWWUrl>
           </li>
         </redback:ifAuthorized>
+        <redback:ifAuthorized permission="archiva-manage-users">
+          <li class="none">
+            <my:currentWWUrl action="roles" namespace="/security">User Roles</my:currentWWUrl>
+          </li>
+        </redback:ifAuthorized>        
         <redback:ifAuthorized permission="archiva-manage-configuration">
           <li class="none">
             <my:currentWWUrl action="configureAppearance" namespace="/admin">Appearance</my:currentWWUrl>
index 62535c64460fe5d440bdf8d9f687f770c9e51a5d..afcbf1c6b8f33a222e47dc4f4f3ac14550e69e22 100644 (file)
 <html>
 <head>
   <title>Reports</title>
-  <s:head/>
+  <s:head theme="ajax" />
 </head>
 
 <body>
 <h1>Reports</h1>
-
+  
 <div id="contentArea">
 
-  <s:form action="generateReport" namespace="/report" validate="true">
+  <h2>Repository Statistics</h2>
+  <s:form action="generateStatisticsReport" namespace="/report" validate="true">
+    
+    <s:optiontransferselect label="Repositories To Be Compared" name="availableRepositories"
+               list="availableRepositories" doubleName="selectedRepositories"
+               doubleList="selectedRepositories" size="8" doubleSize="8"/>
+               
+       <s:datetimepicker label="Start Date" name="startDate" id="startDate"/>
+       <s:datetimepicker label="End Date" name="endDate" id="endDate"/>
+       <s:textfield label="Row Count" name="rowCount" />
+                   
+    <s:submit value="View Statistics"/>
+  </s:form>
+    
+  <h2>Repository Health</h2>
+  <s:form namespace="/report" action="generateReport" validate="true">
     <s:textfield label="Row Count" name="rowCount" />
     <s:textfield label="Group ID" name="groupId"/>
     <s:select label="Repository ID" name="repositoryId" list="repositoryIds"/>
+  
     <s:submit value="Show Report"/>
   </s:form>
 
diff --git a/archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp b/archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp
new file mode 100644 (file)
index 0000000..dd70758
--- /dev/null
@@ -0,0 +1,213 @@
+<%--
+  ~ 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" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="archiva" uri="http://archiva.apache.org" %>
+
+<html>
+<head>
+  <title>Reports</title>
+  <ww:head/>
+</head>
+
+<body>
+<h1>Statistics Report</h1>
+
+<c:url var="imgNextPageUrl" value="/images/icon_next_page.gif"/>
+<c:url var="imgPrevPageUrl" value="/images/icon_prev_page.gif"/>
+<c:url var="imgPrevPageDisabledUrl" value="/images/icon_prev_page_disabled.gif"/>
+<c:url var="imgNextPageDisabledUrl" value="/images/icon_next_page_disabled.gif"/>
+
+<div id="contentArea">                 
+
+  <%-- TODO: fix problem in date format! --%>
+
+  <%-- Pagination - start --%>  
+  <p>
+    
+    <%-- Set Prev & Next icons --%>
+  <c:set var="prevPageUrl">
+    <ww:url action="generateStatisticsReport" namespace="/report">
+      <ww:param name="selectedRepositories" value="%{'${selectedRepositories}'}"/>
+      <ww:param name="rowCount" value="%{'${rowCount}'}"/>
+      <ww:param name="startDate" value="%{'${startDate}'}"/>                      
+      <ww:param name="endDate" value="%{'${endDate}'}"/>
+      <ww:param name="page" value="%{'${page - 1}'}"/>
+    </ww:url>
+  </c:set>
+  <c:set var="nextPageUrl">
+    <ww:url action="generateStatisticsReport" namespace="/report">
+      <ww:param name="selectedRepositories" value="%{'${selectedRepositories}'}"/>
+      <ww:param name="rowCount" value="%{'${rowCount}'}"/>
+      <ww:param name="startDate" value="%{'${startDate}'}"/>                      
+      <ww:param name="endDate" value="%{'${endDate}'}"/>                
+      <ww:param name="page" value="%{'${page + 1}'}"/>
+    </ww:url>
+  </c:set>
+    
+  <c:choose>
+    <c:when test="${page == 1}">                               
+      <img src="${imgPrevPageDisabledUrl}"/>
+    </c:when>
+    <c:otherwise>
+      <a href="${prevPageUrl}">
+        <img src="${imgPrevPageUrl}"/>
+      </a>
+    </c:otherwise>
+  </c:choose>
+    
+  <%-- Google-style pagination --%>
+  <c:choose>
+    <c:when test="${limits.countOfPages > 11}">
+      <c:choose>
+        <c:when test="${(page - 5) < 0}">
+          <c:set var="beginVal">0</c:set>
+          <c:set var="endVal">10</c:set> 
+        </c:when>                              
+        <c:when test="${(page + 5) > (limits.countOfPages - 1)}">
+          <c:set var="beginVal">${(limits.countOfPages -1) - 10}</c:set>
+          <c:set var="endVal">${limits.countOfPages - 1}</c:set>
+        </c:when>
+        <c:otherwise>
+          <c:set var="beginVal">${page - 5}</c:set>
+          <c:set var="endVal">${page + 5}</c:set>
+        </c:otherwise>
+      </c:choose>  
+    </c:when>
+    <c:otherwise>
+      <c:set var="beginVal">0</c:set>
+      <c:set var="endVal">${limits.countOfPages - 1}</c:set> 
+    </c:otherwise>
+  </c:choose>
+    
+  <c:forEach var="i" begin="${beginVal}" end="${endVal}">      
+    <c:choose>                                             
+      <c:when test="${i != (page - 1)}">
+        <c:set var="specificPageUrl">
+          <ww:url action="generateStatisticsReport" namespace="/report">
+            <ww:param name="selectedRepositories" value="%{'${selectedRepositories}'}"/>
+            <ww:param name="rowCount" value="%{'${rowCount}'}"/>
+            <ww:param name="startDate" value="%{'${startDate}'}"/>                      
+            <ww:param name="endDate" value="%{'${endDate}'}"/>
+            <ww:param name="page" value="%{'${page + 1}'}"/>
+          </ww:url>
+        </c:set>
+        <a href="${specificPageUrl}">${i + 1}</a>
+      </c:when>
+      <c:otherwise>            
+        <b>${i + 1}</b>   
+      </c:otherwise>                                                       
+    </c:choose>      
+  </c:forEach>
+     
+  <c:choose>
+    <c:when test="${page == limits.countOfPages}">
+      <img src="${imgNextPageDisabledUrl}"/>
+    </c:when>
+    <c:otherwise>
+      <a href="${nextPageUrl}">
+        <img src="${imgNextPageUrl}"/>
+      </a>
+    </c:otherwise>   
+  </c:choose> 
+  </p>   
+  <%-- Pagination - end --%>
+  
+  <c:choose>
+    <c:when test="${reposSize > 1}">
+       
+      <h1>Latest Statistics Comparison Report</h1>         
+      <table class="infoTable" border="1">
+        <tr>
+          <th>Repository</th>
+          <th>Total File Count</th>
+          <th>Total Size</th>
+          <th>Artifact Count</th>
+          <th>Group Count</th>
+          <th>Project Count</th>
+          <th>Plugins</th>
+          <th>Archetypes</th>
+          <th>Jars</th>
+          <th>Wars</th>
+          <th>Deployments</th>
+          <th>Downloads</th>
+        </tr>                  
+               
+        <c:forEach var="stats" items="${repositoryStatistics}">
+        <tr>
+          <td>${stats.repositoryId}</td>
+          <td align="right">${stats.fileCount}</td>
+          <td align="right">${stats.totalSize}</td>
+          <td align="right">${stats.artifactCount}</td>
+          <td align="right">${stats.groupCount}</td>
+          <td align="right">${stats.projectCount}</td>
+          <td align="right">${stats.pluginCount}</td>
+          <td align="right">${stats.archetypeCount}</td>
+          <td align="right">${stats.jarCount}</td>
+          <td align="right">${stats.warCount}</td>
+          <td align="right">${stats.deploymentCount}</td>
+          <td align="right">${stats.downloadCount}</td>
+        </tr>                          
+        </c:forEach>
+      </table>                 
+    </c:when>
+    <c:otherwise>
+       
+      <h1>Statistics for Repository '${selectedRepo}'</h1>
+      <table class="infoTable" border="1">
+        <tr>
+          <th>Date of Scan</th>
+          <th>Total File Count</th>
+          <th>Total Size</th>
+          <th>Artifact Count</th>
+          <th>Group Count</th>
+          <th>Project Count</th>
+          <th>Plugins</th>
+          <th>Archetypes</th>
+          <th>Jars</th>
+          <th>Wars</th>
+          <th>Deployments</th>
+          <th>Downloads</th>
+        </tr>                  
+                       
+        <c:forEach var="stats" items="${repositoryStatistics}">
+        <tr>
+          <td align="right">${stats.dateOfScan}</td>
+          <td align="right">${stats.fileCount}</td>
+          <td align="right">${stats.totalSize}</td>
+          <td align="right">${stats.artifactCount}</td>
+          <td align="right">${stats.groupCount}</td>
+          <td align="right">${stats.projectCount}</td>
+          <td align="right">${stats.pluginCount}</td>
+          <td align="right">${stats.archetypeCount}</td>
+          <td align="right">${stats.jarCount}</td>
+          <td align="right">${stats.warCount}</td>
+          <td align="right">${stats.deploymentCount}</td>
+          <td align="right">${stats.downloadCount}</td>
+        </tr>                          
+        </c:forEach>
+      </table>
+                                       
+    </c:otherwise>
+  </c:choose>
+</div>
+</body>
+</html>
index 983e387b24089afd941503c3424a680fc8597052..46856bafdb09532df06f5115ece9cc8e8441805f 100644 (file)
@@ -33,7 +33,8 @@ select, input {
 
 select {
     padding-left: 3px;
-       height: 1.4em;  
+       height: auto;
+       width: auto;    
 }
 
 input {
index 8625d2311fed0722993bc3785dc56b6a8e75694c..97dff07d274cabb0de092012c57c06e16c40efc5 100644 (file)
Binary files a/archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/archiva-splat-32.gif and b/archiva-struts2/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/archiva-splat-32.gif differ
index c7b381daa40a13fb9056511bfcd6212b49458ace..14645f61858e2ff70bf252e19d4acdf7940a1612 100644 (file)
@@ -186,14 +186,14 @@ public class ArchivaDavResourceFactory
     {
         checkLocatorIsInstanceOfRepositoryLocator( locator );
         ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
-
+        
         RepositoryGroupConfiguration repoGroupConfig =
             archivaConfiguration.getConfiguration().getRepositoryGroupsAsMap().get( archivaLocator.getRepositoryId() );
         List<String> repositories = new ArrayList<String>();
 
         boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() );
         boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
-
+        
         if ( repoGroupConfig != null )
         {
             if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
@@ -230,7 +230,7 @@ public class ArchivaDavResourceFactory
 
             try
             {
-                managedRepository = getManagedRepository( repositoryId );
+                managedRepository = getManagedRepository( repositoryId );                
             }
             catch ( DavException de )
             {
@@ -241,13 +241,13 @@ public class ArchivaDavResourceFactory
             DavResource resource = null;
             
             if ( !locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) )
-            {
+            {                
                 if ( managedRepository != null )
                 {
                     try
                     {
                         if( isAuthorized( request, repositoryId ) )
-                        {
+                        {   
                             LogicalResource logicalResource =
                                 new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
 
@@ -258,12 +258,12 @@ public class ArchivaDavResourceFactory
 
                             if ( isPut )
                             {
-                                resource = doPut( managedRepository, request, archivaLocator, logicalResource );
+                                resource = doPut( managedRepository, request, archivaLocator, logicalResource );                                
                             }
                         }
                     }
                     catch ( DavException de ) 
-                    {
+                    {                        
                         e = de;
                         continue;
                     }
@@ -273,11 +273,11 @@ public class ArchivaDavResourceFactory
                         e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" );
                     }
                     else
-                    {   
+                    {                           
                         availableResources.add( resource );
 
                         String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() );
-                        resourcesInAbsolutePath.add( managedRepository.getRepoRoot() + logicalResource );
+                        resourcesInAbsolutePath.add( managedRepository.getRepoRoot() + logicalResource );                        
                     }
                 }
                 else
@@ -491,15 +491,16 @@ public class ArchivaDavResourceFactory
 
         File rootDirectory = new File( managedRepository.getRepoRoot() );
         File destDir = new File( rootDirectory, logicalResource.getPath() ).getParentFile();
+        
         if ( request.getMethod().equals(HTTP_PUT_METHOD) && !destDir.exists() )
         {
             destDir.mkdirs();
             String relPath = PathUtil.getRelative( rootDirectory.getAbsolutePath(), destDir );
             triggerAuditEvent( request.getRemoteAddr(), logicalResource.getPath(), relPath, AuditEvent.CREATE_DIR );
         }
-
-        File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
-
+        
+        File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );        
+                
         return new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(),
                                        managedRepository.getRepository(), request.getRemoteAddr(),
                                        request.getDavSession(), locator, this, mimeTypes, auditListeners, consumers, archivaXworkUser );
@@ -721,9 +722,9 @@ public class ArchivaDavResourceFactory
 
     protected boolean isAuthorized( DavServletRequest request, String repositoryId )
         throws DavException
-    {
+    {   
         try
-        {
+        {     
             AuthenticationResult result = httpAuth.getAuthenticationResult( request, null );
             SecuritySession securitySession = httpAuth.getSecuritySession();
 
@@ -732,13 +733,15 @@ public class ArchivaDavResourceFactory
                                           WebdavMethodUtil.isWriteMethod( request.getMethod() ) );
         }
         catch ( AuthenticationException e )
-        {
+        {            
+            boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
+            
             // safety check for MRM-911            
             String guest = archivaXworkUser.getGuest();
             try
             {
                 if( servletAuth.isAuthorized( guest, 
-                      ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId() ) )
+                      ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId(), isPut ) )
                 {   
                     return true;
                 }
@@ -795,6 +798,8 @@ public class ArchivaDavResourceFactory
 
         if( allow )
         {
+            boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
+            
             for( String repository : repositories )
             {
                 // for prompted authentication
@@ -817,7 +822,7 @@ public class ArchivaDavResourceFactory
                     // for the current user logged in
                     try
                     {
-                        if( servletAuth.isAuthorized( activePrincipal, repository ) )
+                        if( servletAuth.isAuthorized( activePrincipal, repository, isPut ) )
                         {
                             getResource( locator, mergedRepositoryContents, logicalResource, repository );
                         }
@@ -909,11 +914,12 @@ public class ArchivaDavResourceFactory
         }
         else
         {
+            boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
             for( String repository : repositories )
             {
                 try
-                {
-                    if( servletAuth.isAuthorized( activePrincipal, repository ) )
+                {   
+                    if( servletAuth.isAuthorized( activePrincipal, repository, isPut ) )
                     {
                         allow = true;
                         break;
@@ -974,4 +980,14 @@ public class ArchivaDavResourceFactory
            return true;
        }
     }
+    
+    public void setServletAuth( ServletAuthenticator servletAuth )
+    {
+        this.servletAuth = servletAuth;
+    }
+    
+    public void setHttpAuth( HttpAuthenticator httpAuth )
+    {
+        this.httpAuth = httpAuth;
+    }
 }
index 5af2a8c193878322496460378555a84ea67a20d0..e06d33176a346439bfea6e81e7cda178600849b5 100644 (file)
@@ -24,6 +24,7 @@ import org.apache.jackrabbit.webdav.WebdavRequest;
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavServletRequest;
 import org.apache.maven.archiva.webdav.util.RepositoryPathUtil;
+import org.apache.maven.archiva.webdav.util.WebdavMethodUtil;
 import org.apache.maven.archiva.security.ArchivaXworkUser;
 import org.apache.maven.archiva.security.ServletAuthenticator;
 import org.codehaus.plexus.redback.authentication.AuthenticationException;
@@ -72,12 +73,14 @@ public class ArchivaDavSessionProvider
         }
         catch ( AuthenticationException e )
         {   
+            boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
+            
             // safety check for MRM-911            
             String guest = archivaXworkUser.getGuest();
             try
             {
                 if( servletAuth.isAuthorized( guest, 
-                      ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId() ) )
+                      ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId(), isPut ) )
                 {
                     request.setDavSession(new ArchivaDavSession());
                     return true;
index ef55e7624bf23bc7d41418ff7d63fe93c3c5d39c..4d0bc445c7fa708bead498a05ccdec7ec5f9145d 100644 (file)
@@ -362,7 +362,7 @@ public class ArchivaDavSessionProviderTest extends TestCase
             return true;
         }
 
-        public boolean isAuthorized(String arg0, String arg1)
+        public boolean isAuthorized(String arg0, String arg1, boolean isWriteRequest)
             throws UnauthorizedException
         {
             return true;
index badd20cb6d9b13d631d06f10153980379b086122..e029ca583e2031fc5302fd1abe88aa8b2964e604 100644 (file)
 package org.apache.maven.archiva.webdav;
 
-/**
- * RepositoryServletSecurityTest 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
  *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletResponse;
+
+import net.sf.ehcache.CacheManager;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.Configuration;
+import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.maven.archiva.security.ArchivaXworkUser;
+import org.apache.maven.archiva.security.ServletAuthenticator;
+import org.codehaus.plexus.redback.authentication.AuthenticationException;
+import org.codehaus.plexus.redback.authentication.AuthenticationResult;
+import org.codehaus.plexus.redback.authorization.UnauthorizedException;
+import org.codehaus.plexus.redback.system.DefaultSecuritySession;
+import org.codehaus.plexus.redback.system.SecuritySession;
+import org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator;
+import org.codehaus.plexus.redback.xwork.filter.authentication.basic.HttpBasicAuthentication;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.easymock.MockControl;
+import org.easymock.classextension.MockClassControl;
+import org.easymock.internal.AlwaysMatcher;
+
+import com.meterware.httpunit.GetMethodWebRequest;
+import com.meterware.httpunit.HttpUnitOptions;
+import com.meterware.httpunit.PutMethodWebRequest;
+import com.meterware.httpunit.WebRequest;
+import com.meterware.httpunit.WebResponse;
+import com.meterware.servletunit.InvocationContext;
+import com.meterware.servletunit.ServletRunner;
+import com.meterware.servletunit.ServletUnitClient;
+
+/**
+ * RepositoryServletSecurityTest
+ * 
+ * Test the flow of the authentication and authorization checks. This does not necessarily
+ * perform redback security checking.
+ * 
  * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
  * @version $Id$
  */
 public class RepositoryServletSecurityTest
-    extends AbstractRepositoryServletTestCase
+    extends PlexusInSpringTestCase
 {
-    public void testSecuredGet()
+    protected static final String REPOID_INTERNAL = "internal";
+
+    protected ServletUnitClient sc;
+
+    protected File repoRootInternal;
+
+    private ServletRunner sr;
+
+    protected ArchivaConfiguration archivaConfiguration;
+
+    private DavSessionProvider davSessionProvider;
+
+    private MockControl servletAuthControl;
+
+    private ServletAuthenticator servletAuth;
+
+    private MockClassControl httpAuthControl;
+
+    private HttpAuthenticator httpAuth;
+
+    private ArchivaXworkUser archivaXworkUser;
+
+    private RepositoryServlet servlet;
+    
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        String appserverBase = getTestFile( "target/appserver-base" ).getAbsolutePath();
+        System.setProperty( "appserver.base", appserverBase );
+
+        File testConf = getTestFile( "src/test/resources/repository-archiva.xml" );
+        File testConfDest = new File( appserverBase, "conf/archiva.xml" );
+        FileUtils.copyFile( testConf, testConfDest );
+
+        archivaConfiguration = (ArchivaConfiguration) lookup( ArchivaConfiguration.class );
+        repoRootInternal = new File( appserverBase, "data/repositories/internal" );
+        Configuration config = archivaConfiguration.getConfiguration();
+
+        config.addManagedRepository( createManagedRepository( REPOID_INTERNAL, "Internal Test Repo", repoRootInternal ) );
+        saveConfiguration( archivaConfiguration );
+
+        CacheManager.getInstance().removeCache( "url-failures-cache" );
+
+        HttpUnitOptions.setExceptionsThrownOnErrorStatus( false );
+
+        sr = new ServletRunner( getTestFile( "src/test/resources/WEB-INF/repository-servlet-security-test/web.xml" ) );
+        sr.registerServlet( "/repository/*", RepositoryServlet.class.getName() );
+        sc = sr.newClient();
+
+        servletAuthControl = MockControl.createControl( ServletAuthenticator.class );
+        servletAuthControl.setDefaultMatcher( MockControl.ALWAYS_MATCHER );
+        servletAuth = (ServletAuthenticator) servletAuthControl.getMock();
+
+        httpAuthControl =
+            MockClassControl.createControl( HttpBasicAuthentication.class, HttpBasicAuthentication.class.getMethods() );
+        httpAuthControl.setDefaultMatcher( MockControl.ALWAYS_MATCHER );
+        httpAuth = (HttpAuthenticator) httpAuthControl.getMock();
+
+        archivaXworkUser = new ArchivaXworkUser();
+        archivaXworkUser.setGuest( "guest" );
+
+        davSessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth, archivaXworkUser );      
+    }
+
+    protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, File location )
     {
+        ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration();
+        repo.setId( id );
+        repo.setName( name );
+        repo.setLocation( location.getAbsolutePath() );
+        return repo;
+    }
+
+    protected void saveConfiguration()
+        throws Exception
+    {
+        saveConfiguration( archivaConfiguration );
+    }
+
+    protected void saveConfiguration( ArchivaConfiguration archivaConfiguration )
+        throws Exception
+    {
+        archivaConfiguration.save( archivaConfiguration.getConfiguration() );
+    }
+
+    protected void setupCleanRepo( File repoRootDir )
+        throws IOException
+    {
+        FileUtils.deleteDirectory( repoRootDir );
+        if ( !repoRootDir.exists() )
+        {
+            repoRootDir.mkdirs();
+        }
+    }
+
+    @Override
+    protected String getPlexusConfigLocation()
+    {
+        return "org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml";
+    }
+
+    @Override
+    protected void tearDown()
+        throws Exception
+    {
+        if ( sc != null )
+        {
+            sc.clearContents();
+        }
+
+        if ( sr != null )
+        {
+            sr.shutDown();
+        }
+
+        if ( repoRootInternal.exists() )
+        {
+            FileUtils.deleteDirectory(repoRootInternal);
+        }
+
+        servlet = null;
         
+        super.tearDown();
     }
-    
-    public void testSecuredBrowse()
+
+    // test deploy with invalid user, and guest has no write access to repo
+    // 401 must be returned
+    public void testPutWithInvalidUserAndGuestHasNoWriteAccess()
+        throws Exception
     {
+        setupCleanRepo( repoRootInternal );
+
+        String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
+        InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
+        assertNotNull( "artifact.jar inputstream", is );
+
+        WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
+                           new AuthenticationException( "Authentication error" ) );
+        
+        servletAuth.isAuthorized( "guest", "internal", true );        
+        servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER );
+        servletAuthControl.setThrowable( new UnauthorizedException( "'guest' has no write access to repository" ) );
+
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+        
+        servlet.service( ic.getRequest(), ic.getResponse() );
+        
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+
+        //assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode());
+    }
+
+    // test deploy with invalid user, but guest has write access to repo
+    public void testPutWithInvalidUserAndGuestHasWriteAccess()
+        throws Exception
+    {
+        setupCleanRepo( repoRootInternal );
+
+        String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
+        InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
+        assertNotNull( "artifact.jar inputstream", is );
+
+        WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
+
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+
+        ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
+        archivaDavResourceFactory.setHttpAuth( httpAuth );
+        archivaDavResourceFactory.setServletAuth( servletAuth );
+
+        servlet.setResourceFactory( archivaDavResourceFactory );
+        
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
+                                           new AuthenticationException( "Authentication error" ) );
+        
+        servletAuth.isAuthorized( "guest", "internal", true );
+        servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER );
+        servletAuthControl.setReturnValue( true );
+                
+     // ArchivaDavResourceFactory#isAuthorized()
+        SecuritySession session = new DefaultSecuritySession();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        httpAuthControl.expectAndReturn( httpAuth.getSecuritySession(), session );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, result ),
+                                           new AuthenticationException( "Authentication error" ) );
+        
+        // check if guest has write access
+        servletAuth.isAuthorized( "guest", "internal", true );
+        servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER );
+        servletAuthControl.setReturnValue( true );
+        
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+
+        servlet.service( ic.getRequest(), ic.getResponse() );
+
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+
+        // assertEquals( HttpServletResponse.SC_CREATED, response.getResponseCode() );
+    }
+
+    // test deploy with a valid user with no write access
+    public void testPutWithValidUserWithNoWriteAccess()
+        throws Exception
+    {
+        setupCleanRepo( repoRootInternal );
+
+        String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
+        InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
+        assertNotNull( "artifact.jar inputstream", is );
+        
+        WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
+        
+        InvocationContext ic = sc.newInvocation( request ); 
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+        
+        ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
+        archivaDavResourceFactory.setHttpAuth( httpAuth );
+        archivaDavResourceFactory.setServletAuth( servletAuth );
+        servlet.setResourceFactory( archivaDavResourceFactory );
+
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
+        
+     // ArchivaDavResourceFactory#isAuthorized()
+        SecuritySession session = new DefaultSecuritySession();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        httpAuthControl.expectAndReturn( httpAuth.getSecuritySession(), session );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthorized( null, session, "internal", true ),
+                                           new UnauthorizedException( "User not authorized" ) );
+                
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+        
+        servlet.service( ic.getRequest(), ic.getResponse() );
+
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+        
+        // assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode());
+    }
+
+    // test deploy with a valid user with write access
+    public void testPutWithValidUserWithWriteAccess()
+        throws Exception
+    {
+        setupCleanRepo( repoRootInternal );
+        assertTrue( repoRootInternal.exists() );
+
+        String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
+        InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
+        assertNotNull( "artifact.jar inputstream", is );
+
+        WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
+
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+
+        ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
+        archivaDavResourceFactory.setHttpAuth( httpAuth );
+        archivaDavResourceFactory.setServletAuth( servletAuth );
+
+        servlet.setResourceFactory( archivaDavResourceFactory );
+
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
+
+        // ArchivaDavResourceFactory#isAuthorized()
+        SecuritySession session = new DefaultSecuritySession();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        httpAuthControl.expectAndReturn( httpAuth.getSecuritySession(), session );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true );
+
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+
+        servlet.service( ic.getRequest(), ic.getResponse() );
+
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+
+        // assertEquals(HttpServletResponse.SC_CREATED, response.getResponseCode());
+    }
+
+    // test get with invalid user, and guest has read access to repo
+    public void testGetWithInvalidUserAndGuestHasReadAccess()
+        throws Exception
+    {
+        String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
+        String expectedArtifactContents = "dummy-commons-lang-artifact";
+
+        File artifactFile = new File( repoRootInternal, commonsLangJar );
+        artifactFile.getParentFile().mkdirs();
+
+        FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
+
+        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+        
+        ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
+        archivaDavResourceFactory.setHttpAuth( httpAuth );
+        archivaDavResourceFactory.setServletAuth( servletAuth );
+
+        servlet.setResourceFactory( archivaDavResourceFactory );
+
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
+                                           new AuthenticationException( "Authentication error" ) );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthorized( "guest", "internal", false ), true );
+        
+     // ArchivaDavResourceFactory#isAuthorized()
+        SecuritySession session = new DefaultSecuritySession();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        httpAuthControl.expectAndReturn( httpAuth.getSecuritySession(), session );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true );
+
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+
+        WebResponse response = sc.getResponse( request );
+
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+
+        assertEquals( HttpServletResponse.SC_OK, response.getResponseCode() );
+        assertEquals( "Expected file contents", expectedArtifactContents, response.getText() );
+    }
+
+    // test get with invalid user, and guest has no read access to repo
+    public void testGetWithInvalidUserAndGuestHasNoReadAccess()
+        throws Exception
+    {
+        String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
+        String expectedArtifactContents = "dummy-commons-lang-artifact";
+
+        File artifactFile = new File( repoRootInternal, commonsLangJar );
+        artifactFile.getParentFile().mkdirs();
+
+        FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
+
+        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
+                                           new AuthenticationException( "Authentication error" ) );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthorized( "guest", "internal", false ), false );
+
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+
+        WebResponse response = sc.getResponse( request );
+
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+
+        assertEquals( HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode() );
+    }
+
+    // test get with valid user with read access to repo
+    public void testGetWithAValidUserWithReadAccess()
+        throws Exception
+    {
+        String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
+        String expectedArtifactContents = "dummy-commons-lang-artifact";
+
+        File artifactFile = new File( repoRootInternal, commonsLangJar );
+        artifactFile.getParentFile().mkdirs();
+
+        FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
+
+        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+
+        ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
+        archivaDavResourceFactory.setHttpAuth( httpAuth );
+        archivaDavResourceFactory.setServletAuth( servletAuth );
+
+        servlet.setResourceFactory( archivaDavResourceFactory );
+        
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
+        
+     // ArchivaDavResourceFactory#isAuthorized()
+        SecuritySession session = new DefaultSecuritySession();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        httpAuthControl.expectAndReturn( httpAuth.getSecuritySession(), session );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true );
+        
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+
+        WebResponse response = sc.getResponse( request );
+        
+        httpAuthControl.verify();
+        servletAuthControl.verify();
+
+        assertEquals( HttpServletResponse.SC_OK, response.getResponseCode() );
+        assertEquals( "Expected file contents", expectedArtifactContents, response.getText() );
+    }
+
+    // test get with valid user with no read access to repo
+    public void testGetWithAValidUserWithNoReadAccess()
+        throws Exception
+    {
+        String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
+        String expectedArtifactContents = "dummy-commons-lang-artifact";
+
+        File artifactFile = new File( repoRootInternal, commonsLangJar );
+        artifactFile.getParentFile().mkdirs();
+
+        FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
+
+        WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
+        InvocationContext ic = sc.newInvocation( request );
+        servlet = (RepositoryServlet) ic.getServlet();
+        servlet.setDavSessionProvider( davSessionProvider );
+
+        ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
+        archivaDavResourceFactory.setHttpAuth( httpAuth );
+        archivaDavResourceFactory.setServletAuth( servletAuth );
+
+        servlet.setResourceFactory( archivaDavResourceFactory );
+        
+        AuthenticationResult result = new AuthenticationResult();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
+
+     // ArchivaDavResourceFactory#isAuthorized()
+        SecuritySession session = new DefaultSecuritySession();
+        httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
+        httpAuthControl.expectAndReturn( httpAuth.getSecuritySession(), session );
+        servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
+        servletAuthControl.expectAndThrow( servletAuth.isAuthorized( null, session, "internal", true ),
+                                           new UnauthorizedException( "User not authorized to read repository." ) );
+        
+        httpAuthControl.replay();
+        servletAuthControl.replay();
+        
+        WebResponse response = sc.getResponse( request );
+
+        httpAuthControl.verify();
+        servletAuthControl.verify();
         
+        assertEquals( HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode() );
     }
 }
diff --git a/archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml b/archiva-struts2/archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml
new file mode 100644 (file)
index 0000000..291aa01
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+  <display-name>Apache Archiva</display-name>
+
+  <listener>
+    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+  </listener>
+
+  <context-param>
+    <param-name>contextClass</param-name>
+    <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
+  </context-param>
+
+   <context-param>
+    <param-name>contextConfigLocation</param-name>
+    <param-value>
+        classpath*:/META-INF/plexus/components.xml
+        classpath*:/META-INF/spring-context.xml
+        target/test-classes/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml
+    </param-value>
+  </context-param>
+
+</web-app>
index d7087095a182e4249b0ecd1f6eccd4b5f4f1a063..53e79073f4b30694cee00ae9d9fc01bed1c4935e 100644 (file)
       <role-hint>default</role-hint>
       <implementation>org.apache.maven.archiva.webdav.DefaultDavServerManager</implementation>
       <description>DefaultDavServerManager</description>
-      <configuration>
-        <provider-hint>proxied</provider-hint>
-      </configuration>
+      <requirements>
+        <requirement>
+          <role>org.apache.maven.archiva.webdav.DavServerComponent</role>
+          <role-hint>proxied</role-hint>
+        </requirement>
+      </requirements>
     </component>
     
     <component>
     <component>
       <role>org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers</role>
       <role-hint>default</role-hint>
-      <implementation>org.apache.maven.archiva.web.repository.StubRepositoryContentConsumers</implementation>
+      <implementation>org.apache.maven.archiva.webdav.StubRepositoryContentConsumers</implementation>
     </component>
-
-    <!-- TODO: shouldn't need so many components just to use in-memory - is flaky since these are auto-generated -->
+    
     <component>
       <role>org.codehaus.plexus.redback.system.SecuritySystem</role>
       <role-hint>default</role-hint>
       <implementation>org.codehaus.plexus.redback.system.DefaultSecuritySystem</implementation>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.redback.authentication.AuthenticationManager</role>
-          <field-name>authnManager</field-name>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.redback.authorization.Authorizer</role>
-          <role-hint>rbac</role-hint>
-          <field-name>authorizer</field-name>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.redback.users.UserManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>userManager</field-name>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.redback.keys.KeyManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>keyManager</field-name>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.redback.policy.UserSecurityPolicy</role>
-          <field-name>policy</field-name>
-        </requirement>
-      </requirements>
     </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.authentication.Authenticator</role>
-      <role-hint>user-manager</role-hint>
-      <implementation>org.codehaus.plexus.redback.authentication.users.UserManagerAuthenticator</implementation>
+       
+       <component>
+      <role>org.apache.maven.archiva.webdav.ArchivaDavResourceFactory</role>
+      <implementation>org.apache.maven.archiva.webdav.ArchivaDavResourceFactory</implementation>
       <requirements>
         <requirement>
-          <role>org.codehaus.plexus.redback.users.UserManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>userManager</field-name>
+          <role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
+          <field-name>archivaConfiguration</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.policy.UserSecurityPolicy</role>
-          <field-name>securityPolicy</field-name>
-        </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.authentication.Authenticator</role>
-      <role-hint>keystore</role-hint>
-      <implementation>org.codehaus.plexus.redback.authentication.keystore.KeyStoreAuthenticator</implementation>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.redback.keys.KeyManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>keystore</field-name>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.redback.users.UserManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>userManager</field-name>
-        </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator</role>
-      <role-hint>default</role-hint>
-      <implementation>org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator
-      </implementation>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.redback.users.UserManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>userManager</field-name>
-        </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.authorization.Authorizer</role>
-      <role-hint>rbac</role-hint>
-      <implementation>org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer</implementation>
-      <requirements>
+          <role>org.apache.maven.archiva.repository.RepositoryContentFactory</role>
+          <field-name>repositoryFactory</field-name>
+        </requirement>        
         <requirement>
-          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>manager</field-name>
+          <role>org.apache.maven.archiva.repository.content.RepositoryRequest</role>
+          <field-name>repositoryRequest</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.users.UserManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>userManager</field-name>
+          <role>org.apache.maven.archiva.proxy.RepositoryProxyConnectors</role>
+          <field-name>connectors</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator</role>
-          <role-hint>default</role-hint>
-          <field-name>evaluator</field-name>
+          <role>org.apache.maven.archiva.repository.metadata.MetadataTools</role>
+          <field-name>metadataTools</field-name>
         </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.role.RoleManager</role>
-      <role-hint>default</role-hint>
-      <implementation>org.codehaus.plexus.redback.role.DefaultRoleManager</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
-      <requirements>
         <requirement>
-          <role>org.codehaus.plexus.redback.role.merger.RoleModelMerger</role>
-          <role-hint>default</role-hint>
-          <field-name>modelMerger</field-name>
+          <role>org.apache.maven.archiva.security.ServletAuthenticator</role>
+          <field-name>servletAuth</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.role.validator.RoleModelValidator</role>
-          <role-hint>default</role-hint>
-          <field-name>modelValidator</field-name>
+          <role>org.apache.maven.archiva.webdav.util.MimeTypes</role>
+          <field-name>mimeTypes</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.role.processor.RoleModelProcessor</role>
-          <role-hint>default</role-hint>
-          <field-name>modelProcessor</field-name>
+          <role>org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator</role>
+          <role-hint>basic</role-hint>
+          <field-name>httpAuth</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.role.template.RoleTemplateProcessor</role>
+          <role>org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers</role>
           <role-hint>default</role-hint>
-          <field-name>templateProcessor</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>rbacManager</field-name>
+          <role>org.codehaus.plexus.digest.ChecksumFile</role>
+          <field-name>checksum</field-name>
         </requirement>
         <requirement>
-          <role>org.codehaus.plexus.PlexusContainer</role>
-          <field-name>container</field-name>
+          <role>org.codehaus.plexus.digest.Digester</role>
+          <role-hint>sha1</role-hint>
+          <field-name>digestSha1</field-name>
         </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.role.processor.RoleModelProcessor</role>
-      <role-hint>default</role-hint>
-      <implementation>org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor</implementation>
-      <requirements>
         <requirement>
-          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>rbacManager</field-name>
+          <role>org.codehaus.plexus.digest.Digester</role>
+          <role-hint>md5</role-hint>
+          <field-name>digestMd5</field-name>
         </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.redback.role.template.RoleTemplateProcessor</role>
-      <role-hint>default</role-hint>
-      <implementation>org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor</implementation>
-      <requirements>
         <requirement>
-          <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
-          <role-hint>memory</role-hint>
-          <field-name>rbacManager</field-name>
-        </requirement>
+          <role>org.apache.maven.archiva.security.ArchivaXworkUser</role>
+          <field-name>archivaXworkUser</field-name>
+        </requirement>        
       </requirements>
     </component>
   </components>
index 56f36a4608580813df286891d942c8cd914cde2e..0dcf1418e0d082ddee0efbfee9fcab089ea7e794 100644 (file)
@@ -64,7 +64,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-enforcer-plugin</artifactId>
-        <version>1.0-alpha-3</version>
+        <version>1.0-alpha-4</version>
         <executions>
           <execution>
             <goals>
       <version>1.2_Java1.3</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+      <version>1.2</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>jcl104-over-slf4j</artifactId>