mirror of https://github.com/apache/archiva.git
[MRM-1573] start work on browse screen
git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1244606 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
dc0f7bd90d
commit
f6ec5a7e86
|
@ -0,0 +1,43 @@
|
||||||
|
package org.apache.archiva.rest.api.services;
|
||||||
|
/*
|
||||||
|
* 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 org.apache.archiva.rest.api.model.GroupIdList;
|
||||||
|
import org.codehaus.plexus.redback.authorization.RedbackAuthorization;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Olivier Lamy
|
||||||
|
* @since 1.4-M3
|
||||||
|
*/
|
||||||
|
@Path( "/browseService/" )
|
||||||
|
public interface BrowseService
|
||||||
|
{
|
||||||
|
@Path( "rootGroups" )
|
||||||
|
@GET
|
||||||
|
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
|
||||||
|
@RedbackAuthorization( noRestriction = true, noPermission = false )
|
||||||
|
GroupIdList getRootGroups()
|
||||||
|
throws ArchivaRestServiceException;
|
||||||
|
}
|
|
@ -20,8 +20,14 @@ package org.apache.archiva.rest.services;
|
||||||
|
|
||||||
import org.apache.archiva.admin.model.AuditInformation;
|
import org.apache.archiva.admin.model.AuditInformation;
|
||||||
import org.apache.archiva.audit.AuditListener;
|
import org.apache.archiva.audit.AuditListener;
|
||||||
|
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
|
||||||
|
import org.apache.archiva.security.AccessDeniedException;
|
||||||
|
import org.apache.archiva.security.ArchivaSecurityException;
|
||||||
|
import org.apache.archiva.security.PrincipalNotFoundException;
|
||||||
|
import org.apache.archiva.security.UserRepositories;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.codehaus.plexus.redback.users.User;
|
import org.codehaus.plexus.redback.users.User;
|
||||||
|
import org.codehaus.plexus.redback.users.UserManager;
|
||||||
import org.codehaus.redback.rest.services.RedbackAuthenticationThreadLocal;
|
import org.codehaus.redback.rest.services.RedbackAuthenticationThreadLocal;
|
||||||
import org.codehaus.redback.rest.services.RedbackRequestInformation;
|
import org.codehaus.redback.rest.services.RedbackRequestInformation;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -29,9 +35,11 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -50,6 +58,14 @@ public abstract class AbstractRestService
|
||||||
@Inject
|
@Inject
|
||||||
private List<AuditListener> auditListeners = new ArrayList<AuditListener>();
|
private List<AuditListener> auditListeners = new ArrayList<AuditListener>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private UserRepositories userRepositories;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Named( value = "repositorySessionFactory" )
|
||||||
|
protected RepositorySessionFactory repositorySessionFactory;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
protected HttpServletRequest httpServletRequest;
|
protected HttpServletRequest httpServletRequest;
|
||||||
|
|
||||||
|
@ -71,6 +87,39 @@ public abstract class AbstractRestService
|
||||||
this.auditListeners = auditListeners;
|
this.auditListeners = auditListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<String> getObservableRepos()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<String> ids = userRepositories.getObservableRepositoryIds( getPrincipal() );
|
||||||
|
return ids == null ? Collections.<String>emptyList() : ids;
|
||||||
|
}
|
||||||
|
catch ( PrincipalNotFoundException e )
|
||||||
|
{
|
||||||
|
log.warn( e.getMessage(), e );
|
||||||
|
}
|
||||||
|
catch ( AccessDeniedException e )
|
||||||
|
{
|
||||||
|
log.warn( e.getMessage(), e );
|
||||||
|
}
|
||||||
|
catch ( ArchivaSecurityException e )
|
||||||
|
{
|
||||||
|
log.warn( e.getMessage(), e );
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getPrincipal()
|
||||||
|
{
|
||||||
|
RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
|
||||||
|
|
||||||
|
return redbackRequestInformation == null
|
||||||
|
? UserManager.GUEST_USERNAME
|
||||||
|
: ( redbackRequestInformation.getUser() == null
|
||||||
|
? UserManager.GUEST_USERNAME
|
||||||
|
: redbackRequestInformation.getUser().getUsername() );
|
||||||
|
}
|
||||||
|
|
||||||
protected String getBaseUrl( HttpServletRequest req )
|
protected String getBaseUrl( HttpServletRequest req )
|
||||||
{
|
{
|
||||||
return req.getScheme() + "://" + req.getServerName() + ( req.getServerPort() == 80
|
return req.getScheme() + "://" + req.getServerName() + ( req.getServerPort() == 80
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
package org.apache.archiva.rest.services;
|
||||||
|
/*
|
||||||
|
* 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 org.apache.archiva.metadata.repository.MetadataResolutionException;
|
||||||
|
import org.apache.archiva.metadata.repository.MetadataResolver;
|
||||||
|
import org.apache.archiva.metadata.repository.RepositorySession;
|
||||||
|
import org.apache.archiva.rest.api.model.GroupIdList;
|
||||||
|
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
|
||||||
|
import org.apache.archiva.rest.api.services.BrowseService;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Olivier Lamy
|
||||||
|
* @since 1.4-M3
|
||||||
|
*/
|
||||||
|
@Service( "browseService#rest" )
|
||||||
|
public class DefaultBrowseService
|
||||||
|
extends AbstractRestService
|
||||||
|
implements BrowseService
|
||||||
|
{
|
||||||
|
|
||||||
|
public GroupIdList getRootGroups()
|
||||||
|
throws ArchivaRestServiceException
|
||||||
|
{
|
||||||
|
List<String> selectedRepos = getObservableRepos();
|
||||||
|
if ( CollectionUtils.isEmpty( selectedRepos ) )
|
||||||
|
{
|
||||||
|
// FIXME 403 ???
|
||||||
|
return new GroupIdList( Collections.<String>emptyList() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> namespaces = new LinkedHashSet<String>();
|
||||||
|
|
||||||
|
// TODO: this logic should be optional, particularly remembering we want to keep this code simple
|
||||||
|
// it is located here to avoid the content repository implementation needing to do too much for what
|
||||||
|
// is essentially presentation code
|
||||||
|
Set<String> namespacesToCollapse;
|
||||||
|
RepositorySession repositorySession = repositorySessionFactory.createSession();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MetadataResolver metadataResolver = repositorySession.getResolver();
|
||||||
|
namespacesToCollapse = new LinkedHashSet<String>();
|
||||||
|
for ( String repoId : selectedRepos )
|
||||||
|
{
|
||||||
|
namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( String n : namespacesToCollapse )
|
||||||
|
{
|
||||||
|
// TODO: check performance of this
|
||||||
|
namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( MetadataResolutionException e )
|
||||||
|
{
|
||||||
|
throw new ArchivaRestServiceException( e.getMessage(),
|
||||||
|
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
repositorySession.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GroupIdList( getSortedList( namespaces ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------
|
||||||
|
// internals
|
||||||
|
//---------------------------
|
||||||
|
|
||||||
|
private List<String> getSortedList( Set<String> set )
|
||||||
|
{
|
||||||
|
List<String> list = new ArrayList<String>( set );
|
||||||
|
Collections.sort( list );
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
|
||||||
|
Collection<String> repoIds, String n )
|
||||||
|
throws MetadataResolutionException
|
||||||
|
{
|
||||||
|
Set<String> subNamespaces = new LinkedHashSet<String>();
|
||||||
|
for ( String repoId : repoIds )
|
||||||
|
{
|
||||||
|
subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
|
||||||
|
}
|
||||||
|
if ( subNamespaces.size() != 1 )
|
||||||
|
{
|
||||||
|
log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( String repoId : repoIds )
|
||||||
|
{
|
||||||
|
Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
|
||||||
|
if ( projects != null && !projects.isEmpty() )
|
||||||
|
{
|
||||||
|
log.debug( "{} is not collapsible as it has projects", n );
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collapseNamespaces( repositorySession, metadataResolver, repoIds,
|
||||||
|
n + "." + subNamespaces.iterator().next() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,20 +56,12 @@ public class DefaultManagedRepositoriesService
|
||||||
@Inject
|
@Inject
|
||||||
private ManagedRepositoryAdmin managedRepositoryAdmin;
|
private ManagedRepositoryAdmin managedRepositoryAdmin;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private PlexusSisuBridge plexusSisuBridge;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private RepositoryCommonValidator repositoryCommonValidator;
|
private RepositoryCommonValidator repositoryCommonValidator;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private RepositoryStatisticsManager repositoryStatisticsManager;
|
private RepositoryStatisticsManager repositoryStatisticsManager;
|
||||||
|
|
||||||
@Inject
|
|
||||||
@Named( value = "repositorySessionFactory" )
|
|
||||||
protected RepositorySessionFactory repositorySessionFactory;
|
|
||||||
|
|
||||||
|
|
||||||
public List<ManagedRepository> getManagedRepositories()
|
public List<ManagedRepository> getManagedRepositories()
|
||||||
throws ArchivaRestServiceException
|
throws ArchivaRestServiceException
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,14 +61,10 @@ public class DefaultSearchService
|
||||||
implements SearchService
|
implements SearchService
|
||||||
{
|
{
|
||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger( getClass() );
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private RepositorySearch repositorySearch;
|
private RepositorySearch repositorySearch;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private UserRepositories userRepositories;
|
|
||||||
|
|
||||||
public List<Artifact> quickSearch( String queryString )
|
public List<Artifact> quickSearch( String queryString )
|
||||||
throws ArchivaRestServiceException
|
throws ArchivaRestServiceException
|
||||||
{
|
{
|
||||||
|
@ -180,40 +176,6 @@ public class DefaultSearchService
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected List<String> getObservableRepos()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<String> ids = userRepositories.getObservableRepositoryIds( getPrincipal() );
|
|
||||||
return ids == null ? Collections.<String>emptyList() : ids;
|
|
||||||
}
|
|
||||||
catch ( PrincipalNotFoundException e )
|
|
||||||
{
|
|
||||||
log.warn( e.getMessage(), e );
|
|
||||||
}
|
|
||||||
catch ( AccessDeniedException e )
|
|
||||||
{
|
|
||||||
log.warn( e.getMessage(), e );
|
|
||||||
}
|
|
||||||
catch ( ArchivaSecurityException e )
|
|
||||||
{
|
|
||||||
log.warn( e.getMessage(), e );
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getPrincipal()
|
|
||||||
{
|
|
||||||
RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
|
|
||||||
|
|
||||||
return redbackRequestInformation == null
|
|
||||||
? UserManager.GUEST_USERNAME
|
|
||||||
: ( redbackRequestInformation.getUser() == null
|
|
||||||
? UserManager.GUEST_USERNAME
|
|
||||||
: redbackRequestInformation.getUser().getUsername() );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<Artifact> getArtifacts( SearchResults searchResults )
|
protected List<Artifact> getArtifacts( SearchResults searchResults )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
<ref bean="archivaAdministrationService#default"/>
|
<ref bean="archivaAdministrationService#default"/>
|
||||||
<ref bean="searchService#rest"/>
|
<ref bean="searchService#rest"/>
|
||||||
<ref bean="commonServices#rest"/>
|
<ref bean="commonServices#rest"/>
|
||||||
|
<ref bean="browseService#rest"/>
|
||||||
</jaxrs:serviceBeans>
|
</jaxrs:serviceBeans>
|
||||||
|
|
||||||
<jaxrs:outInterceptors>
|
<jaxrs:outInterceptors>
|
||||||
|
|
|
@ -17,8 +17,29 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
|
BrowseTopViewModel=function(groupIds){
|
||||||
|
this.groupIds=groupIds;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
displayBrowse=function(){
|
displayBrowse=function(){
|
||||||
$("#main-content" ).html("coming soon :-)");
|
var mainContent = $("#main-content");
|
||||||
|
mainContent.html(mediumSpinnerImg());
|
||||||
|
$.ajax("restServices/archivaServices/browseService/rootGroups", {
|
||||||
|
type: "GET",
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
var groupdIds = $.map(data.groupIdList.groupIds,function(item){
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
$.log("size:"+groupdIds.length);
|
||||||
|
var browseTopViewModel = new BrowseTopViewModel(groupdIds);
|
||||||
|
mainContent.html($("#browse-tmpl" ).tmpl());
|
||||||
|
ko.applyBindings(browseTopViewModel,mainContent.find("#browse_result" ).get(0));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
displaySearch=function(){
|
displaySearch=function(){
|
||||||
|
|
|
@ -16,3 +16,22 @@
|
||||||
~ specific language governing permissions and limitations
|
~ specific language governing permissions and limitations
|
||||||
~ under the License.
|
~ under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<script id="browse-tmpl" type="text/html">
|
||||||
|
<div>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2>${$.i18n.prop('browse.groups')}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="browse_result" data-bind='template:{name:"browse-top-tmpl"}'>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="browse-top-tmpl" type="text/html">
|
||||||
|
<ul>
|
||||||
|
{{each(i,groupId) groupIds}}
|
||||||
|
<li>${groupId}</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</script>
|
|
@ -183,9 +183,9 @@ public class BrowseAction
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<String> getSortedList( Set<String> set )
|
private List<String> getSortedList( Set<String> set )
|
||||||
{
|
{
|
||||||
ArrayList<String> list = new ArrayList<String>( set );
|
List<String> list = new ArrayList<String>( set );
|
||||||
Collections.sort( list );
|
Collections.sort( list );
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue