]> source.dussan.org Git - archiva.git/blob
121a8c8ce00408d70a6c7c608a0acc17a161daa0
[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.xwork2.Validateable;
23 import org.apache.archiva.metadata.model.ArtifactMetadata;
24 import org.apache.archiva.metadata.model.Dependency;
25 import org.apache.archiva.metadata.model.MailingList;
26 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
27 import org.apache.archiva.metadata.model.ProjectVersionReference;
28 import org.apache.archiva.metadata.repository.MetadataResolutionException;
29 import org.apache.archiva.metadata.repository.MetadataResolver;
30 import org.apache.archiva.metadata.repository.storage.maven2.MavenArtifactFacet;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.maven.archiva.model.ArtifactReference;
33 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
34 import org.apache.maven.archiva.repository.RepositoryContentFactory;
35 import org.apache.maven.archiva.repository.RepositoryException;
36 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
37
38 import java.text.DecimalFormat;
39 import java.util.ArrayList;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.Comparator;
43 import java.util.LinkedHashMap;
44 import java.util.List;
45 import java.util.Map;
46
47 /**
48  * Browse the repository.
49  *
50  * TODO change name to ShowVersionedAction to conform to terminology.
51  *
52  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="showArtifactAction" instantiation-strategy="per-lookup"
53  */
54 public class ShowArtifactAction
55     extends AbstractRepositoryBasedAction
56     implements Validateable
57 {
58     /* .\ Not Exposed \._____________________________________________ */
59
60     /**
61      * @plexus.requirement
62      */
63     private MetadataResolver metadataResolver;
64
65     /**
66      * @plexus.requirement
67      */
68     private RepositoryContentFactory repositoryFactory;
69
70     /* .\ Exposed Output Objects \.__________________________________ */
71
72     private String groupId;
73
74     private String artifactId;
75
76     private String version;
77
78     private String repositoryId;
79
80     /**
81      * The model of this versioned project.
82      */
83     private ProjectVersionMetadata model;
84
85     /**
86      * The list of artifacts that depend on this versioned project.
87      */
88     private List<ProjectVersionReference> dependees;
89
90     private List<MailingList> mailingLists;
91
92     private List<Dependency> dependencies;
93
94     private Map<String, List<ArtifactDownloadInfo>> artifacts;
95
96     private boolean dependencyTree = false;
97
98     /**
99      * Show the versioned project information tab.
100      * TODO: Change name to 'project' - we are showing project versions here, not specific artifact information (though
101      * that is rendered in the download box).
102      */
103     public String artifact()
104     {
105         ProjectVersionMetadata versionMetadata = null;
106         artifacts = new LinkedHashMap<String, List<ArtifactDownloadInfo>>();
107
108         List<String> repos = getObservableRepos();
109         // In the future, this should be replaced by the repository grouping mechanism, so that we are only making
110         // simple resource requests here and letting the resolver take care of it
111         String errorMsg = null;
112         for ( String repoId : repos )
113         {
114             if ( versionMetadata == null )
115             {
116                 // we don't want the implementation being that intelligent - so another resolver to do the
117                 // "just-in-time" nature of picking up the metadata (if appropriate for the repository type) is used
118                 try
119                 {
120                     versionMetadata = metadataResolver.getProjectVersion( repoId, groupId, artifactId, version );
121                 }
122                 catch ( MetadataResolutionException e )
123                 {
124                     addIncompleteModelWarning();
125                     
126                     // TODO: need a consistent way to construct this - same in ArchivaMetadataCreationConsumer
127                     versionMetadata = new ProjectVersionMetadata();
128                     versionMetadata.setId( version );
129                 }
130                 if ( versionMetadata != null )
131                 {
132                     repositoryId = repoId;
133
134                     List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(
135                         metadataResolver.getArtifacts( repoId, groupId, artifactId, version ) );
136                     Collections.sort( artifacts, new Comparator<ArtifactMetadata>()
137                     {
138                         public int compare( ArtifactMetadata o1, ArtifactMetadata o2 )
139                         {
140                             // sort by version (reverse), then ID
141                             // TODO: move version sorting into repository handling (maven2 specific), and perhaps add a 
142                             //       way to get latest instead
143                             int result = new DefaultArtifactVersion( o2.getVersion() ).compareTo(
144                                 new DefaultArtifactVersion( o1.getVersion() ) );
145                             return result != 0 ? result : o1.getId().compareTo( o2.getId() );
146                         }
147                     } );
148
149                     for ( ArtifactMetadata artifact : artifacts )
150                     {
151                         List<ArtifactDownloadInfo> l = this.artifacts.get( artifact.getVersion() );
152                         if ( l == null )
153                         {
154                             l = new ArrayList<ArtifactDownloadInfo>();
155                             this.artifacts.put( artifact.getVersion(), l );
156                         }
157                         l.add( new ArtifactDownloadInfo( artifact ) );
158                     }
159                 }
160             }
161         }
162
163         if ( versionMetadata == null )
164         {
165             addActionError( errorMsg != null ? errorMsg : "Artifact not found" );
166             return ERROR;
167         }
168
169         if ( versionMetadata.isIncomplete() )
170         {
171             addIncompleteModelWarning();
172         }
173
174         model = versionMetadata;
175
176         return SUCCESS;
177     }
178
179     private void addIncompleteModelWarning()
180     {
181         addActionMessage( "The model may be incomplete due to a previous error in resolving information. Refer to the repository problem reports for more information." );
182     }
183
184     /**
185      * Show the artifact information tab.
186      */
187     public String dependencies()
188     {
189         String result = artifact();
190
191         this.dependencies = model.getDependencies();
192
193         return result;
194     }
195
196     /**
197      * Show the mailing lists information tab.
198      */
199     public String mailingLists()
200     {
201         String result = artifact();
202
203         this.mailingLists = model.getMailingLists();
204
205         return result;
206     }
207
208     /**
209      * Show the reports tab.
210      */
211     public String reports()
212     {
213         // TODO: hook up reports on project
214
215         return SUCCESS;
216     }
217
218     /**
219      * Show the dependees (other artifacts that depend on this project) tab.
220      */
221     public String dependees()
222     {
223         List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
224         // TODO: what if we get duplicates across repositories?
225         for ( String repoId : getObservableRepos() )
226         {
227             // TODO: what about if we want to see this irrespective of version?
228             references.addAll( metadataResolver.getProjectReferences( repoId, groupId, artifactId, version ) );
229         }
230
231         this.dependees = references;
232
233         // TODO: may need to note on the page that references will be incomplete if the other artifacts are not yet stored in the content repository
234         // (especially in the case of pre-population import)
235
236         return artifact();
237     }
238
239     /**
240      * Show the dependencies of this versioned project tab.
241      */
242     public String dependencyTree()
243     {
244         // temporarily use this as we only need the model for the tag to perform, but we should be resolving the
245         // graph here instead
246
247         // TODO: may need to note on the page that tree will be incomplete if the other artifacts are not yet stored in the content repository
248         // (especially in the case of pre-population import)
249
250         // TODO: a bit ugly, should really be mapping all these results differently now
251         this.dependencyTree = true;
252
253         return artifact();
254     }
255
256     @Override
257     public void validate()
258     {
259         if ( StringUtils.isBlank( groupId ) )
260         {
261             addActionError( "You must specify a group ID to browse" );
262         }
263
264         if ( StringUtils.isBlank( artifactId ) )
265         {
266             addActionError( "You must specify a artifact ID to browse" );
267         }
268
269         if ( StringUtils.isBlank( version ) )
270         {
271             addActionError( "You must specify a version to browse" );
272         }
273     }
274
275     public ProjectVersionMetadata getModel()
276     {
277         return model;
278     }
279
280     public String getGroupId()
281     {
282         return groupId;
283     }
284
285     public void setGroupId( String groupId )
286     {
287         this.groupId = groupId;
288     }
289
290     public String getArtifactId()
291     {
292         return artifactId;
293     }
294
295     public void setArtifactId( String artifactId )
296     {
297         this.artifactId = artifactId;
298     }
299
300     public String getVersion()
301     {
302         return version;
303     }
304
305     public void setVersion( String version )
306     {
307         this.version = version;
308     }
309
310     public List<MailingList> getMailingLists()
311     {
312         return mailingLists;
313     }
314
315     public List<Dependency> getDependencies()
316     {
317         return dependencies;
318     }
319
320     public List<ProjectVersionReference> getDependees()
321     {
322         return dependees;
323     }
324
325     public String getRepositoryId()
326     {
327         return repositoryId;
328     }
329
330     public void setRepositoryId( String repositoryId )
331     {
332         this.repositoryId = repositoryId;
333     }
334
335     public MetadataResolver getMetadataResolver()
336     {
337         return metadataResolver;
338     }
339
340     public Map<String, List<ArtifactDownloadInfo>> getArtifacts()
341     {
342         return artifacts;
343     }
344
345     public Collection<String> getSnapshotVersions()
346     {
347         return artifacts.keySet();
348     }
349
350     public void setRepositoryFactory( RepositoryContentFactory repositoryFactory )
351     {
352         this.repositoryFactory = repositoryFactory;
353     }
354
355     public boolean isDependencyTree()
356     {
357         return dependencyTree;
358     }
359
360     // TODO: move this into the artifact metadata itself via facets where necessary
361
362     public class ArtifactDownloadInfo
363     {
364         private String type;
365
366         private String namespace;
367
368         private String project;
369
370         private String size;
371
372         private String id;
373
374         private String repositoryId;
375
376         private String version;
377
378         private String path;
379
380         public ArtifactDownloadInfo( ArtifactMetadata artifact )
381         {
382             repositoryId = artifact.getRepositoryId();
383
384             // TODO: use metadata resolver capability instead - maybe the storage path could be stored in the metadata
385             //       though keep in mind the request may not necessarily need to reflect the storage
386             ManagedRepositoryContent repo;
387             try
388             {
389                 repo = repositoryFactory.getManagedRepositoryContent( repositoryId );
390             }
391             catch ( RepositoryException e )
392             {
393                 throw new RuntimeException( e );
394             }
395
396             ArtifactReference ref = new ArtifactReference();
397             ref.setArtifactId( artifact.getProject() );
398             ref.setGroupId( artifact.getNamespace() );
399             ref.setVersion( artifact.getVersion() );
400             path = repo.toPath( ref );
401             path = path.substring( 0, path.lastIndexOf( "/" ) + 1 ) + artifact.getId();
402
403             // TODO: need to accommodate Maven 1 layout too. Non-maven repository formats will need to generate this
404             //       facet (perhaps on the fly) if wanting to display the Maven 2 elements on the Archiva pages
405             String type = null;
406             MavenArtifactFacet facet = (MavenArtifactFacet) artifact.getFacet( MavenArtifactFacet.FACET_ID );
407             if ( facet != null )
408             {
409                 type = facet.getType();
410             }
411             this.type = type;
412
413             namespace = artifact.getNamespace();
414             project = artifact.getProject();
415
416             // TODO: find a reusable formatter for this
417             double s = artifact.getSize();
418             String symbol = "b";
419             if ( s > 1024 )
420             {
421                 symbol = "K";
422                 s /= 1024;
423
424                 if ( s > 1024 )
425                 {
426                     symbol = "M";
427                     s /= 1024;
428
429                     if ( s > 1024 )
430                     {
431                         symbol = "G";
432                         s /= 1024;
433                     }
434                 }
435             }
436
437             size = new DecimalFormat( "#,###.##" ).format( s ) + " " + symbol;
438             id = artifact.getId();
439             version = artifact.getVersion();
440         }
441
442         public String getNamespace()
443         {
444             return namespace;
445         }
446
447         public String getType()
448         {
449             return type;
450         }
451
452         public String getProject()
453         {
454             return project;
455         }
456
457         public String getSize()
458         {
459             return size;
460         }
461
462         public String getId()
463         {
464             return id;
465         }
466
467         public String getVersion()
468         {
469             return version;
470         }
471
472         public String getRepositoryId()
473         {
474             return repositoryId;
475         }
476
477         public String getPath()
478         {
479             return path;
480         }
481     }
482 }