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