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.apache.maven.project.DependencyResolutionResult;
61 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
62 import org.springframework.stereotype.Service;
64 import javax.inject.Inject;
65 import javax.ws.rs.core.Response;
67 import java.io.IOException;
68 import java.io.InputStream;
69 import java.util.ArrayList;
70 import java.util.Arrays;
71 import java.util.Collection;
72 import java.util.Collections;
73 import java.util.Enumeration;
74 import java.util.HashMap;
75 import java.util.LinkedHashSet;
76 import java.util.List;
79 import java.util.jar.JarEntry;
80 import java.util.jar.JarFile;
81 import java.util.zip.ZipEntry;
84 * @author Olivier Lamy
87 @Service( "browseService#rest" )
88 public class DefaultBrowseService
89 extends AbstractRestService
90 implements BrowseService
94 private DependencyTreeBuilder dependencyTreeBuilder;
97 private Maven3DependencyTreeBuilder maven3DependencyTreeBuilder;
100 private RepositoryContentFactory repositoryContentFactory;
102 public BrowseResult getRootGroups( String repositoryId )
103 throws ArchivaRestServiceException
105 List<String> selectedRepos = getSelectedRepos( repositoryId );
107 Set<String> namespaces = new LinkedHashSet<String>();
109 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
110 // it is located here to avoid the content repository implementation needing to do too much for what
111 // is essentially presentation code
112 Set<String> namespacesToCollapse;
113 RepositorySession repositorySession = repositorySessionFactory.createSession();
116 MetadataResolver metadataResolver = repositorySession.getResolver();
117 namespacesToCollapse = new LinkedHashSet<String>();
119 for ( String repoId : selectedRepos )
121 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
123 for ( String n : namespacesToCollapse )
125 // TODO: check performance of this
126 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
129 catch ( MetadataResolutionException e )
131 throw new ArchivaRestServiceException( e.getMessage(),
132 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
136 repositorySession.close();
139 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
140 for ( String namespace : namespaces )
142 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
145 Collections.sort( browseGroupResultEntries );
146 return new BrowseResult( browseGroupResultEntries );
149 public BrowseResult browseGroupId( String groupId, String repositoryId )
150 throws ArchivaRestServiceException
152 List<String> selectedRepos = getSelectedRepos( repositoryId );
154 Set<String> projects = new LinkedHashSet<String>();
156 RepositorySession repositorySession = repositorySessionFactory.createSession();
157 Set<String> namespaces;
160 MetadataResolver metadataResolver = repositorySession.getResolver();
162 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
163 for ( String repoId : selectedRepos )
165 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
167 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
170 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
171 // it is located here to avoid the content repository implementation needing to do too much for what
172 // is essentially presentation code
173 namespaces = new LinkedHashSet<String>();
174 for ( String n : namespacesToCollapse )
176 // TODO: check performance of this
178 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
181 catch ( MetadataResolutionException e )
183 throw new ArchivaRestServiceException( e.getMessage(),
184 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
188 repositorySession.close();
190 List<BrowseResultEntry> browseGroupResultEntries =
191 new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
192 for ( String namespace : namespaces )
194 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
196 for ( String project : projects )
198 browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
200 Collections.sort( browseGroupResultEntries );
201 return new BrowseResult( browseGroupResultEntries );
205 public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
206 throws ArchivaRestServiceException
208 List<String> selectedRepos = getSelectedRepos( repositoryId );
212 Collection<String> versions = getVersions( selectedRepos, groupId, artifactId );
213 return new VersionsList( new ArrayList<String>( versions ) );
215 catch ( MetadataResolutionException e )
217 throw new ArchivaRestServiceException( e.getMessage(),
218 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
223 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
224 throws MetadataResolutionException
227 RepositorySession repositorySession = repositorySessionFactory.createSession();
230 MetadataResolver metadataResolver = repositorySession.getResolver();
232 Set<String> versions = new LinkedHashSet<String>();
234 for ( String repoId : selectedRepos )
236 Collection<String> projectVersions =
237 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId );
238 versions.addAll( projectVersions );
241 List<String> sortedVersions = new ArrayList<String>( versions );
243 Collections.sort( sortedVersions, VersionComparator.getInstance() );
245 return sortedVersions;
249 repositorySession.close();
253 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
254 String repositoryId )
255 throws ArchivaRestServiceException
257 List<String> selectedRepos = getSelectedRepos( repositoryId );
259 RepositorySession repositorySession = null;
262 repositorySession = repositorySessionFactory.createSession();
264 MetadataResolver metadataResolver = repositorySession.getResolver();
266 ProjectVersionMetadata versionMetadata = null;
267 for ( String repoId : selectedRepos )
269 if ( versionMetadata == null || versionMetadata.isIncomplete() )
274 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
277 catch ( MetadataResolutionException e )
280 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
281 + " in repo " + repoId + ": " + e.getMessage() );
286 return versionMetadata;
290 if ( repositorySession != null )
292 repositorySession.close();
298 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
299 throws ArchivaRestServiceException
302 List<String> selectedRepos = getSelectedRepos( repositoryId );
304 RepositorySession repositorySession = null;
308 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
310 repositorySession = repositorySessionFactory.createSession();
312 MetadataResolver metadataResolver = repositorySession.getResolver();
314 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
316 MavenProjectFacet mavenFacet = new MavenProjectFacet();
317 mavenFacet.setGroupId( groupId );
318 mavenFacet.setArtifactId( artifactId );
319 sharedModel.addFacet( mavenFacet );
321 boolean isFirstVersion = true;
323 for ( String version : projectVersions )
325 ProjectVersionMetadata versionMetadata = null;
326 for ( String repoId : selectedRepos )
328 if ( versionMetadata == null || versionMetadata.isIncomplete() )
333 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
336 catch ( MetadataResolutionException e )
338 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
339 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
344 if ( versionMetadata == null )
349 if ( isFirstVersion )
351 sharedModel = versionMetadata;
352 sharedModel.setId( null );
356 MavenProjectFacet versionMetadataMavenFacet =
357 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
358 if ( versionMetadataMavenFacet != null )
360 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
361 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
363 mavenFacet.setPackaging( null );
367 if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
368 versionMetadata.getName() ) )
370 sharedModel.setName( versionMetadata.getName() );
373 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
374 sharedModel.getDescription(), versionMetadata.getDescription() ) )
376 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
377 ? versionMetadata.getDescription()
381 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
382 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
383 versionMetadata.getIssueManagement().getUrl() ) )
385 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
388 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
389 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
390 versionMetadata.getCiManagement().getUrl() ) )
392 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
395 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
396 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
397 versionMetadata.getOrganization().getName() ) )
399 sharedModel.setOrganization( versionMetadata.getOrganization() );
402 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
403 versionMetadata.getUrl() ) )
405 sharedModel.setUrl( versionMetadata.getUrl() );
409 isFirstVersion = false;
413 catch ( MetadataResolutionException e )
415 throw new ArchivaRestServiceException( e.getMessage(),
416 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
420 if ( repositorySession != null )
422 repositorySession.close();
427 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
428 throws ArchivaRestServiceException
430 List<String> selectedRepos = getSelectedRepos( repositoryId );
432 List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
433 TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
437 dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
438 treeDependencyNodeVisitor );
440 catch ( DependencyTreeBuilderException e )
442 throw new ArchivaRestServiceException( e.getMessage(),
443 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
448 DependencyResolutionResult result =
449 maven3DependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version, treeDependencyNodeVisitor );
450 log.debug( "result: {}", result );
452 catch ( Exception e )
454 log.error( e.getMessage(), e );
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() );