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.dependency.tree.maven2.Maven3DependencyTreeBuilder;
25 import org.apache.archiva.metadata.generic.GenericMetadataFacet;
26 import org.apache.archiva.metadata.model.ArtifactMetadata;
27 import org.apache.archiva.metadata.model.MetadataFacet;
28 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
29 import org.apache.archiva.metadata.model.ProjectVersionReference;
30 import org.apache.archiva.metadata.repository.MetadataRepository;
31 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
32 import org.apache.archiva.metadata.repository.MetadataResolutionException;
33 import org.apache.archiva.metadata.repository.MetadataResolver;
34 import org.apache.archiva.metadata.repository.RepositorySession;
35 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMetadataVersionComparator;
36 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
37 import org.apache.archiva.model.ArchivaArtifact;
38 import org.apache.archiva.repository.ManagedRepositoryContent;
39 import org.apache.archiva.repository.RepositoryContentFactory;
40 import org.apache.archiva.repository.RepositoryException;
41 import org.apache.archiva.repository.RepositoryNotFoundException;
42 import org.apache.archiva.rest.api.model.Artifact;
43 import org.apache.archiva.rest.api.model.ArtifactContent;
44 import org.apache.archiva.rest.api.model.ArtifactContentEntry;
45 import org.apache.archiva.rest.api.model.BrowseResult;
46 import org.apache.archiva.rest.api.model.BrowseResultEntry;
47 import org.apache.archiva.rest.api.model.Entry;
48 import org.apache.archiva.rest.api.model.TreeEntry;
49 import org.apache.archiva.rest.api.model.VersionsList;
50 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
51 import org.apache.archiva.rest.api.services.BrowseService;
52 import org.apache.archiva.rest.services.utils.ArtifactContentEntryComparator;
53 import org.apache.archiva.rest.services.utils.ArtifactDownloadInfoBuilder;
54 import org.apache.archiva.rest.services.utils.TreeDependencyNodeVisitor;
55 import org.apache.archiva.security.ArchivaSecurityException;
56 import org.apache.commons.collections.CollectionUtils;
57 import org.apache.commons.io.FileUtils;
58 import org.apache.commons.io.IOUtils;
59 import org.apache.commons.lang.StringUtils;
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 Maven3DependencyTreeBuilder maven3DependencyTreeBuilder;
98 private RepositoryContentFactory repositoryContentFactory;
100 public BrowseResult getRootGroups( String repositoryId )
101 throws ArchivaRestServiceException
103 List<String> selectedRepos = getSelectedRepos( repositoryId );
105 Set<String> namespaces = new LinkedHashSet<String>();
107 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
108 // it is located here to avoid the content repository implementation needing to do too much for what
109 // is essentially presentation code
110 Set<String> namespacesToCollapse;
111 RepositorySession repositorySession = repositorySessionFactory.createSession();
114 MetadataResolver metadataResolver = repositorySession.getResolver();
115 namespacesToCollapse = new LinkedHashSet<String>();
117 for ( String repoId : selectedRepos )
119 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
121 for ( String n : namespacesToCollapse )
123 // TODO: check performance of this
124 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
127 catch ( MetadataResolutionException e )
129 throw new ArchivaRestServiceException( e.getMessage(),
130 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
134 repositorySession.close();
137 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
138 for ( String namespace : namespaces )
140 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
143 Collections.sort( browseGroupResultEntries );
144 return new BrowseResult( browseGroupResultEntries );
147 public BrowseResult browseGroupId( String groupId, String repositoryId )
148 throws ArchivaRestServiceException
150 List<String> selectedRepos = getSelectedRepos( repositoryId );
152 Set<String> projects = new LinkedHashSet<String>();
154 RepositorySession repositorySession = repositorySessionFactory.createSession();
155 Set<String> namespaces;
158 MetadataResolver metadataResolver = repositorySession.getResolver();
160 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
161 for ( String repoId : selectedRepos )
163 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
165 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
168 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
169 // it is located here to avoid the content repository implementation needing to do too much for what
170 // is essentially presentation code
171 namespaces = new LinkedHashSet<String>();
172 for ( String n : namespacesToCollapse )
174 // TODO: check performance of this
176 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
179 catch ( MetadataResolutionException e )
181 throw new ArchivaRestServiceException( e.getMessage(),
182 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
186 repositorySession.close();
188 List<BrowseResultEntry> browseGroupResultEntries =
189 new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
190 for ( String namespace : namespaces )
192 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
194 for ( String project : projects )
196 browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
198 Collections.sort( browseGroupResultEntries );
199 return new BrowseResult( browseGroupResultEntries );
203 public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
204 throws ArchivaRestServiceException
206 List<String> selectedRepos = getSelectedRepos( repositoryId );
210 Collection<String> versions = getVersions( selectedRepos, groupId, artifactId );
211 return new VersionsList( new ArrayList<String>( versions ) );
213 catch ( MetadataResolutionException e )
215 throw new ArchivaRestServiceException( e.getMessage(),
216 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
221 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
222 throws MetadataResolutionException
225 RepositorySession repositorySession = repositorySessionFactory.createSession();
228 MetadataResolver metadataResolver = repositorySession.getResolver();
230 Set<String> versions = new LinkedHashSet<String>();
232 for ( String repoId : selectedRepos )
234 Collection<String> projectVersions =
235 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId );
236 versions.addAll( projectVersions );
239 List<String> sortedVersions = new ArrayList<String>( versions );
241 Collections.sort( sortedVersions, VersionComparator.getInstance() );
243 return sortedVersions;
247 repositorySession.close();
251 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
252 String repositoryId )
253 throws ArchivaRestServiceException
255 List<String> selectedRepos = getSelectedRepos( repositoryId );
257 RepositorySession repositorySession = null;
260 repositorySession = repositorySessionFactory.createSession();
262 MetadataResolver metadataResolver = repositorySession.getResolver();
264 ProjectVersionMetadata versionMetadata = null;
265 for ( String repoId : selectedRepos )
267 if ( versionMetadata == null || versionMetadata.isIncomplete() )
272 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
275 catch ( MetadataResolutionException e )
278 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
279 + " in repo " + repoId + ": " + e.getMessage() );
284 return versionMetadata;
288 if ( repositorySession != null )
290 repositorySession.close();
296 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
297 throws ArchivaRestServiceException
300 List<String> selectedRepos = getSelectedRepos( repositoryId );
302 RepositorySession repositorySession = null;
306 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
308 repositorySession = repositorySessionFactory.createSession();
310 MetadataResolver metadataResolver = repositorySession.getResolver();
312 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
314 MavenProjectFacet mavenFacet = new MavenProjectFacet();
315 mavenFacet.setGroupId( groupId );
316 mavenFacet.setArtifactId( artifactId );
317 sharedModel.addFacet( mavenFacet );
319 boolean isFirstVersion = true;
321 for ( String version : projectVersions )
323 ProjectVersionMetadata versionMetadata = null;
324 for ( String repoId : selectedRepos )
326 if ( versionMetadata == null || versionMetadata.isIncomplete() )
331 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
334 catch ( MetadataResolutionException e )
336 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
337 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
342 if ( versionMetadata == null )
347 if ( isFirstVersion )
349 sharedModel = versionMetadata;
350 sharedModel.setId( null );
354 MavenProjectFacet versionMetadataMavenFacet =
355 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
356 if ( versionMetadataMavenFacet != null )
358 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
359 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
361 mavenFacet.setPackaging( null );
365 if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
366 versionMetadata.getName() ) )
368 sharedModel.setName( versionMetadata.getName() );
371 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
372 sharedModel.getDescription(), versionMetadata.getDescription() ) )
374 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
375 ? versionMetadata.getDescription()
379 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
380 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
381 versionMetadata.getIssueManagement().getUrl() ) )
383 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
386 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
387 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
388 versionMetadata.getCiManagement().getUrl() ) )
390 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
393 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
394 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
395 versionMetadata.getOrganization().getName() ) )
397 sharedModel.setOrganization( versionMetadata.getOrganization() );
400 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
401 versionMetadata.getUrl() ) )
403 sharedModel.setUrl( versionMetadata.getUrl() );
407 isFirstVersion = false;
411 catch ( MetadataResolutionException e )
413 throw new ArchivaRestServiceException( e.getMessage(),
414 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
418 if ( repositorySession != null )
420 repositorySession.close();
425 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
426 throws ArchivaRestServiceException
428 List<String> selectedRepos = getSelectedRepos( repositoryId );
430 List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
431 TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
435 dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
436 treeDependencyNodeVisitor );
438 catch ( DependencyTreeBuilderException e )
440 throw new ArchivaRestServiceException( e.getMessage(),
441 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
447 maven3DependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
448 treeDependencyNodeVisitor );
451 catch ( Exception e )
453 log.error( e.getMessage(), e );
456 log.debug( "treeEntrie: {}", treeEntries );
460 public List<ManagedRepository> getUserRepositories()
461 throws ArchivaRestServiceException
465 return userRepositories.getAccessibleRepositories( getPrincipal() );
467 catch ( ArchivaSecurityException e )
469 throw new ArchivaRestServiceException( "repositories.read.observable.error",
470 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
474 public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
475 throws ArchivaRestServiceException
477 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
478 // TODO: what if we get duplicates across repositories?
479 RepositorySession repositorySession = repositorySessionFactory.createSession();
482 MetadataResolver metadataResolver = repositorySession.getResolver();
483 for ( String repoId : getObservableRepos() )
485 // TODO: what about if we want to see this irrespective of version?
487 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
491 catch ( MetadataResolutionException e )
493 throw new ArchivaRestServiceException( e.getMessage(),
494 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
498 repositorySession.close();
501 List<Artifact> artifacts = new ArrayList<Artifact>( references.size() );
503 for ( ProjectVersionReference projectVersionReference : references )
505 artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
506 projectVersionReference.getProjectVersion() ) );
511 public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
512 throws ArchivaRestServiceException
514 ProjectVersionMetadata projectVersionMetadata =
515 getProjectMetadata( groupId, artifactId, version, repositoryId );
516 if ( projectVersionMetadata == null )
518 return Collections.emptyList();
520 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
522 if ( metadataFacet == null )
524 return Collections.emptyList();
526 Map<String, String> map = metadataFacet.toProperties();
527 List<Entry> entries = new ArrayList<Entry>( map.size() );
529 for ( Map.Entry<String, String> entry : map.entrySet() )
531 entries.add( new Entry( entry.getKey(), entry.getValue() ) );
537 public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
538 String repositoryId )
539 throws ArchivaRestServiceException
541 ProjectVersionMetadata projectVersionMetadata =
542 getProjectMetadata( groupId, artifactId, version, repositoryId );
544 if ( projectVersionMetadata == null )
546 return Boolean.FALSE;
549 Map<String, String> properties = new HashMap<String, String>();
551 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
553 if ( metadataFacet != null && metadataFacet.toProperties() != null )
555 properties.putAll( metadataFacet.toProperties() );
559 metadataFacet = new GenericMetadataFacet();
562 properties.put( key, value );
564 metadataFacet.fromProperties( properties );
566 projectVersionMetadata.addFacet( metadataFacet );
568 RepositorySession repositorySession = repositorySessionFactory.createSession();
572 MetadataRepository metadataRepository = repositorySession.getRepository();
574 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
576 repositorySession.save();
578 catch ( MetadataRepositoryException e )
580 log.error( e.getMessage(), e );
581 throw new ArchivaRestServiceException( e.getMessage(),
582 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
586 repositorySession.close();
591 public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
592 throws ArchivaRestServiceException
594 ProjectVersionMetadata projectVersionMetadata =
595 getProjectMetadata( groupId, artifactId, version, repositoryId );
597 if ( projectVersionMetadata == null )
599 return Boolean.FALSE;
602 GenericMetadataFacet metadataFacet =
603 (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
605 if ( metadataFacet != null && metadataFacet.toProperties() != null )
607 Map<String, String> properties = metadataFacet.toProperties();
608 properties.remove( key );
609 metadataFacet.setAdditionalProperties( properties );
616 RepositorySession repositorySession = repositorySessionFactory.createSession();
620 MetadataRepository metadataRepository = repositorySession.getRepository();
622 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
624 repositorySession.save();
626 catch ( MetadataRepositoryException e )
628 log.error( e.getMessage(), e );
629 throw new ArchivaRestServiceException( e.getMessage(),
630 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
634 repositorySession.close();
639 public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
640 String classifier, String type, String path,
641 String repositoryId )
642 throws ArchivaRestServiceException
644 List<String> selectedRepos = getSelectedRepos( repositoryId );
647 for ( String repoId : selectedRepos )
650 ManagedRepositoryContent managedRepositoryContent =
651 repositoryContentFactory.getManagedRepositoryContent( repoId );
652 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
653 StringUtils.isEmpty( type ) ? "jar" : type,
655 File file = managedRepositoryContent.toFile( archivaArtifact );
658 return readFileEntries( file, path, repoId );
662 catch ( IOException e )
664 log.error( e.getMessage(), e );
665 throw new ArchivaRestServiceException( e.getMessage(),
666 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
668 catch ( RepositoryNotFoundException e )
670 log.error( e.getMessage(), e );
671 throw new ArchivaRestServiceException( e.getMessage(),
672 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
674 catch ( RepositoryException e )
676 log.error( e.getMessage(), e );
677 throw new ArchivaRestServiceException( e.getMessage(),
678 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
680 return Collections.emptyList();
683 public List<Artifact> getArtifactDownloadInfos( String groupId, String artifactId, String version,
684 String repositoryId )
685 throws ArchivaRestServiceException
687 List<String> selectedRepos = getSelectedRepos( repositoryId );
689 List<Artifact> artifactDownloadInfos = new ArrayList<Artifact>();
691 RepositorySession session = repositorySessionFactory.createSession();
693 MetadataResolver metadataResolver = session.getResolver();
697 for ( String repoId : selectedRepos )
699 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(
700 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
701 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
703 for ( ArtifactMetadata artifact : artifacts )
706 ArtifactDownloadInfoBuilder builder =
707 new ArtifactDownloadInfoBuilder().forArtifactMetadata( artifact ).withManagedRepositoryContent(
708 repositoryContentFactory.getManagedRepositoryContent( repoId ) );
709 Artifact art = builder.build();
711 art.setUrl( getArtifactUrl( art ) );
712 artifactDownloadInfos.add( art );
717 catch ( RepositoryException e )
719 log.error( e.getMessage(), e );
720 throw new ArchivaRestServiceException( e.getMessage(),
721 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
723 catch ( MetadataResolutionException e )
725 log.error( e.getMessage(), e );
726 throw new ArchivaRestServiceException( e.getMessage(),
727 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
731 if ( session != null )
737 return artifactDownloadInfos;
740 public ArtifactContent getArtifactContentText( String groupId, String artifactId, String version, String classifier,
741 String type, String path, String repositoryId )
742 throws ArchivaRestServiceException
744 List<String> selectedRepos = getSelectedRepos( repositoryId );
747 for ( String repoId : selectedRepos )
750 ManagedRepositoryContent managedRepositoryContent =
751 repositoryContentFactory.getManagedRepositoryContent( repoId );
752 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
753 StringUtils.isEmpty( type ) ? "jar" : type,
755 File file = managedRepositoryContent.toFile( archivaArtifact );
756 if ( !file.exists() )
758 log.debug( "file: {} not exists for repository: {} try next repository", file, repoId );
761 if ( StringUtils.isNotBlank( path ) )
763 // zip entry of the path -> path must a real file entry of the archive
764 JarFile jarFile = new JarFile( file );
765 ZipEntry zipEntry = jarFile.getEntry( path );
766 InputStream inputStream = jarFile.getInputStream( zipEntry );
769 return new ArtifactContent( IOUtils.toString( inputStream ), repoId );
773 closeQuietly( jarFile );
774 IOUtils.closeQuietly( inputStream );
777 return new ArtifactContent( FileUtils.readFileToString( file ), repoId );
780 catch ( IOException e )
782 log.error( e.getMessage(), e );
783 throw new ArchivaRestServiceException( e.getMessage(),
784 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
786 catch ( RepositoryNotFoundException e )
788 log.error( e.getMessage(), e );
789 throw new ArchivaRestServiceException( e.getMessage(),
790 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
792 catch ( RepositoryException e )
794 log.error( e.getMessage(), e );
795 throw new ArchivaRestServiceException( e.getMessage(),
796 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
798 log.debug( "artifact: {}:{}:{}:{}:{} not found",
799 Arrays.asList( groupId, artifactId, version, classifier, type ).toArray( new String[5] ) );
801 return new ArtifactContent();
804 private void closeQuietly( JarFile jarFile )
806 if ( jarFile != null )
812 catch ( IOException e )
814 log.warn( "ignore error closing jarFile {}", jarFile.getName() );
819 //---------------------------
821 //---------------------------
823 protected List<ArtifactContentEntry> readFileEntries( File file, String filterPath, String repoId )
826 Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<String, ArtifactContentEntry>();
827 int filterDepth = StringUtils.countMatches( filterPath, "/" );
828 /*if ( filterDepth == 0 )
832 JarFile jarFile = new JarFile( file );
835 Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
836 while ( jarEntryEnumeration.hasMoreElements() )
838 JarEntry currentEntry = jarEntryEnumeration.nextElement();
839 String cleanedEntryName =
840 StringUtils.endsWith( currentEntry.getName(), "/" ) ? StringUtils.substringBeforeLast(
841 currentEntry.getName(), "/" ) : currentEntry.getName();
842 String entryRootPath = getRootPath( cleanedEntryName );
843 int depth = StringUtils.countMatches( cleanedEntryName, "/" );
844 if ( StringUtils.isEmpty( filterPath ) && !artifactContentEntryMap.containsKey( entryRootPath )
845 && depth == filterDepth )
848 artifactContentEntryMap.put( entryRootPath,
849 new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
854 if ( StringUtils.startsWith( cleanedEntryName, filterPath ) && ( depth == filterDepth || (
855 !currentEntry.isDirectory() && depth == filterDepth ) ) )
857 artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
858 !currentEntry.isDirectory(),
864 if ( StringUtils.isNotEmpty( filterPath ) )
866 Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap =
867 new HashMap<String, ArtifactContentEntry>();
869 for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
871 filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
874 List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
875 if ( sorted == null )
877 return Collections.emptyList();
879 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
885 if ( jarFile != null )
890 List<ArtifactContentEntry> sorted = new ArrayList<ArtifactContentEntry>( artifactContentEntryMap.values() );
891 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
895 private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
897 int smallestDepth = Integer.MAX_VALUE;
898 Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<Integer, List<ArtifactContentEntry>>();
899 for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
902 ArtifactContentEntry current = entry.getValue();
904 if ( current.getDepth() < smallestDepth )
906 smallestDepth = current.getDepth();
909 List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
911 if ( currentList == null )
913 currentList = new ArrayList<ArtifactContentEntry>();
914 currentList.add( current );
915 perDepthList.put( current.getDepth(), currentList );
919 currentList.add( current );
924 return perDepthList.get( smallestDepth );
929 * @return org/apache -> org , org -> org
931 private String getRootPath( String path )
933 if ( StringUtils.contains( path, '/' ) )
935 return StringUtils.substringBefore( path, "/" );
940 private List<String> getSelectedRepos( String repositoryId )
941 throws ArchivaRestServiceException
944 List<String> selectedRepos = getObservableRepos();
946 if ( CollectionUtils.isEmpty( selectedRepos ) )
949 return Collections.emptyList();
952 if ( StringUtils.isNotEmpty( repositoryId ) )
954 // check user has karma on the repository
955 if ( !selectedRepos.contains( repositoryId ) )
957 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
958 Response.Status.FORBIDDEN.getStatusCode(), null );
960 selectedRepos = Collections.singletonList( repositoryId );
962 return selectedRepos;
966 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
967 Collection<String> repoIds, String n )
968 throws MetadataResolutionException
970 Set<String> subNamespaces = new LinkedHashSet<String>();
971 for ( String repoId : repoIds )
973 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
975 if ( subNamespaces.size() != 1 )
977 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
982 for ( String repoId : repoIds )
984 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
985 if ( projects != null && !projects.isEmpty() )
987 log.debug( "{} is not collapsible as it has projects", n );
991 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
992 n + "." + subNamespaces.iterator().next() );