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 com.opensymphony.module.sitemesh.Factory;
23 import com.opensymphony.sitemesh.webapp.SiteMeshFilter;
24 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
25 import org.apache.archiva.metadata.repository.MetadataResolutionException;
26 import org.apache.archiva.metadata.repository.MetadataResolver;
27 import org.apache.archiva.metadata.repository.RepositorySession;
28 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.lang.StringUtils;
31 import org.springframework.context.annotation.Scope;
32 import org.springframework.stereotype.Controller;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.LinkedHashSet;
38 import java.util.List;
42 * Browse the repository.
44 * @todo implement repository selectors (all or specific repository)
45 * plexus.component role="com.opensymphony.xwork2.Action" role-hint="browseAction" instantiation-strategy="per-lookup"
47 @Controller( "browseAction" )
49 public class BrowseAction
50 extends AbstractRepositoryBasedAction
52 private String groupId;
54 private String artifactId;
56 private String repositoryId;
58 private ProjectVersionMetadata sharedModel;
60 private Collection<String> namespaces;
62 private Collection<String> projectIds;
64 private Collection<String> projectVersions;
66 public String browse()
67 throws MetadataResolutionException
69 List<String> selectedRepos = getObservableRepos();
70 if ( CollectionUtils.isEmpty( selectedRepos ) )
72 return GlobalResults.ACCESS_TO_NO_REPOS;
75 Set<String> namespaces = new LinkedHashSet<String>();
77 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
78 // it is located here to avoid the content repository implementation needing to do too much for what
79 // is essentially presentation code
80 Set<String> namespacesToCollapse;
81 RepositorySession repositorySession = repositorySessionFactory.createSession();
84 MetadataResolver metadataResolver = repositorySession.getResolver();
85 namespacesToCollapse = new LinkedHashSet<String>();
86 for ( String repoId : selectedRepos )
88 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
91 for ( String n : namespacesToCollapse )
93 // TODO: check performance of this
94 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
99 repositorySession.close();
102 this.namespaces = getSortedList( namespaces );
106 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
107 Collection<String> repoIds, String n )
108 throws MetadataResolutionException
110 Set<String> subNamespaces = new LinkedHashSet<String>();
111 for ( String repoId : repoIds )
113 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
115 if ( subNamespaces.size() != 1 )
117 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
122 for ( String repoId : repoIds )
124 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
125 if ( projects != null && !projects.isEmpty() )
127 log.debug( "{} is not collapsible as it has projects", n );
131 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
132 n + "." + subNamespaces.iterator().next() );
136 public String browseGroup()
137 throws MetadataResolutionException
139 if ( StringUtils.isEmpty( groupId ) )
142 addActionError( "You must specify a group ID to browse" );
146 List<String> selectedRepos = getObservableRepos();
147 if ( CollectionUtils.isEmpty( selectedRepos ) )
149 return GlobalResults.ACCESS_TO_NO_REPOS;
152 Set<String> projects = new LinkedHashSet<String>();
154 RepositorySession repositorySession = repositorySessionFactory.createSession();
155 Set<String> namespaces;
158 MetadataResolver metadataResolver = repositorySession.getResolver();
160 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
161 for ( String repoId : selectedRepos )
163 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
165 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
168 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
169 // it is located here to avoid the content repository implementation needing to do too much for what
170 // is essentially presentation code
171 namespaces = new LinkedHashSet<String>();
172 for ( String n : namespacesToCollapse )
174 // TODO: check performance of this
176 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
181 repositorySession.close();
184 this.namespaces = getSortedList( namespaces );
185 this.projectIds = getSortedList( projects );
189 private ArrayList<String> getSortedList( Set<String> set )
191 ArrayList<String> list = new ArrayList<String>( set );
192 Collections.sort( list );
196 public String browseArtifact()
197 throws MetadataResolutionException
199 if ( StringUtils.isEmpty( groupId ) )
202 addActionError( "You must specify a group ID to browse" );
206 if ( StringUtils.isEmpty( artifactId ) )
209 addActionError( "You must specify a artifact ID to browse" );
213 List<String> selectedRepos = getObservableRepos();
214 if ( CollectionUtils.isEmpty( selectedRepos ) )
216 return GlobalResults.ACCESS_TO_NO_REPOS;
219 RepositorySession repositorySession = repositorySessionFactory.createSession();
222 MetadataResolver metadataResolver = repositorySession.getResolver();
224 Set<String> versions = new LinkedHashSet<String>();
225 for ( String repoId : selectedRepos )
228 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
231 // TODO: sort by known version ordering method
232 this.projectVersions = new ArrayList<String>( versions );
234 populateSharedModel( repositorySession, metadataResolver, selectedRepos, versions );
238 repositorySession.close();
244 private void populateSharedModel( RepositorySession repositorySession, MetadataResolver metadataResolver,
245 Collection<String> selectedRepos, Collection<String> projectVersions )
247 sharedModel = new ProjectVersionMetadata();
249 MavenProjectFacet mavenFacet = new MavenProjectFacet();
250 mavenFacet.setGroupId( groupId );
251 mavenFacet.setArtifactId( artifactId );
252 sharedModel.addFacet( mavenFacet );
254 boolean isFirstVersion = true;
256 for ( String version : projectVersions )
258 ProjectVersionMetadata versionMetadata = null;
259 for ( String repoId : selectedRepos )
261 if ( versionMetadata == null )
266 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
269 catch ( MetadataResolutionException e )
272 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
273 + " in repo " + repoId + ": " + e.getMessage() );
278 if ( versionMetadata == null )
283 if ( isFirstVersion )
285 sharedModel = versionMetadata;
286 sharedModel.setId( null );
290 MavenProjectFacet versionMetadataMavenFacet =
291 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
292 if ( versionMetadataMavenFacet != null )
294 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase( mavenFacet.getPackaging(),
295 versionMetadataMavenFacet.getPackaging() ) )
297 mavenFacet.setPackaging( null );
301 if ( sharedModel.getName() != null && !StringUtils.equalsIgnoreCase( sharedModel.getName(),
302 versionMetadata.getName() ) )
304 sharedModel.setName( "" );
307 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
308 sharedModel.getDescription(), versionMetadata.getDescription() ) )
310 sharedModel.setDescription( null );
313 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
314 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
315 versionMetadata.getIssueManagement().getUrl() ) )
317 sharedModel.setIssueManagement( null );
320 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
321 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
322 versionMetadata.getCiManagement().getUrl() ) )
324 sharedModel.setCiManagement( null );
327 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
328 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
329 versionMetadata.getOrganization().getName() ) )
331 sharedModel.setOrganization( null );
334 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
335 versionMetadata.getUrl() ) )
337 sharedModel.setUrl( null );
341 isFirstVersion = false;
345 public String getGroupId()
350 public void setGroupId( String groupId )
352 this.groupId = groupId;
355 public String getArtifactId()
360 public void setArtifactId( String artifactId )
362 this.artifactId = artifactId;
365 public Collection<String> getNamespaces()
370 public String getRepositoryId()
376 public void setRepositoryId( String repositoryId )
379 this.repositoryId = repositoryId;
382 public ProjectVersionMetadata getSharedModel()
387 public Collection<String> getProjectIds()
392 public Collection<String> getProjectVersions()
394 return projectVersions;