From aba894a9997b9c6cad4df726fc8eb278b7f3c74b Mon Sep 17 00:00:00 2001 From: "Maria Odea B. Ching" Date: Tue, 7 Oct 2008 05:12:33 +0000 Subject: [PATCH] merged/updated from trunk -r702027 to get the latest changes git-svn-id: https://svn.apache.org/repos/asf/archiva/branches/MRM-124@702347 13f79535-47bb-0310-9956-ffa450edef68 --- archiva-docs/src/site/apt/userguide/rss.apt | 9 +- archiva-jetty/pom.xml | 2 +- .../archiva-core-consumers/pom.xml | 8 - .../ArtifactMissingChecksumsConsumer.java | 20 +- .../consumers/core/AutoRemoveConsumer.java | 20 +- .../repository/AbstractRepositoryPurge.java | 108 +--- ...eanupReleasedSnapshotsRepositoryPurge.java | 50 +- .../repository/DaysOldRepositoryPurge.java | 28 +- .../repository/RepositoryPurgeConsumer.java | 62 +- .../RetentionCountRepositoryPurge.java | 22 +- .../AbstractRepositoryPurgeTest.java | 125 +--- ...pReleasedSnapshotsRepositoryPurgeTest.java | 87 ++- .../DaysOldRepositoryPurgeTest.java | 94 ++- .../RepositoryPurgeConsumerTest.java | 56 +- .../RetentionCountRepositoryPurgeTest.java | 82 ++- ...ceneRepositoryContentIndexFactoryStub.java | 60 -- .../LuceneRepositoryContentIndexStub.java | 147 ----- .../RepositoryPurgeConsumerTest.xml | 119 ---- .../lucene/IndexContentConsumer.java | 14 +- .../RepositoryContentIndexEventListener.java | 70 +++ .../indexer/search/CrossRepositorySearch.java | 17 + .../search/DefaultCrossRepositorySearch.java | 107 +++- .../archiva/indexer/search/SearchResults.java | 5 +- ...positoryContentIndexEventListenerTest.java | 167 ++++++ .../DefaultCrossRepositorySearchTest.java | 56 +- ...epositoryContentIndexEventListenerTest.xml | 22 + .../src/main/mdo/archiva-base.xml | 40 ++ .../repository/events/RepositoryListener.java | 37 ++ archiva-modules/archiva-database/pom.xml | 4 - .../RepositoryDatabaseEventListener.java | 55 ++ .../AbstractDeclarativeConstraint.java | 4 +- .../ArtifactsByRepositoryConstraint.java | 16 +- ...ntentStatisticsByRepositoryConstraint.java | 14 + .../UniqueArtifactIdConstraint.java | 38 +- .../RepositoryDatabaseEventListenerTest.java | 90 +++ .../ArtifactsByRepositoryConstraintTest.java | 75 ++- ...tStatisticsByRepositoryConstraintTest.java | 25 +- .../UniqueArtifactIdConstraintTest.java | 64 ++- .../UniqueGroupIdConstraintTest.java | 4 +- .../archiva-report-manager/pom.xml | 5 + .../reporting/ArchivaReportException.java | 40 ++ .../reporting/RepositoryStatistics.java | 234 ++++++++ .../RepositoryStatisticsReportGenerator.java | 50 ++ ...leRepositoryStatisticsReportGenerator.java | 147 +++++ ...positoryStatisticsReportGeneratorTest.java | 356 ++++++++++++ ...ArchivaRepositoryScanningTaskExecutor.java | 68 ++- .../archiva-web/archiva-rss/pom.xml | 1 + .../NewArtifactsRssFeedProcessor.java | 2 +- .../archiva-web/archiva-security/pom.xml | 14 +- .../security/ArchivaServletAuthenticator.java | 12 +- .../archiva/security/ArchivaXworkUser.java | 39 +- .../security/ServletAuthenticator.java | 36 +- .../security/AbstractSecurityTest.java | 126 ++++ .../ArchivaServletAuthenticatorTest.java | 224 ++++++++ .../security/DefaultUserRepositoriesTest.java | 105 +--- .../ArchivaServletAuthenticatorTest.xml | 202 +++++++ .../archiva-web/archiva-webapp/pom.xml | 24 +- .../archiva/web/action/BrowseAction.java | 7 +- .../archiva/web/action/SearchAction.java | 311 ++++++++-- .../web/action/ShowArtifactAction.java | 7 +- .../archiva/web/action/UploadAction.java | 7 +- .../proxy/ProxyConnectorsAction.java | 12 + .../AbstractManagedRepositoriesAction.java | 2 +- .../action/reports/GenerateReportAction.java | 382 ++++++++++++- .../maven/archiva/web/rss/RssFeedServlet.java | 61 +- .../maven/archiva/web/util/ContextUtils.java | 29 +- .../src/main/resources/log4j.xml | 4 +- ...earchAction-filteredSearch-validation.xml} | 18 +- .../src/main/resources/xwork.xml | 17 + .../webapp/WEB-INF/applicationContext.xml | 16 - .../WEB-INF/jsp/admin/addRepository.jsp | 2 +- .../WEB-INF/jsp/admin/proxyConnectors.jsp | 24 +- .../webapp/WEB-INF/jsp/admin/repositories.jsp | 2 +- .../WEB-INF/jsp/admin/repositoryGroups.jsp | 6 +- .../webapp/WEB-INF/jsp/advancedSearch.jsp | 67 +++ .../src/main/webapp/WEB-INF/jsp/browse.jsp | 11 +- .../webapp/WEB-INF/jsp/decorators/default.jsp | 5 + .../WEB-INF/jsp/include/artifactInfo.jspf | 17 +- .../WEB-INF/jsp/include/quickSearchForm.jspf | 40 -- .../main/webapp/WEB-INF/jsp/quickSearch.jsp | 30 +- .../webapp/WEB-INF/jsp/reports/pickReport.jsp | 22 +- .../WEB-INF/jsp/reports/statisticsReport.jsp | 213 +++++++ .../src/main/webapp/WEB-INF/jsp/results.jsp | 173 ++++-- .../src/main/webapp/WEB-INF/web.xml | 29 +- .../src/main/webapp/css/maven-theme.css | 3 +- .../main/webapp/images/archiva-splat-32.gif | Bin 1294 -> 1227 bytes .../archiva/web/rss/RssFeedServletTest.java | 22 +- .../webapp/WEB-INF/feedServletTest-web.xml | 2 +- .../archiva-web/archiva-webdav/pom.xml | 8 +- .../archiva/webdav/ArchivaDavResource.java | 11 +- .../webdav/ArchivaDavResourceFactory.java | 89 ++- .../webdav/ArchivaDavSessionProvider.java | 29 +- .../archiva/webdav/RepositoryServlet.java | 5 +- .../webdav/ArchivaDavSessionProviderTest.java | 4 +- .../maven/archiva/webdav/DavResourceTest.java | 11 +- .../webdav/RepositoryServletSecurityTest.java | 541 +++++++++++++++++- .../UnauthenticatedDavSessionProvider.java | 2 +- .../repository-servlet-security-test/web.xml | 45 ++ .../webdav/RepositoryServletSecurityTest.xml | 181 ++---- .../archiva/webdav/RepositoryServletTest.xml | 4 + archiva-modules/archiva-web/pom.xml | 1 - pom-4.1.0.xml | 410 ------------- pom.xml | 90 +-- 103 files changed, 4657 insertions(+), 2023 deletions(-) delete mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexFactoryStub.java delete mode 100644 archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexStub.java create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListener.java create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.java create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.xml create mode 100644 archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/events/RepositoryListener.java create mode 100644 archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListener.java create mode 100644 archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListenerTest.java create mode 100644 archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java create mode 100644 archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java create mode 100644 archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java create mode 100644 archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java create mode 100644 archiva-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java create mode 100644 archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java create mode 100644 archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java create mode 100644 archiva-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml rename archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/{reports/GenerateReportAction-validation.xml => SearchAction-filteredSearch-validation.xml} (74%) create mode 100644 archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/advancedSearch.jsp delete mode 100644 archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf create mode 100644 archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp create mode 100644 archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml delete mode 100644 pom-4.1.0.xml diff --git a/archiva-docs/src/site/apt/userguide/rss.apt b/archiva-docs/src/site/apt/userguide/rss.apt index 7b7224717..04d1d8889 100644 --- a/archiva-docs/src/site/apt/userguide/rss.apt +++ b/archiva-docs/src/site/apt/userguide/rss.apt @@ -33,7 +33,8 @@ RSS Feeds * New Artifacts In Repository - The default url for this feed is: <<>> + For versions 1.1 and 1.1.1, the default url for this feed is <<>>. + But since version 1.1.2, this has been changed to <<>> There are two ways to subscribe to this feed: @@ -45,7 +46,8 @@ RSS Feeds * New Versions of an Artifact - The default url for this feed is: <<>> + The default url for this feed for versions 1.1 and 1.1.1 is <<>> + but was changed to <<>> since version 1.1.2 for consistency purposes. You could subscribe to the feed the same way as specified in the New Artifacts In Repository section except that in #1, you need to specify the <<>> and <<>> instead of the <<>>. And in #2, you need to go to the @@ -58,4 +60,5 @@ RSS Feeds note that only users with an Observer role for the specific repository would be able to subscribe to this feed. If the 'guest' account is enabled for the repository, you would no longer be asked for the username and password when you - subscribe to the feed. \ No newline at end of file + subscribe to the feed. + diff --git a/archiva-jetty/pom.xml b/archiva-jetty/pom.xml index a06152b3d..5c88febb9 100644 --- a/archiva-jetty/pom.xml +++ b/archiva-jetty/pom.xml @@ -142,7 +142,7 @@ org.codehaus.mojo appassembler-maven-plugin - 1.0-SNAPSHOT + 1.0-beta-2 diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml index 8b85df5a0..538c0cd4d 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/pom.xml @@ -28,14 +28,6 @@ Archiva Consumers :: Core Consumers - - org.apache.archiva - archiva-database - - - org.apache.archiva - archiva-indexer - org.apache.archiva archiva-configuration diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java index 553289929..7ce2db144 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java @@ -19,7 +19,10 @@ package org.apache.maven.archiva.consumers.core; * under the License. */ +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; @@ -94,9 +97,7 @@ public class ArtifactMissingChecksumsConsumer private static final String TYPE_CHECKSUM_CANNOT_CREATE = "checksum-create-failure"; private File repositoryDir; - - private List propertyNameTriggers = new ArrayList(); - + private List includes = new ArrayList(); public String getId() @@ -172,8 +173,8 @@ public class ArtifactMissingChecksumsConsumer } public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) - { - if ( propertyNameTriggers.contains( propertyName ) ) + { + if ( ConfigurationNames.isRepositoryScanning( propertyName ) ) { initIncludes(); } @@ -194,15 +195,8 @@ public class ArtifactMissingChecksumsConsumer public void initialize() throws InitializationException { - propertyNameTriggers = new ArrayList(); - propertyNameTriggers.add( "repositoryScanning" ); - propertyNameTriggers.add( "fileTypes" ); - propertyNameTriggers.add( "fileType" ); - propertyNameTriggers.add( "patterns" ); - propertyNameTriggers.add( "pattern" ); - configuration.addChangeListener( this ); - + initIncludes(); } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/AutoRemoveConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/AutoRemoveConsumer.java index 618b91f21..a5112272b 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/AutoRemoveConsumer.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/AutoRemoveConsumer.java @@ -19,7 +19,10 @@ package org.apache.maven.archiva.consumers.core; * under the License. */ +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; @@ -69,9 +72,7 @@ public class AutoRemoveConsumer private FileTypes filetypes; private File repositoryDir; - - private List propertyNameTriggers = new ArrayList(); - + private List includes = new ArrayList(); public String getId() @@ -122,8 +123,8 @@ public class AutoRemoveConsumer } public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) - { - if ( propertyNameTriggers.contains( propertyName ) ) + { + if ( ConfigurationNames.isRepositoryScanning( propertyName ) ) { initIncludes(); } @@ -143,14 +144,7 @@ public class AutoRemoveConsumer public void initialize() throws InitializationException - { - propertyNameTriggers = new ArrayList(); - propertyNameTriggers.add( "repositoryScanning" ); - propertyNameTriggers.add( "fileTypes" ); - propertyNameTriggers.add( "fileType" ); - propertyNameTriggers.add( "patterns" ); - propertyNameTriggers.add( "pattern" ); - + { configuration.addChangeListener( this ); initIncludes(); diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurge.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurge.java index f5aaf21ad..598375f2e 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurge.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurge.java @@ -19,26 +19,16 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ -import org.apache.maven.archiva.database.ArchivaDatabaseException; -import org.apache.maven.archiva.database.ArtifactDAO; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; -import org.apache.maven.archiva.indexer.RepositoryIndexException; -import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord; -import org.apache.maven.archiva.indexer.filecontent.FileContentRecord; -import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecord; -import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord; -import org.apache.maven.archiva.model.ArchivaArtifact; -import org.apache.maven.archiva.model.ArtifactReference; -import org.apache.maven.archiva.repository.ManagedRepositoryContent; -import org.apache.maven.archiva.repository.layout.LayoutException; - import java.io.File; import java.io.FilenameFilter; -import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Set; +import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.model.ArtifactReference; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; + /** * Base class for all repository purge tasks. * @@ -47,18 +37,14 @@ import java.util.Set; public abstract class AbstractRepositoryPurge implements RepositoryPurge { - protected ManagedRepositoryContent repository; - - protected ArtifactDAO artifactDao; - - private Map indices; + protected final ManagedRepositoryContent repository; + + protected final List listeners; - public AbstractRepositoryPurge( ManagedRepositoryContent repository, ArtifactDAO artifactDao, - Map indices ) + public AbstractRepositoryPurge( ManagedRepositoryContent repository, List listeners ) { this.repository = repository; - this.artifactDao = artifactDao; - this.indices = indices; + this.listeners = listeners; } /** @@ -98,10 +84,6 @@ public abstract class AbstractRepositoryPurge { if( references != null && !references.isEmpty() ) { - List fileContentRecords = new ArrayList(); - List hashcodeRecords = new ArrayList(); - List bytecodeRecords = new ArrayList(); - for ( ArtifactReference reference : references ) { File artifactFile = repository.toFile( reference ); @@ -110,46 +92,14 @@ public abstract class AbstractRepositoryPurge new ArchivaArtifact( reference.getGroupId(), reference.getArtifactId(), reference.getVersion(), reference.getClassifier(), reference.getType() ); - FileContentRecord fileContentRecord = new FileContentRecord(); - fileContentRecord.setFilename( repository.toPath( artifact ) ); - fileContentRecords.add( fileContentRecord ); - - HashcodesRecord hashcodesRecord = new HashcodesRecord(); - hashcodesRecord.setArtifact( artifact ); - hashcodeRecords.add( hashcodesRecord ); - - BytecodeRecord bytecodeRecord = new BytecodeRecord(); - bytecodeRecord.setArtifact( artifact ); - bytecodeRecords.add( bytecodeRecord ); - + for ( RepositoryListener listener : listeners ) + { + listener.deleteArtifact( repository, artifact ); + } + // TODO: this needs to be logged artifactFile.delete(); purgeSupportFiles( artifactFile ); - - // intended to be swallowed - // continue updating the database for all artifacts - try - { - String artifactPath = toRelativePath( artifactFile ); - updateDatabase( artifactPath ); - } - catch ( ArchivaDatabaseException ae ) - { - // TODO: determine logging to be used - } - catch ( LayoutException le ) - { - // Ignore - } - } - - try - { - updateIndices( fileContentRecords, hashcodeRecords, bytecodeRecords ); - } - catch ( RepositoryIndexException e ) - { - // Ignore } } } @@ -186,32 +136,4 @@ public abstract class AbstractRepositoryPurge } } } - - private void updateDatabase( String path ) - throws ArchivaDatabaseException, LayoutException - { - ArtifactReference artifact = repository.toArtifactReference( path ); - ArchivaArtifact queriedArtifact = - artifactDao.getArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), - artifact.getClassifier(), artifact.getType() ); - - artifactDao.deleteArtifact( queriedArtifact ); - - // TODO [MRM-37]: re-run the database consumers to clean up - } - - private void updateIndices( List fileContentRecords, - List hashcodeRecords, - List bytecodeRecords ) - throws RepositoryIndexException - { - RepositoryContentIndex index = indices.get( "filecontent" ); - index.deleteRecords( fileContentRecords ); - - index = indices.get( "hashcodes" ); - index.deleteRecords( hashcodeRecords ); - - index = indices.get( "bytecode" ); - index.deleteRecords( bytecodeRecords ); - } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurge.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurge.java index b9c1795a7..3bfba763b 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurge.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurge.java @@ -19,12 +19,17 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import org.apache.maven.archiva.common.utils.VersionComparator; import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; -import org.apache.maven.archiva.database.ArtifactDAO; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; +import org.apache.maven.archiva.model.ArchivaArtifact; import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.VersionedReference; @@ -33,17 +38,11 @@ import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryException; import org.apache.maven.archiva.repository.RepositoryNotFoundException; +import org.apache.maven.archiva.repository.events.RepositoryListener; import org.apache.maven.archiva.repository.layout.LayoutException; import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - /** *

