diff options
11 files changed, 403 insertions, 76 deletions
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 42020f657..3630a75bb 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 @@ -19,9 +19,14 @@ package org.apache.maven.archiva.web.action; * under the License. */ +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; +import org.apache.archiva.metadata.repository.MetadataResolver; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.database.ArchivaDatabaseException; @@ -39,7 +44,6 @@ import org.apache.maven.archiva.security.UserRepositories; * * @todo cache browsing results. * @todo implement repository selectors (all or specific repository) - * @todo implement security around browse (based on repository id at first) * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="browseAction" instantiation-strategy="per-lookup" */ public class BrowseAction @@ -49,22 +53,29 @@ public class BrowseAction * @plexus.requirement role-hint="default" */ private RepositoryBrowsing repoBrowsing; - + + /** + * @plexus.requirement + */ + private MetadataResolver metadataResolver; + /** * @plexus.requirement */ private UserRepositories userRepositories; - + + // TODO: eventually, move to just use the metadata directly, with minimal JSP changes private BrowsingResults results; private String groupId; private String artifactId; - + private String repositoryId; - + + // TODO: eventually, move to just use the metadata directly, with minimal JSP changes, mostly for Maven specifics private ArchivaProjectModel sharedModel; - + public String browse() { List<String> selectedRepos = getObservableRepos(); @@ -73,10 +84,49 @@ public class BrowseAction return GlobalResults.ACCESS_TO_NO_REPOS; } - this.results = repoBrowsing.getRoot( getPrincipal(), selectedRepos ); + Set<String> namespaces = new LinkedHashSet<String>(); + for ( String repoId : selectedRepos ) + { + Collection<String> rootNamespaces = metadataResolver.getRootNamespaces( repoId ); + // TODO: this logic should be optional, particularly remembering we want to keep this code simple + // it is located here to avoid the content repository implementation needing to do too much for what + // is essentially presentation code + for ( String n : rootNamespaces ) + { + // TODO: check performance of this + namespaces.add( collapseNamespaces( repoId, n ) ); + } + } + ArrayList<String> list = new ArrayList<String>( namespaces ); + Collections.sort( list ); + + this.results = new BrowsingResults(); + results.setGroupIds( list ); + results.setSelectedRepositoryIds( selectedRepos ); return SUCCESS; } + private String collapseNamespaces( String repoId, String n ) + { + Collection<String> subNamespaces = metadataResolver.getNamespaces( repoId, n ); + if ( subNamespaces.size() != 1 ) + { + return n; + } + else + { + Collection<String> projects = metadataResolver.getProjects( repoId, n ); + if ( projects != null && !projects.isEmpty() ) + { + return n; + } + else + { + return collapseNamespaces( repoId, n + "." + subNamespaces.iterator().next() ); + } + } + } + public String browseGroup() { if ( StringUtils.isEmpty( groupId ) ) @@ -92,7 +142,6 @@ public class BrowseAction return GlobalResults.ACCESS_TO_NO_REPOS; } - this.results = repoBrowsing.selectGroupId( getPrincipal(), selectedRepos, groupId ); return SUCCESS; } @@ -118,11 +167,11 @@ public class BrowseAction { return GlobalResults.ACCESS_TO_NO_REPOS; } - + this.results = repoBrowsing.selectArtifactId( getPrincipal(), selectedRepos, groupId, artifactId ); populateSharedModel(); - + return SUCCESS; } @@ -132,20 +181,20 @@ public class BrowseAction sharedModel.setGroupId( groupId ); sharedModel.setArtifactId( artifactId ); boolean isFirstVersion = true; - - for( String version : this.results.getVersions() ) - { + + for ( String version : this.results.getVersions() ) + { try { ArchivaProjectModel model = repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); - - if( model == null ) + + if ( model == null ) { continue; } - - if( isFirstVersion ) + + if ( isFirstVersion ) { sharedModel = model; sharedModel.setVersion( null ); @@ -157,7 +206,7 @@ public class BrowseAction { sharedModel.setPackaging( null ); } - + if ( sharedModel.getName() != null && !StringUtils.equalsIgnoreCase( sharedModel.getName(), model.getName() ) ) { @@ -171,29 +220,33 @@ public class BrowseAction } if ( sharedModel.getIssueManagement() != null && model.getIssueManagement() != null && - !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getIssueManagementUrl(), model.getIssueManagement().getIssueManagementUrl() ) ) + !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getIssueManagementUrl(), + model.getIssueManagement().getIssueManagementUrl() ) ) { sharedModel.setIssueManagement( null ); } if ( sharedModel.getCiManagement() != null && model.getCiManagement() != null && - !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getCiUrl(), model.getCiManagement().getCiUrl() ) ) + !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getCiUrl(), + model.getCiManagement().getCiUrl() ) ) { sharedModel.setCiManagement( null ); } - if ( sharedModel.getOrganization() != null && model.getOrganization() != null && - !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getOrganizationName(), model.getOrganization().getOrganizationName() ) ) + if ( sharedModel.getOrganization() != null && model.getOrganization() != null && + !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getOrganizationName(), + model.getOrganization().getOrganizationName() ) ) { sharedModel.setOrganization( null ); } - if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(), model.getUrl() ) ) + if ( sharedModel.getUrl() != null && + !StringUtils.equalsIgnoreCase( sharedModel.getUrl(), model.getUrl() ) ) { sharedModel.setUrl( null ); } } - + isFirstVersion = false; } catch ( ObjectNotFoundException e ) @@ -204,9 +257,9 @@ public class BrowseAction { log.debug( e.getMessage(), e ); } - } + } } - + private List<String> getObservableRepos() { try @@ -253,15 +306,17 @@ public class BrowseAction { return results; } - - public String getRepositoryId(){ - - return repositoryId; + + public String getRepositoryId() + { + + return repositoryId; } - - public void setRepositoryId(String repositoryId){ - - this.repositoryId = repositoryId; + + public void setRepositoryId( String repositoryId ) + { + + this.repositoryId = repositoryId; } public ArchivaProjectModel getSharedModel() @@ -273,4 +328,9 @@ public class BrowseAction { this.sharedModel = sharedModel; } + + public MetadataResolver getMetadataResolver() + { + return metadataResolver; + } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/archiva/metadata/repository/memory/TestMetadataResolver.java b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/archiva/metadata/repository/memory/TestMetadataResolver.java index 8287f3aae..b0473b201 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/archiva/metadata/repository/memory/TestMetadataResolver.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/archiva/metadata/repository/memory/TestMetadataResolver.java @@ -22,8 +22,10 @@ package org.apache.archiva.metadata.repository.memory; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.archiva.metadata.model.ProjectMetadata; import org.apache.archiva.metadata.model.ProjectVersionMetadata; @@ -40,6 +42,10 @@ public class TestMetadataResolver private Map<String, List<ProjectVersionReference>> references = new HashMap<String, List<ProjectVersionReference>>(); + private List<String> namespaces; + + private Map<String, Collection<String>> projectsInNamespace = new HashMap<String, Collection<String>>(); + public ProjectMetadata getProject( String repoId, String namespace, String projectId ) { ProjectMetadata metadata = new ProjectMetadata(); @@ -67,10 +73,54 @@ public class TestMetadataResolver return references.get( createMapKey( repoId, namespace, projectId, projectVersion ) ); } + public Collection<String> getRootNamespaces( String repoId ) + { + return getNamespaces( null ); + } + + private Collection<String> getNamespaces( String baseNamespace ) + { + Set<String> namespaces = new LinkedHashSet<String>(); + int fromIndex = baseNamespace != null ? baseNamespace.length() + 1 : 0; + for ( String namespace : this.namespaces ) + { + if ( baseNamespace == null || namespace.startsWith( baseNamespace + "." ) ) + { + int i = namespace.indexOf( '.', fromIndex ); + if ( i >= 0 ) + { + namespaces.add( namespace.substring( fromIndex, i ) ); + } + else + { + namespaces.add( namespace.substring( fromIndex ) ); + } + } + } + return namespaces; + } + + public Collection<String> getNamespaces( String repoId, String namespace ) + { + return getNamespaces( namespace ); + } + + public Collection<String> getProjects( String repoId, String namespace ) + { + return projectsInNamespace.get( namespace ); + } + public void setProjectVersion( String repoId, String namespace, String projectId, ProjectVersionMetadata versionMetadata ) { projectVersions.put( createMapKey( repoId, namespace, projectId, versionMetadata.getId() ), versionMetadata ); + Collection<String> projects = projectsInNamespace.get( namespace ); + if ( projects == null ) + { + projects = new LinkedHashSet<String>(); + projectsInNamespace.put( namespace, projects ); + } + projects.add( projectId ); } public void setArtifactVersions( String repoId, String namespace, String projectId, String projectVersion, @@ -89,4 +139,9 @@ public class TestMetadataResolver { this.references.put( createMapKey( repoId, namespace, projectId, projectVersion ), references ); } + + public void setNamespaces( List<String> namespaces ) + { + this.namespaces = namespaces; + } } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/BrowseActionTest.java b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/BrowseActionTest.java index 2fb9658d2..dd95b40cc 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/BrowseActionTest.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/BrowseActionTest.java @@ -24,6 +24,8 @@ import java.util.Collections; import java.util.List; import com.opensymphony.xwork2.Action; +import org.apache.archiva.metadata.model.ProjectVersionMetadata; +import org.apache.archiva.metadata.repository.memory.TestMetadataResolver; import org.apache.maven.archiva.database.ArchivaDAO; import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.database.ArtifactDAO; @@ -52,7 +54,8 @@ public class BrowseActionTest private ArchivaDAOStub archivaDao; private static final List<String> GROUPS = - Arrays.asList( "org.apache.archiva", "commons-lang", "org.apache.maven", "com.sun", "com.oracle" ); + Arrays.asList( "org.apache.archiva", "commons-lang", "org.apache.maven", "com.sun", "com.oracle", + "repeat.repeat", "org.apache", "single.group" ); public void testInstantiation() { @@ -61,7 +64,9 @@ public class BrowseActionTest public void testBrowse() { - archivaDao.setGroups( GROUPS ); + metadataResolver.setNamespaces( GROUPS ); + // add an artifact in the tree to make sure "single" is not collapsed + metadataResolver.setProjectVersion( TEST_REPO, "single", "single", new ProjectVersionMetadata() ); String result = action.browse(); assertSuccessResult( result ); @@ -69,7 +74,8 @@ public class BrowseActionTest BrowsingResults results = action.getResults(); assertNotNull( results ); assertEquals( Arrays.asList( TEST_REPO ), results.getSelectedRepositoryIds() ); - assertEquals( Arrays.asList( "com", "commons-lang", "org.apache" ), results.getGroupIds() ); + assertEquals( Arrays.asList( "com", "commons-lang", "org.apache", "repeat.repeat", "single" ), + results.getGroupIds() ); assertNull( results.getArtifacts() ); assertNull( results.getSelectedArtifactId() ); assertNull( results.getSelectedGroupId() ); @@ -390,6 +396,7 @@ public class BrowseActionTest super.setUp(); action = (BrowseAction) lookup( Action.class, ACTION_HINT ); archivaDao = (ArchivaDAOStub) lookup( ArchivaDAO.class, "jdo" ); + metadataResolver = (TestMetadataResolver) action.getMetadataResolver(); } protected ArchivaProjectModel createProjectModel( String groupId, String artifactId, String version ) diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/BrowseActionTest.xml b/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/BrowseActionTest.xml index cccf675cb..3bd761e19 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/BrowseActionTest.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/BrowseActionTest.xml @@ -35,5 +35,11 @@ <role-hint>default</role-hint> <implementation>org.apache.maven.archiva.security.UserRepositoriesStub</implementation> </component> + <component> + <role>org.apache.archiva.metadata.repository.MetadataResolver</role> + <role-hint>default</role-hint> + <implementation>org.apache.archiva.metadata.repository.memory.TestMetadataResolver</implementation> + <instantiation-strategy>per-lookup</instantiation-strategy> + </component> </components> </plexus> diff --git a/archiva-modules/metadata/metadata-model/src/main/java/org/apache/archiva/metadata/model/ProjectVersionMetadata.java b/archiva-modules/metadata/metadata-model/src/main/java/org/apache/archiva/metadata/model/ProjectVersionMetadata.java index 0f60d601e..5e4626f94 100644 --- a/archiva-modules/metadata/metadata-model/src/main/java/org/apache/archiva/metadata/model/ProjectVersionMetadata.java +++ b/archiva-modules/metadata/metadata-model/src/main/java/org/apache/archiva/metadata/model/ProjectVersionMetadata.java @@ -43,13 +43,13 @@ public class ProjectVersionMetadata private CiManagement ciManagement; - private List<License> licenses; + private List<License> licenses = new ArrayList<License>(); private Map<String, ProjectVersionFacet> facets = new HashMap<String, ProjectVersionFacet>(); - private List<MailingList> mailingLists; + private List<MailingList> mailingLists = new ArrayList<MailingList>(); - private List<Dependency> dependencies; + private List<Dependency> dependencies = new ArrayList<Dependency>(); public String getId() { @@ -143,10 +143,6 @@ public class ProjectVersionMetadata public void addLicense( License license ) { - if ( this.licenses == null ) - { - this.licenses = new ArrayList<License>(); - } this.licenses.add( license ); } @@ -182,10 +178,6 @@ public class ProjectVersionMetadata public void addMailingList( MailingList mailingList ) { - if ( this.mailingLists == null ) - { - this.mailingLists = new ArrayList<MailingList>(); - } this.mailingLists.add( mailingList ); } @@ -201,10 +193,6 @@ public class ProjectVersionMetadata public void addDependency( Dependency dependency ) { - if ( this.dependencies == null ) - { - this.dependencies = new ArrayList<Dependency>(); - } this.dependencies.add( dependency ); } } diff --git a/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/DefaultMetadataResolver.java b/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/DefaultMetadataResolver.java index 64f15522d..17b237455 100644 --- a/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/DefaultMetadataResolver.java +++ b/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/DefaultMetadataResolver.java @@ -101,4 +101,25 @@ public class DefaultMetadataResolver // not passed to the storage mechanism as resolving references would require iterating all artifacts return metadataRepository.getProjectReferences( repoId, namespace, projectId, projectVersion ); } + + public Collection<String> getRootNamespaces( String repoId ) + { + // TODO: is this assumption correct? could a storage mech. actually know all references in a non-Maven scenario? + // not passed to the storage mechanism as resolving references would require iterating all groups + return metadataRepository.getRootNamespaces( repoId ); + } + + public Collection<String> getNamespaces( String repoId, String namespace ) + { + // TODO: is this assumption correct? could a storage mech. actually know all references in a non-Maven scenario? + // not passed to the storage mechanism as resolving references would require iterating all groups + return metadataRepository.getNamespaces( repoId, namespace ); + } + + public Collection<String> getProjects( String repoId, String namespace ) + { + // TODO: is this assumption correct? could a storage mech. actually know all references in a non-Maven scenario? + // not passed to the storage mechanism as resolving references would require iterating all projects + return metadataRepository.getProjects( repoId, namespace ); + } } diff --git a/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/MetadataResolver.java b/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/MetadataResolver.java index e6f8e6316..2a2600ae0 100644 --- a/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/MetadataResolver.java +++ b/archiva-modules/metadata/metadata-repository-api/src/main/java/org/apache/archiva/metadata/repository/MetadataResolver.java @@ -47,4 +47,10 @@ public interface MetadataResolver */ Collection<ProjectVersionReference> getProjectReferences( String repoId, String namespace, String projectId, String projectVersion ); + + Collection<String> getRootNamespaces( String repoId ); + + Collection<String> getNamespaces( String repoId, String namespace ); + + Collection<String> getProjects( String repoId, String namespace ); } diff --git a/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolver.java b/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolver.java index 54e6f2e50..10ba310b4 100644 --- a/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolver.java +++ b/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/metadata/repository/storage/maven2/Maven2RepositoryMetadataResolver.java @@ -281,4 +281,19 @@ public class Maven2RepositoryMetadataResolver { throw new UnsupportedOperationException(); } + + public Collection<String> getRootNamespaces( String repoId ) + { + throw new UnsupportedOperationException(); + } + + public List<String> getNamespaces( String repoId, String namespace ) + { + throw new UnsupportedOperationException(); + } + + public Collection<String> getProjects( String repoId, String namespace ) + { + throw new UnsupportedOperationException(); + } } diff --git a/archiva-modules/plugins/metadata-repository-file/pom.xml b/archiva-modules/plugins/metadata-repository-file/pom.xml index ec034157b..09eeeb71b 100644 --- a/archiva-modules/plugins/metadata-repository-file/pom.xml +++ b/archiva-modules/plugins/metadata-repository-file/pom.xml @@ -40,5 +40,20 @@ <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-spring</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java b/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java index 728898acc..57772258c 100644 --- a/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java +++ b/archiva-modules/plugins/metadata-repository-file/src/main/java/org/apache/archiva/metadata/repository/file/FileMetadataRepository.java @@ -28,9 +28,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import org.apache.archiva.metadata.model.ArtifactMetadata; import org.apache.archiva.metadata.model.CiManagement; @@ -70,17 +72,30 @@ public class FileMetadataRepository private static final Logger log = LoggerFactory.getLogger( FileMetadataRepository.class ); + private static final String PROJECT_METADATA_KEY = "project-metadata"; + + private static final String PROJECT_VERSION_METADATA_KEY = "version-metadata"; + + private static final String NAMESPACE_METADATA_KEY = "namespace-metadata"; + public void updateProject( String repoId, ProjectMetadata project ) { + updateProject( repoId, project.getNamespace(), project.getId() ); + } + + private void updateProject( String repoId, String namespace, String id ) + { // TODO: this is a more braindead implementation than we would normally expect, for prototyping purposes try { - File projectDirectory = - new File( this.directory, repoId + "/" + project.getNamespace() + "/" + project.getId() ); + File namespaceDirectory = new File( this.directory, repoId + "/" + namespace ); Properties properties = new Properties(); - properties.setProperty( "namespace", project.getNamespace() ); - properties.setProperty( "id", project.getId() ); - writeProperties( properties, projectDirectory ); + properties.setProperty( "namespace", namespace ); + writeProperties( properties, namespaceDirectory, NAMESPACE_METADATA_KEY ); + + properties.setProperty( "id", id ); + writeProperties( properties, new File( namespaceDirectory, id ), PROJECT_METADATA_KEY ); + } catch ( IOException e ) { @@ -92,10 +107,12 @@ public class FileMetadataRepository public void updateProjectVersion( String repoId, String namespace, String projectId, ProjectVersionMetadata versionMetadata ) { + updateProject( repoId, namespace, projectId ); + File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + versionMetadata.getId() ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); // remove properties that are not references or artifacts for ( String name : properties.stringPropertyNames() ) { @@ -167,7 +184,7 @@ public class FileMetadataRepository try { - writeProperties( properties, directory ); + writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY ); } catch ( IOException e ) { @@ -181,7 +198,7 @@ public class FileMetadataRepository { File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); int i = Integer.valueOf( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1; setProperty( properties, "ref:lastReferenceNum", Integer.toString( i ) ); setProperty( properties, "ref:reference." + i + ".namespace", reference.getNamespace() ); @@ -191,7 +208,7 @@ public class FileMetadataRepository try { - writeProperties( properties, directory ); + writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY ); } catch ( IOException e ) { @@ -202,13 +219,17 @@ public class FileMetadataRepository private String join( Collection<String> ids ) { - StringBuilder s = new StringBuilder(); - for ( String id : ids ) + if ( !ids.isEmpty() ) { - s.append( id ); - s.append( "," ); + StringBuilder s = new StringBuilder(); + for ( String id : ids ) + { + s.append( id ); + s.append( "," ); + } + return s.substring( 0, s.length() - 1 ); } - return s.substring( 0, s.length() - 1 ); + return ""; } private void setProperty( Properties properties, String name, String value ) @@ -224,7 +245,7 @@ public class FileMetadataRepository { File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); properties.setProperty( "artifact:updated:" + artifact.getId(), Long.toString( artifact.getUpdated().getTime() ) ); @@ -233,7 +254,7 @@ public class FileMetadataRepository try { - writeProperties( properties, directory ); + writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY ); } catch ( IOException e ) { @@ -242,13 +263,13 @@ public class FileMetadataRepository } } - private Properties readProperties( File directory ) + private Properties readProperties( File directory, String propertiesKey ) { Properties properties = new Properties(); FileInputStream in = null; try { - in = new FileInputStream( new File( directory, "metadata.properties" ) ); + in = new FileInputStream( new File( directory, propertiesKey + ".properties" ) ); properties.load( in ); } catch ( FileNotFoundException e ) @@ -271,7 +292,7 @@ public class FileMetadataRepository { File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); ProjectMetadata project = new ProjectMetadata(); project.setNamespace( properties.getProperty( "namespace" ) ); @@ -284,7 +305,7 @@ public class FileMetadataRepository { File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); String id = properties.getProperty( "id" ); ProjectVersionMetadata versionMetadata = null; if ( id != null ) @@ -443,7 +464,7 @@ public class FileMetadataRepository { File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); List<String> versions = new ArrayList<String>(); for ( Map.Entry entry : properties.entrySet() ) @@ -462,7 +483,7 @@ public class FileMetadataRepository { File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion ); - Properties properties = readProperties( directory ); + Properties properties = readProperties( directory, PROJECT_VERSION_METADATA_KEY ); int numberOfRefs = Integer.valueOf( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1; List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>(); @@ -479,11 +500,70 @@ public class FileMetadataRepository return references; } - private void writeProperties( Properties properties, File directory ) + public Collection<String> getRootNamespaces( String repoId ) + { + return getNamespaces( repoId, null ); + } + + public Collection<String> getNamespaces( String repoId, String baseNamespace ) + { + List<String> allNamespaces = new ArrayList<String>(); + File directory = new File( this.directory, repoId ); + File[] files = directory.listFiles(); + if ( files != null ) + { + for ( File namespace : files ) + { + if ( new File( namespace, NAMESPACE_METADATA_KEY + ".properties" ).exists() ) + { + allNamespaces.add( namespace.getName() ); + } + } + } + + Set<String> namespaces = new LinkedHashSet<String>(); + int fromIndex = baseNamespace != null ? baseNamespace.length() + 1 : 0; + for ( String namespace : allNamespaces ) + { + if ( baseNamespace == null || namespace.startsWith( baseNamespace + "." ) ) + { + int i = namespace.indexOf( '.', fromIndex ); + if ( i >= 0 ) + { + namespaces.add( namespace.substring( fromIndex, i ) ); + } + else + { + namespaces.add( namespace.substring( fromIndex ) ); + } + } + } + return new ArrayList<String>( namespaces ); + } + + public Collection<String> getProjects( String repoId, String namespace ) + { + List<String> projects = new ArrayList<String>(); + File directory = new File( this.directory, repoId + "/" + namespace ); + File[] files = directory.listFiles(); + if ( files != null ) + { + for ( File project : files ) + { + if ( new File( project, PROJECT_METADATA_KEY + ".properties" ).exists() ) + { + projects.add( project.getName() ); + } + } + } + return projects; + } + + private void writeProperties( Properties properties, File directory, String propertiesKey ) throws IOException { directory.mkdirs(); - FileOutputStream os = new FileOutputStream( new File( directory, "metadata.properties" ) ); + FileOutputStream os = new FileOutputStream( new File( directory, propertiesKey + ".properties" ) ); try { properties.store( os, null ); @@ -494,4 +574,8 @@ public class FileMetadataRepository } } + public void setDirectory( File directory ) + { + this.directory = directory; + } } diff --git a/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java b/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java new file mode 100644 index 000000000..45c8bf247 --- /dev/null +++ b/archiva-modules/plugins/metadata-repository-file/src/test/java/org/apache/archiva/metadata/repository/file/FileMetadataRepositoryTest.java @@ -0,0 +1,70 @@ +package org.apache.archiva.metadata.repository.file; + +import java.io.File; +import java.util.Collection; +import java.util.Collections; + +import org.apache.archiva.metadata.model.MailingList; +import org.apache.archiva.metadata.model.ProjectVersionMetadata; +import org.apache.archiva.metadata.repository.MetadataRepository; +import org.apache.commons.io.FileUtils; +import org.codehaus.plexus.spring.PlexusInSpringTestCase; + +/* + * 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. + */ + +public class FileMetadataRepositoryTest + extends PlexusInSpringTestCase +{ + private FileMetadataRepository repository; + + private static final String TEST_REPO_ID = "test"; + + private static final String TEST_PROJECT = "projectId"; + + private static final String TEST_NAMESPACE = "namespace"; + + public void setUp() + throws Exception + { + super.setUp(); + + repository = (FileMetadataRepository) lookup( MetadataRepository.class ); + File directory = getTestFile( "target/test-repository" ); + FileUtils.deleteDirectory( directory ); + repository.setDirectory( directory ); + } + + public void testRootNamespaceWithNoMetadataRepository() + { + Collection<String> namespaces = repository.getRootNamespaces( TEST_REPO_ID ); + assertEquals( Collections.<String>emptyList(), namespaces ); + } + + public void testUpdateProjectVersionMetadataWithNoOtherArchives() + { + ProjectVersionMetadata metadata = new ProjectVersionMetadata(); + metadata.setId( TEST_PROJECT ); + MailingList mailingList = new MailingList(); + mailingList.setName( "Foo List" ); + mailingList.setOtherArchives( Collections.<String>emptyList() ); + metadata.setMailingLists( Collections.singletonList( mailingList ) ); + repository.updateProjectVersion( TEST_REPO_ID, TEST_NAMESPACE, TEST_PROJECT, metadata ); + } +} |