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.RepositoryAdminException;
22 import org.apache.archiva.admin.model.beans.ManagedRepository;
23 import org.apache.archiva.common.utils.VersionComparator;
24 import org.apache.archiva.common.utils.VersionUtil;
25 import org.apache.archiva.dependency.tree.maven2.DependencyTreeBuilder;
26 import org.apache.archiva.maven2.model.Artifact;
27 import org.apache.archiva.maven2.model.TreeEntry;
28 import org.apache.archiva.metadata.generic.GenericMetadataFacet;
29 import org.apache.archiva.metadata.model.ArtifactMetadata;
30 import org.apache.archiva.metadata.model.MetadataFacet;
31 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
32 import org.apache.archiva.metadata.model.ProjectVersionReference;
33 import org.apache.archiva.metadata.repository.MetadataRepository;
34 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
35 import org.apache.archiva.metadata.repository.MetadataResolutionException;
36 import org.apache.archiva.metadata.repository.MetadataResolver;
37 import org.apache.archiva.metadata.repository.RepositorySession;
38 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMetadataVersionComparator;
39 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
40 import org.apache.archiva.model.ArchivaArtifact;
41 import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
42 import org.apache.archiva.repository.ManagedRepositoryContent;
43 import org.apache.archiva.repository.RepositoryContentFactory;
44 import org.apache.archiva.repository.RepositoryException;
45 import org.apache.archiva.repository.RepositoryNotFoundException;
46 import org.apache.archiva.rest.api.model.ArtifactContent;
47 import org.apache.archiva.rest.api.model.ArtifactContentEntry;
48 import org.apache.archiva.rest.api.model.BrowseResult;
49 import org.apache.archiva.rest.api.model.BrowseResultEntry;
50 import org.apache.archiva.rest.api.model.Entry;
51 import org.apache.archiva.rest.api.model.MetadataAddRequest;
52 import org.apache.archiva.rest.api.model.VersionsList;
53 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
54 import org.apache.archiva.rest.api.services.BrowseService;
55 import org.apache.archiva.rest.services.utils.ArtifactContentEntryComparator;
56 import org.apache.archiva.security.ArchivaSecurityException;
57 import org.apache.commons.collections.CollectionUtils;
58 import org.apache.commons.io.FileUtils;
59 import org.apache.commons.io.IOUtils;
60 import org.apache.commons.lang.StringUtils;
61 import org.springframework.stereotype.Service;
63 import javax.inject.Inject;
64 import javax.inject.Named;
65 import javax.ws.rs.PathParam;
66 import javax.ws.rs.QueryParam;
67 import javax.ws.rs.core.Response;
69 import java.io.IOException;
70 import java.io.InputStream;
71 import java.util.ArrayList;
72 import java.util.Collection;
73 import java.util.Collections;
74 import java.util.Enumeration;
75 import java.util.HashMap;
76 import java.util.LinkedHashSet;
77 import java.util.List;
80 import java.util.jar.JarEntry;
81 import java.util.jar.JarFile;
82 import java.util.zip.ZipEntry;
85 * @author Olivier Lamy
88 @Service( "browseService#rest" )
89 public class DefaultBrowseService
90 extends AbstractRestService
91 implements BrowseService
95 private DependencyTreeBuilder dependencyTreeBuilder;
98 private RepositoryContentFactory repositoryContentFactory;
101 @Named( value = "repositoryProxyConnectors#default" )
102 private RepositoryProxyConnectors connectors;
104 public BrowseResult getRootGroups( String repositoryId )
105 throws ArchivaRestServiceException
107 List<String> selectedRepos = getSelectedRepos( repositoryId );
109 Set<String> namespaces = new LinkedHashSet<String>();
111 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
112 // it is located here to avoid the content repository implementation needing to do too much for what
113 // is essentially presentation code
114 Set<String> namespacesToCollapse;
115 RepositorySession repositorySession = repositorySessionFactory.createSession();
118 MetadataResolver metadataResolver = repositorySession.getResolver();
119 namespacesToCollapse = new LinkedHashSet<String>();
121 for ( String repoId : selectedRepos )
123 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
125 for ( String n : namespacesToCollapse )
127 // TODO: check performance of this
128 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
131 catch ( MetadataResolutionException e )
133 throw new ArchivaRestServiceException( e.getMessage(),
134 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
138 repositorySession.close();
141 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
142 for ( String namespace : namespaces )
144 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
147 Collections.sort( browseGroupResultEntries );
148 return new BrowseResult( browseGroupResultEntries );
151 public BrowseResult browseGroupId( String groupId, String repositoryId )
152 throws ArchivaRestServiceException
154 List<String> selectedRepos = getSelectedRepos( repositoryId );
156 Set<String> projects = new LinkedHashSet<String>();
158 RepositorySession repositorySession = repositorySessionFactory.createSession();
159 Set<String> namespaces;
162 MetadataResolver metadataResolver = repositorySession.getResolver();
164 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
165 for ( String repoId : selectedRepos )
167 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
169 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
172 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
173 // it is located here to avoid the content repository implementation needing to do too much for what
174 // is essentially presentation code
175 namespaces = new LinkedHashSet<String>();
176 for ( String n : namespacesToCollapse )
178 // TODO: check performance of this
180 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
183 catch ( MetadataResolutionException e )
185 throw new ArchivaRestServiceException( e.getMessage(),
186 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
190 repositorySession.close();
192 List<BrowseResultEntry> browseGroupResultEntries =
193 new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
194 for ( String namespace : namespaces )
196 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
198 for ( String project : projects )
200 browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
202 Collections.sort( browseGroupResultEntries );
203 return new BrowseResult( browseGroupResultEntries );
207 public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
208 throws ArchivaRestServiceException
210 List<String> selectedRepos = getSelectedRepos( repositoryId );
214 Collection<String> versions = getVersions( selectedRepos, groupId, artifactId );
215 return new VersionsList( new ArrayList<String>( versions ) );
217 catch ( MetadataResolutionException e )
219 throw new ArchivaRestServiceException( e.getMessage(),
220 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
225 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
226 throws MetadataResolutionException
229 RepositorySession repositorySession = repositorySessionFactory.createSession();
232 MetadataResolver metadataResolver = repositorySession.getResolver();
234 Set<String> versions = new LinkedHashSet<String>();
236 for ( String repoId : selectedRepos )
238 Collection<String> projectVersions =
239 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId );
240 versions.addAll( projectVersions );
243 List<String> sortedVersions = new ArrayList<String>( versions );
245 Collections.sort( sortedVersions, VersionComparator.getInstance() );
247 return sortedVersions;
251 repositorySession.close();
255 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
256 String repositoryId )
257 throws ArchivaRestServiceException
259 List<String> selectedRepos = getSelectedRepos( repositoryId );
261 RepositorySession repositorySession = null;
264 repositorySession = repositorySessionFactory.createSession();
266 MetadataResolver metadataResolver = repositorySession.getResolver();
268 ProjectVersionMetadata versionMetadata = null;
269 for ( String repoId : selectedRepos )
271 if ( versionMetadata == null || versionMetadata.isIncomplete() )
276 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
279 catch ( MetadataResolutionException e )
282 "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
283 + " in repo " + repoId + ": " + e.getMessage() );
288 return versionMetadata;
292 if ( repositorySession != null )
294 repositorySession.close();
300 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
301 throws ArchivaRestServiceException
304 List<String> selectedRepos = getSelectedRepos( repositoryId );
306 RepositorySession repositorySession = null;
310 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
312 repositorySession = repositorySessionFactory.createSession();
314 MetadataResolver metadataResolver = repositorySession.getResolver();
316 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
318 MavenProjectFacet mavenFacet = new MavenProjectFacet();
319 mavenFacet.setGroupId( groupId );
320 mavenFacet.setArtifactId( artifactId );
321 sharedModel.addFacet( mavenFacet );
323 boolean isFirstVersion = true;
325 for ( String version : projectVersions )
327 ProjectVersionMetadata versionMetadata = null;
328 for ( String repoId : selectedRepos )
330 if ( versionMetadata == null || versionMetadata.isIncomplete() )
335 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
338 catch ( MetadataResolutionException e )
340 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
341 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
346 if ( versionMetadata == null )
351 if ( isFirstVersion )
353 sharedModel = versionMetadata;
354 sharedModel.setId( null );
358 MavenProjectFacet versionMetadataMavenFacet =
359 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
360 if ( versionMetadataMavenFacet != null )
362 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
363 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
365 mavenFacet.setPackaging( null );
369 if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
370 versionMetadata.getName() ) )
372 sharedModel.setName( versionMetadata.getName() );
375 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
376 sharedModel.getDescription(), versionMetadata.getDescription() ) )
378 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
379 ? versionMetadata.getDescription()
383 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
384 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
385 versionMetadata.getIssueManagement().getUrl() ) )
387 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
390 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
391 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
392 versionMetadata.getCiManagement().getUrl() ) )
394 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
397 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
398 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
399 versionMetadata.getOrganization().getName() ) )
401 sharedModel.setOrganization( versionMetadata.getOrganization() );
404 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
405 versionMetadata.getUrl() ) )
407 sharedModel.setUrl( versionMetadata.getUrl() );
411 isFirstVersion = false;
415 catch ( MetadataResolutionException e )
417 throw new ArchivaRestServiceException( e.getMessage(),
418 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
422 if ( repositorySession != null )
424 repositorySession.close();
429 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
430 throws ArchivaRestServiceException
432 List<String> selectedRepos = getSelectedRepos( repositoryId );
437 return dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version );
440 catch ( Exception e )
442 log.error( e.getMessage(), e );
445 return Collections.emptyList();
448 public List<ManagedRepository> getUserRepositories()
449 throws ArchivaRestServiceException
453 return userRepositories.getAccessibleRepositories( getPrincipal() );
455 catch ( ArchivaSecurityException e )
457 throw new ArchivaRestServiceException( "repositories.read.observable.error",
458 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
462 public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
463 throws ArchivaRestServiceException
465 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
466 // TODO: what if we get duplicates across repositories?
467 RepositorySession repositorySession = repositorySessionFactory.createSession();
470 MetadataResolver metadataResolver = repositorySession.getResolver();
471 for ( String repoId : getObservableRepos() )
473 // TODO: what about if we want to see this irrespective of version?
475 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
479 catch ( MetadataResolutionException e )
481 throw new ArchivaRestServiceException( e.getMessage(),
482 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
486 repositorySession.close();
489 List<Artifact> artifacts = new ArrayList<Artifact>( references.size() );
491 for ( ProjectVersionReference projectVersionReference : references )
493 artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
494 projectVersionReference.getProjectVersion() ) );
499 public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
500 throws ArchivaRestServiceException
502 ProjectVersionMetadata projectVersionMetadata =
503 getProjectMetadata( groupId, artifactId, version, repositoryId );
504 if ( projectVersionMetadata == null )
506 return Collections.emptyList();
508 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
510 if ( metadataFacet == null )
512 return Collections.emptyList();
514 Map<String, String> map = metadataFacet.toProperties();
515 List<Entry> entries = new ArrayList<Entry>( map.size() );
517 for ( Map.Entry<String, String> entry : map.entrySet() )
519 entries.add( new Entry( entry.getKey(), entry.getValue() ) );
525 public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
526 String repositoryId )
527 throws ArchivaRestServiceException
529 ProjectVersionMetadata projectVersionMetadata =
530 getProjectMetadata( groupId, artifactId, version, repositoryId );
532 if ( projectVersionMetadata == null )
534 return Boolean.FALSE;
537 Map<String, String> properties = new HashMap<String, String>();
539 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
541 if ( metadataFacet != null && metadataFacet.toProperties() != null )
543 properties.putAll( metadataFacet.toProperties() );
547 metadataFacet = new GenericMetadataFacet();
550 properties.put( key, value );
552 metadataFacet.fromProperties( properties );
554 projectVersionMetadata.addFacet( metadataFacet );
556 RepositorySession repositorySession = repositorySessionFactory.createSession();
560 MetadataRepository metadataRepository = repositorySession.getRepository();
562 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
564 repositorySession.save();
566 catch ( MetadataRepositoryException e )
568 log.error( e.getMessage(), e );
569 throw new ArchivaRestServiceException( e.getMessage(),
570 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
574 repositorySession.close();
579 public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
580 throws ArchivaRestServiceException
582 ProjectVersionMetadata projectVersionMetadata =
583 getProjectMetadata( groupId, artifactId, version, repositoryId );
585 if ( projectVersionMetadata == null )
587 return Boolean.FALSE;
590 GenericMetadataFacet metadataFacet =
591 (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
593 if ( metadataFacet != null && metadataFacet.toProperties() != null )
595 Map<String, String> properties = metadataFacet.toProperties();
596 properties.remove( key );
597 metadataFacet.setAdditionalProperties( properties );
604 RepositorySession repositorySession = repositorySessionFactory.createSession();
608 MetadataRepository metadataRepository = repositorySession.getRepository();
610 metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
612 repositorySession.save();
614 catch ( MetadataRepositoryException e )
616 log.error( e.getMessage(), e );
617 throw new ArchivaRestServiceException( e.getMessage(),
618 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
622 repositorySession.close();
627 public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
628 String classifier, String type, String path,
629 String repositoryId )
630 throws ArchivaRestServiceException
632 List<String> selectedRepos = getSelectedRepos( repositoryId );
635 for ( String repoId : selectedRepos )
638 ManagedRepositoryContent managedRepositoryContent =
639 repositoryContentFactory.getManagedRepositoryContent( repoId );
640 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
641 StringUtils.isEmpty( type ) ? "jar" : type,
643 File file = managedRepositoryContent.toFile( archivaArtifact );
646 return readFileEntries( file, path, repoId );
650 catch ( IOException e )
652 log.error( e.getMessage(), e );
653 throw new ArchivaRestServiceException( e.getMessage(),
654 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
656 catch ( RepositoryNotFoundException e )
658 log.error( e.getMessage(), e );
659 throw new ArchivaRestServiceException( e.getMessage(),
660 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
662 catch ( RepositoryException e )
664 log.error( e.getMessage(), e );
665 throw new ArchivaRestServiceException( e.getMessage(),
666 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
668 return Collections.emptyList();
671 public List<Artifact> getArtifactDownloadInfos( String groupId, String artifactId, String version,
672 String repositoryId )
673 throws ArchivaRestServiceException
675 List<String> selectedRepos = getSelectedRepos( repositoryId );
677 List<Artifact> artifactDownloadInfos = new ArrayList<Artifact>();
679 RepositorySession session = repositorySessionFactory.createSession();
681 MetadataResolver metadataResolver = session.getResolver();
685 for ( String repoId : selectedRepos )
687 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(
688 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
689 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
690 if ( artifacts != null && !artifacts.isEmpty() )
692 return buildArtifacts( artifacts, repoId );
696 catch ( MetadataResolutionException e )
698 log.error( e.getMessage(), e );
699 throw new ArchivaRestServiceException( e.getMessage(),
700 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
704 if ( session != null )
710 return artifactDownloadInfos;
713 public ArtifactContent getArtifactContentText( String groupId, String artifactId, String version, String classifier,
714 String type, String path, String repositoryId )
715 throws ArchivaRestServiceException
717 List<String> selectedRepos = getSelectedRepos( repositoryId );
720 for ( String repoId : selectedRepos )
723 ManagedRepositoryContent managedRepositoryContent =
724 repositoryContentFactory.getManagedRepositoryContent( repoId );
725 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
726 StringUtils.isEmpty( type ) ? "jar" : type,
728 File file = managedRepositoryContent.toFile( archivaArtifact );
729 if ( !file.exists() )
731 log.debug( "file: {} not exists for repository: {} try next repository", file, repoId );
734 if ( StringUtils.isNotBlank( path ) )
736 // zip entry of the path -> path must a real file entry of the archive
737 JarFile jarFile = new JarFile( file );
738 ZipEntry zipEntry = jarFile.getEntry( path );
739 InputStream inputStream = jarFile.getInputStream( zipEntry );
742 return new ArtifactContent( IOUtils.toString( inputStream ), repoId );
746 closeQuietly( jarFile );
747 IOUtils.closeQuietly( inputStream );
750 return new ArtifactContent( FileUtils.readFileToString( file ), repoId );
753 catch ( IOException e )
755 log.error( e.getMessage(), e );
756 throw new ArchivaRestServiceException( e.getMessage(),
757 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
759 catch ( RepositoryNotFoundException e )
761 log.error( e.getMessage(), e );
762 throw new ArchivaRestServiceException( e.getMessage(),
763 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
765 catch ( RepositoryException e )
767 log.error( e.getMessage(), e );
768 throw new ArchivaRestServiceException( e.getMessage(),
769 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
771 log.debug( "artifact: {}:{}:{}:{}:{} not found", groupId, artifactId, version, classifier, type );
773 return new ArtifactContent();
776 public Boolean artifactAvailable( String groupId, String artifactId, String version, String classifier,
777 String repositoryId )
778 throws ArchivaRestServiceException
780 List<String> selectedRepos = getSelectedRepos( repositoryId );
782 boolean snapshot = VersionUtil.isSnapshot( version );
786 for ( String repoId : selectedRepos )
789 ManagedRepository managedRepository = managedRepositoryAdmin.getManagedRepository( repoId );
791 if ( ( snapshot && !managedRepository.isSnapshots() ) || ( !snapshot
792 && managedRepository.isSnapshots() ) )
796 ManagedRepositoryContent managedRepositoryContent =
797 repositoryContentFactory.getManagedRepositoryContent( repoId );
798 // FIXME default to jar which can be wrong for war zip etc....
799 ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version,
800 StringUtils.isEmpty( classifier )
802 : classifier, "jar", repoId );
803 File file = managedRepositoryContent.toFile( archivaArtifact );
805 if ( file != null && file.exists() )
810 String path = managedRepositoryContent.toPath( archivaArtifact );
812 file = connectors.fetchFromProxies( managedRepositoryContent, path );
814 if ( file != null && file.exists() )
817 String pomPath = StringUtils.substringBeforeLast( path, ".jar" ) + ".pom";
818 connectors.fetchFromProxies( managedRepositoryContent, pomPath );
823 catch ( RepositoryAdminException e )
825 log.error( e.getMessage(), e );
826 throw new ArchivaRestServiceException( e.getMessage(),
827 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
829 catch ( RepositoryException e )
831 log.error( e.getMessage(), e );
832 throw new ArchivaRestServiceException( e.getMessage(),
833 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
839 public Boolean artifactAvailable( String groupId, String artifactId, String version, String repositoryId )
840 throws ArchivaRestServiceException
842 return artifactAvailable( groupId, artifactId, version, null, repositoryId );
845 public List<Artifact> getArtifacts( String repositoryId )
846 throws ArchivaRestServiceException
848 RepositorySession repositorySession = repositorySessionFactory.createSession();
851 List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifacts( repositoryId );
852 return buildArtifacts( artifactMetadatas, repositoryId );
854 catch ( MetadataRepositoryException e )
856 throw new ArchivaRestServiceException( e.getMessage(), e );
860 repositorySession.close();
864 public Boolean importMetadata( MetadataAddRequest metadataAddRequest, String repositoryId )
865 throws ArchivaRestServiceException
867 boolean result = true;
868 for ( Map.Entry<String, String> metadata : metadataAddRequest.getMetadatas().entrySet() )
870 result = addMetadata( metadataAddRequest.getGroupId(), metadataAddRequest.getArtifactId(),
871 metadataAddRequest.getVersion(), metadata.getKey(), metadata.getValue(),
881 //---------------------------
883 //---------------------------
885 private void closeQuietly( JarFile jarFile )
887 if ( jarFile != null )
893 catch ( IOException e )
895 log.warn( "ignore error closing jarFile {}", jarFile.getName() );
900 protected List<ArtifactContentEntry> readFileEntries( File file, String filterPath, String repoId )
903 Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<String, ArtifactContentEntry>();
904 int filterDepth = StringUtils.countMatches( filterPath, "/" );
905 /*if ( filterDepth == 0 )
909 JarFile jarFile = new JarFile( file );
912 Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
913 while ( jarEntryEnumeration.hasMoreElements() )
915 JarEntry currentEntry = jarEntryEnumeration.nextElement();
916 String cleanedEntryName =
917 StringUtils.endsWith( currentEntry.getName(), "/" ) ? StringUtils.substringBeforeLast(
918 currentEntry.getName(), "/" ) : currentEntry.getName();
919 String entryRootPath = getRootPath( cleanedEntryName );
920 int depth = StringUtils.countMatches( cleanedEntryName, "/" );
921 if ( StringUtils.isEmpty( filterPath ) && !artifactContentEntryMap.containsKey( entryRootPath )
922 && depth == filterDepth )
925 artifactContentEntryMap.put( entryRootPath,
926 new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
931 if ( StringUtils.startsWith( cleanedEntryName, filterPath ) && ( depth == filterDepth || (
932 !currentEntry.isDirectory() && depth == filterDepth ) ) )
934 artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
935 !currentEntry.isDirectory(),
941 if ( StringUtils.isNotEmpty( filterPath ) )
943 Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap =
944 new HashMap<String, ArtifactContentEntry>();
946 for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
948 filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
951 List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
952 if ( sorted == null )
954 return Collections.emptyList();
956 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
962 if ( jarFile != null )
967 List<ArtifactContentEntry> sorted = new ArrayList<ArtifactContentEntry>( artifactContentEntryMap.values() );
968 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
972 private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
974 int smallestDepth = Integer.MAX_VALUE;
975 Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<Integer, List<ArtifactContentEntry>>();
976 for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
979 ArtifactContentEntry current = entry.getValue();
981 if ( current.getDepth() < smallestDepth )
983 smallestDepth = current.getDepth();
986 List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
988 if ( currentList == null )
990 currentList = new ArrayList<ArtifactContentEntry>();
991 currentList.add( current );
992 perDepthList.put( current.getDepth(), currentList );
996 currentList.add( current );
1001 return perDepthList.get( smallestDepth );
1006 * @return org/apache -> org , org -> org
1008 private String getRootPath( String path )
1010 if ( StringUtils.contains( path, '/' ) )
1012 return StringUtils.substringBefore( path, "/" );
1017 private List<String> getSelectedRepos( String repositoryId )
1018 throws ArchivaRestServiceException
1021 List<String> selectedRepos = getObservableRepos();
1023 if ( CollectionUtils.isEmpty( selectedRepos ) )
1025 return Collections.emptyList();
1028 if ( StringUtils.isNotEmpty( repositoryId ) )
1030 // check user has karma on the repository
1031 if ( !selectedRepos.contains( repositoryId ) )
1033 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
1034 Response.Status.FORBIDDEN.getStatusCode(), null );
1036 selectedRepos = Collections.singletonList( repositoryId );
1038 return selectedRepos;
1042 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
1043 Collection<String> repoIds, String n )
1044 throws MetadataResolutionException
1046 Set<String> subNamespaces = new LinkedHashSet<String>();
1047 for ( String repoId : repoIds )
1049 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
1051 if ( subNamespaces.size() != 1 )
1053 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
1058 for ( String repoId : repoIds )
1060 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
1061 if ( projects != null && !projects.isEmpty() )
1063 log.debug( "{} is not collapsible as it has projects", n );
1067 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
1068 n + "." + subNamespaces.iterator().next() );