1 package org.apache.maven.archiva.web.action;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
23 import org.apache.archiva.metadata.repository.MetadataResolutionException;
24 import org.apache.archiva.metadata.repository.MetadataResolver;
25 import org.apache.archiva.metadata.repository.RepositorySession;
26 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
27 import org.apache.commons.collections.CollectionUtils;
28 import org.apache.commons.lang.StringUtils;
29 import org.springframework.context.annotation.Scope;
30 import org.springframework.stereotype.Controller;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.LinkedHashSet;
36 import java.util.List;
40 * Browse the repository.
42 * @todo implement repository selectors (all or specific repository)
43 * plexus.component role="com.opensymphony.xwork2.Action" role-hint="browseAction" instantiation-strategy="per-lookup"
45 @Controller( "browseAction" )
47 public class BrowseAction
48 extends AbstractRepositoryBasedAction
50 private String groupId;
52 private String artifactId;
54 private String repositoryId;
56 private ProjectVersionMetadata sharedModel;
58 private Collection<String> namespaces;
60 private Collection<String> projectIds;
62 private Collection<String> projectVersions;
64 public String browse()
65 throws MetadataResolutionException
67 List<String> selectedRepos = getObservableRepos();
68 if ( CollectionUtils.isEmpty( selectedRepos ) )
70 return GlobalResults.ACCESS_TO_NO_REPOS;
73 Set<String> namespaces = new LinkedHashSet<String>();
75 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
76 // it is located here to avoid the content repository implementation needing to do too much for what
77 // is essentially presentation code
78 Set<String> namespacesToCollapse;
79 RepositorySession repositorySession = repositorySessionFactory.createSession();
82 MetadataResolver metadataResolver = repositorySession.getResolver();
83 namespacesToCollapse = new LinkedHashSet<String>();
84 for ( String repoId : selectedRepos )
86 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
89 for ( String n : namespacesToCollapse )
91 // TODO: check performance of this
92 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
97 repositorySession.close();
100 this.namespaces = getSortedList( namespaces );
104 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
105 Collection<String> repoIds, String n )
106 throws MetadataResolutionException
108 Set<String> subNamespaces = new LinkedHashSet<String>();
109 for ( String repoId : repoIds )
111 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
113 if ( subNamespaces.size() != 1 )
115 if ( log.isDebugEnabled() )
117 log.debug( n + " is not collapsible as it has sub-namespaces: " + subNamespaces );
123 for ( String repoId : repoIds )
125 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
126 if ( projects != null && !projects.isEmpty() )
128 if ( log.isDebugEnabled() )
130 log.debug( n + " is not collapsible as it has projects" );
135 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
136 n + "." + subNamespaces.iterator().next() );
140 public String browseGroup()
141 throws MetadataResolutionException
143 if ( StringUtils.isEmpty( groupId ) )
146 addActionError( "You must specify a group ID to browse" );
150 List<String> selectedRepos = getObservableRepos();
151 if ( CollectionUtils.isEmpty( selectedRepos ) )
153 return GlobalResults.ACCESS_TO_NO_REPOS;
156 Set<String> projects = new LinkedHashSet<String>();
158 RepositorySession repositorySession = repositorySessionFactory.createSession();
159 Set<String> namespaces;
162 MetadataResolver metadataResolver = repositorySession.getResolver();
164 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
165 for ( String repoId : selectedRepos )
167 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
169 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
172 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
173 // it is located here to avoid the content repository implementation needing to do too much for what
174 // is essentially presentation code
175 namespaces = new LinkedHashSet<String>();
176 for ( String n : namespacesToCollapse )
178 // TODO: check performance of this
180 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
185 repositorySession.close();
188 this.namespaces = getSortedList( namespaces );
189 this.projectIds = getSortedList( projects );
193 private ArrayList<String> getSortedList( Set<String> set )
195 ArrayList<String> list = new ArrayList<String>( set );
196 Collections.sort( list );
200 public String browseArtifact()
201 throws MetadataResolutionException
203 if ( StringUtils.isEmpty( groupId ) )
206 addActionError( "You must specify a group ID to browse" );
210 if ( StringUtils.isEmpty( artifactId ) )
213 addActionError( "You must specify a artifact ID to browse" );
217 List<String> selectedRepos = getObservableRepos();
218 if ( CollectionUtils.isEmpty( selectedRepos ) )
220 return GlobalResults.ACCESS_TO_NO_REPOS;
223 RepositorySession repositorySession = repositorySessionFactory.createSession();
226 MetadataResolver metadataResolver = repositorySession.getResolver();
228 Set<String> versions = new LinkedHashSet<String>();
229 for ( String repoId : selectedRepos )
232 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
235 // TODO: sort by known version ordering method
236 this.projectVersions = new ArrayList<String>( versions );
238 populateSharedModel( repositorySession, metadataResolver, selectedRepos, versions );
242 repositorySession.close();
248 private void populateSharedModel( RepositorySession repositorySession, MetadataResolver metadataResolver,
249 Collection<String> selectedRepos, Collection<String> projectVersions )
251 sharedModel = new ProjectVersionMetadata();
253 MavenProjectFacet mavenFacet = new MavenProjectFacet();
254 mavenFacet.setGroupId( groupId );
255 mavenFacet.setArtifactId( artifactId );
256 sharedModel.addFacet( mavenFacet );
258 boolean isFirstVersion = true;
260 for ( String version : projectVersions )
262 ProjectVersionMetadata versionMetadata = null;
263 for ( String repoId : selectedRepos )
265 if ( versionMetadata == null )
270 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
273 catch ( MetadataResolutionException e )
276 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
277 + " in repo " + repoId + ": " + e.getMessage() );
282 if ( versionMetadata == null )
287 if ( isFirstVersion )
289 sharedModel = versionMetadata;
290 sharedModel.setId( null );
294 MavenProjectFacet versionMetadataMavenFacet =
295 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
296 if ( versionMetadataMavenFacet != null )
298 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase( mavenFacet.getPackaging(),
299 versionMetadataMavenFacet.getPackaging() ) )
301 mavenFacet.setPackaging( null );
305 if ( sharedModel.getName() != null && !StringUtils.equalsIgnoreCase( sharedModel.getName(),
306 versionMetadata.getName() ) )
308 sharedModel.setName( "" );
311 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
312 sharedModel.getDescription(), versionMetadata.getDescription() ) )
314 sharedModel.setDescription( null );
317 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
318 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
319 versionMetadata.getIssueManagement().getUrl() ) )
321 sharedModel.setIssueManagement( null );
324 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
325 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
326 versionMetadata.getCiManagement().getUrl() ) )
328 sharedModel.setCiManagement( null );
331 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
332 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
333 versionMetadata.getOrganization().getName() ) )
335 sharedModel.setOrganization( null );
338 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
339 versionMetadata.getUrl() ) )
341 sharedModel.setUrl( null );
345 isFirstVersion = false;
349 public String getGroupId()
354 public void setGroupId( String groupId )
356 this.groupId = groupId;
359 public String getArtifactId()
364 public void setArtifactId( String artifactId )
366 this.artifactId = artifactId;
369 public Collection<String> getNamespaces()
374 public String getRepositoryId()
380 public void setRepositoryId( String repositoryId )
383 this.repositoryId = repositoryId;
386 public ProjectVersionMetadata getSharedModel()
391 public Collection<String> getProjectIds()
396 public Collection<String> getProjectVersions()
398 return projectVersions;