1 package org.apache.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.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.Artifact;
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;
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;
56 * Browse the repository.
58 * TODO change name to ShowVersionedAction to conform to terminology.
60 @SuppressWarnings( "serial" )
61 @Controller( "showArtifactAction" )
63 public class ShowArtifactAction
64 extends AbstractRepositoryBasedAction
65 implements Validateable
67 /* .\ Not Exposed \._____________________________________________ */
70 private RepositoryContentFactory repositoryFactory;
72 /* .\ Exposed Output Objects \.__________________________________ */
74 private String groupId;
76 private String artifactId;
78 private String version;
80 private String repositoryId;
83 * The model of this versioned project.
85 private ProjectVersionMetadata model;
88 * The list of artifacts that depend on this versioned project.
90 private List<ProjectVersionReference> dependees;
92 private List<MailingList> mailingLists;
94 private List<Dependency> dependencies;
96 private Map<String, List<Artifact>> artifacts;
98 private boolean dependencyTree = false;
100 private String deleteItem;
102 private Map<String, String> genericMetadata;
104 private String propertyName;
106 private String propertyValue;
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).
112 public String artifact()
114 RepositorySession repositorySession = repositorySessionFactory.createSession();
117 return handleArtifact( repositorySession );
119 catch ( Exception e )
121 log.warn( "Unable to getProjectVersionMetadata: " + e.getMessage(), e );
122 addActionError( "Unable to getProjectVersionMetadata - consult application logs." );
128 repositorySession.close();
133 private String handleArtifact( RepositorySession session )
134 throws RepositoryNotFoundException, RepositoryException
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 );
140 if ( versionMetadata == null )
142 addActionError( "Artifact not found" );
146 if ( versionMetadata.isIncomplete() )
148 addIncompleteModelWarning( "Artifact metadata is incomplete." );
151 model = versionMetadata;
156 private ProjectVersionMetadata getProjectVersionMetadata( RepositorySession session )
157 throws RepositoryNotFoundException, RepositoryException
159 ProjectVersionMetadata versionMetadata = null;
160 artifacts = new LinkedHashMap<String, List<Artifact>>();
162 List<String> repos = getObservableRepos();
164 MetadataResolver metadataResolver = session.getResolver();
165 for ( String repoId : repos )
167 if ( versionMetadata == null )
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
174 metadataResolver.resolveProjectVersion( session, repoId, groupId, artifactId, version );
175 if ( versionMetadata != null )
177 MetadataFacet repoProbFacet;
178 if ( ( repoProbFacet = versionMetadata.getFacet( RepositoryProblemFacet.FACET_ID ) ) != null )
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 );
188 catch ( MetadataResolutionException e )
190 addIncompleteModelWarning( "Error resolving artifact metadata: " + e.getMessage() );
192 // TODO: need a consistent way to construct this - same in ArchivaMetadataCreationConsumer
193 versionMetadata = new ProjectVersionMetadata();
194 versionMetadata.setId( version );
196 if ( versionMetadata != null )
198 repositoryId = repoId;
200 List<ArtifactMetadata> artifacts;
203 artifacts = new ArrayList<ArtifactMetadata>(
204 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
206 catch ( MetadataResolutionException e )
208 addIncompleteModelWarning( "Error resolving artifact metadata: " + e.getMessage() );
209 artifacts = Collections.emptyList();
211 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
213 for ( ArtifactMetadata artifact : artifacts )
215 List<Artifact> l = this.artifacts.get( artifact.getVersion() );
218 l = new ArrayList<Artifact>();
219 this.artifacts.put( artifact.getVersion(), l );
222 ArtifactDownloadInfoBuilder builder = new ArtifactDownloadInfoBuilder().forArtifactMetadata(
223 artifact ).withManagedRepositoryContent(
224 repositoryFactory.getManagedRepositoryContent( repositoryId ) );
225 l.add( builder.build() );
231 return versionMetadata;
234 private void addIncompleteModelWarning( String warningMessage )
236 addActionError( warningMessage );
237 //"The model may be incomplete due to a previous error in resolving information. Refer to the repository problem reports for more information." );
241 * Show the artifact information tab.
243 public String dependencies()
245 String result = artifact();
247 this.dependencies = model.getDependencies();
253 * Show the mailing lists information tab.
255 public String mailingLists()
257 String result = artifact();
259 this.mailingLists = model.getMailingLists();
265 * Show the reports tab.
267 public String reports()
269 // TODO: hook up reports on project
275 * Show the dependees (other artifacts that depend on this project) tab.
277 public String dependees()
278 throws MetadataResolutionException
280 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
281 // TODO: what if we get duplicates across repositories?
282 RepositorySession repositorySession = repositorySessionFactory.createSession();
285 MetadataResolver metadataResolver = repositorySession.getResolver();
286 for ( String repoId : getObservableRepos() )
288 // TODO: what about if we want to see this irrespective of version?
290 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
296 repositorySession.close();
299 this.dependees = references;
301 // TODO: may need to note on the page that references will be incomplete if the other artifacts are not yet
302 // stored in the content repository
303 // (especially in the case of pre-population import)
309 * Show the dependencies of this versioned project tab.
311 public String dependencyTree()
313 // temporarily use this as we only need the model for the tag to perform, but we should be resolving the
314 // graph here instead
316 // TODO: may need to note on the page that tree will be incomplete if the other artifacts are not yet stored in
317 // the content repository
318 // (especially in the case of pre-population import)
320 // TODO: a bit ugly, should really be mapping all these results differently now
321 this.dependencyTree = true;
326 public String projectMetadata()
328 String result = artifact();
330 if ( model.getFacet( GenericMetadataFacet.FACET_ID ) != null )
332 genericMetadata = model.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
335 if ( genericMetadata == null )
337 genericMetadata = new HashMap<String, String>();
343 public String addMetadataProperty()
345 RepositorySession repositorySession = repositorySessionFactory.createSession();
346 ProjectVersionMetadata projectMetadata;
349 MetadataRepository metadataRepository = repositorySession.getRepository();
350 projectMetadata = getProjectVersionMetadata( repositorySession );
351 if ( projectMetadata == null )
353 addActionError( "Artifact not found" );
357 if ( projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ) == null )
359 genericMetadata = new HashMap<String, String>();
363 genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
366 if ( propertyName == null || "".equals( propertyName.trim() ) || propertyValue == null || "".equals(
367 propertyValue.trim() ) )
369 model = projectMetadata;
370 addActionError( "Property Name and Property Value are required." );
374 genericMetadata.put( propertyName, propertyValue );
378 updateProjectMetadata( projectMetadata, metadataRepository );
379 repositorySession.save();
381 catch ( MetadataRepositoryException e )
383 log.warn( "Unable to persist modified project metadata after adding entry: " + e.getMessage(), e );
385 "Unable to add metadata item to underlying content storage - consult application logs." );
389 // TODO: why re-retrieve?
390 projectMetadata = getProjectVersionMetadata( repositorySession );
392 catch ( Exception e )
394 log.warn( "Unable to getProjectVersionMetadata: " + e.getMessage(), e );
395 addActionError( "Unable to getProjectVersionMetadata - consult application logs." );
400 repositorySession.close();
403 genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
405 model = projectMetadata;
413 public String deleteMetadataEntry()
415 RepositorySession repositorySession = repositorySessionFactory.createSession();
418 MetadataRepository metadataRepository = repositorySession.getRepository();
419 ProjectVersionMetadata projectMetadata = getProjectVersionMetadata( repositorySession );
421 if ( projectMetadata == null )
423 addActionError( "Artifact not found" );
427 if ( projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ) != null )
429 genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
431 if ( !StringUtils.isEmpty( deleteItem ) )
433 genericMetadata.remove( deleteItem );
437 updateProjectMetadata( projectMetadata, metadataRepository );
438 repositorySession.save();
440 catch ( MetadataRepositoryException e )
442 log.warn( "Unable to persist modified project metadata after removing entry: " + e.getMessage(),
445 "Unable to remove metadata item to underlying content storage - consult application logs." );
449 // TODO: why re-retrieve?
450 projectMetadata = getProjectVersionMetadata( repositorySession );
452 genericMetadata = projectMetadata.getFacet( GenericMetadataFacet.FACET_ID ).toProperties();
454 model = projectMetadata;
456 addActionMessage( "Property successfully deleted." );
463 addActionError( "No generic metadata facet for this artifact." );
467 catch ( Exception e )
469 log.warn( "Unable to getProjectVersionMetadata: " + e.getMessage(), e );
470 addActionError( "Unable to getProjectVersionMetadata - consult application logs." );
476 repositorySession.close();
482 private void updateProjectMetadata( ProjectVersionMetadata projectMetadata, MetadataRepository metadataRepository )
483 throws MetadataRepositoryException
485 GenericMetadataFacet genericMetadataFacet = new GenericMetadataFacet();
486 genericMetadataFacet.fromProperties( genericMetadata );
488 projectMetadata.addFacet( genericMetadataFacet );
490 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectMetadata );
494 public void validate()
496 if ( StringUtils.isBlank( groupId ) )
498 addActionError( "You must specify a group ID to browse" );
501 if ( StringUtils.isBlank( artifactId ) )
503 addActionError( "You must specify a artifact ID to browse" );
506 if ( StringUtils.isBlank( version ) )
508 addActionError( "You must specify a version to browse" );
512 public ProjectVersionMetadata getModel()
517 public String getGroupId()
522 public void setGroupId( String groupId )
524 this.groupId = groupId;
527 public String getArtifactId()
532 public void setArtifactId( String artifactId )
534 this.artifactId = artifactId;
537 public String getVersion()
542 public void setVersion( String version )
544 this.version = version;
547 public List<MailingList> getMailingLists()
552 public List<Dependency> getDependencies()
557 public List<ProjectVersionReference> getDependees()
562 public String getRepositoryId()
567 public void setRepositoryId( String repositoryId )
569 this.repositoryId = repositoryId;
572 public Map<String, List<Artifact>> getArtifacts()
577 public Collection<String> getSnapshotVersions()
579 return artifacts.keySet();
582 public boolean isDependencyTree()
584 return dependencyTree;
587 public void setDeleteItem( String deleteItem )
589 this.deleteItem = deleteItem;
592 public Map<String, String> getGenericMetadata()
594 return genericMetadata;
597 public void setGenericMetadata( Map<String, String> genericMetadata )
599 this.genericMetadata = genericMetadata;
602 public String getPropertyName()
607 public void setPropertyName( String propertyName )
609 this.propertyName = propertyName;
612 public String getPropertyValue()
614 return propertyValue;
617 public void setPropertyValue( String propertyValue )
619 this.propertyValue = propertyValue;
622 public void setRepositoryFactory( RepositoryContentFactory repositoryFactory )
624 this.repositoryFactory = repositoryFactory;