diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java index c6740b25b..bea69f315 100644 --- a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java @@ -19,6 +19,7 @@ package org.apache.maven.archiva.database.browsing; * under the License. */ +import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -56,7 +57,7 @@ public class DefaultRepositoryBrowsing implements RepositoryBrowsing { private Logger log = LoggerFactory.getLogger( DefaultRepositoryBrowsing.class ); - + /** * @plexus.requirement role-hint="jdo" */ @@ -67,11 +68,14 @@ public class DefaultRepositoryBrowsing */ private DatabaseUpdater dbUpdater; + /** + * @see RepositoryBrowsing#getRoot(String, List) + */ public BrowsingResults getRoot( final String principal, final List observableRepositoryIds ) { final BrowsingResults results = new BrowsingResults(); - if (!observableRepositoryIds.isEmpty()) + if ( !observableRepositoryIds.isEmpty() ) { final List groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds ) ); results.setSelectedRepositoryIds( observableRepositoryIds ); @@ -80,33 +84,40 @@ public class DefaultRepositoryBrowsing return results; } - public BrowsingResults selectArtifactId( final String principal, final List observableRepositoryIds, final String groupId, - final String artifactId ) + /** + * @see RepositoryBrowsing#selectArtifactId(String, List, String, String) + */ + public BrowsingResults selectArtifactId( final String principal, final List observableRepositoryIds, + final String groupId, final String artifactId ) { final BrowsingResults results = new BrowsingResults( groupId, artifactId ); - if (!observableRepositoryIds.isEmpty()) + if ( !observableRepositoryIds.isEmpty() ) { // NOTE: No group Id or artifact Id's should be returned here. - final List versions = dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) ); + List versions = + dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) ); results.setSelectedRepositoryIds( observableRepositoryIds ); - processSnapshots( versions ); - - results.setVersions( versions ); + results.setVersions( processSnapshots( versions ) ); } return results; } - public BrowsingResults selectGroupId( final String principal, final List observableRepositoryIds, final String groupId ) + /** + * @see RepositoryBrowsing#selectGroupId(String, List, String) + */ + public BrowsingResults selectGroupId( final String principal, final List observableRepositoryIds, + final String groupId ) { final BrowsingResults results = new BrowsingResults( groupId ); - if (!observableRepositoryIds.isEmpty()) + if ( !observableRepositoryIds.isEmpty() ) { final List groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds, groupId ) ); - final List artifacts = dao.query( new UniqueArtifactIdConstraint( observableRepositoryIds, groupId ) ); - + final List artifacts = + dao.query( new UniqueArtifactIdConstraint( observableRepositoryIds, groupId ) ); + // Remove searched for groupId from groups list. // Easier to do this here, vs doing it in the SQL query. CollectionUtils.filter( groups, NotPredicate.getInstance( PredicateUtils.equalPredicate( groupId ) ) ); @@ -118,13 +129,16 @@ public class DefaultRepositoryBrowsing return results; } - public ArchivaProjectModel selectVersion( final String principal, final List observableRepositoryIds, final String groupId, - final String artifactId, final String version ) + /** + * @see RepositoryBrowsing#selectVersion(String, List, String, String, String) + */ + public ArchivaProjectModel selectVersion( final String principal, final List observableRepositoryIds, + final String groupId, final String artifactId, final String version ) throws ObjectNotFoundException, ArchivaDatabaseException { - if (observableRepositoryIds.isEmpty()) + if ( observableRepositoryIds.isEmpty() ) { - throw new ArchivaDatabaseException("There are no observable repositories for the user " + principal); + throw new ArchivaDatabaseException( "There are no observable repositories for the user " + principal ); } ArchivaArtifact pomArtifact = getArtifact( principal, observableRepositoryIds, groupId, artifactId, version ); @@ -141,14 +155,14 @@ public class DefaultRepositoryBrowsing return model; } - - public String getRepositoryId( final String principal, final List observableRepositoryIds, final String groupId, - final String artifactId, final String version ) + + public String getRepositoryId( final String principal, final List observableRepositoryIds, + final String groupId, final String artifactId, final String version ) throws ObjectNotFoundException, ArchivaDatabaseException { - if (observableRepositoryIds.isEmpty()) + if ( observableRepositoryIds.isEmpty() ) { - throw new ArchivaDatabaseException("There are no observable repositories for the user " + principal); + throw new ArchivaDatabaseException( "There are no observable repositories for the user " + principal ); } try @@ -160,24 +174,55 @@ public class DefaultRepositoryBrowsing } catch ( ObjectNotFoundException e ) { - return getNoPomArtifactRepoId( principal, observableRepositoryIds, groupId, artifactId, version, observableRepositoryIds.get(0) ); - } + return getNoPomArtifactRepoId( principal, observableRepositoryIds, groupId, artifactId, version, + observableRepositoryIds.get( 0 ) ); + } } - - private ArchivaArtifact getArtifact( final String principal, final List observableRepositoryIds, final String groupId, - final String artifactId, final String version ) + + /** + * @see RepositoryBrowsing#getTimestampedSnapshots(List, String, String, String) + */ + public List getTimestampedSnapshots( List observableRepositoryIds, String groupId, + String artifactId, String version ) + throws ObjectNotFoundException, ArchivaDatabaseException + { + List timestampedVersions = new ArrayList(); + + if ( VersionUtil.isSnapshot( version ) ) + { + List versions = + dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) ); + + for ( String uniqueVersion : versions ) + { + if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) ) + { + if ( !timestampedVersions.contains( uniqueVersion ) ) + { + timestampedVersions.add( uniqueVersion ); + } + } + } + } + + return timestampedVersions; + } + + private ArchivaArtifact getArtifact( final String principal, final List observableRepositoryIds, + final String groupId, final String artifactId, final String version ) throws ObjectNotFoundException, ArchivaDatabaseException { ArchivaArtifact pomArtifact = null; - for (final String repositoryId : observableRepositoryIds) + for ( final String repositoryId : observableRepositoryIds ) { try { - pomArtifact = dao.getArtifactDAO().getArtifact( groupId, artifactId, version, null, "pom", repositoryId ); + pomArtifact = + dao.getArtifactDAO().getArtifact( groupId, artifactId, version, null, "pom", repositoryId ); break; } - catch ( ObjectNotFoundException e ) + catch ( ArchivaDatabaseException e ) { pomArtifact = handleGenericSnapshots( groupId, artifactId, version, repositoryId ); } @@ -187,9 +232,10 @@ public class DefaultRepositoryBrowsing { String type = getArtifactType( groupId, artifactId, version ); - //We dont want these to persist in the database - pomArtifact = new ArchivaArtifact( groupId, artifactId, version, null, type, observableRepositoryIds.get(0) ); - pomArtifact.getModel().setWhenProcessed(new Date()); + // We dont want these to persist in the database + pomArtifact = + new ArchivaArtifact( groupId, artifactId, version, null, type, observableRepositoryIds.get( 0 ) ); + pomArtifact.getModel().setWhenProcessed( new Date() ); } // Allowed to see this? @@ -199,18 +245,18 @@ public class DefaultRepositoryBrowsing } else { - throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) - + " in observable repository [" + StringUtils.join( observableRepositoryIds.iterator(), ", " ) - + "] for user " + principal ); + throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) + + " in observable repository [" + StringUtils.join( observableRepositoryIds.iterator(), ", " ) + + "] for user " + principal ); } } - public List getUsedBy( final String principal, final List observableRepositoryIds, final String groupId, - final String artifactId, final String version ) + public List getUsedBy( final String principal, final List observableRepositoryIds, + final String groupId, final String artifactId, final String version ) throws ArchivaDatabaseException { - ProjectsByArtifactUsageConstraint constraint = new ProjectsByArtifactUsageConstraint( groupId, artifactId, - version ); + ProjectsByArtifactUsageConstraint constraint = + new ProjectsByArtifactUsageConstraint( groupId, artifactId, version ); List results = dao.getProjectModelDAO().queryProjectModels( constraint ); if ( results == null ) { @@ -222,64 +268,54 @@ public class DefaultRepositoryBrowsing } /** - * Add generic (*-SNAPSHOT) snapshot versions in the list for artifacts with only unique version (timestamped) - * snapshots. - *

- * Ex. - * artifact1 has the ff. versions retrieved from the db: - * - 1.0 - * - 1.1-20061118.060401-2 - * - 1.1-20061118.060402-3 - * - 2.2-20071007.070101-1 - * - 2.2-20071007.070110-2 - * - 2.2-SNAPSHOT - *

- * This method will add a '1.1-SNAPSHOT' in the list since there is no generic snapshot entry for it. - * When this version is browsed, the pom of the latest snapshot will be displayed. - * + * Removes SNAPSHOT versions with build numbers. Retains only the generic SNAPSHOT version. + * Example, if the list of versions are: + * - 2.0 + * - 2.0.1 + * - 2.1-20070522.143249-1 + * - 2.1-20070522.157829-2 + * + * the returned version list would contain 2.0, 2.0.1 and 2.1-SNAPSHOT. + * * @param versions */ - private void processSnapshots( final List versions ) + private List processSnapshots( List versions ) { - Map snapshots = new HashMap(); + List cleansedVersions = new ArrayList(); for ( String version : versions ) { if ( VersionUtil.isSnapshot( version ) ) - { + { String baseVersion = VersionUtil.getBaseVersion( version ); - if ( !snapshots.containsKey( baseVersion ) ) + if ( !cleansedVersions.contains( baseVersion ) ) { - snapshots.put( baseVersion, baseVersion ); + cleansedVersions.add( baseVersion ); } } + else + { + cleansedVersions.add( version ); + } } - for ( Entry entry : snapshots.entrySet() ) - { - String baseVersion = entry.getValue(); - if ( !versions.contains( baseVersion ) ) - { - versions.add( baseVersion ); - } - } + return cleansedVersions; } /** - * Handles querying of generic (*-SNAPSHOT) snapshot version. - * Process: - * - Get all the timestamped/unique versions of the artifact from the db - * - Sort the queried project models - * - Reverse the list of queried project models to get the latest timestamp version - * - Loop through the list and get the first one to match the generic (*-SNAPHOT) version - * + * Handles querying of generic (*-SNAPSHOT) snapshot version. Process: - Get all the timestamped/unique versions of + * the artifact from the db - Sort the queried project models - Reverse the list of queried project models to get + * the latest timestamp version - Loop through the list and get the first one to match the generic (*-SNAPHOT) + * version + * * @param groupId * @param artifactId * @param version * @param pomArtifact * @throws ArchivaDatabaseException */ - private ArchivaArtifact handleGenericSnapshots( final String groupId, final String artifactId, final String version, final String repositoryId ) + private ArchivaArtifact handleGenericSnapshots( final String groupId, final String artifactId, + final String version, final String repositoryId ) throws ArchivaDatabaseException { ArchivaArtifact result = null; @@ -294,8 +330,19 @@ public class DefaultRepositoryBrowsing { if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) ) { - log.info( "Retrieving artifact with version " + uniqueVersion ); - result = dao.getArtifactDAO().getArtifact( groupId, artifactId, uniqueVersion, null, "pom", repositoryId ); + try + { + log.info( "Retrieving artifact with version " + uniqueVersion ); + result = + dao.getArtifactDAO().getArtifact( groupId, artifactId, uniqueVersion, null, "pom", repositoryId ); + break; + } + catch ( ArchivaDatabaseException e ) + { + log.warn( "Artifact '" + groupId + ":" + artifactId + ":" + uniqueVersion + + "' in repository '" + repositoryId + "' not found in the database." ); + continue; + } } } } @@ -304,7 +351,7 @@ public class DefaultRepositoryBrowsing /** * Get the project model from the database. - * + * * @param groupId * @param artifactId * @param version @@ -320,57 +367,59 @@ public class DefaultRepositoryBrowsing { model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version ); } - catch (ObjectNotFoundException e) + catch ( ObjectNotFoundException e ) { - log.debug("Unable to find project model for [" + Keys.toKey( groupId, artifactId, version ) + "]", e); + log.debug( "Unable to find project model for [" + Keys.toKey( groupId, artifactId, version ) + "]", e ); } if ( model == null ) { model = new ArchivaProjectModel(); - model.setGroupId(groupId); - model.setArtifactId(artifactId); - model.setVersion(version); + model.setGroupId( groupId ); + model.setArtifactId( artifactId ); + model.setVersion( version ); } return model; } - - private String getNoPomArtifactRepoId( String principal, List observableRepos, String groupId, String artifactId, String version, String repositoryId ) + + private String getNoPomArtifactRepoId( String principal, List observableRepos, String groupId, + String artifactId, String version, String repositoryId ) throws ObjectNotFoundException, ArchivaDatabaseException { ArchivaArtifact artifact = null; - + String type = getArtifactType( groupId, artifactId, version ); - + artifact = dao.getArtifactDAO().createArtifact( groupId, artifactId, version, null, type, repositoryId ); if ( artifact == null ) { - //Lets not persist these + // Lets not persist these artifact = new ArchivaArtifact( groupId, artifactId, version, null, type, repositoryId ); } // Allowed to see this? if ( !observableRepos.contains( artifact.getModel().getRepositoryId() ) ) { - throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) - + " in observable repository [" + StringUtils.join( observableRepos.iterator(), ", " ) - + "] for user " + principal ); + throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) + + " in observable repository [" + StringUtils.join( observableRepos.iterator(), ", " ) + "] for user " + + principal ); } return artifact.getModel().getRepositoryId(); } - + private String getArtifactType( String groupId, String artifactId, String version ) throws ObjectNotFoundException, ArchivaDatabaseException { String type = "jar"; - + try { - List artifacts = dao.getArtifactDAO().queryArtifacts( new ArtifactsRelatedConstraint( groupId, artifactId, version ) ); - + List artifacts = + dao.getArtifactDAO().queryArtifacts( new ArtifactsRelatedConstraint( groupId, artifactId, version ) ); + if ( artifacts.size() > 0 ) { type = artifacts.get( 0 ).getType(); @@ -378,10 +427,10 @@ public class DefaultRepositoryBrowsing } catch ( ObjectNotFoundException e ) { - //swallow exception? + // swallow exception? } - + return type; } - + } diff --git a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java index fd79a67c8..270291d2f 100644 --- a/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java +++ b/archiva-modules/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java @@ -89,4 +89,20 @@ public interface RepositoryBrowsing public String getRepositoryId( String principle, List observableRepositoryIds, String groupId, String artifactId, String version ) throws ObjectNotFoundException, ArchivaDatabaseException; + + /** + * Get the timestamped versions or versions with build numbers of the given SNAPSHOT artifact. + * + * @param observableRepositoryIds + * @param groupId + * @param artifactId + * @param version + * @return + * @throws ObjectNotFoundException + * @throws ArchivaDatabaseException + */ + public List getTimestampedSnapshots( List observableRepositoryIds, + String groupId, String artifactId, String version ) + throws ObjectNotFoundException, ArchivaDatabaseException; + } diff --git a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java index 8ac9c80a5..b574d829c 100644 --- a/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java +++ b/archiva-modules/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java @@ -89,6 +89,12 @@ public class RepositoryBrowsingTest artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1-SNAPSHOT" ); artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1-20070522.143249-1" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1-20070522.153141-2" ); + artifactDao.saveArtifact( artifact ); artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1.1" ); artifactDao.saveArtifact( artifact ); @@ -142,6 +148,22 @@ public class RepositoryBrowsingTest assertEquals( "commons-lang", artifact.getArtifactId() ); assertEquals( "2.0", artifact.getVersion() ); } + + public void testSelectArtifactId() + throws Exception + { + saveTestData(); + + RepositoryBrowsing browser = lookupBrowser(); + BrowsingResults results = + browser.selectArtifactId( USER_GUEST, GUEST_REPO_IDS, "org.apache.maven.shared", "test-two" ); + assertNotNull( "Browsing results should not be null.", results ); + assertEquals( 4, results.getVersions().size() ); + assertTrue( results.getVersions().contains( "2.0" ) ); + assertTrue( results.getVersions().contains( "2.1-SNAPSHOT" ) ); + assertTrue( results.getVersions().contains( "2.1.1" ) ); + assertTrue( results.getVersions().contains( "2.1-alpha-1" ) ); + } private void assertGroupIds( String msg, List actualGroupIds, String[] expectedGroupIds ) { 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 8ec411f0d..be1323844 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 @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import org.apache.commons.lang.StringUtils; +import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.database.ObjectNotFoundException; import org.apache.maven.archiva.database.browsing.RepositoryBrowsing; @@ -94,6 +95,8 @@ public class ShowArtifactAction private List mailingLists; private List dependencies; + + private List snapshotVersions; /** * Show the versioned project information tab. TODO: Change name to 'project' @@ -103,14 +106,30 @@ public class ShowArtifactAction { try { - this.model = - repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); + if( VersionUtil.isSnapshot( version ) ) + { + this.model = + repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); + + this.snapshotVersions = + repoBrowsing.getTimestampedSnapshots( getObservableRepos(), groupId, artifactId, version ); + if( this.snapshotVersions.contains( version ) ) + { + this.snapshotVersions.remove( version ); + } + } + else + { + this.model = + repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); + } + this.repositoryId = repoBrowsing.getRepositoryId( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); } catch ( ObjectNotFoundException e ) { - getLogger().debug(e.getMessage(), e); + getLogger().debug( e.getMessage(), e ); addActionError( e.getMessage() ); return ERROR; } @@ -292,4 +311,14 @@ public class ShowArtifactAction this.repositoryId = repositoryId; } + public List getSnapshotVersions() + { + return snapshotVersions; + } + + public void setSnapshotVersions( List snapshotVersions ) + { + this.snapshotVersions = snapshotVersions; + } + } 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 fae9f6eed..a85f9ccd4 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 @@ -90,6 +90,23 @@ + + + Other Versions + + + + + + + + + + ${snapshot} + + + + <%-- TODO: deployment timestamp Deployment Date