* This will look in a single managed repository, and purge any snapshots that are present @@ -78,11 +77,12 @@ public class CleanupReleasedSnapshotsRepositoryPurge private RepositoryContentFactory repoContentFactory; - public CleanupReleasedSnapshotsRepositoryPurge( ManagedRepositoryContent repository, ArtifactDAO artifactDao, - MetadataTools metadataTools, Map indices, - ArchivaConfiguration archivaConfig, RepositoryContentFactory repoContentFactory ) + public CleanupReleasedSnapshotsRepositoryPurge( ManagedRepositoryContent repository, MetadataTools metadataTools, + ArchivaConfiguration archivaConfig, + RepositoryContentFactory repoContentFactory, + List listeners ) { - super( repository, artifactDao, indices ); + super( repository, listeners ); this.metadataTools = metadataTools; this.archivaConfig = archivaConfig; this.repoContentFactory = repoContentFactory; @@ -101,17 +101,17 @@ public class CleanupReleasedSnapshotsRepositoryPurge return; } - ArtifactReference artifact = repository.toArtifactReference( path ); + ArtifactReference artifactRef = repository.toArtifactReference( path ); - if ( !VersionUtil.isSnapshot( artifact.getVersion() ) ) + if ( !VersionUtil.isSnapshot( artifactRef.getVersion() ) ) { // Nothing to do here, not a snapshot, skip it. return; } ProjectReference reference = new ProjectReference(); - reference.setGroupId( artifact.getGroupId() ); - reference.setArtifactId( artifact.getArtifactId() ); + reference.setGroupId( artifactRef.getGroupId() ); + reference.setArtifactId( artifactRef.getArtifactId() ); // Gather up all of the versions. List allVersions = new ArrayList( repository.getVersions( reference ) ); @@ -161,8 +161,12 @@ public class CleanupReleasedSnapshotsRepositoryPurge boolean needsMetadataUpdate = false; VersionedReference versionRef = new VersionedReference(); - versionRef.setGroupId( artifact.getGroupId() ); - versionRef.setArtifactId( artifact.getArtifactId() ); + versionRef.setGroupId( artifactRef.getGroupId() ); + versionRef.setArtifactId( artifactRef.getArtifactId() ); + + ArchivaArtifact artifact = + new ArchivaArtifact( artifactRef.getGroupId(), artifactRef.getArtifactId(), artifactRef.getVersion(), + artifactRef.getClassifier(), artifactRef.getType() ); for ( String version : snapshotVersions ) { @@ -170,13 +174,19 @@ public class CleanupReleasedSnapshotsRepositoryPurge { versionRef.setVersion( version ); repository.deleteVersion( versionRef ); + + for ( RepositoryListener listener : listeners ) + { + listener.deleteArtifact( repository, artifact ); + } + needsMetadataUpdate = true; } } if ( needsMetadataUpdate ) { - updateMetadata( artifact ); + updateMetadata( artifactRef ); } } catch ( LayoutException e ) diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurge.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurge.java index a844128c3..415fa6082 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurge.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurge.java @@ -19,17 +19,6 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ -import org.apache.commons.lang.time.DateUtils; -import org.apache.maven.archiva.common.utils.VersionComparator; -import org.apache.maven.archiva.common.utils.VersionUtil; -import org.apache.maven.archiva.database.ArtifactDAO; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; -import org.apache.maven.archiva.model.ArtifactReference; -import org.apache.maven.archiva.model.VersionedReference; -import org.apache.maven.archiva.repository.ContentNotFoundException; -import org.apache.maven.archiva.repository.ManagedRepositoryContent; -import org.apache.maven.archiva.repository.layout.LayoutException; - import java.io.File; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -38,10 +27,19 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; +import org.apache.commons.lang.time.DateUtils; +import org.apache.maven.archiva.common.utils.VersionComparator; +import org.apache.maven.archiva.common.utils.VersionUtil; +import org.apache.maven.archiva.model.ArtifactReference; +import org.apache.maven.archiva.model.VersionedReference; +import org.apache.maven.archiva.repository.ContentNotFoundException; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; +import org.apache.maven.archiva.repository.layout.LayoutException; + /** * Purge from repository all snapshots older than the specified days in the repository configuration. * @@ -56,10 +54,10 @@ public class DaysOldRepositoryPurge private int retentionCount; - public DaysOldRepositoryPurge( ManagedRepositoryContent repository, ArtifactDAO artifactDao, int daysOlder, - int retentionCount, Map indices ) + public DaysOldRepositoryPurge( ManagedRepositoryContent repository, int daysOlder, + int retentionCount, List listeners ) { - super( repository, artifactDao, indices ); + super( repository, listeners ); this.daysOlder = daysOlder; this.retentionCount = retentionCount; timestampParser = new SimpleDateFormat( "yyyyMMdd.HHmmss" ); diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java index dacee4891..d388814c9 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumer.java @@ -19,30 +19,29 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; import org.apache.maven.archiva.consumers.ConsumerException; import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer; -import org.apache.maven.archiva.database.ArchivaDAO; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; -import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory; import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryException; import org.apache.maven.archiva.repository.RepositoryNotFoundException; +import org.apache.maven.archiva.repository.events.RepositoryListener; import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.codehaus.plexus.registry.Registry; import org.codehaus.plexus.registry.RegistryListener; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import edu.emory.mathcs.backport.java.util.Collections; /** * Consumer for removing old snapshots in the repository based on the criteria @@ -74,11 +73,6 @@ public class RepositoryPurgeConsumer */ private ArchivaConfiguration configuration; - /** - * @plexus.requirement role-hint="jdo" - */ - private ArchivaDAO dao; - /** * @plexus.requirement */ @@ -96,19 +90,15 @@ public class RepositoryPurgeConsumer private List includes = new ArrayList(); - private List propertyNameTriggers = new ArrayList(); - private RepositoryPurge repoPurge; private RepositoryPurge cleanUp; private boolean deleteReleasedSnapshots; - - /** - * @plexus.requirement role-hint="lucene" - */ - private RepositoryContentIndexFactory indexFactory; + /** @plexus.requirement role="org.apache.maven.archiva.repository.events.RepositoryListener" */ + private List listeners = Collections.emptyList(); + public String getId() { return this.id; @@ -139,27 +129,23 @@ public class RepositoryPurgeConsumer { try { - Map indices = new HashMap(); - indices.put( "bytecode", indexFactory.createBytecodeIndex( repository ) ); - indices.put( "hashcodes", indexFactory.createHashcodeIndex( repository ) ); - indices.put( "filecontent", indexFactory.createFileContentIndex( repository ) ); - ManagedRepositoryContent repositoryContent = repositoryFactory.getManagedRepositoryContent( repository .getId() ); if ( repository.getDaysOlder() != 0 ) { - repoPurge = new DaysOldRepositoryPurge( repositoryContent, dao.getArtifactDAO(), repository - .getDaysOlder(), repository.getRetentionCount(), indices ); + repoPurge = new DaysOldRepositoryPurge( repositoryContent, repository.getDaysOlder(), + repository.getRetentionCount(), listeners ); } else { - repoPurge = new RetentionCountRepositoryPurge( repositoryContent, dao.getArtifactDAO(), repository - .getRetentionCount(), indices ); + repoPurge = new RetentionCountRepositoryPurge( repositoryContent, repository.getRetentionCount(), + listeners ); } - cleanUp = new CleanupReleasedSnapshotsRepositoryPurge( repositoryContent, dao.getArtifactDAO(), - metadataTools, indices, configuration, repositoryFactory ); + cleanUp = + new CleanupReleasedSnapshotsRepositoryPurge( repositoryContent, metadataTools, configuration, + repositoryFactory, listeners ); deleteReleasedSnapshots = repository.isDeleteReleasedSnapshots(); } @@ -198,7 +184,7 @@ public class RepositoryPurgeConsumer public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) { - if ( propertyNameTriggers.contains( propertyName ) ) + if ( ConfigurationNames.isRepositoryScanning( propertyName ) ) { initIncludes(); } @@ -219,13 +205,6 @@ public class RepositoryPurgeConsumer public void initialize() throws InitializationException { - propertyNameTriggers = new ArrayList(); - propertyNameTriggers.add( "repositoryScanning" ); - propertyNameTriggers.add( "fileTypes" ); - propertyNameTriggers.add( "fileType" ); - propertyNameTriggers.add( "patterns" ); - propertyNameTriggers.add( "pattern" ); - configuration.addChangeListener( this ); initIncludes(); @@ -236,9 +215,4 @@ public class RepositoryPurgeConsumer // we need to check all files for deletion, especially if not modified return true; } - - public void setRepositoryContentIndexFactory( RepositoryContentIndexFactory indexFactory ) - { - this.indexFactory = indexFactory; - } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurge.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurge.java index 20c728f00..2580c3d96 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurge.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurge.java @@ -19,23 +19,21 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + import org.apache.maven.archiva.common.utils.VersionComparator; import org.apache.maven.archiva.common.utils.VersionUtil; -import org.apache.maven.archiva.database.ArtifactDAO; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.VersionedReference; import org.apache.maven.archiva.repository.ContentNotFoundException; import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; import org.apache.maven.archiva.repository.layout.LayoutException; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - /** * Purge the repository by retention count. Retain only the specified number of snapshots. * @@ -46,10 +44,10 @@ public class RetentionCountRepositoryPurge { private int retentionCount; - public RetentionCountRepositoryPurge( ManagedRepositoryContent repository, ArtifactDAO artifactDao, - int retentionCount, Map indices ) + public RetentionCountRepositoryPurge( ManagedRepositoryContent repository, + int retentionCount, List listeners ) { - super( repository, artifactDao, indices ); + super( repository, listeners ); this.retentionCount = retentionCount; } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java index 5d0869942..7335d4694 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java @@ -19,28 +19,16 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ +import java.io.File; +import java.io.IOException; + import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; -import org.apache.maven.archiva.database.ArchivaDatabaseException; -import org.apache.maven.archiva.database.ArtifactDAO; import org.apache.maven.archiva.model.ArchivaArtifact; import org.apache.maven.archiva.repository.ManagedRepositoryContent; -import org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory; -import org.codehaus.plexus.jdo.JdoFactory; +import org.apache.maven.archiva.repository.events.RepositoryListener; import org.codehaus.plexus.spring.PlexusInSpringTestCase; -import org.jpox.SchemaTool; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Properties; -import java.util.Map.Entry; - -import javax.jdo.PersistenceManager; -import javax.jdo.PersistenceManagerFactory; +import org.easymock.MockControl; /** * @author Maria Odea Ching @@ -74,74 +62,21 @@ public abstract class AbstractRepositoryPurgeTest private ManagedRepositoryContent repo; - protected ArtifactDAO dao; - protected RepositoryPurge repoPurge; + protected MockControl listenerControl; + + protected RepositoryListener listener; + + @Override protected void setUp() throws Exception { super.setUp(); + + listenerControl = MockControl.createControl( RepositoryListener.class ); - DefaultConfigurableJdoFactory jdoFactory = (DefaultConfigurableJdoFactory) lookup( JdoFactory.ROLE, "archiva" ); - assertEquals( DefaultConfigurableJdoFactory.class.getName(), jdoFactory.getClass().getName() ); - - jdoFactory.setPersistenceManagerFactoryClass( "org.jpox.PersistenceManagerFactoryImpl" ); - - jdoFactory.setDriverName( System.getProperty( "jdo.test.driver", "org.hsqldb.jdbcDriver" ) ); - jdoFactory.setUrl( System.getProperty( "jdo.test.url", "jdbc:hsqldb:mem:testdb" ) ); - - jdoFactory.setUserName( System.getProperty( "jdo.test.user", "sa" ) ); - - jdoFactory.setPassword( System.getProperty( "jdo.test.pass", "" ) ); - - jdoFactory.setProperty( "org.jpox.transactionIsolation", "READ_COMMITTED" ); - - jdoFactory.setProperty( "org.jpox.poid.transactionIsolation", "READ_COMMITTED" ); - - jdoFactory.setProperty( "org.jpox.autoCreateSchema", "true" ); - - jdoFactory.setProperty( "javax.jdo.option.RetainValues", "true" ); - - jdoFactory.setProperty( "javax.jdo.option.RestoreValues", "true" ); - - // jdoFactory.setProperty( "org.jpox.autoCreateColumns", "true" ); - - jdoFactory.setProperty( "org.jpox.validateTables", "true" ); - - jdoFactory.setProperty( "org.jpox.validateColumns", "true" ); - - jdoFactory.setProperty( "org.jpox.validateConstraints", "true" ); - - Properties properties = jdoFactory.getProperties(); - - for ( Entry entry : properties.entrySet() ) - { - System.setProperty( (String) entry.getKey(), (String) entry.getValue() ); - } - - URL jdoFileUrls[] = new URL[] { getClass().getResource( "/org/apache/maven/archiva/model/package.jdo" ) }; - - if ( ( jdoFileUrls == null ) || ( jdoFileUrls[0] == null ) ) - { - fail( "Unable to process test " + getName() + " - missing package.jdo." ); - } - - File propsFile = null; // intentional - boolean verbose = true; - - SchemaTool.deleteSchemaTables( jdoFileUrls, new URL[] {}, propsFile, verbose ); - SchemaTool.createSchemaTables( jdoFileUrls, new URL[] {}, propsFile, verbose, null ); - - PersistenceManagerFactory pmf = jdoFactory.getPersistenceManagerFactory(); - - assertNotNull( pmf ); - - PersistenceManager pm = pmf.getPersistenceManager(); - - pm.close(); - - dao = (ArtifactDAO) lookup( ArtifactDAO.class.getName(), "jdo" ); + listener = (RepositoryListener) listenerControl.getMock(); } @Override @@ -180,28 +115,6 @@ public abstract class AbstractRepositoryPurgeTest return repo; } - protected void populateDb( String groupId, String artifactId, List versions ) - throws ArchivaDatabaseException - { - for ( String version : versions ) - { - ArchivaArtifact artifact = dao.createArtifact( groupId, artifactId, version, "", "jar" ); - assertNotNull( artifact ); - artifact.getModel().setLastModified( new Date() ); - artifact.getModel().setOrigin( "test" ); - ArchivaArtifact savedArtifact = dao.saveArtifact( artifact ); - assertNotNull( savedArtifact ); - - //POM - artifact = dao.createArtifact( groupId, artifactId, version, "", "pom" ); - assertNotNull( artifact ); - artifact.getModel().setLastModified( new Date() ); - artifact.getModel().setOrigin( "test" ); - savedArtifact = dao.saveArtifact( artifact ); - assertNotNull( savedArtifact ); - } - } - protected void assertDeleted( String path ) { assertFalse( "File should have been deleted: " + path, new File( path ).exists() ); @@ -230,15 +143,9 @@ public abstract class AbstractRepositoryPurgeTest return testDir.getAbsolutePath(); } - - protected void populateDbForTestOrderOfDeletion() - throws Exception + + protected ArchivaArtifact createArtifact( String groupId, String artifactId, String version, String type ) { - List versions = new ArrayList(); - versions.add( "1.1.2-20070427.065136-1" ); - versions.add( "1.1.2-20070506.163513-2" ); - versions.add( "1.1.2-20070615.105019-3" ); - - populateDb( "org.apache.maven.plugins", "maven-assembly-plugin", versions ); + return new ArchivaArtifact( groupId, artifactId, version, null, type ); } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java index b133c54d3..50956d265 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/CleanupReleasedSnapshotsRepositoryPurgeTest.java @@ -19,21 +19,18 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ +import java.io.File; +import java.util.Collections; + import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.Configuration; -import org.apache.maven.archiva.consumers.core.repository.stubs.LuceneRepositoryContentIndexStub; -import org.apache.maven.archiva.database.ArchivaDatabaseException; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; import org.apache.maven.archiva.repository.RepositoryContentFactory; +import org.apache.maven.archiva.repository.events.RepositoryListener; import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.custommonkey.xmlunit.XMLAssert; +import org.easymock.MockControl; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; /** * @author Maria Odea Ching @@ -42,6 +39,8 @@ public class CleanupReleasedSnapshotsRepositoryPurgeTest extends AbstractRepositoryPurgeTest { private ArchivaConfiguration archivaConfiguration; + + private MockControl listenerControl; public static final String PATH_TO_RELEASED_SNAPSHOT_IN_DIFF_REPO = "org/apache/archiva/released-artifact-in-diff-repo/1.0-SNAPSHOT/released-artifact-in-diff-repo-1.0-SNAPSHOT.jar"; @@ -49,40 +48,45 @@ public class CleanupReleasedSnapshotsRepositoryPurgeTest public static final String PATH_TO_HIGHER_SNAPSHOT_EXISTS_IN_SAME_REPO = "org/apache/maven/plugins/maven-source-plugin/2.0.3-SNAPSHOT/maven-source-plugin-2.0.3-SNAPSHOT.jar"; public static final String PATH_TO_RELEASED_SNAPSHOT_IN_SAME_REPO = "org/apache/maven/plugins/maven-plugin-plugin/2.3-SNAPSHOT/maven-plugin-plugin-2.3-SNAPSHOT.jar"; + + private RepositoryListener listener; protected void setUp() throws Exception { - super.setUp(); - - Map map = new HashMap(); - map.put( "filecontent", new LuceneRepositoryContentIndexStub() ); - map.put( "hashcodes", new LuceneRepositoryContentIndexStub() ); - map.put( "bytecode", new LuceneRepositoryContentIndexStub() ); + super.setUp(); MetadataTools metadataTools = (MetadataTools) lookup( MetadataTools.class ); RepositoryContentFactory factory = (RepositoryContentFactory) lookup( RepositoryContentFactory.class, "cleanup-released-snapshots"); archivaConfiguration = (ArchivaConfiguration) lookup( ArchivaConfiguration.class, "cleanup-released-snapshots" ); - + + listenerControl = MockControl.createControl( RepositoryListener.class ); + + listener = (RepositoryListener) listenerControl.getMock(); repoPurge = - new CleanupReleasedSnapshotsRepositoryPurge( getRepository(), dao, metadataTools, map, archivaConfiguration, factory ); + new CleanupReleasedSnapshotsRepositoryPurge( getRepository(), metadataTools, archivaConfiguration, factory, + Collections.singletonList( listener ) ); } public void testReleasedSnapshotsExistsInSameRepo() throws Exception { - Configuration config = archivaConfiguration.getConfiguration(); config.removeManagedRepository( config.findManagedRepositoryById( TEST_REPO_ID ) ); config.addManagedRepository( getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ) ); - populateReleasedSnapshotsTest(); - String repoRoot = prepareTestRepos(); + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-plugin-plugin", + "2.3-SNAPSHOT", "maven-plugin" ) ); + listenerControl.replay(); + repoPurge.process( CleanupReleasedSnapshotsRepositoryPurgeTest.PATH_TO_RELEASED_SNAPSHOT_IN_SAME_REPO ); + + listenerControl.verify(); String projectRoot = repoRoot + "/org/apache/maven/plugins/maven-plugin-plugin"; @@ -130,12 +134,18 @@ public class CleanupReleasedSnapshotsRepositoryPurgeTest config.addManagedRepository( getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ) ); config.addManagedRepository( getRepoConfiguration( RELEASES_TEST_REPO_ID, RELEASES_TEST_REPO_NAME ) ); - populateReleasedSnapshotsTestInDiffRepo(); - String repoRoot = prepareTestRepos(); + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.archiva", + "released-artifact-in-diff-repo", "1.0-SNAPSHOT", + "jar" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_RELEASED_SNAPSHOT_IN_DIFF_REPO ); + listenerControl.verify(); + String projectRoot = repoRoot + "/org/apache/archiva/released-artifact-in-diff-repo"; // check if the snapshot was removed @@ -168,11 +178,14 @@ public class CleanupReleasedSnapshotsRepositoryPurgeTest config.removeManagedRepository( config.findManagedRepositoryById( TEST_REPO_ID ) ); config.addManagedRepository( getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ) ); - populateHigherSnapshotExistsTest(); - String repoRoot = prepareTestRepos(); + // test listeners for the correct artifacts - no deletions + listenerControl.replay(); + repoPurge.process( CleanupReleasedSnapshotsRepositoryPurgeTest.PATH_TO_HIGHER_SNAPSHOT_EXISTS_IN_SAME_REPO ); + + listenerControl.verify(); String projectRoot = repoRoot + "/org/apache/maven/plugins/maven-source-plugin"; @@ -207,32 +220,4 @@ public class CleanupReleasedSnapshotsRepositoryPurgeTest "//metadata/versioning/versions/version", metadataXml ); XMLAssert.assertXpathEvaluatesTo( "20070427033345", "//metadata/versioning/lastUpdated", metadataXml ); } - - private void populateReleasedSnapshotsTest() - throws ArchivaDatabaseException - { - List versions = new ArrayList(); - versions.add( "2.3-SNAPSHOT" ); - - populateDb( "org.apache.maven.plugins", "maven-plugin-plugin", versions ); - } - - private void populateHigherSnapshotExistsTest() - throws Exception - { - List versions = new ArrayList(); - versions.add( "2.0.3-SNAPSHOT" ); - - populateDb( "org.apache.maven.plugins", "maven-source-plugin", versions ); - } - - private void populateReleasedSnapshotsTestInDiffRepo() - throws ArchivaDatabaseException - { - List versions = new ArrayList(); - versions.add( "1.0-SNAPSHOT" ); - - populateDb( "org.apache.archiva", "released-artifact-in-diff-repo", versions ); - } - } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurgeTest.java index 5d51d71aa..48f630e25 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/DaysOldRepositoryPurgeTest.java @@ -19,17 +19,14 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ -import org.apache.commons.lang.time.DateUtils; -import org.apache.maven.archiva.consumers.core.repository.stubs.LuceneRepositoryContentIndexStub; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; - import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; -import java.util.HashMap; +import java.util.Collections; import java.util.List; -import java.util.Map; + +import org.apache.commons.lang.time.DateUtils; /** * @author Maria Odea Ching @@ -37,9 +34,6 @@ import java.util.Map; public class DaysOldRepositoryPurgeTest extends AbstractRepositoryPurgeTest { - - private Map map; - private static final String[] extensions = new String[] { "-5.jar", "-5.pom", "-6.jar", "-6.pom", "-7.jar", "-7.pom" }; @@ -55,12 +49,6 @@ public class DaysOldRepositoryPurgeTest private String sec; - protected void setUp() - throws Exception - { - super.setUp(); - } - private void setLastModified( String dirPath, long lastModified ) { File dir = new File( dirPath ); @@ -74,14 +62,11 @@ public class DaysOldRepositoryPurgeTest public void testByLastModified() throws Exception { - map = new HashMap(); - map.put( "filecontent", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "hashcodes", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "bytecode", new LuceneRepositoryContentIndexStub( 2 ) ); - repoPurge = - new DaysOldRepositoryPurge( getRepository(), dao, getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getDaysOlder(), - getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), map ); + new DaysOldRepositoryPurge( getRepository(), + getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getDaysOlder(), + getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), + Collections.singletonList( listener ) ); String repoRoot = prepareTestRepos(); @@ -89,9 +74,16 @@ public class DaysOldRepositoryPurgeTest setLastModified( projectRoot + "/2.2-SNAPSHOT/", 1179382029 ); - populateDbForTestByLastModified(); - + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-install-plugin", + "2.2-SNAPSHOT", "maven-plugin" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-install-plugin", + "2.2-SNAPSHOT", "pom" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_BY_DAYS_OLD_ARTIFACT ); + + listenerControl.verify(); assertDeleted( projectRoot + "/2.2-SNAPSHOT/maven-install-plugin-2.2-SNAPSHOT.jar" ); assertDeleted( projectRoot + "/2.2-SNAPSHOT/maven-install-plugin-2.2-SNAPSHOT.jar.md5" ); @@ -119,14 +111,10 @@ public class DaysOldRepositoryPurgeTest public void testOrderOfDeletion() throws Exception { - map = new HashMap(); - map.put( "filecontent", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "hashcodes", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "bytecode", new LuceneRepositoryContentIndexStub( 2 ) ); - repoPurge = - new DaysOldRepositoryPurge( getRepository(), dao, getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getDaysOlder(), - getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), map ); + new DaysOldRepositoryPurge( getRepository(), getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getDaysOlder(), + getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), + Collections.singletonList( listener ) ); String repoRoot = prepareTestRepos(); @@ -134,10 +122,17 @@ public class DaysOldRepositoryPurgeTest setLastModified( projectRoot + "/1.1.2-SNAPSHOT/", 1179382029 ); - populateDbForTestOrderOfDeletion(); - + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-assembly-plugin", + "1.1.2-20070427.065136-1", "maven-plugin" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-assembly-plugin", + "1.1.2-20070427.065136-1", "pom" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_TEST_ORDER_OF_DELETION ); + listenerControl.verify(); + assertDeleted( projectRoot + "/1.1.2-SNAPSHOT/maven-assembly-plugin-1.1.2-20070427.065136-1.jar" ); assertDeleted( projectRoot + "/1.1.2-SNAPSHOT/maven-assembly-plugin-1.1.2-20070427.065136-1.jar.sha1" ); assertDeleted( projectRoot + "/1.1.2-SNAPSHOT/maven-assembly-plugin-1.1.2-20070427.065136-1.jar.md5" ); @@ -164,14 +159,11 @@ public class DaysOldRepositoryPurgeTest public void testMetadataDrivenSnapshots() throws Exception { - map = new HashMap(); - map.put( "filecontent", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "hashcodes", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "bytecode", new LuceneRepositoryContentIndexStub( 2 ) ); - repoPurge = - new DaysOldRepositoryPurge( getRepository(), dao, getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getDaysOlder(), - getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), map ); + new DaysOldRepositoryPurge( getRepository(), + getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getDaysOlder(), + getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), + Collections.singletonList( listener ) ); String repoRoot = prepareTestRepos(); @@ -221,10 +213,17 @@ public class DaysOldRepositoryPurgeTest versions.add( "1.4.3-" + year + mon + day + "." + hr + min + sec + "-7" ); versions.add( "1.4.3-SNAPSHOT" ); - populateDb( "org.codehaus.plexus", "plexus-utils", versions ); - + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.codehaus.plexus", "plexus-utils", + "1.4.3-20070113.163208-4", "jar" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.codehaus.plexus", "plexus-utils", + "1.4.3-20070113.163208-4", "pom" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_BY_DAYS_OLD_METADATA_DRIVEN_ARTIFACT ); + listenerControl.verify(); + // this should be deleted since the filename version (timestamp) is older than // 100 days even if the last modified date was <100 days ago assertDeleted( versionRoot + "/plexus-utils-1.4.3-20070113.163208-4.jar" ); @@ -260,15 +259,4 @@ public class DaysOldRepositoryPurgeTest super.tearDown(); repoPurge = null; } - - private void populateDbForTestByLastModified() - throws Exception - { - List versions = new ArrayList(); - versions.add( "2.2-20061118.060401-2" ); - versions.add( "2.2-20070513.034619-5" ); - versions.add( "2.2-SNAPSHOT" ); - - populateDb( "org.apache.maven.plugins", "maven-install-plugin", versions ); - } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.java index ca8b63f6c..f7e1c5a15 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.java @@ -19,6 +19,8 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ +import java.io.File; + import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.common.utils.BaseFile; import org.apache.maven.archiva.configuration.ArchivaConfiguration; @@ -27,15 +29,9 @@ import org.apache.maven.archiva.configuration.FileType; import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer; -import org.apache.maven.archiva.consumers.core.repository.stubs.LuceneRepositoryContentIndexFactoryStub; -import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.repository.scanner.functors.ConsumerWantsFilePredicate; import org.custommonkey.xmlunit.XMLAssert; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - /** * @author Maria Odea Ching */ @@ -99,13 +95,6 @@ public class RepositoryPurgeConsumerTest (KnownRepositoryContentConsumer) lookup( KnownRepositoryContentConsumer.class, "repo-purge-consumer-by-retention-count" ); - LuceneRepositoryContentIndexFactoryStub indexFactory = new LuceneRepositoryContentIndexFactoryStub(); - indexFactory.setExpectedRecordsSize( 2 ); - - ( (RepositoryPurgeConsumer) repoPurgeConsumer ).setRepositoryContentIndexFactory( indexFactory ); - - populateDbForRetentionCountTest(); - ManagedRepositoryConfiguration repoConfiguration = getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ); repoConfiguration.setDaysOlder( 0 ); // force days older off to allow retention count purge to execute. repoConfiguration.setRetentionCount( TEST_RETENTION_COUNT ); @@ -163,17 +152,10 @@ public class RepositoryPurgeConsumerTest public void testConsumerByDaysOld() throws Exception { - populateDbForDaysOldTest(); - KnownRepositoryContentConsumer repoPurgeConsumer = (KnownRepositoryContentConsumer) lookup( KnownRepositoryContentConsumer.class, "repo-purge-consumer-by-days-old" ); - LuceneRepositoryContentIndexFactoryStub indexFactory = new LuceneRepositoryContentIndexFactoryStub(); - indexFactory.setExpectedRecordsSize( 2 ); - - ( (RepositoryPurgeConsumer) repoPurgeConsumer ).setRepositoryContentIndexFactory( indexFactory ); - ManagedRepositoryConfiguration repoConfiguration = getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ); repoConfiguration.setDaysOlder( TEST_DAYS_OLDER ); addRepoToConfiguration( "days-old", repoConfiguration ); @@ -222,8 +204,6 @@ public class RepositoryPurgeConsumerTest (KnownRepositoryContentConsumer) lookup( KnownRepositoryContentConsumer.class, "repo-purge-consumer-by-retention-count" ); - populateDbForReleasedSnapshotsTest(); - ManagedRepositoryConfiguration repoConfiguration = getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ); repoConfiguration.setDeleteReleasedSnapshots( false ); // Set to NOT delete released snapshots. addRepoToConfiguration( "retention-count", repoConfiguration ); @@ -265,8 +245,6 @@ public class RepositoryPurgeConsumerTest (KnownRepositoryContentConsumer) lookup( KnownRepositoryContentConsumer.class, "repo-purge-consumer-by-days-old" ); - populateDbForReleasedSnapshotsTest(); - ManagedRepositoryConfiguration repoConfiguration = getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ); repoConfiguration.setDeleteReleasedSnapshots( true ); addRepoToConfiguration( "days-old", repoConfiguration ); @@ -301,34 +279,4 @@ public class RepositoryPurgeConsumerTest "//metadata/versioning/versions/version", metadataXml ); XMLAssert.assertXpathEvaluatesTo( "20070315032817", "//metadata/versioning/lastUpdated", metadataXml ); } - - public void populateDbForRetentionCountTest() - throws ArchivaDatabaseException - { - List versions = new ArrayList(); - versions.add( "1.0RC1-20070504.153317-1" ); - versions.add( "1.0RC1-20070504.160758-2" ); - versions.add( "1.0RC1-20070505.090015-3" ); - versions.add( "1.0RC1-20070506.090132-4" ); - - populateDb( "org.jruby.plugins", "jruby-rake-plugin", versions ); - } - - private void populateDbForDaysOldTest() - throws ArchivaDatabaseException - { - List versions = new ArrayList(); - versions.add( "2.2-SNAPSHOT" ); - - populateDb( "org.apache.maven.plugins", "maven-install-plugin", versions ); - } - - public void populateDbForReleasedSnapshotsTest() - throws ArchivaDatabaseException - { - List versions = new ArrayList(); - versions.add( "2.3-SNAPSHOT" ); - - populateDb( "org.apache.maven.plugins", "maven-plugin-plugin", versions ); - } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurgeTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurgeTest.java index f67720ccf..e38f712d8 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurgeTest.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/RetentionCountRepositoryPurgeTest.java @@ -1,5 +1,7 @@ package org.apache.maven.archiva.consumers.core.repository; +import java.util.Collections; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,14 +21,6 @@ package org.apache.maven.archiva.consumers.core.repository; * under the License. */ -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.maven.archiva.consumers.core.repository.stubs.LuceneRepositoryContentIndexStub; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; - /** * Test RetentionsCountRepositoryPurgeTest * @@ -41,13 +35,11 @@ public class RetentionCountRepositoryPurgeTest { super.setUp(); - Map map = new HashMap(); - map.put( "filecontent", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "hashcodes", new LuceneRepositoryContentIndexStub( 2 ) ); - map.put( "bytecode", new LuceneRepositoryContentIndexStub( 2 ) ); - - repoPurge = new RetentionCountRepositoryPurge( getRepository(), dao, - getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), map ); + repoPurge = + new RetentionCountRepositoryPurge( + getRepository(), + getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ).getRetentionCount(), + Collections.singletonList( listener ) ); } /** @@ -58,12 +50,23 @@ public class RetentionCountRepositoryPurgeTest public void testIfAJarWasFound() throws Exception { - populateIfJarWasFoundDb(); - String repoRoot = prepareTestRepos(); + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.jruby.plugins", "jruby-rake-plugin", + "1.0RC1-20070504.153317-1", "jar" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.jruby.plugins", "jruby-rake-plugin", + "1.0RC1-20070504.153317-1", "pom" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.jruby.plugins", "jruby-rake-plugin", + "1.0RC1-20070504.160758-2", "jar" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.jruby.plugins", "jruby-rake-plugin", + "1.0RC1-20070504.160758-2", "pom" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_BY_RETENTION_COUNT_ARTIFACT ); + listenerControl.verify(); + String versionRoot = repoRoot + "/org/jruby/plugins/jruby-rake-plugin/1.0RC1-SNAPSHOT"; // assert if removed from repo @@ -105,11 +108,18 @@ public class RetentionCountRepositoryPurgeTest public void testIfAPomWasFound() throws Exception { - populateIfPomWasFoundDb(); - String repoRoot = prepareTestRepos(); + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.codehaus.castor", "castor-anttasks", + "1.1.2-20070427.065136-1", "jar" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.codehaus.castor", "castor-anttasks", + "1.1.2-20070427.065136-1", "pom" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_BY_RETENTION_COUNT_POM ); + + listenerControl.verify(); String versionRoot = repoRoot + "/org/codehaus/castor/castor-anttasks/1.1.2-SNAPSHOT"; @@ -146,12 +156,19 @@ public class RetentionCountRepositoryPurgeTest public void testOrderOfDeletion() throws Exception { - populateDbForTestOrderOfDeletion(); - String repoRoot = prepareTestRepos(); + // test listeners for the correct artifacts + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-assembly-plugin", + "1.1.2-20070427.065136-1", "maven-plugin" ) ); + listener.deleteArtifact( getRepository(), createArtifact( "org.apache.maven.plugins", "maven-assembly-plugin", + "1.1.2-20070427.065136-1", "pom" ) ); + listenerControl.replay(); + repoPurge.process( PATH_TO_TEST_ORDER_OF_DELETION ); + listenerControl.verify(); + String versionRoot = repoRoot + "/org/apache/maven/plugins/maven-assembly-plugin/1.1.2-SNAPSHOT"; @@ -177,27 +194,4 @@ public class RetentionCountRepositoryPurgeTest assertExists( versionRoot + "/maven-assembly-plugin-1.1.2-20070615.105019-3.pom.sha1" ); assertExists( versionRoot + "/maven-assembly-plugin-1.1.2-20070615.105019-3.pom.md5" ); } - - public void populateIfJarWasFoundDb() - throws Exception - { - List versions = new ArrayList(); - versions.add( "1.0RC1-20070504.153317-1" ); - versions.add( "1.0RC1-20070504.160758-2" ); - versions.add( "1.0RC1-20070505.090015-3" ); - versions.add( "1.0RC1-20070506.090132-4" ); - - populateDb( "org.jruby.plugins", "jruby-rake-plugin", versions ); - } - - public void populateIfPomWasFoundDb() - throws Exception - { - List versions = new ArrayList(); - versions.add( "1.1.2-20070427.065136-1" ); - versions.add( "1.1.2-20070615.105019-3" ); - versions.add( "1.1.2-20070506.163513-2" ); - - populateDb( "org.codehaus.castor", "castor-anttasks", versions ); - } } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexFactoryStub.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexFactoryStub.java deleted file mode 100644 index f1958abe9..000000000 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexFactoryStub.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.apache.maven.archiva.consumers.core.repository.stubs; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; -import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory; - -/** - * LuceneRepositoryContenIndexFactoryStub - * - * @author Maria Odea Ching - * @version - */ -public class LuceneRepositoryContentIndexFactoryStub - implements RepositoryContentIndexFactory -{ - - private int expectedRecordsSize = 0; - - public RepositoryContentIndex createBytecodeIndex( ManagedRepositoryConfiguration repository ) - { - // TODO Auto-generated method stub - return new LuceneRepositoryContentIndexStub( expectedRecordsSize ); - } - - public RepositoryContentIndex createFileContentIndex( ManagedRepositoryConfiguration repository ) - { - // TODO Auto-generated method stub - return new LuceneRepositoryContentIndexStub( expectedRecordsSize ); - } - - public RepositoryContentIndex createHashcodeIndex( ManagedRepositoryConfiguration repository ) - { - // TODO Auto-generated method stub - return new LuceneRepositoryContentIndexStub( expectedRecordsSize ); - } - - public void setExpectedRecordsSize( int size ) - { - expectedRecordsSize = size; - } -} diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexStub.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexStub.java deleted file mode 100644 index bd891e17b..000000000 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/maven/archiva/consumers/core/repository/stubs/LuceneRepositoryContentIndexStub.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.apache.maven.archiva.consumers.core.repository.stubs; - -/* - * 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.Collection; - -import junit.framework.Assert; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.queryParser.QueryParser; -import org.apache.lucene.search.Searchable; -import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; -import org.apache.maven.archiva.indexer.RepositoryContentIndex; -import org.apache.maven.archiva.indexer.RepositoryIndexException; -import org.apache.maven.archiva.indexer.RepositoryIndexSearchException; -import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter; -import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord; - -/** - * @author Maria Odea Ching - * @version - */ -public class LuceneRepositoryContentIndexStub - implements RepositoryContentIndex -{ - private int expectedRecordsSize; - - public LuceneRepositoryContentIndexStub() - { - - } - - public LuceneRepositoryContentIndexStub( int size ) - { - expectedRecordsSize = size; - } - - public void deleteRecords( Collection records ) - throws RepositoryIndexException - { - Assert.assertEquals( expectedRecordsSize, records.size() ); - } - - public boolean exists() - throws RepositoryIndexException - { - // TODO Auto-generated method stub - return false; - } - - public Collection getAllRecordKeys() - throws RepositoryIndexException - { - // TODO Auto-generated method stub - return null; - } - - public Analyzer getAnalyzer() - { - // TODO Auto-generated method stub - return null; - } - - public LuceneEntryConverter getEntryConverter() - { - // TODO Auto-generated method stub - return null; - } - - public String getId() - { - // TODO Auto-generated method stub - return null; - } - - public File getIndexDirectory() - { - // TODO Auto-generated method stub - return null; - } - - public QueryParser getQueryParser() - { - // TODO Auto-generated method stub - return null; - } - - public ManagedRepositoryConfiguration getRepository() - { - // TODO Auto-generated method stub - return null; - } - - public Searchable getSearchable() - throws RepositoryIndexSearchException - { - // TODO Auto-generated method stub - return null; - } - - public void indexRecords( Collection records ) - throws RepositoryIndexException - { - // TODO Auto-generated method stub - - } - - public void modifyRecord( LuceneRepositoryContentRecord record ) - throws RepositoryIndexException - { - // TODO Auto-generated method stub - - } - - public void modifyRecords( Collection records ) - throws RepositoryIndexException - { - // TODO Auto-generated method stub - - } - - public void deleteRecord( LuceneRepositoryContentRecord record ) - throws RepositoryIndexException - { - // TODO Auto-generated method stub - - } - -} diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.xml index 52e286e66..63f9b0d4d 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.xml +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/org/apache/maven/archiva/consumers/core/repository/RepositoryPurgeConsumerTest.xml @@ -31,10 +31,6 @@ org.apache.maven.archiva.configuration.ArchivaConfiguration retention-count - - org.apache.maven.archiva.database.ArchivaDAO - jdo - org.apache.maven.archiva.repository.RepositoryContentFactory retention-count @@ -46,11 +42,6 @@ org.apache.maven.archiva.configuration.FileTypes retention-count - - org.apache.maven.archiva.indexer.RepositoryContentIndexFactory - lucene - indexFactory - repository-purge @@ -123,10 +114,6 @@ org.apache.maven.archiva.configuration.ArchivaConfiguration days-old - - org.apache.maven.archiva.database.ArchivaDAO - jdo - org.apache.maven.archiva.repository.RepositoryContentFactory days-old @@ -138,11 +125,6 @@ org.apache.maven.archiva.configuration.FileTypes days-old - - org.apache.maven.archiva.indexer.RepositoryContentIndexFactory - lucene - indexFactory - repository-purge @@ -203,106 +185,5 @@ - - - - - org.apache.maven.archiva.database.ArchivaDAO - jdo - org.apache.maven.archiva.database.jdo.JdoArchivaDAO - - - org.apache.maven.archiva.database.jdo.JdoAccess - archiva - - - org.apache.maven.archiva.database.ArtifactDAO - jdo - - - org.apache.maven.archiva.database.ProjectModelDAO - jdo - - - org.apache.maven.archiva.database.RepositoryProblemDAO - jdo - - - - - org.apache.maven.archiva.database.ArtifactDAO - jdo - org.apache.maven.archiva.database.jdo.JdoArtifactDAO - - - org.apache.maven.archiva.database.jdo.JdoAccess - archiva - - - - - org.apache.maven.archiva.database.ProjectModelDAO - jdo - org.apache.maven.archiva.database.jdo.JdoProjectModelDAO - - - org.apache.maven.archiva.database.jdo.JdoAccess - archiva - - - - - org.apache.maven.archiva.database.RepositoryProblemDAO - jdo - org.apache.maven.archiva.database.jdo.JdoRepositoryProblemDAO - - - org.apache.maven.archiva.database.jdo.JdoAccess - archiva - - - - - - - - org.apache.maven.archiva.database.jdo.JdoAccess - archiva - org.apache.maven.archiva.database.jdo.JdoAccess - - - org.codehaus.plexus.jdo.JdoFactory - archiva - - - - - - - org.codehaus.plexus.jdo.JdoFactory - archiva - org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory - - org.jpox.PersistenceManagerFactoryImpl - org.hsqldb.jdbcDriver - sa - - jdbc:hsqldb:mem:testdb - - - javax.jdo.PersistenceManagerFactoryClass - org.jpox.PersistenceManagerFactoryImpl - - - - - - - - org.apache.maven.archiva.indexer.RepositoryContentIndexFactory - lucene - org.apache.maven.archiva.consumers.core.repository.stubs.LuceneRepositoryContentIndexFactoryStub - - diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java index 3bb2b8677..1cdcb6033 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java @@ -21,6 +21,7 @@ package org.apache.maven.archiva.consumers.lucene; import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; @@ -98,9 +99,7 @@ public class IndexContentConsumer * @plexus.requirement role-hint="lucene" */ private RepositoryContentIndexFactory indexFactory; - - private List propertyNameTriggers = new ArrayList(); - + private List includes = new ArrayList(); private RepositoryContentIndex index; @@ -198,7 +197,7 @@ public class IndexContentConsumer public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) { - if ( propertyNameTriggers.contains( propertyName ) ) + if ( ConfigurationNames.isRepositoryScanning( propertyName ) ) { initIncludes(); } @@ -219,13 +218,6 @@ public class IndexContentConsumer public void initialize() throws InitializationException { - propertyNameTriggers = new ArrayList(); - propertyNameTriggers.add( "repositoryScanning" ); - propertyNameTriggers.add( "fileTypes" ); - propertyNameTriggers.add( "fileType" ); - propertyNameTriggers.add( "patterns" ); - propertyNameTriggers.add( "pattern" ); - configuration.addChangeListener( this ); initIncludes(); diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListener.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListener.java new file mode 100644 index 000000000..80aaf14d2 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListener.java @@ -0,0 +1,70 @@ +package org.apache.maven.archiva.indexer; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord; +import org.apache.maven.archiva.indexer.filecontent.FileContentRecord; +import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecord; +import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; + +/** + * Process repository management events and respond appropriately. + * + * @todo creating index instances every time is inefficient, the plugin needs to have a repository context to operate in + * @plexus.component role="org.apache.maven.archiva.repository.events.RepositoryListener" role-hint="indexer" + */ +public class RepositoryContentIndexEventListener + implements RepositoryListener +{ + /** + * @plexus.requirement role-hint="lucene" + */ + private RepositoryContentIndexFactory indexFactory; + + public void deleteArtifact( ManagedRepositoryContent repository, ArchivaArtifact artifact ) + { + try + { + RepositoryContentIndex index = indexFactory.createFileContentIndex( repository.getRepository() ); + FileContentRecord fileContentRecord = new FileContentRecord(); + fileContentRecord.setRepositoryId( repository.getRepository().getId() ); + fileContentRecord.setFilename( repository.toPath( artifact ) ); + index.deleteRecord( fileContentRecord ); + + index = indexFactory.createHashcodeIndex( repository.getRepository() ); + HashcodesRecord hashcodesRecord = new HashcodesRecord(); + fileContentRecord.setRepositoryId( repository.getRepository().getId() ); + hashcodesRecord.setArtifact( artifact ); + index.deleteRecord( hashcodesRecord ); + + index = indexFactory.createBytecodeIndex( repository.getRepository() ); + BytecodeRecord bytecodeRecord = new BytecodeRecord(); + fileContentRecord.setRepositoryId( repository.getRepository().getId() ); + bytecodeRecord.setArtifact( artifact ); + index.deleteRecord( bytecodeRecord ); + } + catch ( RepositoryIndexException e ) + { + // Ignore + } + } +} diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java index 63e21151c..52596ff9f 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java @@ -69,4 +69,21 @@ public interface CrossRepositorySearch * @return the results. */ public SearchResults searchForChecksum( String principal, List selectedRepos, String checksum, SearchResultLimits limits ); + + /** + * Search for a specific artifact matching the given field values. The search is performed on the bytecode + * index/indices. + * + * @param principal + * @param selectedRepos repository to be searched + * @param groupId groupId to be matched + * @param artifactId artifactId to be matched + * @param version version to be matched + * @param className Java class or package name to be matched + * @param limits the limits to apply to the search results + * @return + */ + public SearchResults executeFilteredSearch( String principal, List selectedRepos, String groupId, + String artifactId, String version, String className, + SearchResultLimits limits ); } diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java index ede311346..a21c4fa6b 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.lucene.document.Document; +import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.MultiFieldQueryParser; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; @@ -32,16 +33,20 @@ import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Filter; import org.apache.lucene.search.Hits; import org.apache.lucene.search.MultiSearcher; +import org.apache.lucene.search.Query; import org.apache.lucene.search.QueryWrapperFilter; import org.apache.lucene.search.Searchable; +import org.apache.lucene.search.TermQuery; import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.indexer.ArtifactKeys; import org.apache.maven.archiva.indexer.RepositoryContentIndex; import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory; import org.apache.maven.archiva.indexer.RepositoryIndexException; import org.apache.maven.archiva.indexer.RepositoryIndexSearchException; import org.apache.maven.archiva.indexer.bytecode.BytecodeHandlers; +import org.apache.maven.archiva.indexer.bytecode.BytecodeKeys; import org.apache.maven.archiva.indexer.filecontent.FileContentHandlers; import org.apache.maven.archiva.indexer.hashcodes.HashcodesHandlers; import org.apache.maven.archiva.indexer.hashcodes.HashcodesKeys; @@ -57,7 +62,7 @@ import org.slf4j.LoggerFactory; /** * DefaultCrossRepositorySearch - * + * * @author Joakim Erdfelt * @version $Id$ * @plexus.component role="org.apache.maven.archiva.indexer.search.CrossRepositorySearch" role-hint="default" @@ -66,12 +71,12 @@ public class DefaultCrossRepositorySearch implements CrossRepositorySearch, RegistryListener, Initializable { private Logger log = LoggerFactory.getLogger( DefaultCrossRepositorySearch.class ); - + /** * @plexus.requirement role-hint="lucene" */ private RepositoryContentIndexFactory indexFactory; - + /** * @plexus.requirement */ @@ -79,14 +84,61 @@ public class DefaultCrossRepositorySearch private List localIndexedRepositories = new ArrayList(); - public SearchResults searchForChecksum( String principal, List selectedRepos, String checksum, SearchResultLimits limits ) + public SearchResults executeFilteredSearch( String principal, List selectedRepos, String groupId, + String artifactId, String version, String className, + SearchResultLimits limits ) + { + List indexes = getBytecodeIndexes( principal, selectedRepos ); + SearchResults results = new SearchResults(); + BooleanQuery booleanQuery = new BooleanQuery(); + + if ( groupId != null && groupId.length() > 0 ) + { + parseAndAdd( booleanQuery, ArtifactKeys.GROUPID, groupId, "\\.|-" ); + } + + if ( artifactId != null && artifactId.length() > 0 ) + { + parseAndAdd( booleanQuery, ArtifactKeys.ARTIFACTID, artifactId, "\\.|-" ); + } + + if ( version != null && version.length() > 0 ) + { + parseAndAdd( booleanQuery, ArtifactKeys.VERSION, version, "\\.|-" ); + } + + if ( className != null && className.length() > 0 ) + { + + try + { + QueryParser parser = + new MultiFieldQueryParser( new String[] { BytecodeKeys.CLASSES, BytecodeKeys.FILES, + BytecodeKeys.METHODS }, new BytecodeHandlers().getAnalyzer() ); + booleanQuery.add( parser.parse( className ), BooleanClause.Occur.MUST ); + } + catch ( ParseException e ) + { + + } + } + + LuceneQuery query = new LuceneQuery( booleanQuery ); + results = searchAll( query, limits, indexes, null ); + results.getRepositories().add( this.localIndexedRepositories ); + + return results; + } + + public SearchResults searchForChecksum( String principal, List selectedRepos, String checksum, + SearchResultLimits limits ) { List indexes = getHashcodeIndexes( principal, selectedRepos ); try { QueryParser parser = new MultiFieldQueryParser( new String[]{HashcodesKeys.MD5, HashcodesKeys.SHA1}, - new HashcodesHandlers().getAnalyzer() ); + new HashcodesHandlers().getAnalyzer() ); LuceneQuery query = new LuceneQuery( parser.parse( checksum ) ); SearchResults results = searchAll( query, limits, indexes, null ); results.getRepositories().addAll( this.localIndexedRepositories ); @@ -124,23 +176,22 @@ public class DefaultCrossRepositorySearch return new SearchResults(); } - public SearchResults searchForTerm( String principal, List selectedRepos, String term, SearchResultLimits limits ) { return searchForTerm( principal, selectedRepos, term, limits, null ); } - + public SearchResults searchForTerm( String principal, List selectedRepos, String term, SearchResultLimits limits, List previousSearchTerms ) { List indexes = getFileContentIndexes( principal, selectedRepos ); - + try { QueryParser parser = new FileContentHandlers().getQueryParser(); LuceneQuery query = null; SearchResults results = null; - if( previousSearchTerms == null || previousSearchTerms.isEmpty() ) + if ( previousSearchTerms == null || previousSearchTerms.isEmpty() ) { query = new LuceneQuery( parser.parse( term ) ); results = searchAll( query, limits, indexes, null ); @@ -149,17 +200,17 @@ public class DefaultCrossRepositorySearch { // AND the previous search terms BooleanQuery booleanQuery = new BooleanQuery(); - for( String previousSearchTerm : previousSearchTerms ) + for ( String previousSearchTerm : previousSearchTerms ) { booleanQuery.add( parser.parse( previousSearchTerm ), BooleanClause.Occur.MUST ); } - - query = new LuceneQuery( booleanQuery ); + + query = new LuceneQuery( booleanQuery ); Filter filter = new QueryWrapperFilter( parser.parse( term ) ); results = searchAll( query, limits, indexes, filter ); - } + } results.getRepositories().addAll( this.localIndexedRepositories ); - + return results; } catch ( ParseException e ) @@ -168,9 +219,9 @@ public class DefaultCrossRepositorySearch } // empty results. - return new SearchResults(); + return new SearchResults(); } - + private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List indexes, Filter filter ) { org.apache.lucene.search.Query specificQuery = luceneQuery.getLuceneQuery(); @@ -203,7 +254,7 @@ public class DefaultCrossRepositorySearch // Perform the search. Hits hits = null; - if( filter != null ) + if ( filter != null ) { hits = searcher.search( specificQuery, filter ); } @@ -355,7 +406,7 @@ public class DefaultCrossRepositorySearch return ret; } - + private boolean indexExists( RepositoryContentIndex index ) { try @@ -402,6 +453,26 @@ public class DefaultCrossRepositorySearch } } + private void parseAndAdd( BooleanQuery query, String key, String value, String delimiter ) + { + if ( value != null && value.length() > 0 ) + { + String[] terms = value.split( delimiter ); + for ( int i = 0; i < terms.length; i++ ) + { + Term valueTerm = new Term( key, terms[i] ); + Query valueQuery = new TermQuery( valueTerm ); + query.add( valueQuery, BooleanClause.Occur.MUST ); + } + } + else + { + Term valueTerm = new Term( key, value ); + Query valueQuery = new TermQuery( valueTerm ); + query.add( valueQuery, BooleanClause.Occur.MUST ); + } + } + public void initialize() throws InitializationException { diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java index c82097467..4f0a420a8 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java @@ -74,7 +74,7 @@ public class SearchResults private void addBytecodeHit( BytecodeRecord bytecode ) { String key = toKey( bytecode.getArtifact() ); - + SearchResultHit hit = (SearchResultHit) this.hits.get( key ); if ( hit == null ) @@ -95,7 +95,8 @@ public class SearchResults key.append( StringUtils.defaultString( artifact.getModel().getRepositoryId() ) ).append( ":" ); key.append( StringUtils.defaultString( artifact.getGroupId() ) ).append( ":" ); - key.append( StringUtils.defaultString( artifact.getArtifactId() ) ); + key.append( StringUtils.defaultString( artifact.getArtifactId() ) ).append( ":" ); + key.append( StringUtils.defaultString( artifact.getVersion() ) ); return key.toString(); } diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.java b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.java new file mode 100644 index 000000000..a402c46e7 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.java @@ -0,0 +1,167 @@ +package org.apache.maven.archiva.indexer; + +/* + * 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.List; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.apache.lucene.search.Hits; +import org.apache.lucene.search.MatchAllDocsQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.Searcher; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord; +import org.apache.maven.archiva.indexer.filecontent.FileContentRecord; +import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecord; +import org.apache.maven.archiva.indexer.search.BytecodeIndexPopulator; +import org.apache.maven.archiva.indexer.search.FileContentIndexPopulator; +import org.apache.maven.archiva.indexer.search.HashcodesIndexPopulator; +import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; +import org.codehaus.plexus.spring.PlexusInSpringTestCase; +import org.codehaus.plexus.spring.PlexusToSpringUtils; + +public class RepositoryContentIndexEventListenerTest + extends PlexusInSpringTestCase +{ + private static final String TEST_DEFAULT_REPOSITORY_NAME = "Test Default Repository"; + + private static final String TEST_DEFAULT_REPO_ID = "test-repo"; + + private RepositoryListener listener; + + @Override + protected void setUp() + throws Exception + { + super.setUp(); + + listener = (RepositoryListener) lookup( RepositoryListener.class.getName(), "indexer" ); + } + + public void testWiring() + { + List listeners = + PlexusToSpringUtils.lookupList( PlexusToSpringUtils.buildSpringId( RepositoryListener.class ), + getApplicationContext() ); + + assertEquals( 1, listeners.size() ); + assertEquals( listener, listeners.get( 0 ) ); + } + + public ArchivaArtifact createArtifact( String artifactId, String version ) + { + ArchivaArtifact artifact = + new ArchivaArtifact( "org.apache.maven.archiva.test", artifactId, version, "", "jar" ); + artifact.getModel().setRepositoryId( "testable_repo" ); + return artifact; + } + + public void testDeleteArtifact() + throws Exception + { + RepositoryContentIndexFactory indexFactory = + (RepositoryContentIndexFactory) lookup( RepositoryContentIndexFactory.class.getName(), "lucene" ); + + File repoDir = new File( getBasedir(), "src/test/managed-repository" ); + + assertTrue( "Default Test Repository should exist.", repoDir.exists() && repoDir.isDirectory() ); + + ManagedRepositoryConfiguration repository = + createRepository( TEST_DEFAULT_REPO_ID, TEST_DEFAULT_REPOSITORY_NAME, repoDir ); + + File indexLocation = new File( "target/index-events-" + getName() + "/" ); + + MockConfiguration config = (MockConfiguration) lookup( ArchivaConfiguration.class.getName(), "mock" ); + + ManagedRepositoryConfiguration repoConfig = new ManagedRepositoryConfiguration(); + repoConfig.setId( TEST_DEFAULT_REPO_ID ); + repoConfig.setName( TEST_DEFAULT_REPOSITORY_NAME ); + repoConfig.setLocation( repoDir.getAbsolutePath() ); + repoConfig.setIndexDir( indexLocation.getAbsolutePath() ); + repoConfig.setScanned( true ); + + if ( indexLocation.exists() ) + { + FileUtils.deleteDirectory( indexLocation ); + } + + config.getConfiguration().addManagedRepository( repoConfig ); + + // Create the (empty) indexes. + RepositoryContentIndex indexHashcode = indexFactory.createHashcodeIndex( repository ); + RepositoryContentIndex indexBytecode = indexFactory.createBytecodeIndex( repository ); + RepositoryContentIndex indexContents = indexFactory.createFileContentIndex( repository ); + + // Now populate them. + Map hashcodesMap = new HashcodesIndexPopulator().populate( new File( getBasedir() ) ); + indexHashcode.indexRecords( hashcodesMap.values() ); + assertEquals( "Hashcode Key Count", hashcodesMap.size(), indexHashcode.getAllRecordKeys().size() ); + assertRecordCount( indexHashcode, hashcodesMap.size() ); + + Map bytecodeMap = new BytecodeIndexPopulator().populate( new File( getBasedir() ) ); + indexBytecode.indexRecords( bytecodeMap.values() ); + assertEquals( "Bytecode Key Count", bytecodeMap.size(), indexBytecode.getAllRecordKeys().size() ); + assertRecordCount( indexBytecode, bytecodeMap.size() ); + + Map contentMap = new FileContentIndexPopulator().populate( new File( getBasedir() ) ); + indexContents.indexRecords( contentMap.values() ); + assertEquals( "File Content Key Count", contentMap.size(), indexContents.getAllRecordKeys().size() ); + assertRecordCount( indexContents, contentMap.size() ); + + ManagedRepositoryContent repositoryContent = + (ManagedRepositoryContent) lookup( ManagedRepositoryContent.class.getName(), "default" ); + repositoryContent.setRepository( repository ); + + ArchivaArtifact artifact = + new ArchivaArtifact( "org.apache.maven.archiva", "archiva-common", "1.0", "", "jar" ); + listener.deleteArtifact( repositoryContent, artifact ); + + artifact = + new ArchivaArtifact( "org.apache.maven.archiva.record", "test-pom", "1.0", "", "pom" ); + listener.deleteArtifact( repositoryContent, artifact ); + + assertRecordCount( indexHashcode, hashcodesMap.size() - 1 ); + assertRecordCount( indexBytecode, bytecodeMap.size() - 1 ); + assertRecordCount( indexContents, contentMap.size() - 1 ); + } + + protected ManagedRepositoryConfiguration createRepository( String id, String name, File location ) + { + ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration(); + repo.setId( id ); + repo.setName( name ); + repo.setLocation( location.getAbsolutePath() ); + return repo; + } + + private void assertRecordCount( RepositoryContentIndex index, int expectedCount ) + throws Exception + { + Query query = new MatchAllDocsQuery(); + Searcher searcher = (Searcher) index.getSearchable(); + Hits hits = searcher.search( query ); + assertEquals( "Expected Record Count for " + index.getId(), expectedCount, hits.length() ); + } +} diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java index 71c872d67..005e3e719 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java @@ -242,6 +242,51 @@ public class DefaultCrossRepositorySearchTest "org.apache.maven.continuum.web.action.BuildDefinitionAction.isBuildFresh", null, true ); } + public void testExecuteFilteredSearch() + throws Exception + { + CrossRepositorySearch search = lookupCrossRepositorySearch(); + + String expectedRepos[] = new String[] { TEST_DEFAULT_REPO_ID }; + + String expectedResults[] = new String[] { "org1", "org2", "org3", "org4", "org5", "org6", "org7", "org8" }; + + String secondExpectedResults[] = new String[] { "continuum-webapp" }; + + String thirdExpectedResults[] = new String[] { "archiva-common" }; + + // search for groupId + assertFilteredSearchResults( expectedRepos, expectedResults, search, "org", null, null, null, 30 ); + + // search for groupId and artifactId + assertFilteredSearchResults( expectedRepos, secondExpectedResults, search, "org.apache.maven", + "continuum-webapp", null, null, 30 ); + + // search for groupId , artifactId and version + assertFilteredSearchResults( expectedRepos, thirdExpectedResults, search, "org.apache.maven.archiva", + "archiva-common", "1.0", null, 30 ); + } + + private void assertFilteredSearchResults ( String expectedRepos[], String expectedResults[], CrossRepositorySearch search, + String groupId, String artifactId, String version, String className , int rowCount ) + { + SearchResultLimits limits = new SearchResultLimits( 0 ); + limits.setPageSize( rowCount ); + + List selectedRepos = new ArrayList(); + selectedRepos.addAll( Arrays.asList( expectedRepos ) ); + + SearchResults results = null; + + results = search.executeFilteredSearch( "guest" , selectedRepos, groupId, artifactId, version, className, limits ); + + assertNotNull( "Search Results should not be null.", results ); + assertEquals( "Repository Hits", expectedRepos.length, results.getRepositories().size() ); + assertEquals( expectedRepos.length, 1); + assertEquals( TEST_DEFAULT_REPO_ID , selectedRepos.get( 0 ) ); + assertEquals( "Search Result Hits", expectedResults.length, results.getHits().size() ); + } + private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search, String term, List previousSearchTerms, boolean bytecode ) throws Exception @@ -251,11 +296,12 @@ public class DefaultCrossRepositorySearchTest List selectedRepos = new ArrayList(); selectedRepos.addAll( Arrays.asList( expectedRepos ) ); - + SearchResults results = null; + if( previousSearchTerms == null ) - { - if( bytecode ) + { + if( bytecode ) { results = search.searchForBytecode( "guest", selectedRepos, term, limits ); } @@ -268,16 +314,18 @@ public class DefaultCrossRepositorySearchTest { results = search.searchForTerm( "guest", selectedRepos, term, limits, previousSearchTerms ); } + assertNotNull( "Search Results should not be null.", results ); assertEquals( "Repository Hits", expectedRepos.length, results.getRepositories().size() ); + // TODO: test the repository ids returned. assertEquals( "Search Result Hits", expectedResults.length, results.getHits().size() ); // TODO: test the order of hits. // TODO: test the value of the hits. } - + protected ManagedRepositoryConfiguration createRepository( String id, String name, File location ) { ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration(); diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.xml b/archiva-modules/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.xml new file mode 100644 index 000000000..af15697a1 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/RepositoryContentIndexEventListenerTest.xml @@ -0,0 +1,22 @@ + + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + mock + org.apache.maven.archiva.indexer.MockConfiguration + + + org.apache.maven.archiva.indexer.RepositoryContentIndexFactory + lucene + org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentIndexFactory + Factory for Lucene repository content index instances. + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + mock + configuration + + + + + diff --git a/archiva-modules/archiva-base/archiva-model/src/main/mdo/archiva-base.xml b/archiva-modules/archiva-base/archiva-model/src/main/mdo/archiva-base.xml index 9bf4c2017..b7e03b5af 100644 --- a/archiva-modules/archiva-base/archiva-model/src/main/mdo/archiva-base.xml +++ b/archiva-modules/archiva-base/archiva-model/src/main/mdo/archiva-base.xml @@ -2346,6 +2346,46 @@ The number of new files discovered. + + totalProjectCount + 1.0.0+ + false + true + long + + The total number of unique projects in the repository. + + + + totalGroupCount + 1.0.0+ + false + true + long + + The total number of unique groups in the repository. + + + + totalArtifactCount + 1.0.0+ + false + true + long + + The total number of artifacts in the repository. + + + + totalSize + 1.0.0+ + false + true + long + + The total size in bytes of the repository. + + diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/events/RepositoryListener.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/events/RepositoryListener.java new file mode 100644 index 000000000..f725071ab --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/events/RepositoryListener.java @@ -0,0 +1,37 @@ +package org.apache.maven.archiva.repository.events; + +import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; + +/* + * 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. + */ + +/** + * Listen to events on the repository. This class is a stopgap + * refactoring measure until an event bus is in place to handle + * generic events such as these. + */ +public interface RepositoryListener +{ + /** + * Event for the deletion of a given artifact. + * @param artifactPath the path to the artifact that was deleted. + */ + void deleteArtifact( ManagedRepositoryContent repository, ArchivaArtifact artifact ); +} diff --git a/archiva-modules/archiva-database/pom.xml b/archiva-modules/archiva-database/pom.xml index 5268b9531..fad154168 100755 --- a/archiva-modules/archiva-database/pom.xml +++ b/archiva-modules/archiva-database/pom.xml @@ -74,10 +74,6 @@ log4j log4j - - org.apache.derby - derby - org.codehaus.plexus.registry diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListener.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListener.java new file mode 100644 index 000000000..fa865e3ba --- /dev/null +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListener.java @@ -0,0 +1,55 @@ +package org.apache.maven.archiva.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 org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; + +/** + * Process repository management events and respond appropriately. + * + * @plexus.component role="org.apache.maven.archiva.repository.events.RepositoryListener" role-hint="database" + */ +public class RepositoryDatabaseEventListener + implements RepositoryListener +{ + /** + * @plexus.requirement role-hint="jdo" + */ + private ArtifactDAO artifactDAO; + + public void deleteArtifact( ManagedRepositoryContent repository, ArchivaArtifact artifact ) + { + try + { + ArchivaArtifact queriedArtifact = + artifactDAO.getArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), + artifact.getClassifier(), artifact.getType() ); + artifactDAO.deleteArtifact( queriedArtifact ); + } + catch ( ArchivaDatabaseException e ) + { + // ignored + } + + // TODO [MRM-37]: re-run the database consumers to clean up + } +} diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java index fe3985a02..8559e035c 100644 --- a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/AbstractDeclarativeConstraint.java @@ -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() diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraint.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraint.java index 4506123a2..9b3afab0a 100644 --- a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraint.java +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraint.java @@ -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() { diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraint.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraint.java index dc3990980..ac3aad061 100644 --- a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraint.java +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraint.java @@ -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() { diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java index 47766b94e..d64382c7d 100644 --- a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java @@ -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 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 ) diff --git a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListenerTest.java b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListenerTest.java new file mode 100644 index 000000000..7e76ee6b0 --- /dev/null +++ b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/RepositoryDatabaseEventListenerTest.java @@ -0,0 +1,90 @@ +package org.apache.maven.archiva.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.util.Date; +import java.util.List; + +import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.repository.ManagedRepositoryContent; +import org.apache.maven.archiva.repository.events.RepositoryListener; +import org.codehaus.plexus.spring.PlexusToSpringUtils; + +public class RepositoryDatabaseEventListenerTest + extends AbstractArchivaDatabaseTestCase +{ + private RepositoryListener listener; + + @Override + protected void setUp() + throws Exception + { + super.setUp(); + + listener = (RepositoryListener) lookup( RepositoryListener.class.getName(), "database" ); + } + + public void testWiring() + { + List listeners = + PlexusToSpringUtils.lookupList( PlexusToSpringUtils.buildSpringId( RepositoryListener.class ), + getApplicationContext() ); + + assertEquals( 1, listeners.size() ); + assertEquals( listener, listeners.get( 0 ) ); + } + + public ArchivaArtifact createArtifact( String artifactId, String version, ArtifactDAO artifactDao ) + { + ArchivaArtifact artifact = + artifactDao.createArtifact( "org.apache.maven.archiva.test", artifactId, version, "", "jar" ); + artifact.getModel().setLastModified( new Date() ); + artifact.getModel().setRepositoryId( "testable_repo" ); + return artifact; + } + + public void testDeleteArtifact() + throws Exception + { + ArtifactDAO artifactDao = (ArtifactDAO) lookup( ArtifactDAO.class.getName(), "jdo" ); + + // Setup artifacts in fresh DB. + ArchivaArtifact artifact = createArtifact( "test-artifact", "1.0", artifactDao ); + artifactDao.saveArtifact( artifact ); + + assertEquals( artifact, artifactDao.getArtifact( "org.apache.maven.archiva.test", "test-artifact", "1.0", null, + "jar" ) ); + + artifact = new ArchivaArtifact( "org.apache.maven.archiva.test", "test-artifact", "1.0", null, "jar" ); + ManagedRepositoryContent repository = + (ManagedRepositoryContent) lookup( ManagedRepositoryContent.class.getName(), "default" ); + listener.deleteArtifact( repository, artifact ); + + try + { + artifactDao.getArtifact( "org.apache.maven.archiva.test", "test-artifact", "1.0", null, "jar" ); + fail( "Should not find artifact" ); + } + catch ( ObjectNotFoundException e ) + { + assertTrue( true ); + } + } +} diff --git a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraintTest.java b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraintTest.java index c503ffcfa..41516e7d5 100644 --- a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraintTest.java +++ b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/ArtifactsByRepositoryConstraintTest.java @@ -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 { diff --git a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraintTest.java b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraintTest.java index 3e036b554..4a6b4555c 100644 --- a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraintTest.java +++ b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/RepositoryContentStatisticsByRepositoryConstraintTest.java @@ -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() ); + } } diff --git a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraintTest.java b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraintTest.java index 45191ec3a..db9fc81bb 100644 --- a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraintTest.java +++ b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraintTest.java @@ -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 results = dao.query( constraint ); + assertNotNull( prefix + "Not Null", results ); + assertEquals( prefix + "Results.size", artifactIds.length, results.size() ); + + List expectedArtifactIds = Arrays.asList( artifactIds ); + + Iterator 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 results = dao.query( constraint ); assertNotNull( prefix + "Not Null", results ); assertEquals( prefix + "Results.size", artifactIds.length, results.size() ); - List expectedArtifactIds = Arrays.asList( artifactIds ); + List expectedArtifactIds = Arrays.asList( artifactIds ); - Iterator it = results.iterator(); + Iterator it = results.iterator(); while ( it.hasNext() ) { String actualArtifactId = (String) it.next(); diff --git a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java index b32ea06cf..eef212eb2 100644 --- a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java +++ b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java @@ -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 { diff --git a/archiva-modules/archiva-reporting/archiva-report-manager/pom.xml b/archiva-modules/archiva-reporting/archiva-report-manager/pom.xml index 2220a81f1..cf94e84b8 100755 --- a/archiva-modules/archiva-reporting/archiva-report-manager/pom.xml +++ b/archiva-modules/archiva-reporting/archiva-report-manager/pom.xml @@ -48,6 +48,11 @@ commons-io commons-io + + org.codehaus.plexus + plexus-spring + test + diff --git a/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java new file mode 100644 index 000000000..3eca9bf21 --- /dev/null +++ b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/ArchivaReportException.java @@ -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 Maria Odea Ching + * @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-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java new file mode 100644 index 000000000..44d6d4a71 --- /dev/null +++ b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatistics.java @@ -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 Maria Odea Ching + */ +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-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java new file mode 100644 index 000000000..1b1e0aa78 --- /dev/null +++ b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/RepositoryStatisticsReportGenerator.java @@ -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 Maria Odea Ching + * @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 generateReport( List repoContentStats, String repository, Date startDate, Date endDate, DataLimits limits ) + throws ArchivaReportException; + + public List generateReport( List repoContentStats, String repository, Date startDate, Date endDate ) + throws ArchivaReportException; +} diff --git a/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java new file mode 100644 index 000000000..8eb75864b --- /dev/null +++ b/archiva-modules/archiva-reporting/archiva-report-manager/src/main/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGenerator.java @@ -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 Maria Odea Ching + * @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 generateReport( List 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 generateReport( List repoContentStats, String repository, Date startDate, Date endDate ) + throws ArchivaReportException + { + return constructRepositoryStatistics( repoContentStats, repository, endDate, 0, repoContentStats.size() - 1 ); + } + + private List constructRepositoryStatistics( + List repoContentStats, + String repository, Date endDate, + int start, int end ) + { + ArtifactDAO artifactDao = dao.getArtifactDAO(); + + List repoStatisticsList = new ArrayList(); + 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-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java b/archiva-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java new file mode 100644 index 000000000..49828e0dc --- /dev/null +++ b/archiva-modules/archiva-reporting/archiva-report-manager/src/test/java/org/apache/maven/archiva/reporting/SimpleRepositoryStatisticsReportGeneratorTest.java @@ -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 Maria Odea Ching + * @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 createArtifacts( String type ) + { + List artifacts = new ArrayList(); + 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 createStatisticsHistoryForSingleRepositoryTest( String repoId ) + { + List repoContentStatsList = new ArrayList(); + + 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 jarArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.JAR_TYPE ); + List warArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.WAR_TYPE ); + List mavenPlugins = createArtifacts( RepositoryStatisticsReportGenerator.MAVEN_PLUGIN ); + + List 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 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 jarArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.JAR_TYPE ); + List warArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.WAR_TYPE ); + List mavenPlugins = createArtifacts( RepositoryStatisticsReportGenerator.MAVEN_PLUGIN ); + + List 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 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 jarArtifacts = new ArrayList(); + List warArtifacts = new ArrayList(); + List mavenPlugins = new ArrayList(); + + List 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 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 repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO ); + + try + { + List 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 + } +} diff --git a/archiva-modules/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaRepositoryScanningTaskExecutor.java b/archiva-modules/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaRepositoryScanningTaskExecutor.java index 527ee34fc..b07388b04 100644 --- a/archiva-modules/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaRepositoryScanningTaskExecutor.java +++ b/archiva-modules/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaRepositoryScanningTaskExecutor.java @@ -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 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 repos = new ArrayList(); + repos.add( arepo.getId() ); + + List groupIds = dao.query( new UniqueGroupIdConstraint( repos ) ); + dbstats.setTotalGroupCount( groupIds.size() ); + + List artifactIds = dao.query( new UniqueArtifactIdConstraint( arepo.getId(), true ) ); + dbstats.setTotalProjectCount( artifactIds.size() ); + + return dbstats; + } } diff --git a/archiva-modules/archiva-web/archiva-rss/pom.xml b/archiva-modules/archiva-web/archiva-rss/pom.xml index 9aa671e60..be70c4a21 100644 --- a/archiva-modules/archiva-web/archiva-rss/pom.xml +++ b/archiva-modules/archiva-web/archiva-rss/pom.xml @@ -18,6 +18,7 @@ org.apache.archiva archiva-model + org.apache.archiva archiva-database diff --git a/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java b/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java index 3ef5c9182..031fc11d4 100644 --- a/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java +++ b/archiva-modules/archiva-web/archiva-rss/src/main/java/org/apache/archiva/rss/processor/NewArtifactsRssFeedProcessor.java @@ -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 artifacts = artifactDAO.queryArtifacts( artifactsByRepo ); List entries = processData( artifacts, true ); diff --git a/archiva-modules/archiva-web/archiva-security/pom.xml b/archiva-modules/archiva-web/archiva-security/pom.xml index a5da9f400..e61b0b47b 100644 --- a/archiva-modules/archiva-web/archiva-security/pom.xml +++ b/archiva-modules/archiva-web/archiva-security/pom.xml @@ -43,35 +43,35 @@ test - org.codehaus.plexus.redback + org.codehaus.redback redback-system - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-model - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-role-manager - org.codehaus.plexus.redback + org.codehaus.redback redback-authorization-rbac test - org.codehaus.plexus.redback + org.codehaus.redback redback-keys-memory test - org.codehaus.plexus.redback + org.codehaus.redback redback-users-memory test - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-memory test diff --git a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java index 4e8c040b7..7059598df 100644 --- a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java +++ b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaServletAuthenticator.java @@ -93,11 +93,18 @@ public class ArchivaServletAuthenticator return true; } - public boolean isAuthorizedToAccessVirtualRepository( 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 ) { diff --git a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaXworkUser.java b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaXworkUser.java index 4189392e6..c03405425 100644 --- a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaXworkUser.java +++ b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaXworkUser.java @@ -19,27 +19,38 @@ package org.apache.maven.archiva.security; * under the License. */ -import java.util.HashMap; import java.util.Map; import org.apache.maven.archiva.security.ArchivaRoleConstants; import org.codehaus.plexus.redback.system.SecuritySession; import org.codehaus.plexus.redback.system.SecuritySystemConstants; import org.codehaus.plexus.redback.users.User; +import org.codehaus.plexus.registry.Registry; /** * ArchivaXworkUser * * @author Joakim Erdfelt * @version $Id$ + * + * @plexus.component role="org.apache.maven.archiva.security.ArchivaXworkUser" */ public class ArchivaXworkUser { - public static String getActivePrincipal( Map sessionMap ) - { + /** + * @plexus.requirement role-hint="commons-configuration" + */ + private Registry registry; + + private static final String KEY = "org.codehaus.plexus.redback"; + + private static String guest; + + public String getActivePrincipal( Map sessionMap ) + { if ( sessionMap == null ) { - return ArchivaRoleConstants.PRINCIPAL_GUEST; + return getGuest(); } SecuritySession securitySession = @@ -52,15 +63,31 @@ public class ArchivaXworkUser if ( securitySession == null ) { - return ArchivaRoleConstants.PRINCIPAL_GUEST; + return getGuest(); } User user = securitySession.getUser(); if ( user == null ) { - return ArchivaRoleConstants.PRINCIPAL_GUEST; + return getGuest(); } return (String) user.getPrincipal(); + } + + public String getGuest() + { + if( guest == null || "".equals( guest ) ) + { + Registry subset = registry.getSubset( KEY ); + guest = subset.getString( "redback.default.guest", ArchivaRoleConstants.PRINCIPAL_GUEST ); + } + + return guest; + } + + public void setGuest( String guesT ) + { + guest = guesT; } } diff --git a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java index fb39b4bca..adc6ad1ab 100644 --- a/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java +++ b/archiva-modules/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ServletAuthenticator.java @@ -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 isAuthorizedToAccessVirtualRepository( 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-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java new file mode 100644 index 000000000..399c87eed --- /dev/null +++ b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/AbstractSecurityTest.java @@ -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 Maria Odea Ching + * @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-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java new file mode 100644 index 000000000..d100b88ac --- /dev/null +++ b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.java @@ -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 Maria Odea Ching + * @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 ); + } +} diff --git a/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java index ceb0a357c..a9f8c1897 100644 --- a/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java +++ b/archiva-modules/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java @@ -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-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml b/archiva-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml new file mode 100644 index 000000000..adfb9b2b4 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/ArchivaServletAuthenticatorTest.xml @@ -0,0 +1,202 @@ + + + + + + org.apache.maven.archiva.security.ServletAuthenticator + default + org.apache.maven.archiva.security.ArchivaServletAuthenticator + ArchivaServletAuthenticator + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + securitySystem + + + + + + org.apache.maven.archiva.security.UserRepositories + default + org.apache.maven.archiva.security.DefaultUserRepositories + DefaultUserRepositories + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + securitySystem + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration + + + + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + org.codehaus.plexus.redback.system.DefaultSecuritySystem + DefaultSecuritySystem: + + + org.codehaus.plexus.redback.authentication.AuthenticationManager + authnManager + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + authorizer + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.keys.KeyManager + memory + keyManager + + + org.codehaus.plexus.redback.policy.UserSecurityPolicy + policy + + + + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer + RbacAuthorizer: + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + manager + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + evaluator + + + org.codehaus.plexus.redback.configuration.UserConfiguration + default + config + + + + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + + + + org.codehaus.plexus.redback.role.RoleManager + default + org.codehaus.plexus.redback.role.DefaultRoleManager + RoleProfileManager: + + + org.codehaus.plexus.redback.role.validator.RoleModelValidator + default + modelValidator + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + modelProcessor + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + templateProcessor + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor + DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor + DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + org.apache.maven.archiva.configuration.DefaultArchivaConfiguration + + + org.codehaus.plexus.registry.Registry + configured + + + + + org.codehaus.plexus.registry.Registry + configured + org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry + + + + + + + + + + diff --git a/archiva-modules/archiva-web/archiva-webapp/pom.xml b/archiva-modules/archiva-web/archiva-webapp/pom.xml index d89bfd11a..97bfcd57a 100644 --- a/archiva-modules/archiva-web/archiva-webapp/pom.xml +++ b/archiva-modules/archiva-web/archiva-webapp/pom.xml @@ -84,14 +84,6 @@ org.apache.archiva archiva-rss - - org.apache.archiva - archiva-xmlrpc-services - - - org.apache.archiva - archiva-xmlrpc-security - javax.servlet servlet-api @@ -153,17 +145,17 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-xwork-content war runtime - org.codehaus.plexus.redback + org.codehaus.redback redback-xwork-integration - org.codehaus.plexus.redback + org.codehaus.redback redback-taglib @@ -179,11 +171,6 @@ org.springframework spring-web - - org.apache.derby - derby - provided - javax.mail mail @@ -229,11 +216,6 @@ commons-logging-api 1.1 - - com.atlassian.xmlrpc - atlassian-xmlrpc-binder-server-spring - runtime - diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java index 7dee82270..92b4c8c91 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java @@ -52,6 +52,11 @@ public class BrowseAction */ private UserRepositories userRepositories; + /** + * @plexus.requirement + */ + private ArchivaXworkUser archivaXworkUser; + private BrowsingResults results; private String groupId; @@ -121,7 +126,7 @@ public class BrowseAction private String getPrincipal() { - return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); + return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); } private List getObservableRepos() diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java index 39c3bb361..35e770b26 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java @@ -1,5 +1,5 @@ package org.apache.maven.archiva.web.action; - + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -23,10 +23,12 @@ import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; -import com.opensymphony.xwork.ActionContext; import org.apache.commons.collections.CollectionUtils; 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.Constraint; import org.apache.maven.archiva.database.constraints.ArtifactsByChecksumConstraint; @@ -42,6 +44,9 @@ import org.apache.maven.archiva.security.PrincipalNotFoundException; import org.apache.maven.archiva.security.UserRepositories; import org.codehaus.plexus.xwork.action.PlexusActionSupport; +import com.opensymphony.xwork.ActionContext; +import com.opensymphony.xwork.Preparable; + /** * Search all indexed fields by the given criteria. * @@ -49,10 +54,16 @@ import org.codehaus.plexus.xwork.action.PlexusActionSupport; */ public class SearchAction extends PlexusActionSupport -{ + implements Preparable +{ /** * Query string. */ + + private ArchivaConfiguration archivaConfiguration; + + private Map managedRepositories; + private String q; /** @@ -75,6 +86,11 @@ public class SearchAction */ private UserRepositories userRepositories; + /** + * @plexus.requirement + */ + private ArchivaXworkUser archivaXworkUser; + private static final String RESULTS = "results"; private static final String ARTIFACT = "artifact"; @@ -85,27 +101,132 @@ public class SearchAction private int totalPages; - private boolean searchResultsOnly; + private boolean searchResultsOnly; private String completeQueryString; private static final String COMPLETE_QUERY_STRING_SEPARATOR = ";"; - + private static final String BYTECODE_KEYWORD = "bytecode:"; + private List managedRepositoryList; + + private String groupId; + + private String artifactId; + + private String version; + + private String className; + + private int rowCount = 30; + + private String repositoryId; + + private boolean fromFilterSearch; + + private boolean filterSearch = false; + + private boolean fromResultsPage; + + private int num; + + public boolean isFromResultsPage() + { + return fromResultsPage; + } + + public void setFromResultsPage( boolean fromResultsPage ) + { + this.fromResultsPage = fromResultsPage; + } + + public boolean isFromFilterSearch() + { + return fromFilterSearch; + } + + public void setFromFilterSearch( boolean fromFilterSearch ) + { + this.fromFilterSearch = fromFilterSearch; + } + + public void prepare() + { + managedRepositoryList = new ArrayList(); + managedRepositoryList = getObservableRepos(); + + if ( managedRepositoryList.size() > 0 ) + { + managedRepositoryList.add( "all" ); + } + } + + // advanced search MRM-90 -- filtered search + public String filteredSearch() + throws MalformedURLException, RepositoryIndexException, RepositoryIndexSearchException + { + fromFilterSearch = true; + + if ( CollectionUtils.isEmpty( managedRepositoryList ) ) + { + return GlobalResults.ACCESS_TO_NO_REPOS; + } + + SearchResultLimits limits = new SearchResultLimits( currentPage ); + + limits.setPageSize( rowCount ); + List selectedRepos = new ArrayList(); + + if ( repositoryId.equals( "all" ) ) + { + selectedRepos = getObservableRepos(); + } + else + { + selectedRepos.add( repositoryId ); + } + + if ( CollectionUtils.isEmpty( selectedRepos ) ) + { + return GlobalResults.ACCESS_TO_NO_REPOS; + } + + results = + crossRepoSearch.executeFilteredSearch( getPrincipal(), selectedRepos, groupId, artifactId, version, + className, limits ); + + if ( results.isEmpty() ) + { + addActionError( "No results found" ); + return INPUT; + } + + totalPages = results.getTotalHits() / limits.getPageSize(); + + if ( ( results.getTotalHits() % limits.getPageSize() ) != 0 ) + { + totalPages = totalPages + 1; + } + + return SUCCESS; + } + public String quickSearch() throws MalformedURLException, RepositoryIndexException, RepositoryIndexSearchException { /* TODO: give action message if indexing is in progress. * This should be based off a count of 'unprocessed' artifacts. - * This (yet to be written) routine could tell the user that X (unprocessed) artifacts are not yet + * This (yet to be written) routine could tell the user that X (unprocessed) artifacts are not yet * present in the full text search. */ assert q != null && q.length() != 0; - + + fromFilterSearch = false; + SearchResultLimits limits = new SearchResultLimits( currentPage ); - + List selectedRepos = getObservableRepos(); if ( CollectionUtils.isEmpty( selectedRepos ) ) { @@ -113,13 +234,13 @@ public class SearchAction } if( isBytecodeSearch( q ) ) - { + { results = crossRepoSearch.searchForBytecode( getPrincipal(), selectedRepos, removeKeyword( q ), limits ); } else { if( searchResultsOnly && !completeQueryString.equals( "" ) ) - { + { results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits, parseCompleteQueryString() ); } else @@ -128,33 +249,33 @@ public class SearchAction results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits ); } } - + if ( results.isEmpty() ) { addActionError( "No results found" ); return INPUT; } - + totalPages = results.getTotalHits() / limits.getPageSize(); - + if( (results.getTotalHits() % limits.getPageSize()) != 0 ) { totalPages = totalPages + 1; } // TODO: filter / combine the artifacts by version? (is that even possible with non-artifact hits?) - /* I don't think that we should, as I expect us to utilize the 'score' system in lucene in + /* I don't think that we should, as I expect us to utilize the 'score' system in lucene in * the future to return relevant links better. * I expect the lucene scoring system to take multiple hits on different areas of a single document - * to result in a higher score. + * to result in a higher score. * - Joakim */ - + if( !isEqualToPreviousSearchTerm( q ) ) { buildCompleteQueryString( q ); } - + return SUCCESS; } @@ -180,10 +301,10 @@ public class SearchAction if ( databaseResults.size() == 1 ) { - // 1 hit? return it's information directly! + // 1 hit? return it's information directly! return ARTIFACT; } - + return RESULTS; } @@ -192,12 +313,12 @@ public class SearchAction { return INPUT; } - + private String getPrincipal() { - return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); + return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); } - + private List getObservableRepos() { try @@ -222,44 +343,44 @@ public class SearchAction private void buildCompleteQueryString( String searchTerm ) { - if( searchTerm.indexOf( COMPLETE_QUERY_STRING_SEPARATOR ) != -1 ) + if ( searchTerm.indexOf( COMPLETE_QUERY_STRING_SEPARATOR ) != -1 ) { searchTerm = StringUtils.remove( searchTerm, COMPLETE_QUERY_STRING_SEPARATOR ); } - - if( completeQueryString == null || "".equals( completeQueryString ) ) + + if ( completeQueryString == null || "".equals( completeQueryString ) ) { completeQueryString = searchTerm; } else - { + { completeQueryString = completeQueryString + COMPLETE_QUERY_STRING_SEPARATOR + searchTerm; } } - + private List parseCompleteQueryString() { - List parsedCompleteQueryString = new ArrayList(); + List parsedCompleteQueryString = new ArrayList(); String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR ); CollectionUtils.addAll( parsedCompleteQueryString, parsed ); - + return parsedCompleteQueryString; } - + private boolean isEqualToPreviousSearchTerm( String searchTerm ) { - if( !"".equals( completeQueryString ) ) + if ( !"".equals( completeQueryString ) ) { String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR ); - if( StringUtils.equalsIgnoreCase( searchTerm, parsed[ parsed.length - 1 ] ) ) + if ( StringUtils.equalsIgnoreCase( searchTerm, parsed[parsed.length - 1] ) ) { return true; } } - + return false; } - + public String getQ() { return q; @@ -279,12 +400,12 @@ public class SearchAction { return databaseResults; } - + public void setCurrentPage( int page ) { this.currentPage = page; } - + public int getCurrentPage() { return currentPage; @@ -318,23 +439,123 @@ public class SearchAction public void setCompleteQueryString( String completeQueryString ) { this.completeQueryString = completeQueryString; - } - + } + private boolean isBytecodeSearch( String queryString ) { - if( queryString.startsWith( BYTECODE_KEYWORD ) ) + if ( queryString.startsWith( BYTECODE_KEYWORD ) ) { - return true; + return true; } - + return false; } - + private String removeKeyword( String queryString ) - { + { String qString = StringUtils.uncapitalize( queryString ); - qString= StringUtils.remove( queryString, BYTECODE_KEYWORD ); - + qString = StringUtils.remove( queryString, BYTECODE_KEYWORD ); + return qString; } + + public ArchivaConfiguration getArchivaConfiguration() + { + return archivaConfiguration; + } + + public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration ) + { + this.archivaConfiguration = archivaConfiguration; + } + + public Map getManagedRepositories() + { + return getArchivaConfiguration().getConfiguration().getManagedRepositoriesAsMap(); + } + + public void setManagedRepositories( Map managedRepositories ) + { + this.managedRepositories = managedRepositories; + } + + public String getGroupId() + { + return groupId; + } + + public void setGroupId( String groupId ) + { + this.groupId = groupId; + } + + public String getArtifactId() + { + return artifactId; + } + + public void setArtifactId( String artifactId ) + { + this.artifactId = artifactId; + } + + public String getVersion() + { + return version; + } + + public void setVersion( String version ) + { + this.version = version; + } + + public int getRowCount() + { + return rowCount; + } + + public void setRowCount( int rowCount ) + { + this.rowCount = rowCount; + } + + public boolean isFilterSearch() + { + return filterSearch; + } + + public void setFilterSearch( boolean filterSearch ) + { + this.filterSearch = filterSearch; + } + + public String getRepositoryId() + { + return repositoryId; + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId; + } + + public List getManagedRepositoryList() + { + return managedRepositoryList; + } + + public void setManagedRepositoryList( List managedRepositoryList ) + { + this.managedRepositoryList = managedRepositoryList; + } + + public String getClassName() + { + return className; + } + + public void setClassName( String className ) + { + this.className = className; + } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java index 97dca610e..a402515c3 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java @@ -59,6 +59,11 @@ public class ShowArtifactAction * @plexus.requirement */ private UserRepositories userRepositories; + + /** + * @plexus.requirement + */ + private ArchivaXworkUser archivaXworkUser; /* .\ Input Parameters \.________________________________________ */ @@ -179,7 +184,7 @@ public class ShowArtifactAction private String getPrincipal() { - return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); + return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); } private List getObservableRepos() diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/UploadAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/UploadAction.java index c539f1962..cb8bcfe48 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/UploadAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/UploadAction.java @@ -86,6 +86,11 @@ public class UploadAction * @plexus.requirement */ private RepositoryContentConsumers consumers; + + /** + * @plexus.requirement + */ + private ArchivaXworkUser archivaXworkUser; /** * The groupId of the artifact to be deployed. @@ -456,7 +461,7 @@ public class UploadAction private String getPrincipal() { - return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); + return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); } private void copyFile( File sourceFile, File targetPath, String targetFilename ) diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/ProxyConnectorsAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/ProxyConnectorsAction.java index fccbd380e..3cfb0ece9 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/ProxyConnectorsAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/ProxyConnectorsAction.java @@ -43,6 +43,11 @@ public class ProxyConnectorsAction { private Map repoMap; + /** + * boolean to indicate that remote repo is present. Used for Add Link + */ + private boolean remoteRepoExists=false; + /** * Map of Proxy Connectors. */ @@ -57,6 +62,8 @@ public class ProxyConnectorsAction repoMap.putAll( config.getManagedRepositoriesAsMap() ); proxyConnectorMap = createProxyConnectorMap(); + + remoteRepoExists=config.getRemoteRepositories().size()>0; } public Map getRepoMap() @@ -68,4 +75,9 @@ public class ProxyConnectorsAction { return proxyConnectorMap; } + + public boolean getRemoteRepoExists() + { + return remoteRepoExists; + } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/repositories/AbstractManagedRepositoriesAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/repositories/AbstractManagedRepositoriesAction.java index 7fc658676..a16700f75 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/repositories/AbstractManagedRepositoriesAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/repositories/AbstractManagedRepositoriesAction.java @@ -69,7 +69,7 @@ public abstract class AbstractManagedRepositoriesAction } if ( !file.exists() || !file.isDirectory() ) { - throw new IOException( "unable to add repository - can not create the root directory: " + file ); + throw new IOException( "Unable to add repository - no write access, can not create the root directory: " + file ); } configuration.addManagedRepository( repository ); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java index 747ec9802..0fcb62342 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java @@ -21,25 +21,44 @@ package org.apache.maven.archiva.web.action.reports; import com.opensymphony.webwork.interceptor.ServletRequestAware; import com.opensymphony.xwork.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.codehaus.plexus.redback.rbac.Resource; import org.codehaus.plexus.redback.xwork.interceptor.SecureAction; import org.codehaus.plexus.redback.xwork.interceptor.SecureActionBundle; import org.codehaus.plexus.redback.xwork.interceptor.SecureActionException; import org.codehaus.plexus.xwork.action.PlexusActionSupport; +import 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; @@ -51,10 +70,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 +116,50 @@ public class GenerateReportAction protected Map> repositoriesMap = new TreeMap>(); - + + // for statistics report + /** + * @plexus.requirement role-hint="simple" + */ + private RepositoryStatisticsReportGenerator generator; + + private List selectedRepositories = new ArrayList(); + + private List availableRepositories; + + private String startDate; + + private String endDate; + + private int reposSize; + + private String selectedRepo; + + private List repositoryStatistics = new ArrayList(); + + 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(); 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(); + + // 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 getRepositoryIds() @@ -104,9 +167,202 @@ public class GenerateReportAction return repositoryIds; } + /** + * 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 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 problemArtifacts = dao.getRepositoryProblemDAO().queryRepositoryProblems( configureConstraint() ); @@ -156,7 +412,7 @@ public class GenerateReportAction return SUCCESS; } } - + private static boolean isJasperPresent() { if ( jasperPresent == null ) @@ -207,6 +463,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 problemsList = null; + + if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) ) + { + problemsList = ( List ) repositoriesMap.get( repoProblemReport.getRepositoryId() ); + } + else + { + problemsList = new ArrayList(); + repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList ); + } + + problemsList.add( repoProblemReport ); + } public void setServletRequest( HttpServletRequest request ) { @@ -283,31 +567,83 @@ public class GenerateReportAction return repositoriesMap; } - public SecureActionBundle getSecureActionBundle() - throws SecureActionException + public List getSelectedRepositories() { - SecureActionBundle bundle = new SecureActionBundle(); + return selectedRepositories; + } - bundle.setRequiresAuthentication( true ); - bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL ); + public void setSelectedRepositories( List selectedRepositories ) + { + this.selectedRepositories = selectedRepositories; + } - return bundle; + public List getAvailableRepositories() + { + return availableRepositories; + } + + public void setAvailableRepositories( List 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 getRepositoryStatistics() + { + return repositoryStatistics; + } + + public void setRepositoryStatistics( List 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 problemsList = null; - - if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) ) - { - problemsList = ( List ) repositoriesMap.get( repoProblemReport.getRepositoryId() ); - } - else - { - problemsList = new ArrayList(); - repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList ); - } - - problemsList.add( repoProblemReport ); + this.limits = limits; } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java index caedf31bf..89570523a 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java @@ -35,10 +35,12 @@ import org.apache.archiva.rss.processor.RssFeedProcessor; import org.apache.commons.codec.Decoder; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.security.AccessDeniedException; import org.apache.maven.archiva.security.ArchivaRoleConstants; import org.apache.maven.archiva.security.ArchivaSecurityException; +import org.apache.maven.archiva.security.ArchivaXworkUser; import org.apache.maven.archiva.security.PrincipalNotFoundException; import org.apache.maven.archiva.security.ServletAuthenticator; import org.apache.maven.archiva.security.UserRepositories; @@ -89,6 +91,8 @@ public class RssFeedServlet private ServletAuthenticator servletAuth; private HttpAuthenticator httpAuth; + + private ArchivaXworkUser archivaXworkUser; public void init( javax.servlet.ServletConfig servletConfig ) throws ServletException @@ -101,27 +105,39 @@ public class RssFeedServlet (ServletAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( ServletAuthenticator.class.getName() ) ); httpAuth = (HttpAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( HttpAuthenticator.ROLE, "basic" ) ); + archivaXworkUser = (ArchivaXworkUser) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaXworkUser.class ) ); } public void doGet( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException { - String repoId = req.getParameter( "repoId" ); - String groupId = req.getParameter( "groupId" ); - String artifactId = req.getParameter( "artifactId" ); + String repoId = null; + String groupId = null; + String artifactId = null; + + String url = StringUtils.removeEnd( req.getRequestURL().toString(), "/" ); + if( StringUtils.countMatches( StringUtils.substringAfter( url, "feeds/" ), "/" ) > 0 ) + { + artifactId = StringUtils.substringAfterLast( url, "/" ); + groupId = StringUtils.substringBeforeLast( StringUtils.substringAfter( url, "feeds/" ), "/"); + groupId = StringUtils.replaceChars( groupId, '/', '.' ); + } + else if( StringUtils.countMatches( StringUtils.substringAfter( url, "feeds/" ), "/" ) == 0 ) + { + repoId = StringUtils.substringAfterLast( url, "/" ); + } + else + { + res.sendError( HttpServletResponse.SC_BAD_REQUEST, "Invalid request url." ); + return; + } try { Map map = new HashMap(); SyndFeed feed = null; - - if ( ( repoId == null ) && ( groupId == null && artifactId == null ) ) - { - res.sendError( HttpServletResponse.SC_BAD_REQUEST, "Required fields not found in request." ); - return; - } - - if ( isAllowed( req ) ) + + if ( isAllowed( req, repoId, groupId, artifactId ) ) { if ( repoId != null ) { @@ -157,14 +173,14 @@ public class RssFeedServlet } res.setContentType( MIME_TYPE ); - + if ( repoId != null ) - { - feed.setLink( req.getRequestURL() + "?repoId=" + repoId ); + { + feed.setLink( req.getRequestURL().toString() ); } else if ( ( groupId != null ) && ( artifactId != null ) ) { - feed.setLink( req.getRequestURL() + "?groupId=" + groupId + "&artifactId=" + artifactId ); + feed.setLink( req.getRequestURL().toString() ); } SyndFeedOutput output = new SyndFeedOutput(); @@ -218,20 +234,23 @@ public class RssFeedServlet * Basic authentication. * * @param req + * @param repositoryId TODO + * @param groupId TODO + * @param artifactId TODO * @return */ - private boolean isAllowed( HttpServletRequest req ) + private boolean isAllowed( HttpServletRequest req, String repositoryId, String groupId, String artifactId ) throws UserNotFoundException, AccountLockedException, AuthenticationException, MustChangePasswordException, UnauthorizedException { String auth = req.getHeader( "Authorization" ); List repoIds = new ArrayList(); - if ( req.getParameter( "repoId" ) != null ) + if ( repositoryId != null ) { - repoIds.add( req.getParameter( "repoId" ) ); + repoIds.add( repositoryId ); } - else if ( req.getParameter( "artifactId" ) != null && req.getParameter( "groupId" ) != null ) + else if ( artifactId != null && groupId != null ) { if ( auth != null ) { @@ -254,7 +273,7 @@ public class RssFeedServlet if ( usernamePassword == null || usernamePassword.trim().equals( "" ) ) { - repoIds = getObservableRepos( ArchivaRoleConstants.PRINCIPAL_GUEST ); + repoIds = getObservableRepos( archivaXworkUser.getGuest() ); } else { @@ -264,7 +283,7 @@ public class RssFeedServlet } else { - repoIds = getObservableRepos( ArchivaRoleConstants.PRINCIPAL_GUEST ); + repoIds = getObservableRepos( archivaXworkUser.getGuest() ); } } else diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ContextUtils.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ContextUtils.java index 55c2e54ac..3cdb25caf 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ContextUtils.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ContextUtils.java @@ -80,15 +80,7 @@ public class ContextUtils StringBuffer baseUrl = new StringBuffer(); baseUrl.append( request.getScheme() ).append( "://" ); - baseUrl.append( request.getServerName() ); - int portnum = request.getServerPort(); - - // Only add port if non-standard. - Integer defaultPortnum = (Integer) defaultSchemePortMap.get( request.getScheme() ); - if ( ( defaultPortnum == null ) || ( defaultPortnum.intValue() != portnum ) ) - { - baseUrl.append( ":" ).append( String.valueOf( portnum ) ); - } + baseUrl.append( getServerName( request ) ); baseUrl.append( request.getContextPath() ); if ( StringUtils.isNotBlank( resource ) ) @@ -103,4 +95,23 @@ public class ContextUtils return baseUrl.toString(); } + + private static String getServerName( HttpServletRequest request ) + { + String name = request.getHeader( "X-Forwarded-Host" ); + if ( name == null ) + { + name = request.getServerName(); + int portnum = request.getServerPort(); + + // Only add port if non-standard. + Integer defaultPortnum = (Integer) defaultSchemePortMap.get( request.getScheme() ); + if ( ( defaultPortnum == null ) || ( defaultPortnum.intValue() != portnum ) ) + { + name = name + ":" + String.valueOf( portnum ); + } + return name; + } + return name; + } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j.xml index 284f1bcc7..19bb54331 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/log4j.xml @@ -37,7 +37,7 @@ - + @@ -122,4 +122,4 @@ - \ No newline at end of file + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/reports/GenerateReportAction-validation.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/SearchAction-filteredSearch-validation.xml similarity index 74% rename from archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/reports/GenerateReportAction-validation.xml rename to archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/SearchAction-filteredSearch-validation.xml index a31c0652d..5f9c89750 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/reports/GenerateReportAction-validation.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/org/apache/maven/archiva/web/action/SearchAction-filteredSearch-validation.xml @@ -24,21 +24,11 @@ - 10 - Row count must be larger than ${min}. - - - - - - You must provide a repository id. + + 1 + Row count must be larger than ${min}. diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml index 88297d58a..b9580cfa9 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml @@ -143,6 +143,16 @@ /WEB-INF/jsp/quickSearch.jsp + + + /WEB-INF/jsp/advancedSearch.jsp + + + + /WEB-INF/jsp/advancedSearch.jsp + /WEB-INF/jsp/results.jsp + /WEB-INF/jsp/quickSearch.jsp + /WEB-INF/jsp/quickSearch.jsp @@ -501,6 +511,13 @@ /WEB-INF/jsp/reports/blankReport.jsp /WEB-INF/jsp/reports/basicReport.jsp + + + /WEB-INF/jsp/reports/pickReport.jsp + /WEB-INF/jsp/reports/blankReport.jsp + /WEB-INF/jsp/reports/statisticsReport.jsp + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml index fe37b68a4..93bd4a30b 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/applicationContext.xml @@ -30,20 +30,4 @@ - - - - - - - - - - - - - - - - diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/addRepository.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/addRepository.jsp index 55bbda151..d31e092de 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/addRepository.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/addRepository.jsp @@ -30,7 +30,7 @@

Admin: Add Managed Repository

- + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp index b084a1d34..43a0b5da2 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp @@ -46,14 +46,22 @@ -
- - - - "/> - Add - - +
+ + + + + + "/> + Add + + + + + "/> + Add (Disabled. No remote repositories) + +

Repository Proxy Connectors

diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp index ecd8719b0..8f1e91178 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp @@ -88,7 +88,7 @@ - +
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryGroups.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryGroups.jsp index 85c78aeea..15981a30e 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryGroups.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryGroups.jsp @@ -152,6 +152,10 @@
<%-- admin --%> - <%-- content area --%> + <%-- content area --%> + + + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/advancedSearch.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/advancedSearch.jsp new file mode 100644 index 000000000..3a87d1f5e --- /dev/null +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/advancedSearch.jsp @@ -0,0 +1,67 @@ +<%-- + ~ 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" %> + + + Advanced Search + + + + +

${infoMessage}

+
+ + + +

Advanced Search

+ + +
+ + + + + + +
+ + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp index 762cead71..a9efdca3b 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/browse.jsp @@ -69,13 +69,14 @@ - + +
  • ${artifactId}/ - - - -
  • + + + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp index 41f165b70..bb5174510 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp @@ -115,6 +115,11 @@ User Management + +
  • + User Roles +
  • +
  • Appearance diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf index d15092665..309b8420f 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf @@ -109,15 +109,28 @@ -

    POM Dependency Snippet

    +

    POM Snippet

    + + +
    +    <plugin>
    +      <groupId>${model.groupId}</groupId>
    +      <artifactId>${model.artifactId}</artifactId>
    +      <version>${version}</version>
    +    </plugin>
    +
    +
    +
         <dependency>
           <groupId>${model.groupId}</groupId>
    -      <artifactId>${model.artifactId}</artifactId>     
    +      <artifactId>${model.artifactId}</artifactId>
           <version>${version}</version>
           <type>${model.packaging}</type>
         </dependency>
     
    +
    +
    - -<%@ taglib prefix="ww" uri="/webwork" %> - - \ No newline at end of file diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/quickSearch.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/quickSearch.jsp index 690ea4f25..45a435e75 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/quickSearch.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/quickSearch.jsp @@ -33,8 +33,34 @@

    Search

    - <%@ include file="/WEB-INF/jsp/include/quickSearchForm.jspf" %> + +

    + Enter your search terms. A variety of data will be searched for your keywords.
    + To search for Java classes, packages or methods, use the keyword bytecode: + before the term. For example: + bytecode:MyClass, or: + bytecode:myMethod +

    +
    - \ No newline at end of file + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp index 117db55eb..62c12bb38 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp @@ -27,13 +27,29 @@

    Reports

    - +
    - +

    Repository Statistics

    + + + + + + + + + + + +

    Repository Health

    + - + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp new file mode 100644 index 000000000..dd70758c2 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp @@ -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" %> + + + + Reports + + + + +

    Statistics Report

    + + + + + + +
    + + <%-- TODO: fix problem in date format! --%> + + <%-- Pagination - start --%> +

    + + <%-- Set Prev & Next icons --%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <%-- Google-style pagination --%> + + + + + 0 + 10 + + + ${(limits.countOfPages -1) - 10} + ${limits.countOfPages - 1} + + + ${page - 5} + ${page + 5} + + + + + 0 + ${limits.countOfPages - 1} + + + + + + + + + + + + + + + + ${i + 1} + + + ${i + 1} + + + + + + + + + + + + + + +

    + <%-- Pagination - end --%> + + + + +

    Latest Statistics Comparison Report

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RepositoryTotal File CountTotal SizeArtifact CountGroup CountProject CountPluginsArchetypesJarsWarsDeploymentsDownloads
    ${stats.repositoryId}${stats.fileCount}${stats.totalSize}${stats.artifactCount}${stats.groupCount}${stats.projectCount}${stats.pluginCount}${stats.archetypeCount}${stats.jarCount}${stats.warCount}${stats.deploymentCount}${stats.downloadCount}
    +
    + + +

    Statistics for Repository '${selectedRepo}'

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Date of ScanTotal File CountTotal SizeArtifact CountGroup CountProject CountPluginsArchetypesJarsWarsDeploymentsDownloads
    ${stats.dateOfScan}${stats.fileCount}${stats.totalSize}${stats.artifactCount}${stats.groupCount}${stats.projectCount}${stats.pluginCount}${stats.archetypeCount}${stats.jarCount}${stats.warCount}${stats.deploymentCount}${stats.downloadCount}
    + +
    +
    + +
    + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp index 685f24cfe..9df361cd1 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp @@ -30,7 +30,12 @@ -

    Search

    + +

    Advanced Search

    +
    + +

    Search

    +
    @@ -39,7 +44,44 @@

    Results

    @@ -49,10 +91,10 @@ <%-- search was made from the indices --%> - ${fn:length(results.hits) + (currentPage * results.limits.pageSize)} + ${fn:length(results.hits) + (currentPage * results.limits.pageSize)} -

    Hits: ${(hitsNum - results.limits.pageSize) + 1} to ${hitsNum} of ${results.totalHits}

    +

    Hits: ${(hitsNum - results.limits.pageSize) + 1} to ${hitsNum} of ${results.totalHits}

    Hits: 1 to ${hitsNum} of ${results.totalHits}

    @@ -67,18 +109,53 @@ <%-- Pagination start --%>

    <%-- Prev & Next icons --%> - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -116,25 +193,53 @@ - - - - - - - - - - - ${i + 1} - - - ${i + 1} - - + + + + + + + + + + + + ${i + 1} + + + ${i + 1} + + + + + + + + + + + + + + + + + + + + + + + ${i + 1} + + + ${i + 1} + + + - - + + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml index 7c7e8c63f..e9127bda2 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/web.xml @@ -1,4 +1,4 @@ - + - + + Apache Archiva @@ -82,20 +85,6 @@ 1 - - - XmlRpcServlet - com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet - - serviceListBeanName - xmlrpcServicesList - - - authHandlerBeanName - xmlRpcAuthenticator - - 1 - RssFeedServlet @@ -104,7 +93,7 @@ RssFeedServlet - /rss/rss_feeds + /feeds/* @@ -112,11 +101,6 @@ /repository/* - - XmlRpcServlet - /xmlrpc - - jdbc/users javax.sql.DataSource @@ -135,4 +119,5 @@ Container Shareable + diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css index 983e387b2..46856bafd 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css @@ -33,7 +33,8 @@ select, input { select { padding-left: 3px; - height: 1.4em; + height: auto; + width: auto; } input { diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/archiva-splat-32.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/archiva-splat-32.gif index 8625d2311fed0722993bc3785dc56b6a8e75694c..97dff07d274cabb0de092012c57c06e16c40efc5 100644 GIT binary patch delta 436 zcmV;l0Zaal3d;$wA_IT_2^>hUpuvL(6DnNDu%SbNt3=HjILy>2V-F7wx?qEqz%Lk- z6w4@3*}!L1L}d9lipC311BE>dGie~H96B0dIpJj>uqn41rc#k)*+4TgcIfy~Yv7;^ zX&TxBLc-9%TS9oi$a6J_i9!w)vG9@0=?Nsi29hZe#hJrrQc8c28Ay!Cqk*Mx+~~y6 zQkODnp7f}3Y9Oj+0;^f6F$4^nF>II}q?N)#hYl@dfMAl$;GzvNVua|xVFI3moYwGJ zy?W0YSOycxVZC||pl2j=>)y@#Af_#6f(JLlWtBlcVT1=4;|6y@Trw(j@Zf^Rhbhnu zQUVb}hKLRtD5-x~J@~0kAVN`e=x{agimHKGW(;W~s1KrP3zs<=0cT(+0ul_=3J)`6 z@{k@V6yeK25CDL{CIiKB!VP&3d10vu4l z0CWuGhz52z^oAw_RUtqDO)vm}0>=o1j265&RLwxIBmgWx1ONOn002h}6pd~XI9Q25 e4*-zBd%Rr&2`B^gA_*h9^k(LnXr`%KKma>Cx~_-- delta 503 zcmVOK^fA7YiJ7y2}1;L3E=@FkGp}lf|w{o&Y>a}K5~CuJ%Qxcz;9$qL~-`; znUoS_+P))3U@gNRIE`a{xWt*sirgb||A86o;@K^@8cj zAxvlPAf_#6!t8&CH^XI>L2G`(hz~Eu&2oddWK`(j!3B*EQ=l1aM+rm>86tF`0R@H# zX3!^f1VTs@I_TgEL070UP&Qf2Fhm=I^nu7U3@zit2yis_PACLOKu{|@%#g`L?dX9* z5xxv`4g>%ou*pE`#BstB!8jDl4l6`L&>;pC5P$>T476{H5hUDUphB{|00lJzNwa_e z2NW;>9RxX|fgMjK)Xp245LAT#1vJ3`016y45Hecu@=!I}4D?C@05q`99|Hhz1VPb= txY0Nf)L6+o-aG(60uo9$&^DJq0*XNI^dbo(x;U!orkr-_=|TYk06Sq!)JOmT diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java index df208f0b9..eed126ab2 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java @@ -59,7 +59,7 @@ public class RssFeedServletTest throws Exception { RssFeedServlet servlet = - (RssFeedServlet) client.newInvocation( "http://localhost/rss/rss_feeds?repoId=test-repo" ).getServlet(); + (RssFeedServlet) client.newInvocation( "http://localhost/feeds/test-repo" ).getServlet(); assertNotNull( servlet ); } @@ -67,10 +67,10 @@ public class RssFeedServletTest throws Exception { RssFeedServlet servlet = - (RssFeedServlet) client.newInvocation( "http://localhost/rss/rss_feeds?repoId=test-repo" ).getServlet(); + (RssFeedServlet) client.newInvocation( "http://localhost/feeds/test-repo" ).getServlet(); assertNotNull( servlet ); - WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?repoId=test-repo" ); + WebRequest request = new GetMethodWebRequest( "http://localhost/feeds/test-repo" ); BASE64Encoder encoder = new BASE64Encoder(); String userPass = "user1:password1"; @@ -88,10 +88,10 @@ public class RssFeedServletTest { RssFeedServlet servlet = (RssFeedServlet) client.newInvocation( - "http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" ).getServlet(); + "http://localhost/feeds/org/apache/archiva/artifact-two" ).getServlet(); assertNotNull( servlet ); - WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" ); + WebRequest request = new GetMethodWebRequest( "http://localhost/feeds/org/apache/archiva/artifact-two" ); BASE64Encoder encoder = new BASE64Encoder(); String userPass = "user1:password1"; @@ -109,12 +109,12 @@ public class RssFeedServletTest { RssFeedServlet servlet = (RssFeedServlet) client.newInvocation( - "http://localhost/rss/rss_feeds?invalid_param=xxx" ).getServlet(); + "http://localhost/feeds?invalid_param=xxx" ).getServlet(); assertNotNull( servlet ); try { - WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds?invalid_param=xxx" ); + WebResponse response = client.getResponse( "http://localhost/feeds?invalid_param=xxx" ); } catch ( HttpException he ) { @@ -127,11 +127,11 @@ public class RssFeedServletTest { RssFeedServlet servlet = (RssFeedServlet) client.newInvocation( - "http://localhost/rss/rss_feeds?repoId=unauthorized-repo" ).getServlet(); + "http://localhost/feeds/unauthorized-repo" ).getServlet(); assertNotNull( servlet ); - WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?repoId=unauthorized-repo" ); + WebRequest request = new GetMethodWebRequest( "http://localhost/feeds/unauthorized-repo" ); Encoder encoder = new Base64(); String userPass = "unauthUser:unauthPass"; @@ -153,11 +153,11 @@ public class RssFeedServletTest { RssFeedServlet servlet = (RssFeedServlet) client.newInvocation( - "http://localhost/rss/rss_feeds?repoId=unauthorized-repo" ).getServlet(); + "http://localhost/feeds/unauthorized-repo" ).getServlet(); assertNotNull( servlet ); - WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?repoId=unauthorized-repo" ); + WebRequest request = new GetMethodWebRequest( "http://localhost/feeds/unauthorized-repo" ); BASE64Encoder encoder = new BASE64Encoder(); String userPass = "user1:password1"; diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml b/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml index fcdd3503f..106e9cb73 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/webapp/WEB-INF/feedServletTest-web.xml @@ -35,7 +35,7 @@ RssFeedServlet - /rss/* + /feeds/* diff --git a/archiva-modules/archiva-web/archiva-webdav/pom.xml b/archiva-modules/archiva-web/archiva-webdav/pom.xml index 99142b078..9c95ff00d 100644 --- a/archiva-modules/archiva-web/archiva-webdav/pom.xml +++ b/archiva-modules/archiva-web/archiva-webdav/pom.xml @@ -80,21 +80,21 @@ maven-model - org.codehaus.plexus.redback + org.codehaus.redback redback-xwork-integration - org.codehaus.plexus.redback + org.codehaus.redback redback-keys-memory test - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-memory test - org.codehaus.plexus.redback + org.codehaus.redback redback-users-memory test diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResource.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResource.java index 0472b7f68..fb47038b3 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResource.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResource.java @@ -97,17 +97,20 @@ public class ArchivaDavResource private final MimeTypes mimeTypes; private List auditListeners; + + private ArchivaXworkUser archivaXworkUser; public ArchivaDavResource( String localResource, String logicalResource, ManagedRepositoryConfiguration repository, DavSession session, ArchivaDavResourceLocator locator, DavResourceFactory factory, MimeTypes mimeTypes, List auditListeners, - RepositoryContentConsumers consumers ) + RepositoryContentConsumers consumers, ArchivaXworkUser archivaXworkUser ) { this.localResource = new File( localResource ); this.logicalResource = logicalResource; this.locator = locator; this.factory = factory; this.session = session; + this.archivaXworkUser = archivaXworkUser; // TODO: push into locator as well as moving any references out of the resource factory this.repository = repository; @@ -121,10 +124,10 @@ public class ArchivaDavResource public ArchivaDavResource( String localResource, String logicalResource, ManagedRepositoryConfiguration repository, String remoteAddr, DavSession session, ArchivaDavResourceLocator locator, DavResourceFactory factory, MimeTypes mimeTypes, List auditListeners, - RepositoryContentConsumers consumers ) + RepositoryContentConsumers consumers, ArchivaXworkUser archivaXworkUser ) { this( localResource, logicalResource, repository, session, locator, factory, mimeTypes, auditListeners, - consumers ); + consumers, archivaXworkUser ); this.remoteAddr = remoteAddr; } @@ -614,7 +617,7 @@ public class ArchivaDavResource private void triggerAuditEvent( String remoteIP, String repositoryId, String resource, String action ) { - String activePrincipal = ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); + String activePrincipal = archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); AuditEvent event = new AuditEvent( repositoryId, activePrincipal, resource, action ); event.setRemoteIP( remoteIP ); diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java index da69aa7bc..f56d7abe6 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java @@ -174,6 +174,11 @@ public class ArchivaDavResourceFactory * @plexus.requirement role-hint="md5"; */ private Digester digestMd5; + + /** + * @plexus.requirement + */ + private ArchivaXworkUser archivaXworkUser; public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request, final DavServletResponse response ) @@ -181,14 +186,14 @@ public class ArchivaDavResourceFactory { checkLocatorIsInstanceOfRepositoryLocator( locator ); ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator; - + RepositoryGroupConfiguration repoGroupConfig = archivaConfiguration.getConfiguration().getRepositoryGroupsAsMap().get( archivaLocator.getRepositoryId() ); List repositories = new ArrayList(); boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() ); boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - + if ( repoGroupConfig != null ) { if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) ) @@ -225,7 +230,7 @@ public class ArchivaDavResourceFactory try { - managedRepository = getManagedRepository( repositoryId ); + managedRepository = getManagedRepository( repositoryId ); } catch ( DavException de ) { @@ -236,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() ) ); @@ -253,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; } @@ -268,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 @@ -317,7 +322,7 @@ public class ArchivaDavResourceFactory ArchivaDavResource metadataChecksumResource = new ArchivaDavResource( metadataChecksum.getAbsolutePath(), logicalResource.getPath(), null, request.getRemoteAddr(), request.getDavSession(), archivaLocator, this, - mimeTypes, auditListeners, consumers ); + mimeTypes, auditListeners, consumers, archivaXworkUser ); availableResources.add( 0, metadataChecksumResource ); } } @@ -349,7 +354,7 @@ public class ArchivaDavResourceFactory ArchivaDavResource metadataResource = new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), null, request.getRemoteAddr(), request.getDavSession(), archivaLocator, this, - mimeTypes, auditListeners, consumers ); + mimeTypes, auditListeners, consumers, archivaXworkUser ); availableResources.add( 0, metadataResource ); } catch ( RepositoryMetadataException r ) @@ -398,7 +403,7 @@ public class ArchivaDavResourceFactory resource = new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource, managedRepository.getRepository(), davSession, archivaLocator, this, mimeTypes, - auditListeners, consumers ); + auditListeners, consumers, archivaXworkUser ); } resource.addLockManager(lockManager); return resource; @@ -423,7 +428,7 @@ public class ArchivaDavResourceFactory ArchivaDavResource resource = new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), managedRepository.getRepository(), request.getRemoteAddr(), - request.getDavSession(), locator, this, mimeTypes, auditListeners, consumers ); + request.getDavSession(), locator, this, mimeTypes, auditListeners, consumers, archivaXworkUser ); if ( !resource.isCollection() ) { @@ -468,7 +473,7 @@ public class ArchivaDavResourceFactory new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), managedRepository.getRepository(), request.getRemoteAddr(), request.getDavSession(), locator, this, mimeTypes, auditListeners, - consumers ); + consumers, archivaXworkUser ); } } return resource; @@ -486,18 +491,19 @@ 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 ); + request.getDavSession(), locator, this, mimeTypes, auditListeners, consumers, archivaXworkUser ); } private boolean fetchContentFromProxies( ManagedRepositoryContent managedRepository, DavServletRequest request, @@ -622,7 +628,7 @@ public class ArchivaDavResourceFactory // TODO: remove? private void triggerAuditEvent( String remoteIP, String repositoryId, String resource, String action ) { - String activePrincipal = ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); + String activePrincipal = archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() ); AuditEvent event = new AuditEvent( repositoryId, activePrincipal, resource, action ); event.setRemoteIP( remoteIP ); @@ -716,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(); @@ -727,7 +733,25 @@ 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(), isPut ) ) + { + return true; + } + } + catch ( UnauthorizedException ae ) + { + throw new UnauthorizedDavException( repositoryId, + "You are not authenticated and authorized to access any repository." ); + } + throw new UnauthorizedDavException( repositoryId, "You are not authenticated" ); } catch ( MustChangePasswordException e ) @@ -769,11 +793,13 @@ public class ArchivaDavResourceFactory request.getSession().getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY ) ); } - String activePrincipal = ArchivaXworkUser.getActivePrincipal( sessionMap ); + String activePrincipal = archivaXworkUser.getActivePrincipal( sessionMap ); boolean allow = isAllowedToContinue( request, repositories, activePrincipal ); if( allow ) { + boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); + for( String repository : repositories ) { // for prompted authentication @@ -796,7 +822,7 @@ public class ArchivaDavResourceFactory // for the current user logged in try { - if( servletAuth.isAuthorizedToAccessVirtualRepository( activePrincipal, repository ) ) + if( servletAuth.isAuthorized( activePrincipal, repository, isPut ) ) { getResource( locator, mergedRepositoryContents, logicalResource, repository ); } @@ -888,11 +914,12 @@ public class ArchivaDavResourceFactory } else { + boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); for( String repository : repositories ) { try - { - if( servletAuth.isAuthorizedToAccessVirtualRepository( activePrincipal, repository ) ) + { + if( servletAuth.isAuthorized( activePrincipal, repository, isPut ) ) { allow = true; break; @@ -953,4 +980,14 @@ public class ArchivaDavResourceFactory return true; } } + + public void setServletAuth( ServletAuthenticator servletAuth ) + { + this.servletAuth = servletAuth; + } + + public void setHttpAuth( HttpAuthenticator httpAuth ) + { + this.httpAuth = httpAuth; + } } diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java index ad96939d1..1ebf02a93 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProvider.java @@ -24,9 +24,12 @@ 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; import org.codehaus.plexus.redback.authentication.AuthenticationResult; +import org.codehaus.plexus.redback.authorization.UnauthorizedException; import org.codehaus.plexus.redback.policy.MustChangePasswordException; import org.codehaus.plexus.redback.policy.AccountLockedException; import org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator; @@ -45,10 +48,13 @@ public class ArchivaDavSessionProvider private HttpAuthenticator httpAuth; - public ArchivaDavSessionProvider( ServletAuthenticator servletAuth, HttpAuthenticator httpAuth ) + private ArchivaXworkUser archivaXworkUser; + + public ArchivaDavSessionProvider( ServletAuthenticator servletAuth, HttpAuthenticator httpAuth, ArchivaXworkUser archivaXworkUser ) { this.servletAuth = servletAuth; this.httpAuth = httpAuth; + this.archivaXworkUser = archivaXworkUser; } public boolean attachSession( WebdavRequest request ) @@ -67,7 +73,26 @@ public class ArchivaDavSessionProvider } catch ( AuthenticationException e ) { - throw new UnauthorizedDavException( repositoryId, "You are not authenticated" ); + boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); + + // safety check for MRM-911 + String guest = archivaXworkUser.getGuest(); + try + { + if( servletAuth.isAuthorized( guest, + ( ( ArchivaDavResourceLocator ) request.getRequestLocator() ).getRepositoryId(), isPut ) ) + { + request.setDavSession(new ArchivaDavSession()); + return true; + } + } + catch ( UnauthorizedException ae ) + { + throw new UnauthorizedDavException( repositoryId, + "You are not authenticated and authorized to access any repository." ); + } + + throw new UnauthorizedDavException( repositoryId, "You are not authenticated." ); } catch ( MustChangePasswordException e ) { diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java index ca9aa5aed..a73e72d5e 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java @@ -44,6 +44,7 @@ import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ConfigurationEvent; import org.apache.maven.archiva.configuration.ConfigurationListener; 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.xwork.filter.authentication.HttpAuthenticator; import org.codehaus.plexus.spring.PlexusToSpringUtils; @@ -195,7 +196,9 @@ public class RepositoryServlet HttpAuthenticator httpAuth = (HttpAuthenticator) wac.getBean( PlexusToSpringUtils.buildSpringId( HttpAuthenticator.ROLE, "basic" ) ); - sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth ); + ArchivaXworkUser archivaXworkUser = + (ArchivaXworkUser) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaXworkUser.class.getName() ) ); + sessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth, archivaXworkUser ); } public void configurationEvent( ConfigurationEvent event ) diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java index 2a53bf99d..1b7d82bda 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/ArchivaDavSessionProviderTest.java @@ -59,7 +59,7 @@ public class ArchivaDavSessionProviderTest extends TestCase throws Exception { super.setUp(); - sessionProvider = new ArchivaDavSessionProvider(new ServletAuthenticatorMock(), new HttpAuthenticatorMock()); + sessionProvider = new ArchivaDavSessionProvider(new ServletAuthenticatorMock(), new HttpAuthenticatorMock(), null); request = new WebdavRequestImpl(new HttpServletRequestMock(), null); } @@ -362,7 +362,7 @@ public class ArchivaDavSessionProviderTest extends TestCase return true; } - public boolean isAuthorizedToAccessVirtualRepository(String arg0, String arg1) + public boolean isAuthorized(String arg0, String arg1, boolean isWriteRequest) throws UnauthorizedException { return true; diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/DavResourceTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/DavResourceTest.java index cbbc8f589..b53007004 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/DavResourceTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/DavResourceTest.java @@ -20,7 +20,6 @@ package org.apache.maven.archiva.webdav; */ import java.io.File; -import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.jackrabbit.webdav.DavException; @@ -37,12 +36,11 @@ import org.apache.jackrabbit.webdav.lock.Scope; import org.apache.jackrabbit.webdav.lock.SimpleLockManager; import org.apache.jackrabbit.webdav.lock.Type; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; -import org.apache.maven.archiva.repository.audit.AuditListener; import org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers; +import org.apache.maven.archiva.security.ArchivaXworkUser; import org.apache.maven.archiva.webdav.util.MimeTypes; import org.codehaus.plexus.spring.PlexusInSpringTestCase; import org.codehaus.plexus.spring.PlexusToSpringUtils; -import org.easymock.MockControl; import edu.emory.mathcs.backport.java.util.Collections; @@ -69,6 +67,8 @@ public class DavResourceTest extends PlexusInSpringTestCase private RepositoryContentConsumers consumers; private ManagedRepositoryConfiguration repository = new ManagedRepositoryConfiguration(); + + private ArchivaXworkUser archivaXworkUser; @Override protected void setUp() @@ -87,6 +87,7 @@ public class DavResourceTest extends PlexusInSpringTestCase lockManager = new SimpleLockManager(); resource.addLockManager(lockManager); consumers = new RepositoryContentConsumers(); + archivaXworkUser = (ArchivaXworkUser) getApplicationContext().getBean( PlexusToSpringUtils.buildSpringId( ArchivaXworkUser.class ) ); } @Override @@ -101,7 +102,7 @@ public class DavResourceTest extends PlexusInSpringTestCase private DavResource getDavResource(String logicalPath, File file) { return new ArchivaDavResource( file.getAbsolutePath(), logicalPath, repository, session, resourceLocator, - resourceFactory, mimeTypes, Collections.emptyList(), consumers ); + resourceFactory, mimeTypes, Collections.emptyList(), consumers, archivaXworkUser ); } public void testDeleteNonExistantResourceShould404() @@ -302,7 +303,7 @@ public class DavResourceTest extends PlexusInSpringTestCase public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { return new ArchivaDavResource( baseDir.getAbsolutePath(), "/", repository, session, resourceLocator, - resourceFactory, mimeTypes, Collections.emptyList(), consumers ); + resourceFactory, mimeTypes, Collections.emptyList(), consumers, archivaXworkUser ); } } } diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java index badd20cb6..e029ca583 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.java @@ -1,21 +1,550 @@ 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 Joakim Erdfelt * @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-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/UnauthenticatedDavSessionProvider.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/UnauthenticatedDavSessionProvider.java index 13082cf4d..082d62dfc 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/UnauthenticatedDavSessionProvider.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/UnauthenticatedDavSessionProvider.java @@ -29,7 +29,7 @@ public class UnauthenticatedDavSessionProvider extends ArchivaDavSessionProvider { public UnauthenticatedDavSessionProvider() { - super(null, null); + super(null, null, null); } @Override diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml new file mode 100644 index 000000000..291aa01ec --- /dev/null +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/WEB-INF/repository-servlet-security-test/web.xml @@ -0,0 +1,45 @@ + + + + + + Apache Archiva + + + org.springframework.web.context.ContextLoaderListener + + + + contextClass + org.codehaus.plexus.spring.PlexusWebApplicationContext + + + + contextConfigLocation + + classpath*:/META-INF/plexus/components.xml + classpath*:/META-INF/spring-context.xml + target/test-classes/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml + + + + diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml index d7087095a..53e79073f 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml @@ -68,9 +68,12 @@ default org.apache.maven.archiva.webdav.DefaultDavServerManager DefaultDavServerManager - - proxied - + + + org.apache.maven.archiva.webdav.DavServerComponent + proxied + + @@ -99,174 +102,74 @@ org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers default - org.apache.maven.archiva.web.repository.StubRepositoryContentConsumers + org.apache.maven.archiva.webdav.StubRepositoryContentConsumers - - + org.codehaus.plexus.redback.system.SecuritySystem default org.codehaus.plexus.redback.system.DefaultSecuritySystem - - - org.codehaus.plexus.redback.authentication.AuthenticationManager - authnManager - - - org.codehaus.plexus.redback.authorization.Authorizer - rbac - authorizer - - - org.codehaus.plexus.redback.users.UserManager - memory - userManager - - - org.codehaus.plexus.redback.keys.KeyManager - memory - keyManager - - - org.codehaus.plexus.redback.policy.UserSecurityPolicy - policy - - - - - org.codehaus.plexus.redback.authentication.Authenticator - user-manager - org.codehaus.plexus.redback.authentication.users.UserManagerAuthenticator + + + org.apache.maven.archiva.webdav.ArchivaDavResourceFactory + org.apache.maven.archiva.webdav.ArchivaDavResourceFactory - org.codehaus.plexus.redback.users.UserManager - memory - userManager + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration - org.codehaus.plexus.redback.policy.UserSecurityPolicy - securityPolicy - - - - - - org.codehaus.plexus.redback.authentication.Authenticator - keystore - org.codehaus.plexus.redback.authentication.keystore.KeyStoreAuthenticator - - - org.codehaus.plexus.redback.keys.KeyManager - memory - keystore - - - org.codehaus.plexus.redback.users.UserManager - memory - userManager - - - - - - org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator - default - org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator - - - - org.codehaus.plexus.redback.users.UserManager - memory - userManager - - - - - - org.codehaus.plexus.redback.authorization.Authorizer - rbac - org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer - + org.apache.maven.archiva.repository.RepositoryContentFactory + repositoryFactory + - org.codehaus.plexus.redback.rbac.RBACManager - memory - manager + org.apache.maven.archiva.repository.content.RepositoryRequest + repositoryRequest - org.codehaus.plexus.redback.users.UserManager - memory - userManager + org.apache.maven.archiva.proxy.RepositoryProxyConnectors + connectors - org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator - default - evaluator + org.apache.maven.archiva.repository.metadata.MetadataTools + metadataTools - - - - - org.codehaus.plexus.redback.role.RoleManager - default - org.codehaus.plexus.redback.role.DefaultRoleManager - singleton - - org.codehaus.plexus.redback.role.merger.RoleModelMerger - default - modelMerger + org.apache.maven.archiva.security.ServletAuthenticator + servletAuth - org.codehaus.plexus.redback.role.validator.RoleModelValidator - default - modelValidator + org.apache.maven.archiva.webdav.util.MimeTypes + mimeTypes - org.codehaus.plexus.redback.role.processor.RoleModelProcessor - default - modelProcessor + org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator + basic + httpAuth - org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers default - templateProcessor - org.codehaus.plexus.redback.rbac.RBACManager - memory - rbacManager + org.codehaus.plexus.digest.ChecksumFile + checksum - org.codehaus.plexus.PlexusContainer - container + org.codehaus.plexus.digest.Digester + sha1 + digestSha1 - - - - - org.codehaus.plexus.redback.role.processor.RoleModelProcessor - default - org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor - - org.codehaus.plexus.redback.rbac.RBACManager - memory - rbacManager + org.codehaus.plexus.digest.Digester + md5 + digestMd5 - - - - - org.codehaus.plexus.redback.role.template.RoleTemplateProcessor - default - org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor - - org.codehaus.plexus.redback.rbac.RBACManager - memory - rbacManager - + org.apache.maven.archiva.security.ArchivaXworkUser + archivaXworkUser + diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml index 83fd2a4e6..c691ee037 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml +++ b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml @@ -165,6 +165,10 @@ org.codehaus.plexus.digest.Digester md5 digestMd5 + + + org.apache.maven.archiva.security.ArchivaXworkUser + archivaXworkUser diff --git a/archiva-modules/archiva-web/pom.xml b/archiva-modules/archiva-web/pom.xml index 3e784c43a..a46196010 100644 --- a/archiva-modules/archiva-web/pom.xml +++ b/archiva-modules/archiva-web/pom.xml @@ -32,7 +32,6 @@ archiva-webapp archiva-webdav archiva-rss - archiva-xmlrpc diff --git a/pom-4.1.0.xml b/pom-4.1.0.xml deleted file mode 100644 index c19624797..000000000 --- a/pom-4.1.0.xml +++ /dev/null @@ -1,410 +0,0 @@ - - - - - - 4.1.0 - - - - - Archiva - archiva - pom - 1.1-SNAPSHOT - - - http://maven.apache.org/archiva/ - - - - - - - descriptor - - - - - - - - 1.5 - 1.5 - - - - - 1.5 - - - - - - - - process - - - - org.apache:apache-jar-resource-bundle:1.3 - - - - - - - - - - - 1.4 - - - - - https://svn.apache.org/repos/asf/archiva/tags - clean install - - - - - - - - archiva-base - archiva-database - archiva-reporting - archiva-scheduled - archiva-web - archiva-cli - archiva-docs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - config/maven_checks.xml - - - - - - - - true - - - - - - 1.5 - true - gr.spinellis.umlgraph.doclet.UmlGraphDoc - - gr.spinellis - UmlGraph - 4.6 - - - -inferrel -inferdep -quiet -hide java.* - -collpackages java.util.* -qualify - -postfixpackage -nodefontsize 9 - -nodefontpackagesize 7 - - - - - - - 1.5 - - - - - - - - - - - - - - - - - cpd-check - - - - - - - - - - - - - - - - - - 77 - 95 - - - - **/*$* - - - - - - - clean - - - - - check - - - - - - - - - - - - - - - - src/main/assembly/src.xml - - gnu - false - apache-archiva-${project.version}-src - - - - - single - - - - - - - - - - 2.0.5 - 1.0-rc1-SNAPSHOT - 1.0-alpha-4 - - - - - diff --git a/pom.xml b/pom.xml index 06b80399b..bdffb05b2 100644 --- a/pom.xml +++ b/pom.xml @@ -204,6 +204,12 @@ 1.2_Java1.3 test + + easymock + easymockclassextension + 1.2 + test + org.slf4j jcl104-over-slf4j @@ -381,21 +387,6 @@ archiva-webdav 1.2-SNAPSHOT - - org.apache.archiva - archiva-xmlrpc-api - 1.2-SNAPSHOT - - - org.apache.archiva - archiva-xmlrpc-services - 1.2-SNAPSHOT - - - org.apache.archiva - archiva-xmlrpc-security - 1.2-SNAPSHOT - org.apache.archiva archiva-rss @@ -516,11 +507,6 @@ mail 1.4 - - org.apache.xmlrpc - xmlrpc-server - 3.1 - org.apache.maven maven-artifact-manager @@ -648,7 +634,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-memory ${redback.version} test @@ -660,7 +646,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-users-memory ${redback.version} test @@ -672,7 +658,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-keys-memory ${redback.version} test @@ -684,7 +670,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-model ${redback.version} @@ -695,7 +681,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-authorization-rbac ${redback.version} @@ -706,7 +692,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-rbac-role-manager ${redback.version} @@ -717,7 +703,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-system ${redback.version} @@ -728,7 +714,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-taglib ${redback.version} @@ -739,7 +725,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-xwork-content ${redback.version} war @@ -751,7 +737,7 @@ - org.codehaus.plexus.redback + org.codehaus.redback redback-xwork-integration ${redback.version} @@ -890,36 +876,6 @@ ${jetty.version} - - - com.atlassian.xmlrpc - atlassian-xmlrpc-binder-annotations - ${binder.version} - - - com.atlassian.xmlrpc - atlassian-xmlrpc-binder-server-spring - ${binder.version} - - - commons-logging - commons-logging - - - - - com.atlassian.xmlrpc - atlassian-xmlrpc-binder - ${binder.version} - test - - - com.atlassian.xmlrpc - atlassian-xmlrpc-binder-testing - ${binder.version} - test - - org.springframework @@ -1002,9 +958,8 @@ 2.0.8 1.0-beta-4 - 1.0.3 + 1.1.1 6.1.6 - 0.8 @@ -1100,17 +1055,6 @@ Codehaus Snapshots Repository http://snapshots.repository.codehaus.org - - - false - - - true - - com.atlassian.snapshots - Atlassian Snapshots Repository - https://maven.atlassian.com/public-snapshot - -- 2.39.5