]> source.dussan.org Git - archiva.git/blob
9da515b53da25094f4fd7e7b64d389354eedc9f8
[archiva.git] /
1 package org.apache.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.generic.GenericMetadataFacet;
24 import org.apache.archiva.metadata.model.ArtifactMetadata;
25 import org.apache.archiva.metadata.model.Dependency;
26 import org.apache.archiva.metadata.model.MailingList;
27 import org.apache.archiva.metadata.model.MetadataFacet;
28 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
29 import org.apache.archiva.metadata.model.ProjectVersionReference;
30 import org.apache.archiva.metadata.repository.MetadataRepository;
31 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
32 import org.apache.archiva.metadata.repository.MetadataResolutionException;
33 import org.apache.archiva.metadata.repository.MetadataResolver;
34 import org.apache.archiva.metadata.repository.RepositorySession;
35 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMetadataVersionComparator;
36 import org.apache.archiva.reports.RepositoryProblemFacet;
37 import org.apache.archiva.repository.RepositoryContentFactory;
38 import org.apache.archiva.repository.RepositoryException;
39 import org.apache.archiva.repository.RepositoryNotFoundException;
40 import org.apache.archiva.rest.api.model.ArtifactDownloadInfo;
41 import org.apache.archiva.rest.services.utils.ArtifactDownloadInfoBuilder;
42 import org.apache.commons.lang.StringUtils;
43 import org.springframework.context.annotation.Scope;
44 import org.springframework.stereotype.Controller;
45
46 import javax.inject.Inject;
47 import java.util.ArrayList;
48 import java.util.Collection;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.LinkedHashMap;
52 import java.util.List;
53 import java.util.Map;
54
55 /**
56  * Browse the repository.
57  * <p/>
58  * TODO change name to ShowVersionedAction to conform to terminology.
59  */
60 @SuppressWarnings( "serial" )
61 @Controller( "showArtifactAction" )
62 @Scope( "prototype" )
63 public class ShowArtifactAction
64     extends AbstractRepositoryBasedAction
65     implements Validateable
66 {
67     /* .\ Not Exposed \._____________________________________________ */
68
69     @Inject
70     private RepositoryContentFactory repositoryFactory;
71
72     /* .\ Exposed Output Objects \.__________________________________ */
73
74     private String groupId;
75
76     private String artifactId;
77
78     private String version;
79
80     private String repositoryId;
81
82     /**
83      * The model of this versioned project.
84      */
85     private ProjectVersionMetadata model;
86
87     /**
88      * The list of artifacts that depend on this versioned project.
89      */
90     private List<ProjectVersionReference> dependees;
91
92     private List<MailingList> mailingLists;
93
94     private List<Dependency> dependencies;
95
96     private Map<String, List<ArtifactDownloadInfo>> artifacts;
97
98     private boolean dependencyTree = false;
99
100     private String deleteItem;
101
102     private Map<String, String> genericMetadata;
103
104     private String propertyName;
105
106     private String propertyValue;
107
108     /**
109      * Show the versioned project information tab. TODO: Change name to 'project' - we are showing project versions
110      * here, not specific artifact information (though that is rendered in the download box).
111      */
112     public String artifact()
113     {
114         RepositorySession repositorySession = repositorySessionFactory.createSession();
115         try
116         {
117             return handleArtifact( repositorySession );
118         }
119         catch ( Exception e )
120         {
121             log.warn( "Unable to getProjectVersionMetadata: " + e.getMessage(), e );
122             addActionError( "Unable to getProjectVersionMetadata - consult application logs." );
123             return ERROR;
124         }
125         finally
126
127         {
128             repositorySession.close();
129         }
130
131     }
132
133     private String handleArtifact( RepositorySession session )
134         throws RepositoryNotFoundException, RepositoryException
135     {
136         // In the future, this should be replaced by the repository grouping mechanism, so that we are only making
137         // simple resource requests here and letting the resolver take care of it
138         ProjectVersionMetadata versionMetadata = getProjectVersionMetadata( session );
139
140         if ( versionMetadata == null )
141         {
142             addActionError( "Artifact not found" );
143             return ERROR;
144         }
145
146         if ( versionMetadata.isIncomplete() )
147         {
148             addIncompleteModelWarning( "Artifact metadata is incomplete." );
149         }
150
151         model = versionMetadata;
152
153         return SUCCESS;
154     }
155
156     private ProjectVersionMetadata getProjectVersionMetadata( RepositorySession session )
157         throws RepositoryNotFoundException, RepositoryException
158     {
159         ProjectVersionMetadata versionMetadata = null;
160         artifacts = new LinkedHashMap<String, List<ArtifactDownloadInfo>>();
161
162         List<String> repos = getObservableRepos();
163
164         MetadataResolver metadataResolver = session.getResolver();
165         for ( String repoId : repos )
166         {
167             if ( versionMetadata == null )
168             {
169                 // we don't want the implementation being that intelligent - so another resolver to do the
170                 // "just-in-time" nature of picking up the metadata (if appropriate for the repository type) is used
171                 try
172                 {
173                     versionMetadata =
174                         metadataResolver.resolveProjectVersion( session, repoId, groupId, artifactId, version );
175                     if ( versionMetadata != null )
176                     {
177                         MetadataFacet repoProbFacet;
178                         if ( ( repoProbFacet = versionMetadata.getFacet( RepositoryProblemFacet.FACET_ID ) ) != null )
179                         {
180                             addIncompleteModelWarning( "Artifact metadata is incomplete: "
181                                                            + ( (RepositoryProblemFacet) repoProbFacet ).getProblem() );
182                             //set metadata to complete so that no additional 'Artifact metadata is incomplete' warning is logged
183                             versionMetadata.setIncomplete( false );
184                         }
185                     }
186
187                 }
188                 catch ( MetadataResolutionException e )
189                 {
190                     addIncompleteModelWarning( "Error resolving artifact metadata: " + e.getMessage() );
191
192                     // TODO: need a consistent way to construct this - same in ArchivaMetadataCreationConsumer
193                     versionMetadata = new ProjectVersionMetadata();
194                     versionMetadata.setId( version );
195                 }
196                 if ( versionMetadata != null )
197                 {
198                     repositoryId = repoId;
199
200                     List<ArtifactMetadata> artifacts;
201                     try
202                     {
203                         artifacts = new ArrayList<ArtifactMetadata>(
204                             metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
205                     }
206                     catch ( MetadataResolutionException e )
207                     {
208                         addIncompleteModelWarning( "Error resolving artifact metadata: " + e.getMessage() );
209                         artifacts = Collections.emptyList();
210                     }
211                     Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
212
213                     for ( ArtifactMetadata artifact : artifacts )
214                     {
215                         List<ArtifactDownloadInfo> l = this.artifacts.get( artifact.getVersion() );
216                         if ( l == null )
217                         {
218                             l = new ArrayList<ArtifactDownloadInfo>();
219                             this.artifacts.put( artifact.getVersion(), l );
220                         }
221                         ArtifactDownloadInfoBuilder builder = new ArtifactDownloadInfoBuilder().forArtifactMetadata(
222                             artifact ).withManagedRepositoryContent(
223                             repositoryFactory.getManagedRepositoryContent( repositoryId ) );
224                         l.add( builder.build() );
225                     }
226                 }
227             }
228         }
229
230         return versionMetadata;
231     }
232
233     private void addIncompleteModelWarning( String warningMessage )
234     {
235         addActionError( warningMessage );
236         //"The model may be incomplete due to a previous error in resolving information. Refer to the repository problem reports for more information." );
237     }
238
239     /**
240      * Show the artifact information tab.
241      */
242     public String dependencies()
243     {
244         String result = artifact();
245
246         this.dependencies = model.getDependencies();
247
248         return result;
249     }
250
251     /**
252      * Show the mailing lists information tab.
253      */
254     public String mailingLists()
255     {
256         String result = artifact();
257
258         this.mailingLists = model.getMailingLists();
259
260         return result;
261     }
262
263     /**
264      * Show the reports tab.
265      */
266     public String reports()
267     {
268         // TODO: hook up reports on project
269
270         return SUCCESS;
271     }
272
273     /**
274      * Show the dependees (other artifacts that depend on this project) tab.
275      */
276     public String dependees()
277         throws MetadataResolutionException
278     {
279         List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
280         // TODO: what if we get duplicates across repositories?
281         RepositorySession repositorySession = repositorySessionFactory.createSession();
282         try
283         {
284             MetadataResolver metadataResolver = repositorySession.getResolver();
285             for ( String repoId : getObservableRepos() )
286             {
287                 // TODO: what about if we want to see this irrespective of version?
288                 references.addAll(
289                     metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
290                                                                version ) );
291             }
292         }
293         finally
294         {
295             repositorySession.close();
296         }
297
298         this.dependees = references;
299
300         // TODO: may need to note on the page that references will be incomplete if the other artifacts are not yet
301         // stored in the content repository
302         // (especially in the case of pre-population import)
303
304         return artifact();
305     }
306
307     /**
308      * Show the dependencies of this versioned project tab.
309      */
310     public String dependencyTree()
311     {
312         // temporarily use this as we only need the model for the tag to perform, but we should be resolving the
313         // graph here instead
314
315         // TODO: may need to note on the page that tree will be incomplete if the other artifacts are not yet stored in
316         // the content repository
317         // (especially in the case of pre-population import)
318
319         // TODO: a bit ugly, should really be mapping all these results differently now
320         this.dependencyTree = true;
321
322         return artifact();
323     }
324
325     public String projectMetadata()
326     {
327         String result = artifact();
328
329         if ( model.getFacet( GenericMetadataFacet.FACET_ID ) != null )
330         {
331             genericMetadata = model.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
332         }
333
334         if ( genericMetadata == null )
335         {
336             genericMetadata = new HashMap<String, String>();
337         }
338
339         return result;
340     }
341
342     public String addMetadataProperty()
343     {
344         RepositorySession repositorySession = repositorySessionFactory.createSession();
345         ProjectVersionMetadata projectMetadata;
346         try
347         {
348             MetadataRepository metadataRepository = repositorySession.getRepository();
349             projectMetadata = getProjectVersionMetadata( repositorySession );
350             if ( projectMetadata == null )
351             {
352                 addActionError( "Artifact not found" );
353                 return ERROR;
354             }
355
356             if ( projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ) == null )
357             {
358                 genericMetadata = new HashMap<String, String>();
359             }
360             else
361             {
362                 genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
363             }
364
365             if ( propertyName == null || "".equals( propertyName.trim() ) || propertyValue == null || "".equals(
366                 propertyValue.trim() ) )
367             {
368                 model = projectMetadata;
369                 addActionError( "Property Name and Property Value are required." );
370                 return INPUT;
371             }
372
373             genericMetadata.put( propertyName, propertyValue );
374
375             try
376             {
377                 updateProjectMetadata( projectMetadata, metadataRepository );
378                 repositorySession.save();
379             }
380             catch ( MetadataRepositoryException e )
381             {
382                 log.warn( "Unable to persist modified project metadata after adding entry: " + e.getMessage(), e );
383                 addActionError(
384                     "Unable to add metadata item to underlying content storage - consult application logs." );
385                 return ERROR;
386             }
387
388             // TODO: why re-retrieve?
389             projectMetadata = getProjectVersionMetadata( repositorySession );
390         }
391         catch ( Exception e )
392         {
393             log.warn( "Unable to getProjectVersionMetadata: " + e.getMessage(), e );
394             addActionError( "Unable to getProjectVersionMetadata - consult application logs." );
395             return ERROR;
396         }
397         finally
398         {
399             repositorySession.close();
400         }
401
402         genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
403
404         model = projectMetadata;
405
406         propertyName = "";
407         propertyValue = "";
408
409         return SUCCESS;
410     }
411
412     public String deleteMetadataEntry()
413     {
414         RepositorySession repositorySession = repositorySessionFactory.createSession();
415         try
416         {
417             MetadataRepository metadataRepository = repositorySession.getRepository();
418             ProjectVersionMetadata projectMetadata = getProjectVersionMetadata( repositorySession );
419
420             if ( projectMetadata == null )
421             {
422                 addActionError( "Artifact not found" );
423                 return ERROR;
424             }
425
426             if ( projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ) != null )
427             {
428                 genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
429
430                 if ( !StringUtils.isEmpty( deleteItem ) )
431                 {
432                     genericMetadata.remove( deleteItem );
433
434                     try
435                     {
436                         updateProjectMetadata( projectMetadata, metadataRepository );
437                         repositorySession.save();
438                     }
439                     catch ( MetadataRepositoryException e )
440                     {
441                         log.warn( "Unable to persist modified project metadata after removing entry: " + e.getMessage(),
442                                   e );
443                         addActionError(
444                             "Unable to remove metadata item to underlying content storage - consult application logs." );
445                         return ERROR;
446                     }
447
448                     // TODO: why re-retrieve?
449                     projectMetadata = getProjectVersionMetadata( repositorySession );
450
451                     genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
452
453                     model = projectMetadata;
454
455                     addActionMessage( "Property successfully deleted." );
456                 }
457
458                 deleteItem = "";
459             }
460             else
461             {
462                 addActionError( "No generic metadata facet for this artifact." );
463                 return ERROR;
464             }
465         }
466         catch ( Exception e )
467         {
468             log.warn( "Unable to getProjectVersionMetadata: " + e.getMessage(), e );
469             addActionError( "Unable to getProjectVersionMetadata - consult application logs." );
470             return ERROR;
471
472         }
473         finally
474         {
475             repositorySession.close();
476         }
477
478         return SUCCESS;
479     }
480
481     private void updateProjectMetadata( ProjectVersionMetadata projectMetadata, MetadataRepository metadataRepository )
482         throws MetadataRepositoryException
483     {
484         GenericMetadataFacet genericMetadataFacet = new GenericMetadataFacet();
485         genericMetadataFacet.fromProperties( genericMetadata );
486
487         projectMetadata.addFacet( genericMetadataFacet );
488
489         metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectMetadata );
490     }
491
492     @Override
493     public void validate()
494     {
495         if ( StringUtils.isBlank( groupId ) )
496         {
497             addActionError( "You must specify a group ID to browse" );
498         }
499
500         if ( StringUtils.isBlank( artifactId ) )
501         {
502             addActionError( "You must specify a artifact ID to browse" );
503         }
504
505         if ( StringUtils.isBlank( version ) )
506         {
507             addActionError( "You must specify a version to browse" );
508         }
509     }
510
511     public ProjectVersionMetadata getModel()
512     {
513         return model;
514     }
515
516     public String getGroupId()
517     {
518         return groupId;
519     }
520
521     public void setGroupId( String groupId )
522     {
523         this.groupId = groupId;
524     }
525
526     public String getArtifactId()
527     {
528         return artifactId;
529     }
530
531     public void setArtifactId( String artifactId )
532     {
533         this.artifactId = artifactId;
534     }
535
536     public String getVersion()
537     {
538         return version;
539     }
540
541     public void setVersion( String version )
542     {
543         this.version = version;
544     }
545
546     public List<MailingList> getMailingLists()
547     {
548         return mailingLists;
549     }
550
551     public List<Dependency> getDependencies()
552     {
553         return dependencies;
554     }
555
556     public List<ProjectVersionReference> getDependees()
557     {
558         return dependees;
559     }
560
561     public String getRepositoryId()
562     {
563         return repositoryId;
564     }
565
566     public void setRepositoryId( String repositoryId )
567     {
568         this.repositoryId = repositoryId;
569     }
570
571     public Map<String, List<ArtifactDownloadInfo>> getArtifacts()
572     {
573         return artifacts;
574     }
575
576     public Collection<String> getSnapshotVersions()
577     {
578         return artifacts.keySet();
579     }
580
581     public boolean isDependencyTree()
582     {
583         return dependencyTree;
584     }
585
586     public void setDeleteItem( String deleteItem )
587     {
588         this.deleteItem = deleteItem;
589     }
590
591     public Map<String, String> getGenericMetadata()
592     {
593         return genericMetadata;
594     }
595
596     public void setGenericMetadata( Map<String, String> genericMetadata )
597     {
598         this.genericMetadata = genericMetadata;
599     }
600
601     public String getPropertyName()
602     {
603         return propertyName;
604     }
605
606     public void setPropertyName( String propertyName )
607     {
608         this.propertyName = propertyName;
609     }
610
611     public String getPropertyValue()
612     {
613         return propertyValue;
614     }
615
616     public void setPropertyValue( String propertyValue )
617     {
618         this.propertyValue = propertyValue;
619     }
620
621     public void setRepositoryFactory( RepositoryContentFactory repositoryFactory )
622     {
623         this.repositoryFactory = repositoryFactory;
624     }
625
626
627 }