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.ArtifactContent;
43 import org.apache.archiva.rest.api.model.ArtifactContentEntry;
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 Collection<String> versions = getVersions( selectedRepos, groupId, artifactId );
208 return new VersionsList( new ArrayList<String>( versions ) );
210 catch ( MetadataResolutionException e )
212 throw new ArchivaRestServiceException( e.getMessage(),
213 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
218 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
219 throws MetadataResolutionException
222 RepositorySession repositorySession = repositorySessionFactory.createSession();
225 MetadataResolver metadataResolver = repositorySession.getResolver();
227 Set<String> versions = new LinkedHashSet<String>();
229 for ( String repoId : selectedRepos )
231 Collection<String> projectVersions =
232 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId );
233 versions.addAll( projectVersions );
236 List<String> sortedVersions = new ArrayList<String>( versions );
238 Collections.sort( sortedVersions, VersionComparator.getInstance() );
240 return sortedVersions;
244 repositorySession.close();
248 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
249 String repositoryId )
250 throws ArchivaRestServiceException
252 List<String> selectedRepos = getSelectedRepos( repositoryId );
254 RepositorySession repositorySession = null;
257 repositorySession = repositorySessionFactory.createSession();
259 MetadataResolver metadataResolver = repositorySession.getResolver();
261 ProjectVersionMetadata versionMetadata = null;
262 for ( String repoId : selectedRepos )
264 if ( versionMetadata == null || versionMetadata.isIncomplete() )
269 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
272 catch ( MetadataResolutionException e )
275 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
276 + " in repo " + repoId + ": " + e.getMessage() );
281 return versionMetadata;
285 if ( repositorySession != null )
287 repositorySession.close();
293 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
294 throws ArchivaRestServiceException
297 List<String> selectedRepos = getSelectedRepos( repositoryId );
299 RepositorySession repositorySession = null;
303 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
305 repositorySession = repositorySessionFactory.createSession();
307 MetadataResolver metadataResolver = repositorySession.getResolver();
309 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
311 MavenProjectFacet mavenFacet = new MavenProjectFacet();
312 mavenFacet.setGroupId( groupId );
313 mavenFacet.setArtifactId( artifactId );
314 sharedModel.addFacet( mavenFacet );
316 boolean isFirstVersion = true;
318 for ( String version : projectVersions )
320 ProjectVersionMetadata versionMetadata = null;
321 for ( String repoId : selectedRepos )
323 if ( versionMetadata == null || versionMetadata.isIncomplete() )
328 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
331 catch ( MetadataResolutionException e )
333 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
334 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
339 if ( versionMetadata == null )
344 if ( isFirstVersion )
346 sharedModel = versionMetadata;
347 sharedModel.setId( null );
351 MavenProjectFacet versionMetadataMavenFacet =
352 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
353 if ( versionMetadataMavenFacet != null )
355 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
356 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
358 mavenFacet.setPackaging( null );
362 if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
363 versionMetadata.getName() ) )
365 sharedModel.setName( versionMetadata.getName() );
368 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
369 sharedModel.getDescription(), versionMetadata.getDescription() ) )
371 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
372 ? versionMetadata.getDescription()
376 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
377 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
378 versionMetadata.getIssueManagement().getUrl() ) )
380 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
383 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
384 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
385 versionMetadata.getCiManagement().getUrl() ) )
387 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
390 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
391 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
392 versionMetadata.getOrganization().getName() ) )
394 sharedModel.setOrganization( versionMetadata.getOrganization() );
397 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
398 versionMetadata.getUrl() ) )
400 sharedModel.setUrl( versionMetadata.getUrl() );
404 isFirstVersion = false;
408 catch ( MetadataResolutionException e )
410 throw new ArchivaRestServiceException( e.getMessage(),
411 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
415 if ( repositorySession != null )
417 repositorySession.close();
422 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
423 throws ArchivaRestServiceException
425 List<String> selectedRepos = getSelectedRepos( repositoryId );
427 List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
428 TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
431 dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
432 treeDependencyNodeVisitor );
434 catch ( DependencyTreeBuilderException e )
436 throw new ArchivaRestServiceException( e.getMessage(),
437 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
442 public List<ManagedRepository> getUserRepositories()
443 throws ArchivaRestServiceException
447 return userRepositories.getAccessibleRepositories( getPrincipal() );
449 catch ( ArchivaSecurityException e )
451 throw new ArchivaRestServiceException( "repositories.read.observable.error",
452 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
456 public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
457 throws ArchivaRestServiceException
459 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
460 // TODO: what if we get duplicates across repositories?
461 RepositorySession repositorySession = repositorySessionFactory.createSession();
464 MetadataResolver metadataResolver = repositorySession.getResolver();
465 for ( String repoId : getObservableRepos() )
467 // TODO: what about if we want to see this irrespective of version?
469 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
473 catch ( MetadataResolutionException e )
475 throw new ArchivaRestServiceException( e.getMessage(),
476 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
480 repositorySession.close();
483 List<Artifact> artifacts = new ArrayList<Artifact>( references.size() );
485 for ( ProjectVersionReference projectVersionReference : references )
487 artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
488 projectVersionReference.getProjectVersion() ) );
493 public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
494 throws ArchivaRestServiceException
496 ProjectVersionMetadata projectVersionMetadata =
497 getProjectMetadata( groupId, artifactId, version, repositoryId );
498 if ( projectVersionMetadata == null )
500 return Collections.emptyList();
502 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
504 if ( metadataFacet == null )
506 return Collections.emptyList();
508 Map<String, String> map = metadataFacet.toProperties();
509 List<Entry> entries = new ArrayList<Entry>( map.size() );
511 for ( Map.Entry<String, String> entry : map.entrySet() )
513 entries.add( new Entry( entry.getKey(), entry.getValue() ) );
519 public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
520 String repositoryId )
521 throws ArchivaRestServiceException
523 ProjectVersionMetadata projectVersionMetadata =
524 getProjectMetadata( groupId, artifactId, version, repositoryId );
526 if ( projectVersionMetadata == null )
528 return Boolean.FALSE;
531 Map<String, String> properties = new HashMap<String, String>();
533 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
535 if ( metadataFacet != null && metadataFacet.toProperties() != null )
537 properties.putAll( metadataFacet.toProperties() );
541 metadataFacet = new GenericMetadataFacet();
544 properties.put( key, value );
546 metadataFacet.fromProperties( properties );
548 projectVersionMetadata.addFacet( metadataFacet );
550 RepositorySession repositorySession = repositorySessionFactory.createSession();
554 MetadataRepository metadataRepository = repositorySession.getRepository();
556 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
558 repositorySession.save();
560 catch ( MetadataRepositoryException e )
562 log.error( e.getMessage(), e );
563 throw new ArchivaRestServiceException( e.getMessage(),
564 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
568 repositorySession.close();
573 public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
574 throws ArchivaRestServiceException
576 ProjectVersionMetadata projectVersionMetadata =
577 getProjectMetadata( groupId, artifactId, version, repositoryId );
579 if ( projectVersionMetadata == null )
581 return Boolean.FALSE;
584 GenericMetadataFacet metadataFacet =
585 (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
587 if ( metadataFacet != null && metadataFacet.toProperties() != null )
589 Map<String, String> properties = metadataFacet.toProperties();
590 properties.remove( key );
591 metadataFacet.setAdditionalProperties( properties );
598 RepositorySession repositorySession = repositorySessionFactory.createSession();
602 MetadataRepository metadataRepository = repositorySession.getRepository();
604 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
606 repositorySession.save();
608 catch ( MetadataRepositoryException e )
610 log.error( e.getMessage(), e );
611 throw new ArchivaRestServiceException( e.getMessage(),
612 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
616 repositorySession.close();
621 public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
622 String classifier, String type, String path,
623 String repositoryId )
624 throws ArchivaRestServiceException
626 List<String> selectedRepos = getSelectedRepos( repositoryId );
629 for ( String repoId : selectedRepos )
632 ManagedRepositoryContent managedRepositoryContent =
633 repositoryContentFactory.getManagedRepositoryContent( repoId );
634 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
635 StringUtils.isEmpty( type ) ? "jar" : type,
637 File file = managedRepositoryContent.toFile( archivaArtifact );
640 return readFileEntries( file, path, repoId );
644 catch ( IOException e )
646 log.error( e.getMessage(), e );
647 throw new ArchivaRestServiceException( e.getMessage(),
648 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
650 catch ( RepositoryNotFoundException e )
652 log.error( e.getMessage(), e );
653 throw new ArchivaRestServiceException( e.getMessage(),
654 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
656 catch ( RepositoryException e )
658 log.error( e.getMessage(), e );
659 throw new ArchivaRestServiceException( e.getMessage(),
660 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
662 return Collections.emptyList();
665 public List<Artifact> getArtifactDownloadInfos( String groupId, String artifactId, String version,
666 String repositoryId )
667 throws ArchivaRestServiceException
669 List<String> selectedRepos = getSelectedRepos( repositoryId );
671 List<Artifact> artifactDownloadInfos = new ArrayList<Artifact>();
673 RepositorySession session = repositorySessionFactory.createSession();
675 MetadataResolver metadataResolver = session.getResolver();
679 for ( String repoId : selectedRepos )
681 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(
682 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
683 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
685 for ( ArtifactMetadata artifact : artifacts )
688 ArtifactDownloadInfoBuilder builder =
689 new ArtifactDownloadInfoBuilder().forArtifactMetadata( artifact ).withManagedRepositoryContent(
690 repositoryContentFactory.getManagedRepositoryContent( repoId ) );
691 Artifact art = builder.build();
693 art.setUrl( getArtifactUrl( art ) );
694 artifactDownloadInfos.add( art );
699 catch ( RepositoryException e )
701 log.error( e.getMessage(), e );
702 throw new ArchivaRestServiceException( e.getMessage(),
703 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
705 catch ( MetadataResolutionException e )
707 log.error( e.getMessage(), e );
708 throw new ArchivaRestServiceException( e.getMessage(),
709 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
713 if ( session != null )
719 return artifactDownloadInfos;
722 public ArtifactContent getArtifactContentText( String groupId, String artifactId, String version, String classifier,
723 String type, String path, String repositoryId )
724 throws ArchivaRestServiceException
726 List<String> selectedRepos = getSelectedRepos( repositoryId );
729 for ( String repoId : selectedRepos )
732 ManagedRepositoryContent managedRepositoryContent =
733 repositoryContentFactory.getManagedRepositoryContent( repoId );
734 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
735 StringUtils.isEmpty( type ) ? "jar" : type,
737 File file = managedRepositoryContent.toFile( archivaArtifact );
738 if ( !file.exists() )
740 log.debug( "file: {} not exists for repository: {} try next repository", file, repoId );
743 if ( StringUtils.isNotBlank( path ) )
745 // zip entry of the path -> path must a real file entry of the archive
746 JarFile jarFile = new JarFile( file );
747 ZipEntry zipEntry = jarFile.getEntry( path );
748 InputStream inputStream = jarFile.getInputStream( zipEntry );
751 return new ArtifactContent( IOUtils.toString( inputStream ), repoId );
755 closeQuietly( jarFile );
756 IOUtils.closeQuietly( inputStream );
759 return new ArtifactContent( FileUtils.readFileToString( file ), repoId );
762 catch ( IOException e )
764 log.error( e.getMessage(), e );
765 throw new ArchivaRestServiceException( e.getMessage(),
766 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
768 catch ( RepositoryNotFoundException e )
770 log.error( e.getMessage(), e );
771 throw new ArchivaRestServiceException( e.getMessage(),
772 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
774 catch ( RepositoryException e )
776 log.error( e.getMessage(), e );
777 throw new ArchivaRestServiceException( e.getMessage(),
778 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
780 log.debug( "artifact: {}:{}:{}:{}:{} not found",
781 Arrays.asList( groupId, artifactId, version, classifier, type ).toArray( new String[5] ) );
783 return new ArtifactContent();
786 private void closeQuietly( JarFile jarFile )
788 if ( jarFile != null )
794 catch ( IOException e )
796 log.warn( "ignore error closing jarFile {}", jarFile.getName() );
801 //---------------------------
803 //---------------------------
805 protected List<ArtifactContentEntry> readFileEntries( File file, String filterPath, String repoId )
808 Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<String, ArtifactContentEntry>();
809 int filterDepth = StringUtils.countMatches( filterPath, "/" );
810 /*if ( filterDepth == 0 )
814 JarFile jarFile = new JarFile( file );
817 Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
818 while ( jarEntryEnumeration.hasMoreElements() )
820 JarEntry currentEntry = jarEntryEnumeration.nextElement();
821 String cleanedEntryName =
822 StringUtils.endsWith( currentEntry.getName(), "/" ) ? StringUtils.substringBeforeLast(
823 currentEntry.getName(), "/" ) : currentEntry.getName();
824 String entryRootPath = getRootPath( cleanedEntryName );
825 int depth = StringUtils.countMatches( cleanedEntryName, "/" );
826 if ( StringUtils.isEmpty( filterPath ) && !artifactContentEntryMap.containsKey( entryRootPath )
827 && depth == filterDepth )
830 artifactContentEntryMap.put( entryRootPath,
831 new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
836 if ( StringUtils.startsWith( cleanedEntryName, filterPath ) && ( depth == filterDepth || (
837 !currentEntry.isDirectory() && depth == filterDepth ) ) )
839 artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
840 !currentEntry.isDirectory(),
846 if ( StringUtils.isNotEmpty( filterPath ) )
848 Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap =
849 new HashMap<String, ArtifactContentEntry>();
851 for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
853 filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
856 List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
857 if ( sorted == null )
859 return Collections.emptyList();
861 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
867 if ( jarFile != null )
872 List<ArtifactContentEntry> sorted = new ArrayList<ArtifactContentEntry>( artifactContentEntryMap.values() );
873 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
877 private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
879 int smallestDepth = Integer.MAX_VALUE;
880 Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<Integer, List<ArtifactContentEntry>>();
881 for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
884 ArtifactContentEntry current = entry.getValue();
886 if ( current.getDepth() < smallestDepth )
888 smallestDepth = current.getDepth();
891 List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
893 if ( currentList == null )
895 currentList = new ArrayList<ArtifactContentEntry>();
896 currentList.add( current );
897 perDepthList.put( current.getDepth(), currentList );
901 currentList.add( current );
906 return perDepthList.get( smallestDepth );
911 * @return org/apache -> org , org -> org
913 private String getRootPath( String path )
915 if ( StringUtils.contains( path, '/' ) )
917 return StringUtils.substringBefore( path, "/" );
922 private List<String> getSelectedRepos( String repositoryId )
923 throws ArchivaRestServiceException
926 List<String> selectedRepos = getObservableRepos();
928 if ( CollectionUtils.isEmpty( selectedRepos ) )
931 return Collections.emptyList();
934 if ( StringUtils.isNotEmpty( repositoryId ) )
936 // check user has karma on the repository
937 if ( !selectedRepos.contains( repositoryId ) )
939 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
940 Response.Status.FORBIDDEN.getStatusCode(), null );
942 selectedRepos = Collections.singletonList( repositoryId );
944 return selectedRepos;
948 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
949 Collection<String> repoIds, String n )
950 throws MetadataResolutionException
952 Set<String> subNamespaces = new LinkedHashSet<String>();
953 for ( String repoId : repoIds )
955 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
957 if ( subNamespaces.size() != 1 )
959 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
964 for ( String repoId : repoIds )
966 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
967 if ( projects != null && !projects.isEmpty() )
969 log.debug( "{} is not collapsible as it has projects", n );
973 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
974 n + "." + subNamespaces.iterator().next() );