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.Arrays;
69 import java.util.Collection;
70 import java.util.Collections;
71 import java.util.Enumeration;
72 import java.util.HashMap;
73 import java.util.LinkedHashSet;
74 import java.util.List;
77 import java.util.jar.JarEntry;
78 import java.util.jar.JarFile;
79 import java.util.zip.ZipEntry;
82 * @author Olivier Lamy
85 @Service( "browseService#rest" )
86 public class DefaultBrowseService
87 extends AbstractRestService
88 implements BrowseService
92 private DependencyTreeBuilder dependencyTreeBuilder;
95 private RepositoryContentFactory repositoryContentFactory;
97 public BrowseResult getRootGroups( String repositoryId )
98 throws ArchivaRestServiceException
100 List<String> selectedRepos = getSelectedRepos( repositoryId );
102 Set<String> namespaces = new LinkedHashSet<String>();
104 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
105 // it is located here to avoid the content repository implementation needing to do too much for what
106 // is essentially presentation code
107 Set<String> namespacesToCollapse;
108 RepositorySession repositorySession = repositorySessionFactory.createSession();
111 MetadataResolver metadataResolver = repositorySession.getResolver();
112 namespacesToCollapse = new LinkedHashSet<String>();
114 for ( String repoId : selectedRepos )
116 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
118 for ( String n : namespacesToCollapse )
120 // TODO: check performance of this
121 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
124 catch ( MetadataResolutionException e )
126 throw new ArchivaRestServiceException( e.getMessage(),
127 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
131 repositorySession.close();
134 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
135 for ( String namespace : namespaces )
137 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
140 Collections.sort( browseGroupResultEntries );
141 return new BrowseResult( browseGroupResultEntries );
144 public BrowseResult browseGroupId( String groupId, String repositoryId )
145 throws ArchivaRestServiceException
147 List<String> selectedRepos = getSelectedRepos( repositoryId );
149 Set<String> projects = new LinkedHashSet<String>();
151 RepositorySession repositorySession = repositorySessionFactory.createSession();
152 Set<String> namespaces;
155 MetadataResolver metadataResolver = repositorySession.getResolver();
157 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
158 for ( String repoId : selectedRepos )
160 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
162 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
165 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
166 // it is located here to avoid the content repository implementation needing to do too much for what
167 // is essentially presentation code
168 namespaces = new LinkedHashSet<String>();
169 for ( String n : namespacesToCollapse )
171 // TODO: check performance of this
173 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
176 catch ( MetadataResolutionException e )
178 throw new ArchivaRestServiceException( e.getMessage(),
179 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
183 repositorySession.close();
185 List<BrowseResultEntry> browseGroupResultEntries =
186 new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
187 for ( String namespace : namespaces )
189 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
191 for ( String project : projects )
193 browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
195 Collections.sort( browseGroupResultEntries );
196 return new BrowseResult( browseGroupResultEntries );
200 public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
201 throws ArchivaRestServiceException
203 List<String> selectedRepos = getSelectedRepos( repositoryId );
207 return new VersionsList( new ArrayList<String>( getVersions( selectedRepos, groupId, artifactId ) ) );
209 catch ( MetadataResolutionException e )
211 throw new ArchivaRestServiceException( e.getMessage(),
212 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
217 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
218 throws MetadataResolutionException
221 RepositorySession repositorySession = repositorySessionFactory.createSession();
224 MetadataResolver metadataResolver = repositorySession.getResolver();
226 Set<String> versions = new LinkedHashSet<String>();
228 for ( String repoId : selectedRepos )
231 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
234 List<String> sortedVersions = new ArrayList<String>( versions );
236 Collections.sort( sortedVersions, VersionComparator.getInstance() );
238 return sortedVersions;
242 repositorySession.close();
246 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
247 String repositoryId )
248 throws ArchivaRestServiceException
250 List<String> selectedRepos = getSelectedRepos( repositoryId );
252 RepositorySession repositorySession = null;
255 repositorySession = repositorySessionFactory.createSession();
257 MetadataResolver metadataResolver = repositorySession.getResolver();
259 ProjectVersionMetadata versionMetadata = null;
260 for ( String repoId : selectedRepos )
262 if ( versionMetadata == null || versionMetadata.isIncomplete() )
267 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
270 catch ( MetadataResolutionException e )
273 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
274 + " in repo " + repoId + ": " + e.getMessage() );
279 return versionMetadata;
283 if ( repositorySession != null )
285 repositorySession.close();
291 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
292 throws ArchivaRestServiceException
295 List<String> selectedRepos = getSelectedRepos( repositoryId );
297 RepositorySession repositorySession = null;
301 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
303 repositorySession = repositorySessionFactory.createSession();
305 MetadataResolver metadataResolver = repositorySession.getResolver();
307 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
309 MavenProjectFacet mavenFacet = new MavenProjectFacet();
310 mavenFacet.setGroupId( groupId );
311 mavenFacet.setArtifactId( artifactId );
312 sharedModel.addFacet( mavenFacet );
314 boolean isFirstVersion = true;
316 for ( String version : projectVersions )
318 ProjectVersionMetadata versionMetadata = null;
319 for ( String repoId : selectedRepos )
321 if ( versionMetadata == null || versionMetadata.isIncomplete() )
326 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
329 catch ( MetadataResolutionException e )
331 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
332 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
337 if ( versionMetadata == null )
342 if ( isFirstVersion )
344 sharedModel = versionMetadata;
345 sharedModel.setId( null );
349 MavenProjectFacet versionMetadataMavenFacet =
350 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
351 if ( versionMetadataMavenFacet != null )
353 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
354 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
356 mavenFacet.setPackaging( null );
360 if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
361 versionMetadata.getName() ) )
363 sharedModel.setName( versionMetadata.getName() );
366 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
367 sharedModel.getDescription(), versionMetadata.getDescription() ) )
369 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
370 ? versionMetadata.getDescription()
374 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
375 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
376 versionMetadata.getIssueManagement().getUrl() ) )
378 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
381 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
382 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
383 versionMetadata.getCiManagement().getUrl() ) )
385 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
388 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
389 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
390 versionMetadata.getOrganization().getName() ) )
392 sharedModel.setOrganization( versionMetadata.getOrganization() );
395 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
396 versionMetadata.getUrl() ) )
398 sharedModel.setUrl( versionMetadata.getUrl() );
402 isFirstVersion = false;
406 catch ( MetadataResolutionException e )
408 throw new ArchivaRestServiceException( e.getMessage(),
409 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
413 if ( repositorySession != null )
415 repositorySession.close();
420 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
421 throws ArchivaRestServiceException
423 List<String> selectedRepos = getSelectedRepos( repositoryId );
425 List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
426 TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
429 dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
430 treeDependencyNodeVisitor );
432 catch ( DependencyTreeBuilderException e )
434 throw new ArchivaRestServiceException( e.getMessage(),
435 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
440 public List<ManagedRepository> getUserRepositories()
441 throws ArchivaRestServiceException
445 return userRepositories.getAccessibleRepositories( getPrincipal() );
447 catch ( ArchivaSecurityException e )
449 throw new ArchivaRestServiceException( "repositories.read.observable.error",
450 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
454 public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
455 throws ArchivaRestServiceException
457 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
458 // TODO: what if we get duplicates across repositories?
459 RepositorySession repositorySession = repositorySessionFactory.createSession();
462 MetadataResolver metadataResolver = repositorySession.getResolver();
463 for ( String repoId : getObservableRepos() )
465 // TODO: what about if we want to see this irrespective of version?
467 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
471 catch ( MetadataResolutionException e )
473 throw new ArchivaRestServiceException( e.getMessage(),
474 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
478 repositorySession.close();
481 List<Artifact> artifacts = new ArrayList<Artifact>( references.size() );
483 for ( ProjectVersionReference projectVersionReference : references )
485 artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
486 projectVersionReference.getProjectVersion() ) );
491 public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
492 throws ArchivaRestServiceException
494 ProjectVersionMetadata projectVersionMetadata =
495 getProjectMetadata( groupId, artifactId, version, repositoryId );
496 if ( projectVersionMetadata == null )
498 return Collections.emptyList();
500 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
502 if ( metadataFacet == null )
504 return Collections.emptyList();
506 Map<String, String> map = metadataFacet.toProperties();
507 List<Entry> entries = new ArrayList<Entry>( map.size() );
509 for ( Map.Entry<String, String> entry : map.entrySet() )
511 entries.add( new Entry( entry.getKey(), entry.getValue() ) );
517 public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
518 String repositoryId )
519 throws ArchivaRestServiceException
521 ProjectVersionMetadata projectVersionMetadata =
522 getProjectMetadata( groupId, artifactId, version, repositoryId );
524 if ( projectVersionMetadata == null )
526 return Boolean.FALSE;
529 Map<String, String> properties = new HashMap<String, String>();
531 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
533 if ( metadataFacet != null && metadataFacet.toProperties() != null )
535 properties.putAll( metadataFacet.toProperties() );
539 metadataFacet = new GenericMetadataFacet();
542 properties.put( key, value );
544 metadataFacet.fromProperties( properties );
546 projectVersionMetadata.addFacet( metadataFacet );
548 RepositorySession repositorySession = repositorySessionFactory.createSession();
552 MetadataRepository metadataRepository = repositorySession.getRepository();
554 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
556 repositorySession.save();
558 catch ( MetadataRepositoryException e )
560 log.error( e.getMessage(), e );
561 throw new ArchivaRestServiceException( e.getMessage(),
562 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
566 repositorySession.close();
571 public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
572 throws ArchivaRestServiceException
574 ProjectVersionMetadata projectVersionMetadata =
575 getProjectMetadata( groupId, artifactId, version, repositoryId );
577 if ( projectVersionMetadata == null )
579 return Boolean.FALSE;
582 GenericMetadataFacet metadataFacet =
583 (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
585 if ( metadataFacet != null && metadataFacet.toProperties() != null )
587 Map<String, String> properties = metadataFacet.toProperties();
588 properties.remove( key );
589 metadataFacet.setAdditionalProperties( properties );
596 RepositorySession repositorySession = repositorySessionFactory.createSession();
600 MetadataRepository metadataRepository = repositorySession.getRepository();
602 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
604 repositorySession.save();
606 catch ( MetadataRepositoryException e )
608 log.error( e.getMessage(), e );
609 throw new ArchivaRestServiceException( e.getMessage(),
610 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
614 repositorySession.close();
619 public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
620 String classifier, String type, String path,
621 String repositoryId )
622 throws ArchivaRestServiceException
624 List<String> selectedRepos = getSelectedRepos( repositoryId );
627 for ( String repoId : selectedRepos )
630 ManagedRepositoryContent managedRepositoryContent =
631 repositoryContentFactory.getManagedRepositoryContent( repoId );
632 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
633 StringUtils.isEmpty( type ) ? "jar" : type,
635 File file = managedRepositoryContent.toFile( archivaArtifact );
638 return readFileEntries( file, path );
642 catch ( IOException e )
644 log.error( e.getMessage(), e );
645 throw new ArchivaRestServiceException( e.getMessage(),
646 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
648 catch ( RepositoryNotFoundException e )
650 log.error( e.getMessage(), e );
651 throw new ArchivaRestServiceException( e.getMessage(),
652 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
654 catch ( RepositoryException e )
656 log.error( e.getMessage(), e );
657 throw new ArchivaRestServiceException( e.getMessage(),
658 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
660 return Collections.emptyList();
663 public List<ArtifactDownloadInfo> getArtifactDownloadInfos( String groupId, String artifactId, String version,
664 String repositoryId )
665 throws ArchivaRestServiceException
667 List<String> selectedRepos = getSelectedRepos( repositoryId );
669 List<ArtifactDownloadInfo> artifactDownloadInfos = new ArrayList<ArtifactDownloadInfo>();
671 RepositorySession session = repositorySessionFactory.createSession();
673 MetadataResolver metadataResolver = session.getResolver();
677 for ( String repoId : selectedRepos )
679 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(
680 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
681 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
683 for ( ArtifactMetadata artifact : artifacts )
686 ArtifactDownloadInfoBuilder builder =
687 new ArtifactDownloadInfoBuilder().forArtifactMetadata( artifact ).withManagedRepositoryContent(
688 repositoryContentFactory.getManagedRepositoryContent( repoId ) );
689 artifactDownloadInfos.add( builder.build() );
694 catch ( RepositoryException e )
696 log.error( e.getMessage(), e );
697 throw new ArchivaRestServiceException( e.getMessage(),
698 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
700 catch ( MetadataResolutionException e )
702 log.error( e.getMessage(), e );
703 throw new ArchivaRestServiceException( e.getMessage(),
704 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
708 if ( session != null )
714 return artifactDownloadInfos;
717 public String getArtifactContentText( String groupId, String artifactId, String version, String classifier,
718 String type, String path, String repositoryId )
719 throws ArchivaRestServiceException
721 List<String> selectedRepos = getSelectedRepos( repositoryId );
724 for ( String repoId : selectedRepos )
727 ManagedRepositoryContent managedRepositoryContent =
728 repositoryContentFactory.getManagedRepositoryContent( repoId );
729 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
730 StringUtils.isEmpty( type ) ? "jar" : type,
732 File file = managedRepositoryContent.toFile( archivaArtifact );
733 if ( !file.exists() )
735 log.debug( "file: {} not exists for repository: {} try next repository", file, repoId );
738 if ( StringUtils.isNotBlank( path ) )
740 // zip entry of the path -> path must a real file entry of the archive
741 JarFile jarFile = new JarFile( file );
742 ZipEntry zipEntry = jarFile.getEntry( path );
743 InputStream inputStream = jarFile.getInputStream( zipEntry );
746 return IOUtils.toString( inputStream );
750 IOUtils.closeQuietly( inputStream );
753 return FileUtils.readFileToString( file );
756 catch ( IOException e )
758 log.error( e.getMessage(), e );
759 throw new ArchivaRestServiceException( e.getMessage(),
760 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
762 catch ( RepositoryNotFoundException e )
764 log.error( e.getMessage(), e );
765 throw new ArchivaRestServiceException( e.getMessage(),
766 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
768 catch ( RepositoryException e )
770 log.error( e.getMessage(), e );
771 throw new ArchivaRestServiceException( e.getMessage(),
772 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
774 log.debug( "artifact: {}:{}:{}:{}:{} not found",
775 Arrays.asList( groupId, artifactId, version, classifier, type ).toArray( new String[5] ) );
780 //---------------------------
782 //---------------------------
784 protected List<ArtifactContentEntry> readFileEntries( File file, String filterPath )
787 Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<String, ArtifactContentEntry>();
788 int filterDepth = StringUtils.countMatches( filterPath, "/" );
789 /*if ( filterDepth == 0 )
793 JarFile jarFile = new JarFile( file );
796 Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
797 while ( jarEntryEnumeration.hasMoreElements() )
799 JarEntry currentEntry = jarEntryEnumeration.nextElement();
800 String cleanedEntryName =
801 StringUtils.endsWith( currentEntry.getName(), "/" ) ? StringUtils.substringBeforeLast(
802 currentEntry.getName(), "/" ) : currentEntry.getName();
803 String entryRootPath = getRootPath( cleanedEntryName );
804 int depth = StringUtils.countMatches( cleanedEntryName, "/" );
805 if ( StringUtils.isEmpty( filterPath ) && !artifactContentEntryMap.containsKey( entryRootPath )
806 && depth == filterDepth )
809 artifactContentEntryMap.put( entryRootPath,
810 new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
815 if ( StringUtils.startsWith( cleanedEntryName, filterPath ) && ( depth == filterDepth || (
816 !currentEntry.isDirectory() && depth == filterDepth ) ) )
818 artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
819 !currentEntry.isDirectory(),
825 if ( StringUtils.isNotEmpty( filterPath ) )
827 Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap =
828 new HashMap<String, ArtifactContentEntry>();
830 for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
832 filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
835 List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
836 if ( sorted == null )
838 return Collections.emptyList();
840 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
846 if ( jarFile != null )
851 List<ArtifactContentEntry> sorted = new ArrayList<ArtifactContentEntry>( artifactContentEntryMap.values() );
852 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
856 private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
858 int smallestDepth = Integer.MAX_VALUE;
859 Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<Integer, List<ArtifactContentEntry>>();
860 for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
863 ArtifactContentEntry current = entry.getValue();
865 if ( current.getDepth() < smallestDepth )
867 smallestDepth = current.getDepth();
870 List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
872 if ( currentList == null )
874 currentList = new ArrayList<ArtifactContentEntry>();
875 currentList.add( current );
876 perDepthList.put( current.getDepth(), currentList );
880 currentList.add( current );
885 return perDepthList.get( smallestDepth );
890 * @return org/apache -> org , org -> org
892 private String getRootPath( String path )
894 if ( StringUtils.contains( path, '/' ) )
896 return StringUtils.substringBefore( path, "/" );
901 private List<String> getSelectedRepos( String repositoryId )
902 throws ArchivaRestServiceException
905 List<String> selectedRepos = getObservableRepos();
907 if ( CollectionUtils.isEmpty( selectedRepos ) )
910 return Collections.emptyList();
913 if ( StringUtils.isNotEmpty( repositoryId ) )
915 // check user has karma on the repository
916 if ( !selectedRepos.contains( repositoryId ) )
918 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
919 Response.Status.FORBIDDEN.getStatusCode(), null );
921 selectedRepos = Collections.singletonList( repositoryId );
923 return selectedRepos;
927 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
928 Collection<String> repoIds, String n )
929 throws MetadataResolutionException
931 Set<String> subNamespaces = new LinkedHashSet<String>();
932 for ( String repoId : repoIds )
934 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
936 if ( subNamespaces.size() != 1 )
938 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
943 for ( String repoId : repoIds )
945 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
946 if ( projects != null && !projects.isEmpty() )
948 log.debug( "{} is not collapsible as it has projects", n );
952 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
953 n + "." + subNamespaces.iterator().next() );