]> source.dussan.org Git - archiva.git/blob
961839766b126188853e6b1ebadc0de61ae5fd9f
[archiva.git] /
1 package org.apache.maven.archiva.web.action;
2
3 /*
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
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
31
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;
37 import java.util.Set;
38
39 /**
40  * Browse the repository.
41  *
42  * @todo implement repository selectors (all or specific repository)
43  * plexus.component role="com.opensymphony.xwork2.Action" role-hint="browseAction" instantiation-strategy="per-lookup"
44  */
45 @Controller( "browseAction" )
46 @Scope( "prototype" )
47 public class BrowseAction
48     extends AbstractRepositoryBasedAction
49 {
50     private String groupId;
51
52     private String artifactId;
53
54     private String repositoryId;
55
56     private ProjectVersionMetadata sharedModel;
57
58     private Collection<String> namespaces;
59
60     private Collection<String> projectIds;
61
62     private Collection<String> projectVersions;
63
64     public String browse()
65         throws MetadataResolutionException
66     {
67         List<String> selectedRepos = getObservableRepos();
68         if ( CollectionUtils.isEmpty( selectedRepos ) )
69         {
70             return GlobalResults.ACCESS_TO_NO_REPOS;
71         }
72
73         Set<String> namespaces = new LinkedHashSet<String>();
74
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();
80         try
81         {
82             MetadataResolver metadataResolver = repositorySession.getResolver();
83             namespacesToCollapse = new LinkedHashSet<String>();
84             for ( String repoId : selectedRepos )
85             {
86                 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
87             }
88
89             for ( String n : namespacesToCollapse )
90             {
91                 // TODO: check performance of this
92                 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
93             }
94         }
95         finally
96         {
97             repositorySession.close();
98         }
99
100         this.namespaces = getSortedList( namespaces );
101         return SUCCESS;
102     }
103
104     private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
105                                        Collection<String> repoIds, String n )
106         throws MetadataResolutionException
107     {
108         Set<String> subNamespaces = new LinkedHashSet<String>();
109         for ( String repoId : repoIds )
110         {
111             subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
112         }
113         if ( subNamespaces.size() != 1 )
114         {
115             if ( log.isDebugEnabled() )
116             {
117                 log.debug( n + " is not collapsible as it has sub-namespaces: " + subNamespaces );
118             }
119             return n;
120         }
121         else
122         {
123             for ( String repoId : repoIds )
124             {
125                 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
126                 if ( projects != null && !projects.isEmpty() )
127                 {
128                     if ( log.isDebugEnabled() )
129                     {
130                         log.debug( n + " is not collapsible as it has projects" );
131                     }
132                     return n;
133                 }
134             }
135             return collapseNamespaces( repositorySession, metadataResolver, repoIds,
136                                        n + "." + subNamespaces.iterator().next() );
137         }
138     }
139
140     public String browseGroup()
141         throws MetadataResolutionException
142     {
143         if ( StringUtils.isEmpty( groupId ) )
144         {
145             // TODO: i18n
146             addActionError( "You must specify a group ID to browse" );
147             return ERROR;
148         }
149
150         List<String> selectedRepos = getObservableRepos();
151         if ( CollectionUtils.isEmpty( selectedRepos ) )
152         {
153             return GlobalResults.ACCESS_TO_NO_REPOS;
154         }
155
156         Set<String> projects = new LinkedHashSet<String>();
157
158         RepositorySession repositorySession = repositorySessionFactory.createSession();
159         Set<String> namespaces;
160         try
161         {
162             MetadataResolver metadataResolver = repositorySession.getResolver();
163
164             Set<String> namespacesToCollapse = new LinkedHashSet<String>();
165             for ( String repoId : selectedRepos )
166             {
167                 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
168
169                 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
170             }
171
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 )
177             {
178                 // TODO: check performance of this
179                 namespaces.add(
180                     collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
181             }
182         }
183         finally
184         {
185             repositorySession.close();
186         }
187
188         this.namespaces = getSortedList( namespaces );
189         this.projectIds = getSortedList( projects );
190         return SUCCESS;
191     }
192
193     private ArrayList<String> getSortedList( Set<String> set )
194     {
195         ArrayList<String> list = new ArrayList<String>( set );
196         Collections.sort( list );
197         return list;
198     }
199
200     public String browseArtifact()
201         throws MetadataResolutionException
202     {
203         if ( StringUtils.isEmpty( groupId ) )
204         {
205             // TODO: i18n
206             addActionError( "You must specify a group ID to browse" );
207             return ERROR;
208         }
209
210         if ( StringUtils.isEmpty( artifactId ) )
211         {
212             // TODO: i18n
213             addActionError( "You must specify a artifact ID to browse" );
214             return ERROR;
215         }
216
217         List<String> selectedRepos = getObservableRepos();
218         if ( CollectionUtils.isEmpty( selectedRepos ) )
219         {
220             return GlobalResults.ACCESS_TO_NO_REPOS;
221         }
222
223         RepositorySession repositorySession = repositorySessionFactory.createSession();
224         try
225         {
226             MetadataResolver metadataResolver = repositorySession.getResolver();
227
228             Set<String> versions = new LinkedHashSet<String>();
229             for ( String repoId : selectedRepos )
230             {
231                 versions.addAll(
232                     metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
233             }
234
235             // TODO: sort by known version ordering method
236             this.projectVersions = new ArrayList<String>( versions );
237
238             populateSharedModel( repositorySession, metadataResolver, selectedRepos, versions );
239         }
240         finally
241         {
242             repositorySession.close();
243         }
244
245         return SUCCESS;
246     }
247
248     private void populateSharedModel( RepositorySession repositorySession, MetadataResolver metadataResolver,
249                                       Collection<String> selectedRepos, Collection<String> projectVersions )
250     {
251         sharedModel = new ProjectVersionMetadata();
252
253         MavenProjectFacet mavenFacet = new MavenProjectFacet();
254         mavenFacet.setGroupId( groupId );
255         mavenFacet.setArtifactId( artifactId );
256         sharedModel.addFacet( mavenFacet );
257
258         boolean isFirstVersion = true;
259
260         for ( String version : projectVersions )
261         {
262             ProjectVersionMetadata versionMetadata = null;
263             for ( String repoId : selectedRepos )
264             {
265                 if ( versionMetadata == null )
266                 {
267                     try
268                     {
269                         versionMetadata =
270                             metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
271                                                                     version );
272                     }
273                     catch ( MetadataResolutionException e )
274                     {
275                         log.error(
276                             "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
277                                 + " in repo " + repoId + ": " + e.getMessage() );
278                     }
279                 }
280             }
281
282             if ( versionMetadata == null )
283             {
284                 continue;
285             }
286
287             if ( isFirstVersion )
288             {
289                 sharedModel = versionMetadata;
290                 sharedModel.setId( null );
291             }
292             else
293             {
294                 MavenProjectFacet versionMetadataMavenFacet =
295                     (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
296                 if ( versionMetadataMavenFacet != null )
297                 {
298                     if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase( mavenFacet.getPackaging(),
299                                                                                              versionMetadataMavenFacet.getPackaging() ) )
300                     {
301                         mavenFacet.setPackaging( null );
302                     }
303                 }
304
305                 if ( sharedModel.getName() != null && !StringUtils.equalsIgnoreCase( sharedModel.getName(),
306                                                                                      versionMetadata.getName() ) )
307                 {
308                     sharedModel.setName( "" );
309                 }
310
311                 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
312                     sharedModel.getDescription(), versionMetadata.getDescription() ) )
313                 {
314                     sharedModel.setDescription( null );
315                 }
316
317                 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
318                     && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
319                                                       versionMetadata.getIssueManagement().getUrl() ) )
320                 {
321                     sharedModel.setIssueManagement( null );
322                 }
323
324                 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
325                     && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
326                                                       versionMetadata.getCiManagement().getUrl() ) )
327                 {
328                     sharedModel.setCiManagement( null );
329                 }
330
331                 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
332                     && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
333                                                       versionMetadata.getOrganization().getName() ) )
334                 {
335                     sharedModel.setOrganization( null );
336                 }
337
338                 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
339                                                                                     versionMetadata.getUrl() ) )
340                 {
341                     sharedModel.setUrl( null );
342                 }
343             }
344
345             isFirstVersion = false;
346         }
347     }
348
349     public String getGroupId()
350     {
351         return groupId;
352     }
353
354     public void setGroupId( String groupId )
355     {
356         this.groupId = groupId;
357     }
358
359     public String getArtifactId()
360     {
361         return artifactId;
362     }
363
364     public void setArtifactId( String artifactId )
365     {
366         this.artifactId = artifactId;
367     }
368
369     public Collection<String> getNamespaces()
370     {
371         return namespaces;
372     }
373
374     public String getRepositoryId()
375     {
376
377         return repositoryId;
378     }
379
380     public void setRepositoryId( String repositoryId )
381     {
382
383         this.repositoryId = repositoryId;
384     }
385
386     public ProjectVersionMetadata getSharedModel()
387     {
388         return sharedModel;
389     }
390
391     public Collection<String> getProjectIds()
392     {
393         return projectIds;
394     }
395
396     public Collection<String> getProjectVersions()
397     {
398         return projectVersions;
399     }
400 }