mirror of https://github.com/apache/archiva.git
[MRM-1615] Artifact detail view
start working on dependency tree tab add a rest service. git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1303921 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f1c69d471f
commit
110d011627
|
@ -0,0 +1,69 @@
|
||||||
|
package org.apache.archiva.rest.api.model;
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Olivier Lamy
|
||||||
|
*/
|
||||||
|
@XmlRootElement( name = "treeEntry" )
|
||||||
|
public class TreeEntry
|
||||||
|
implements Serializable
|
||||||
|
{
|
||||||
|
|
||||||
|
private List<TreeEntry> childs = new ArrayList<TreeEntry>();
|
||||||
|
|
||||||
|
|
||||||
|
private Artifact artifact;
|
||||||
|
|
||||||
|
public TreeEntry()
|
||||||
|
{
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeEntry( Artifact artifact )
|
||||||
|
{
|
||||||
|
this.artifact = artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Artifact getArtifact()
|
||||||
|
{
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArtifact( Artifact artifact )
|
||||||
|
{
|
||||||
|
this.artifact = artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TreeEntry> getChilds()
|
||||||
|
{
|
||||||
|
return childs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChilds( List<TreeEntry> childs )
|
||||||
|
{
|
||||||
|
this.childs = childs;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ package org.apache.archiva.rest.api.services;
|
||||||
import org.apache.archiva.admin.model.beans.ManagedRepository;
|
import org.apache.archiva.admin.model.beans.ManagedRepository;
|
||||||
import org.apache.archiva.metadata.model.ProjectVersionMetadata;
|
import org.apache.archiva.metadata.model.ProjectVersionMetadata;
|
||||||
import org.apache.archiva.rest.api.model.BrowseResult;
|
import org.apache.archiva.rest.api.model.BrowseResult;
|
||||||
|
import org.apache.archiva.rest.api.model.TreeEntry;
|
||||||
import org.apache.archiva.rest.api.model.VersionsList;
|
import org.apache.archiva.rest.api.model.VersionsList;
|
||||||
import org.codehaus.plexus.redback.authorization.RedbackAuthorization;
|
import org.codehaus.plexus.redback.authorization.RedbackAuthorization;
|
||||||
|
|
||||||
|
@ -86,4 +87,13 @@ public interface BrowseService
|
||||||
@RedbackAuthorization( noPermission = true, noRestriction = true )
|
@RedbackAuthorization( noPermission = true, noRestriction = true )
|
||||||
List<ManagedRepository> getUserRepositories()
|
List<ManagedRepository> getUserRepositories()
|
||||||
throws ArchivaRestServiceException;
|
throws ArchivaRestServiceException;
|
||||||
|
|
||||||
|
@Path( "treeEntries/{g}/{a}/{v}" )
|
||||||
|
@GET
|
||||||
|
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
|
||||||
|
@RedbackAuthorization( noPermission = true, noRestriction = true )
|
||||||
|
List<TreeEntry> getTreeEntries( @PathParam( "g" ) String groupId, @PathParam( "a" ) String artifactId,
|
||||||
|
@PathParam( "v" ) String version,
|
||||||
|
@QueryParam( "repositoryId" ) String repositoryId )
|
||||||
|
throws ArchivaRestServiceException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,23 +18,31 @@ package org.apache.archiva.rest.services;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import net.sf.beanlib.provider.replicator.BeanReplicator;
|
||||||
import org.apache.archiva.admin.model.beans.ManagedRepository;
|
import org.apache.archiva.admin.model.beans.ManagedRepository;
|
||||||
import org.apache.archiva.common.utils.VersionComparator;
|
import org.apache.archiva.common.utils.VersionComparator;
|
||||||
|
import org.apache.archiva.dependency.tree.maven2.DependencyTreeBuilder;
|
||||||
import org.apache.archiva.metadata.model.ProjectVersionMetadata;
|
import org.apache.archiva.metadata.model.ProjectVersionMetadata;
|
||||||
import org.apache.archiva.metadata.repository.MetadataResolutionException;
|
import org.apache.archiva.metadata.repository.MetadataResolutionException;
|
||||||
import org.apache.archiva.metadata.repository.MetadataResolver;
|
import org.apache.archiva.metadata.repository.MetadataResolver;
|
||||||
import org.apache.archiva.metadata.repository.RepositorySession;
|
import org.apache.archiva.metadata.repository.RepositorySession;
|
||||||
import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
|
import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
|
||||||
|
import org.apache.archiva.rest.api.model.Artifact;
|
||||||
import org.apache.archiva.rest.api.model.BrowseResult;
|
import org.apache.archiva.rest.api.model.BrowseResult;
|
||||||
import org.apache.archiva.rest.api.model.BrowseResultEntry;
|
import org.apache.archiva.rest.api.model.BrowseResultEntry;
|
||||||
|
import org.apache.archiva.rest.api.model.TreeEntry;
|
||||||
import org.apache.archiva.rest.api.model.VersionsList;
|
import org.apache.archiva.rest.api.model.VersionsList;
|
||||||
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
|
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
|
||||||
import org.apache.archiva.rest.api.services.BrowseService;
|
import org.apache.archiva.rest.api.services.BrowseService;
|
||||||
import org.apache.archiva.security.ArchivaSecurityException;
|
import org.apache.archiva.security.ArchivaSecurityException;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.maven.shared.dependency.tree.DependencyNode;
|
||||||
|
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
|
||||||
|
import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -53,6 +61,9 @@ public class DefaultBrowseService
|
||||||
implements BrowseService
|
implements BrowseService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private DependencyTreeBuilder dependencyTreeBuilder;
|
||||||
|
|
||||||
public BrowseResult getRootGroups( String repositoryId )
|
public BrowseResult getRootGroups( String repositoryId )
|
||||||
throws ArchivaRestServiceException
|
throws ArchivaRestServiceException
|
||||||
{
|
{
|
||||||
|
@ -459,6 +470,109 @@ public class DefaultBrowseService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
|
||||||
|
throws ArchivaRestServiceException
|
||||||
|
{
|
||||||
|
List<String> selectedRepos = getObservableRepos();
|
||||||
|
|
||||||
|
if ( CollectionUtils.isEmpty( selectedRepos ) )
|
||||||
|
{
|
||||||
|
// FIXME 403 ???
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( StringUtils.isNotEmpty( repositoryId ) )
|
||||||
|
{
|
||||||
|
// check user has karma on the repository
|
||||||
|
if ( !selectedRepos.contains( repositoryId ) )
|
||||||
|
{
|
||||||
|
throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
|
||||||
|
Response.Status.FORBIDDEN.getStatusCode() );
|
||||||
|
}
|
||||||
|
selectedRepos = Collections.singletonList( repositoryId );
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
|
||||||
|
TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
|
||||||
|
treeDependencyNodeVisitor );
|
||||||
|
}
|
||||||
|
catch ( DependencyTreeBuilderException e )
|
||||||
|
{
|
||||||
|
throw new ArchivaRestServiceException( e.getMessage(),
|
||||||
|
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
|
||||||
|
}
|
||||||
|
return treeEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TreeDependencyNodeVisitor
|
||||||
|
implements DependencyNodeVisitor
|
||||||
|
{
|
||||||
|
final List<TreeEntry> treeEntries;
|
||||||
|
|
||||||
|
private TreeEntry currentEntry;
|
||||||
|
|
||||||
|
private DependencyNode firstNode;
|
||||||
|
|
||||||
|
private TreeDependencyNodeVisitor( List<TreeEntry> treeEntries )
|
||||||
|
{
|
||||||
|
this.treeEntries = treeEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit( DependencyNode node )
|
||||||
|
{
|
||||||
|
if ( firstNode == null )
|
||||||
|
{
|
||||||
|
firstNode = node;
|
||||||
|
}
|
||||||
|
if ( currentEntry == null )
|
||||||
|
{
|
||||||
|
currentEntry =
|
||||||
|
new TreeEntry( new BeanReplicator().replicateBean( node.getArtifact(), Artifact.class ) );
|
||||||
|
treeEntries.add( currentEntry );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( node.getChildren().isEmpty() )
|
||||||
|
{
|
||||||
|
currentEntry.getChilds().add(
|
||||||
|
new TreeEntry( new BeanReplicator().replicateBean( node.getArtifact(), Artifact.class ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !node.getChildren().isEmpty() )
|
||||||
|
{
|
||||||
|
for ( DependencyNode dependencyNode : (List<DependencyNode>) node.getChildren() )
|
||||||
|
{
|
||||||
|
if ( dependencyNode.getChildren().isEmpty() )
|
||||||
|
{
|
||||||
|
this.currentEntry.getChilds().add( new TreeEntry(
|
||||||
|
new BeanReplicator().replicateBean( dependencyNode.getArtifact(), Artifact.class ) ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TreeEntry backup = this.currentEntry;
|
||||||
|
this.currentEntry = new TreeEntry(
|
||||||
|
new BeanReplicator().replicateBean( dependencyNode.getArtifact(), Artifact.class ) );
|
||||||
|
visit( dependencyNode );
|
||||||
|
this.currentEntry = backup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean endVisit( DependencyNode node )
|
||||||
|
{
|
||||||
|
firstNode = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public List<ManagedRepository> getUserRepositories()
|
public List<ManagedRepository> getUserRepositories()
|
||||||
throws ArchivaRestServiceException
|
throws ArchivaRestServiceException
|
||||||
{
|
{
|
||||||
|
|
|
@ -202,7 +202,25 @@ $(function() {
|
||||||
mainContent.find("#browse-autocomplete-divider" ).hide();
|
mainContent.find("#browse-autocomplete-divider" ).hide();
|
||||||
mainContent.find("#artifact-details-tabs").on('show', function (e) {
|
mainContent.find("#artifact-details-tabs").on('show', function (e) {
|
||||||
if ($(e.target).attr("href")=="#artifact-details-dependency-tree-content") {
|
if ($(e.target).attr("href")=="#artifact-details-dependency-tree-content") {
|
||||||
$.log("#artifact-details-dependency-tree-content");
|
var treeContentDiv=$("#artifact-details-dependency-tree-content" );
|
||||||
|
//if( $.trim(treeContentDiv.html()).length<1){
|
||||||
|
treeContentDiv.html(mediumSpinnerImg());
|
||||||
|
var treeDependencyUrl="restServices/archivaServices/browseService/treeEntries/"+encodeURIComponent(groupId);
|
||||||
|
treeDependencyUrl+="/"+encodeURIComponent(artifactId);
|
||||||
|
treeDependencyUrl+="/"+encodeURIComponent(version);
|
||||||
|
var selectedRepo=getSelectedBrowsingRepository();
|
||||||
|
if (selectedRepo){
|
||||||
|
treeDependencyUrl+="?repositoryId="+encodeURIComponent(selectedRepo);
|
||||||
|
}
|
||||||
|
var treeDependencyUrl=
|
||||||
|
$.ajax(treeDependencyUrl, {
|
||||||
|
type: "GET",
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
treeContentDiv.html($("#dependency_tree_tmpl" ).tmpl({treeEntries: [data[0]]}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
if ($(e.target).attr("href")=="#artifact-details-used-by-content") {
|
if ($(e.target).attr("href")=="#artifact-details-used-by-content") {
|
||||||
$.log("#artifact-details-used-by-content");
|
$.log("#artifact-details-used-by-content");
|
||||||
|
@ -231,6 +249,8 @@ $(function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
displayArtifactDetail=function(groupId,artifactId,parentBrowseViewModel,restUrl){
|
displayArtifactDetail=function(groupId,artifactId,parentBrowseViewModel,restUrl){
|
||||||
var artifactDetailViewModel=new ArtifactDetailViewModel(groupId,artifactId);
|
var artifactDetailViewModel=new ArtifactDetailViewModel(groupId,artifactId);
|
||||||
var mainContent = $("#main-content");
|
var mainContent = $("#main-content");
|
||||||
|
|
|
@ -607,9 +607,7 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="artifact-details-dependency-tree-content" class="tab-pane">
|
<div id="artifact-details-dependency-tree-content" class="tab-pane"></div>
|
||||||
dependency tree
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="artifact-details-used-by-content" class="tab-pane">
|
<div id="artifact-details-used-by-content" class="tab-pane">
|
||||||
used by
|
used by
|
||||||
|
@ -674,4 +672,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="dependency_tree_tmpl" type="text/html">
|
||||||
|
<ul>
|
||||||
|
{{each(i,treeEntry) treeEntries}}
|
||||||
|
<li>${treeEntry.artifact.groupId}:${treeEntry.artifact.artifactId}:${treeEntry.artifact.version}</li>
|
||||||
|
{{if treeEntry.childs.length>0}}
|
||||||
|
{{tmpl({treeEntries:treeEntry.childs}) "#dependency_tree_tmpl"}}
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
</script>
|
</script>
|
Loading…
Reference in New Issue