1 package org.apache.archiva.rest.services;
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
21 import org.apache.archiva.admin.model.beans.ManagedRepository;
22 import org.apache.archiva.common.utils.VersionComparator;
23 import org.apache.archiva.dependency.tree.maven2.DependencyTreeBuilder;
24 import org.apache.archiva.metadata.generic.GenericMetadataFacet;
25 import org.apache.archiva.metadata.model.ArtifactMetadata;
26 import org.apache.archiva.metadata.model.MetadataFacet;
27 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
28 import org.apache.archiva.metadata.model.ProjectVersionReference;
29 import org.apache.archiva.metadata.repository.MetadataRepository;
30 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
31 import org.apache.archiva.metadata.repository.MetadataResolutionException;
32 import org.apache.archiva.metadata.repository.MetadataResolver;
33 import org.apache.archiva.metadata.repository.RepositorySession;
34 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMetadataVersionComparator;
35 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
36 import org.apache.archiva.model.ArchivaArtifact;
37 import org.apache.archiva.repository.ManagedRepositoryContent;
38 import org.apache.archiva.repository.RepositoryContentFactory;
39 import org.apache.archiva.repository.RepositoryException;
40 import org.apache.archiva.repository.RepositoryNotFoundException;
41 import org.apache.archiva.rest.api.model.Artifact;
42 import org.apache.archiva.rest.api.model.ArtifactContentEntry;
43 import org.apache.archiva.rest.api.model.ArtifactDownloadInfo;
44 import org.apache.archiva.rest.api.model.BrowseResult;
45 import org.apache.archiva.rest.api.model.BrowseResultEntry;
46 import org.apache.archiva.rest.api.model.Entry;
47 import org.apache.archiva.rest.api.model.TreeEntry;
48 import org.apache.archiva.rest.api.model.VersionsList;
49 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
50 import org.apache.archiva.rest.api.services.BrowseService;
51 import org.apache.archiva.rest.services.utils.ArtifactContentEntryComparator;
52 import org.apache.archiva.rest.services.utils.ArtifactDownloadInfoBuilder;
53 import org.apache.archiva.rest.services.utils.TreeDependencyNodeVisitor;
54 import org.apache.archiva.security.ArchivaSecurityException;
55 import org.apache.commons.collections.CollectionUtils;
56 import org.apache.commons.io.FileUtils;
57 import org.apache.commons.io.IOUtils;
58 import org.apache.commons.lang.StringUtils;
59 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
60 import org.springframework.stereotype.Service;
62 import javax.inject.Inject;
63 import javax.ws.rs.core.Response;
65 import java.io.IOException;
66 import java.io.InputStream;
67 import java.util.ArrayList;
68 import java.util.Collection;
69 import java.util.Collections;
70 import java.util.Enumeration;
71 import java.util.HashMap;
72 import java.util.LinkedHashSet;
73 import java.util.List;
76 import java.util.jar.JarEntry;
77 import java.util.jar.JarFile;
78 import java.util.zip.ZipEntry;
81 * @author Olivier Lamy
84 @Service( "browseService#rest" )
85 public class DefaultBrowseService
86 extends AbstractRestService
87 implements BrowseService
91 private DependencyTreeBuilder dependencyTreeBuilder;
94 private RepositoryContentFactory repositoryContentFactory;
96 public BrowseResult getRootGroups( String repositoryId )
97 throws ArchivaRestServiceException
99 List<String> selectedRepos = getSelectedRepos( repositoryId );
101 Set<String> namespaces = new LinkedHashSet<String>();
103 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
104 // it is located here to avoid the content repository implementation needing to do too much for what
105 // is essentially presentation code
106 Set<String> namespacesToCollapse;
107 RepositorySession repositorySession = repositorySessionFactory.createSession();
110 MetadataResolver metadataResolver = repositorySession.getResolver();
111 namespacesToCollapse = new LinkedHashSet<String>();
113 for ( String repoId : selectedRepos )
115 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
117 for ( String n : namespacesToCollapse )
119 // TODO: check performance of this
120 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
123 catch ( MetadataResolutionException e )
125 throw new ArchivaRestServiceException( e.getMessage(),
126 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
130 repositorySession.close();
133 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
134 for ( String namespace : namespaces )
136 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
139 Collections.sort( browseGroupResultEntries );
140 return new BrowseResult( browseGroupResultEntries );
143 public BrowseResult browseGroupId( String groupId, String repositoryId )
144 throws ArchivaRestServiceException
146 List<String> selectedRepos = getSelectedRepos( repositoryId );
148 Set<String> projects = new LinkedHashSet<String>();
150 RepositorySession repositorySession = repositorySessionFactory.createSession();
151 Set<String> namespaces;
154 MetadataResolver metadataResolver = repositorySession.getResolver();
156 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
157 for ( String repoId : selectedRepos )
159 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
161 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
164 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
165 // it is located here to avoid the content repository implementation needing to do too much for what
166 // is essentially presentation code
167 namespaces = new LinkedHashSet<String>();
168 for ( String n : namespacesToCollapse )
170 // TODO: check performance of this
172 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
175 catch ( MetadataResolutionException e )
177 throw new ArchivaRestServiceException( e.getMessage(),
178 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
182 repositorySession.close();
184 List<BrowseResultEntry> browseGroupResultEntries =
185 new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
186 for ( String namespace : namespaces )
188 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
190 for ( String project : projects )
192 browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
194 Collections.sort( browseGroupResultEntries );
195 return new BrowseResult( browseGroupResultEntries );
199 public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
200 throws ArchivaRestServiceException
202 List<String> selectedRepos = getSelectedRepos( repositoryId );
206 return new VersionsList( new ArrayList<String>( getVersions( selectedRepos, groupId, artifactId ) ) );
208 catch ( MetadataResolutionException e )
210 throw new ArchivaRestServiceException( e.getMessage(),
211 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
216 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
217 throws MetadataResolutionException
220 RepositorySession repositorySession = repositorySessionFactory.createSession();
223 MetadataResolver metadataResolver = repositorySession.getResolver();
225 Set<String> versions = new LinkedHashSet<String>();
227 for ( String repoId : selectedRepos )
230 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
233 List<String> sortedVersions = new ArrayList<String>( versions );
235 Collections.sort( sortedVersions, VersionComparator.getInstance() );
237 return sortedVersions;
241 repositorySession.close();
245 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
246 String repositoryId )
247 throws ArchivaRestServiceException
249 List<String> selectedRepos = getSelectedRepos( repositoryId );
251 RepositorySession repositorySession = null;
254 repositorySession = repositorySessionFactory.createSession();
256 MetadataResolver metadataResolver = repositorySession.getResolver();
258 ProjectVersionMetadata versionMetadata = null;
259 for ( String repoId : selectedRepos )
261 if ( versionMetadata == null || versionMetadata.isIncomplete() )
266 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
269 catch ( MetadataResolutionException e )
272 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
273 + " in repo " + repoId + ": " + e.getMessage() );
278 return versionMetadata;
282 if ( repositorySession != null )
284 repositorySession.close();
290 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
291 throws ArchivaRestServiceException
294 List<String> selectedRepos = getSelectedRepos( repositoryId );
296 RepositorySession repositorySession = null;
300 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
302 repositorySession = repositorySessionFactory.createSession();
304 MetadataResolver metadataResolver = repositorySession.getResolver();
306 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
308 MavenProjectFacet mavenFacet = new MavenProjectFacet();
309 mavenFacet.setGroupId( groupId );
310 mavenFacet.setArtifactId( artifactId );
311 sharedModel.addFacet( mavenFacet );
313 boolean isFirstVersion = true;
315 for ( String version : projectVersions )
317 ProjectVersionMetadata versionMetadata = null;
318 for ( String repoId : selectedRepos )
320 if ( versionMetadata == null || versionMetadata.isIncomplete() )
325 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
328 catch ( MetadataResolutionException e )
330 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
331 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
336 if ( versionMetadata == null )
341 if ( isFirstVersion )
343 sharedModel = versionMetadata;
344 sharedModel.setId( null );
348 MavenProjectFacet versionMetadataMavenFacet =
349 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
350 if ( versionMetadataMavenFacet != null )
352 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
353 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
355 mavenFacet.setPackaging( null );
359 if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
360 versionMetadata.getName() ) )
362 sharedModel.setName( versionMetadata.getName() );
365 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
366 sharedModel.getDescription(), versionMetadata.getDescription() ) )
368 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
369 ? versionMetadata.getDescription()
373 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
374 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
375 versionMetadata.getIssueManagement().getUrl() ) )
377 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
380 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
381 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
382 versionMetadata.getCiManagement().getUrl() ) )
384 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
387 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
388 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
389 versionMetadata.getOrganization().getName() ) )
391 sharedModel.setOrganization( versionMetadata.getOrganization() );
394 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
395 versionMetadata.getUrl() ) )
397 sharedModel.setUrl( versionMetadata.getUrl() );
401 isFirstVersion = false;
405 catch ( MetadataResolutionException e )
407 throw new ArchivaRestServiceException( e.getMessage(),
408 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
412 if ( repositorySession != null )
414 repositorySession.close();
419 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
420 throws ArchivaRestServiceException
422 List<String> selectedRepos = getSelectedRepos( repositoryId );
424 List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
425 TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
428 dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
429 treeDependencyNodeVisitor );
431 catch ( DependencyTreeBuilderException e )
433 throw new ArchivaRestServiceException( e.getMessage(),
434 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
439 public List<ManagedRepository> getUserRepositories()
440 throws ArchivaRestServiceException
444 return userRepositories.getAccessibleRepositories( getPrincipal() );
446 catch ( ArchivaSecurityException e )
448 throw new ArchivaRestServiceException( "repositories.read.observable.error",
449 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
453 public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
454 throws ArchivaRestServiceException
456 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
457 // TODO: what if we get duplicates across repositories?
458 RepositorySession repositorySession = repositorySessionFactory.createSession();
461 MetadataResolver metadataResolver = repositorySession.getResolver();
462 for ( String repoId : getObservableRepos() )
464 // TODO: what about if we want to see this irrespective of version?
466 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
470 catch ( MetadataResolutionException e )
472 throw new ArchivaRestServiceException( e.getMessage(),
473 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
477 repositorySession.close();
480 List<Artifact> artifacts = new ArrayList<Artifact>( references.size() );
482 for ( ProjectVersionReference projectVersionReference : references )
484 artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
485 projectVersionReference.getProjectVersion() ) );
490 public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
491 throws ArchivaRestServiceException
493 ProjectVersionMetadata projectVersionMetadata =
494 getProjectMetadata( groupId, artifactId, version, repositoryId );
495 if ( projectVersionMetadata == null )
497 return Collections.emptyList();
499 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
501 if ( metadataFacet == null )
503 return Collections.emptyList();
505 Map<String, String> map = metadataFacet.toProperties();
506 List<Entry> entries = new ArrayList<Entry>( map.size() );
508 for ( Map.Entry<String, String> entry : map.entrySet() )
510 entries.add( new Entry( entry.getKey(), entry.getValue() ) );
516 public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
517 String repositoryId )
518 throws ArchivaRestServiceException
520 ProjectVersionMetadata projectVersionMetadata =
521 getProjectMetadata( groupId, artifactId, version, repositoryId );
523 if ( projectVersionMetadata == null )
525 return Boolean.FALSE;
528 Map<String, String> properties = new HashMap<String, String>();
530 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
532 if ( metadataFacet != null && metadataFacet.toProperties() != null )
534 properties.putAll( metadataFacet.toProperties() );
538 metadataFacet = new GenericMetadataFacet();
541 properties.put( key, value );
543 metadataFacet.fromProperties( properties );
545 projectVersionMetadata.addFacet( metadataFacet );
547 RepositorySession repositorySession = repositorySessionFactory.createSession();
551 MetadataRepository metadataRepository = repositorySession.getRepository();
553 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
555 repositorySession.save();
557 catch ( MetadataRepositoryException e )
559 log.error( e.getMessage(), e );
560 throw new ArchivaRestServiceException( e.getMessage(),
561 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
565 repositorySession.close();
570 public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
571 throws ArchivaRestServiceException
573 ProjectVersionMetadata projectVersionMetadata =
574 getProjectMetadata( groupId, artifactId, version, repositoryId );
576 if ( projectVersionMetadata == null )
578 return Boolean.FALSE;
581 GenericMetadataFacet metadataFacet =
582 (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
584 if ( metadataFacet != null && metadataFacet.toProperties() != null )
586 Map<String, String> properties = metadataFacet.toProperties();
587 properties.remove( key );
588 metadataFacet.setAdditionalProperties( properties );
595 RepositorySession repositorySession = repositorySessionFactory.createSession();
599 MetadataRepository metadataRepository = repositorySession.getRepository();
601 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
603 repositorySession.save();
605 catch ( MetadataRepositoryException e )
607 log.error( e.getMessage(), e );
608 throw new ArchivaRestServiceException( e.getMessage(),
609 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
613 repositorySession.close();
618 public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
619 String classifier, String type, String path,
620 String repositoryId )
621 throws ArchivaRestServiceException
623 List<String> selectedRepos = getSelectedRepos( repositoryId );
626 for ( String repoId : selectedRepos )
629 ManagedRepositoryContent managedRepositoryContent =
630 repositoryContentFactory.getManagedRepositoryContent( repoId );
631 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
632 StringUtils.isEmpty( type ) ? "jar" : type,
634 File file = managedRepositoryContent.toFile( archivaArtifact );
637 return readFileEntries( file, path );
641 catch ( IOException e )
643 log.error( e.getMessage(), e );
644 throw new ArchivaRestServiceException( e.getMessage(),
645 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
647 catch ( RepositoryNotFoundException e )
649 log.error( e.getMessage(), e );
650 throw new ArchivaRestServiceException( e.getMessage(),
651 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
653 catch ( RepositoryException e )
655 log.error( e.getMessage(), e );
656 throw new ArchivaRestServiceException( e.getMessage(),
657 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
659 return Collections.emptyList();
662 public List<ArtifactDownloadInfo> getArtifactDownloadInfos( String groupId, String artifactId, String version,
663 String repositoryId )
664 throws ArchivaRestServiceException
666 List<String> selectedRepos = getSelectedRepos( repositoryId );
668 List<ArtifactDownloadInfo> artifactDownloadInfos = new ArrayList<ArtifactDownloadInfo>();
670 RepositorySession session = repositorySessionFactory.createSession();
672 MetadataResolver metadataResolver = session.getResolver();
676 for ( String repoId : selectedRepos )
678 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(
679 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
680 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
682 for ( ArtifactMetadata artifact : artifacts )
685 ArtifactDownloadInfoBuilder builder =
686 new ArtifactDownloadInfoBuilder().forArtifactMetadata( artifact ).withManagedRepositoryContent(
687 repositoryContentFactory.getManagedRepositoryContent( repoId ) );
688 artifactDownloadInfos.add( builder.build() );
693 catch ( RepositoryException e )
695 log.error( e.getMessage(), e );
696 throw new ArchivaRestServiceException( e.getMessage(),
697 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
699 catch ( MetadataResolutionException e )
701 log.error( e.getMessage(), e );
702 throw new ArchivaRestServiceException( e.getMessage(),
703 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
707 if ( session != null )
713 return artifactDownloadInfos;
716 public String getArtifactContentText( String groupId, String artifactId, String version, String classifier,
717 String type, String path, String repositoryId )
718 throws ArchivaRestServiceException
720 List<String> selectedRepos = getSelectedRepos( repositoryId );
723 for ( String repoId : selectedRepos )
726 ManagedRepositoryContent managedRepositoryContent =
727 repositoryContentFactory.getManagedRepositoryContent( repoId );
728 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
729 StringUtils.isEmpty( type ) ? "jar" : type,
731 File file = managedRepositoryContent.toFile( archivaArtifact );
732 if ( !file.exists() )
737 if ( StringUtils.isNotBlank( path ) )
739 // zip entry of the path -> path must a real file entry of the archive
740 JarFile jarFile = new JarFile( file );
741 ZipEntry zipEntry = jarFile.getEntry( path );
742 InputStream inputStream = jarFile.getInputStream( zipEntry );
745 return IOUtils.toString( inputStream );
749 IOUtils.closeQuietly( inputStream );
752 return FileUtils.readFileToString( file );
755 catch ( IOException e )
757 log.error( e.getMessage(), e );
758 throw new ArchivaRestServiceException( e.getMessage(),
759 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
761 catch ( RepositoryNotFoundException e )
763 log.error( e.getMessage(), e );
764 throw new ArchivaRestServiceException( e.getMessage(),
765 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
767 catch ( RepositoryException e )
769 log.error( e.getMessage(), e );
770 throw new ArchivaRestServiceException( e.getMessage(),
771 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
776 //---------------------------
778 //---------------------------
780 protected List<ArtifactContentEntry> readFileEntries( File file, String filterPath )
783 Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<String, ArtifactContentEntry>();
784 int filterDepth = StringUtils.countMatches( filterPath, "/" );
785 /*if ( filterDepth == 0 )
789 JarFile jarFile = new JarFile( file );
792 Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
793 while ( jarEntryEnumeration.hasMoreElements() )
795 JarEntry currentEntry = jarEntryEnumeration.nextElement();
796 String cleanedEntryName =
797 StringUtils.endsWith( currentEntry.getName(), "/" ) ? StringUtils.substringBeforeLast(
798 currentEntry.getName(), "/" ) : currentEntry.getName();
799 String entryRootPath = getRootPath( cleanedEntryName );
800 int depth = StringUtils.countMatches( cleanedEntryName, "/" );
801 if ( StringUtils.isEmpty( filterPath ) && !artifactContentEntryMap.containsKey( entryRootPath )
802 && depth == filterDepth )
805 artifactContentEntryMap.put( entryRootPath,
806 new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
811 if ( StringUtils.startsWith( cleanedEntryName, filterPath ) && ( depth == filterDepth || (
812 !currentEntry.isDirectory() && depth == filterDepth ) ) )
814 artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
815 !currentEntry.isDirectory(),
821 if ( StringUtils.isNotEmpty( filterPath ) )
823 Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap =
824 new HashMap<String, ArtifactContentEntry>();
826 for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
828 filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
831 List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
832 if ( sorted == null )
834 return Collections.emptyList();
836 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
842 if ( jarFile != null )
847 List<ArtifactContentEntry> sorted = new ArrayList<ArtifactContentEntry>( artifactContentEntryMap.values() );
848 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
852 private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
854 int smallestDepth = Integer.MAX_VALUE;
855 Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<Integer, List<ArtifactContentEntry>>();
856 for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
859 ArtifactContentEntry current = entry.getValue();
861 if ( current.getDepth() < smallestDepth )
863 smallestDepth = current.getDepth();
866 List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
868 if ( currentList == null )
870 currentList = new ArrayList<ArtifactContentEntry>();
871 currentList.add( current );
872 perDepthList.put( current.getDepth(), currentList );
876 currentList.add( current );
881 return perDepthList.get( smallestDepth );
886 * @return org/apache -> org , org -> org
888 private String getRootPath( String path )
890 if ( StringUtils.contains( path, '/' ) )
892 return StringUtils.substringBefore( path, "/" );
897 private List<String> getSelectedRepos( String repositoryId )
898 throws ArchivaRestServiceException
901 List<String> selectedRepos = getObservableRepos();
903 if ( CollectionUtils.isEmpty( selectedRepos ) )
906 return Collections.emptyList();
909 if ( StringUtils.isNotEmpty( repositoryId ) )
911 // check user has karma on the repository
912 if ( !selectedRepos.contains( repositoryId ) )
914 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
915 Response.Status.FORBIDDEN.getStatusCode(), null );
917 selectedRepos = Collections.singletonList( repositoryId );
919 return selectedRepos;
923 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
924 Collection<String> repoIds, String n )
925 throws MetadataResolutionException
927 Set<String> subNamespaces = new LinkedHashSet<String>();
928 for ( String repoId : repoIds )
930 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
932 if ( subNamespaces.size() != 1 )
934 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
939 for ( String repoId : repoIds )
941 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
942 if ( projects != null && !projects.isEmpty() )
944 log.debug( "{} is not collapsible as it has projects", n );
948 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
949 n + "." + subNamespaces.iterator().next() );