This project has retired. For details please refer to its
Attic page.
DefaultBrowseService xref
1 package org.apache.archiva.rest.services;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import org.apache.archiva.admin.model.beans.ManagedRepository;
22 import org.apache.archiva.common.utils.VersionComparator;
23 import org.apache.archiva.common.utils.VersionUtil;
24 import org.apache.archiva.dependency.tree.maven2.DependencyTreeBuilder;
25 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
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.*;
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.model.ArchivaRepositoryMetadata;
38 import org.apache.archiva.proxy.ProxyRegistry;
39 import org.apache.archiva.proxy.model.RepositoryProxyHandler;
40 import org.apache.archiva.components.cache.Cache;
41 import org.apache.archiva.repository.ManagedRepositoryContent;
42 import org.apache.archiva.repository.ReleaseScheme;
43 import org.apache.archiva.repository.RepositoryException;
44 import org.apache.archiva.repository.RepositoryNotFoundException;
45 import org.apache.archiva.repository.metadata.base.MetadataTools;
46 import org.apache.archiva.repository.storage.StorageAsset;
47 import org.apache.archiva.repository.storage.StorageUtil;
48 import org.apache.archiva.rest.api.model.*;
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.security.ArchivaSecurityException;
53 import org.apache.archiva.xml.XMLException;
54 import org.apache.commons.collections4.CollectionUtils;
55 import org.apache.commons.io.IOUtils;
56 import org.apache.commons.lang3.StringUtils;
57 import org.springframework.stereotype.Service;
58
59 import javax.inject.Inject;
60 import javax.inject.Named;
61 import javax.ws.rs.core.Response;
62 import java.io.IOException;
63 import java.io.InputStream;
64 import java.nio.charset.Charset;
65 import java.nio.file.Files;
66 import java.util.*;
67 import java.util.jar.JarEntry;
68 import java.util.jar.JarFile;
69 import java.util.zip.ZipEntry;
70
71
72
73
74
75 @Service( "browseService#rest" )
76 public class DefaultBrowseService
77 extends AbstractRestService
78 implements BrowseService
79 {
80
81 private final Charset ARTIFACT_CONTENT_ENCODING=Charset.forName( "UTF-8" );
82
83 @Inject
84 private DependencyTreeBuilder dependencyTreeBuilder;
85
86 @Inject
87 ProxyRegistry proxyRegistry;
88
89 @Inject
90 @Named( value = "browse#versionMetadata" )
91 private Cache<String, ProjectVersionMetadata> versionMetadataCache;
92
93 private ManagedRepositoryContent getManagedRepositoryContent(String id) throws RepositoryException
94 {
95 org.apache.archiva.repository.ManagedRepository repo = repositoryRegistry.getManagedRepository( id );
96 if (repo==null) {
97 throw new RepositoryException( "Could not find repository "+id );
98 }
99 return repo.getContent();
100 }
101
102 @Override
103 public BrowseResult getRootGroups( String repositoryId )
104 throws ArchivaRestServiceException
105 {
106 List<String> selectedRepos = getSelectedRepos( repositoryId );
107
108 Set<String> namespaces = new LinkedHashSet<String>();
109
110
111
112
113 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
114 RepositorySession repositorySession = null;
115 try
116 {
117 repositorySession = repositorySessionFactory.createSession();
118 }
119 catch ( MetadataRepositoryException e )
120 {
121 e.printStackTrace( );
122 }
123 try
124 {
125 MetadataResolver metadataResolver = repositorySession.getResolver();
126
127 for ( String repoId : selectedRepos )
128 {
129 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
130 }
131 for ( String n : namespacesToCollapse )
132 {
133
134 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
135 }
136 }
137 catch ( MetadataResolutionException e )
138 {
139 throw new ArchivaRestServiceException( e.getMessage(),
140 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
141 }
142 finally
143 {
144 repositorySession.close();
145 }
146
147 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<>( namespaces.size() );
148 for ( String namespace : namespaces )
149 {
150 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
151 }
152
153 Collections.sort( browseGroupResultEntries );
154 return new BrowseResult( browseGroupResultEntries );
155 }
156
157 @Override
158 public BrowseResult browseGroupId( String groupId, String repositoryId )
159 throws ArchivaRestServiceException
160 {
161 List<String> selectedRepos = getSelectedRepos( repositoryId );
162
163 Set<String> projects = new LinkedHashSet<>();
164
165 RepositorySession repositorySession = null;
166 try
167 {
168 repositorySession = repositorySessionFactory.createSession();
169 }
170 catch ( MetadataRepositoryException e )
171 {
172 e.printStackTrace( );
173 }
174 Set<String> namespaces;
175 try
176 {
177 MetadataResolver metadataResolver = repositorySession.getResolver();
178
179 Set<String> namespacesToCollapse = new LinkedHashSet<>();
180 for ( String repoId : selectedRepos )
181 {
182 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
183
184 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
185 }
186
187
188
189
190 namespaces = new LinkedHashSet<>();
191 for ( String n : namespacesToCollapse )
192 {
193
194 namespaces.add(
195 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
196 }
197 }
198 catch ( MetadataResolutionException e )
199 {
200 throw new ArchivaRestServiceException( e.getMessage(),
201 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
202 }
203 finally
204 {
205 repositorySession.close();
206 }
207 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<>( namespaces.size() + projects.size() );
208 for ( String namespace : namespaces )
209 {
210 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ).groupId( namespace ) );
211 }
212 for ( String project : projects )
213 {
214 browseGroupResultEntries.add(
215 new BrowseResultEntry( groupId + '.' + project, true ).groupId( groupId ).artifactId( project ) );
216 }
217 Collections.sort( browseGroupResultEntries );
218 return new BrowseResult( browseGroupResultEntries );
219
220 }
221
222 @Override
223 public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
224 throws ArchivaRestServiceException
225 {
226 List<String> selectedRepos = getSelectedRepos( repositoryId );
227
228 try
229 {
230 Collection<String> versions = getVersions( selectedRepos, groupId, artifactId );
231 return new VersionsList( new ArrayList<>( versions ) );
232 }
233 catch ( MetadataResolutionException e )
234 {
235 throw new ArchivaRestServiceException( e.getMessage(),
236 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
237 }
238
239 }
240
241 private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
242 throws MetadataResolutionException
243
244 {
245 RepositorySession repositorySession = null;
246 try
247 {
248 repositorySession = repositorySessionFactory.createSession();
249 }
250 catch ( MetadataRepositoryException e )
251 {
252 e.printStackTrace( );
253 }
254 try
255 {
256 MetadataResolver metadataResolver = repositorySession.getResolver();
257
258 Set<String> versions = new LinkedHashSet<String>();
259
260 for ( String repoId : selectedRepos )
261 {
262 Collection<String> projectVersions =
263 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId );
264 versions.addAll( projectVersions );
265 }
266
267 List<String> sortedVersions = new ArrayList<>( versions );
268
269 Collections.sort( sortedVersions, VersionComparator.getInstance() );
270
271 return sortedVersions;
272 }
273 finally
274 {
275 repositorySession.close();
276 }
277 }
278
279 @Override
280 public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
281 String repositoryId )
282 throws ArchivaRestServiceException
283 {
284 List<String> selectedRepos = getSelectedRepos( repositoryId );
285
286 RepositorySession repositorySession = null;
287 try
288 {
289 repositorySession = repositorySessionFactory.createSession();
290
291 MetadataResolver metadataResolver = repositorySession.getResolver();
292
293 ProjectVersionMetadata versionMetadata = null;
294 for ( String repoId : selectedRepos )
295 {
296 if ( versionMetadata == null || versionMetadata.isIncomplete() )
297 {
298 try
299 {
300 ProjectVersionMetadata versionMetadataTmp =
301 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
302 version );
303
304 if ( versionMetadata == null && versionMetadataTmp != null )
305 {
306 versionMetadata = versionMetadataTmp;
307 }
308
309
310 }
311 catch ( MetadataResolutionException e )
312 {
313 log.warn( "Skipping invalid metadata while compiling shared model for {}:{} in repo {}: {}",
314 groupId, artifactId, repoId, e.getMessage() );
315 }
316 }
317 }
318
319 return versionMetadata;
320 } catch (MetadataRepositoryException e) {
321 throw new ArchivaRestServiceException(e.getMessage(), e);
322 } finally
323 {
324 if ( repositorySession != null )
325 {
326 repositorySession.close();
327 }
328 }
329
330 }
331
332 @Override
333 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
334 throws ArchivaRestServiceException
335 {
336
337 List<String> selectedRepos = getSelectedRepos( repositoryId );
338
339 RepositorySession repositorySession = null;
340 try
341 {
342
343 Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
344
345 repositorySession = repositorySessionFactory.createSession();
346
347 MetadataResolver metadataResolver = repositorySession.getResolver();
348
349 ProjectVersionMetadataonMetadata.html#ProjectVersionMetadata">ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
350
351 MavenProjectFacettorage/maven2/MavenProjectFacet.html#MavenProjectFacet">MavenProjectFacet mavenFacet = new MavenProjectFacet();
352 mavenFacet.setGroupId( groupId );
353 mavenFacet.setArtifactId( artifactId );
354 sharedModel.addFacet( mavenFacet );
355
356 boolean isFirstVersion = true;
357
358 for ( String version : projectVersions )
359 {
360 ProjectVersionMetadata versionMetadata = null;
361 for ( String repoId : selectedRepos )
362 {
363 if ( versionMetadata == null || versionMetadata.isIncomplete() )
364 {
365 try
366 {
367 ProjectVersionMetadata projectVersionMetadataResolved = null;
368 boolean useCache = !StringUtils.endsWith( version, VersionUtil.SNAPSHOT );
369 String cacheKey = null;
370 boolean cacheToUpdate = false;
371
372
373 if ( useCache )
374 {
375 cacheKey = repoId + groupId + artifactId + version;
376 projectVersionMetadataResolved = versionMetadataCache.get( cacheKey );
377 }
378 if ( useCache && projectVersionMetadataResolved != null )
379 {
380 versionMetadata = projectVersionMetadataResolved;
381 }
382 else
383 {
384 projectVersionMetadataResolved =
385 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId,
386 artifactId, version );
387 versionMetadata = projectVersionMetadataResolved;
388 cacheToUpdate = true;
389 }
390
391 if ( useCache && cacheToUpdate )
392 {
393 versionMetadataCache.put( cacheKey, projectVersionMetadataResolved );
394 }
395
396 }
397 catch ( MetadataResolutionException e )
398 {
399 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
400 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
401 }
402 }
403 }
404
405 if ( versionMetadata == null )
406 {
407 continue;
408 }
409
410 if ( isFirstVersion )
411 {
412 sharedModel = versionMetadata;
413 sharedModel.setId( null );
414 }
415 else
416 {
417 MavenProjectFacet versionMetadataMavenFacet =
418 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
419 if ( versionMetadataMavenFacet != null )
420 {
421 if ( mavenFacet.getPackaging() != null
422 && !StringUtils.equalsIgnoreCase( mavenFacet.getPackaging(),
423 versionMetadataMavenFacet.getPackaging() ) )
424 {
425 mavenFacet.setPackaging( null );
426 }
427 }
428
429 if ( StringUtils.isEmpty( sharedModel.getName() )
430 && !StringUtils.isEmpty( versionMetadata.getName() ) )
431 {
432 sharedModel.setName( versionMetadata.getName() );
433 }
434
435 if ( sharedModel.getDescription() != null
436 && !StringUtils.equalsIgnoreCase( sharedModel.getDescription(),
437 versionMetadata.getDescription() ) )
438 {
439 sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
440 ? versionMetadata.getDescription()
441 : "" );
442 }
443
444 if ( sharedModel.getIssueManagement() != null
445 && versionMetadata.getIssueManagement() != null
446 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
447 versionMetadata.getIssueManagement().getUrl() ) )
448 {
449 sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
450 }
451
452 if ( sharedModel.getCiManagement() != null
453 && versionMetadata.getCiManagement() != null
454 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
455 versionMetadata.getCiManagement().getUrl() ) )
456 {
457 sharedModel.setCiManagement( versionMetadata.getCiManagement() );
458 }
459
460 if ( sharedModel.getOrganization() != null
461 && versionMetadata.getOrganization() != null
462 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
463 versionMetadata.getOrganization().getName() ) )
464 {
465 sharedModel.setOrganization( versionMetadata.getOrganization() );
466 }
467
468 if ( sharedModel.getUrl() != null
469 && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(), versionMetadata.getUrl() ) )
470 {
471 sharedModel.setUrl( versionMetadata.getUrl() );
472 }
473 }
474
475 isFirstVersion = false;
476 }
477 return sharedModel;
478 }
479 catch (MetadataResolutionException | MetadataRepositoryException e )
480 {
481 throw new ArchivaRestServiceException( e.getMessage(),
482 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
483 }
484 finally
485 {
486 if ( repositorySession != null )
487 {
488 repositorySession.close();
489 }
490 }
491 }
492
493 @Override
494 public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
495 throws ArchivaRestServiceException
496 {
497 List<String> selectedRepos = getSelectedRepos( repositoryId );
498
499 try
500 {
501 return dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version );
502 }
503 catch ( Exception e )
504 {
505 log.error( e.getMessage(), e );
506 }
507
508 return Collections.emptyList();
509 }
510
511 @Override
512 public List<ManagedRepository> getUserRepositories()
513 throws ArchivaRestServiceException
514 {
515 try
516 {
517 return userRepositories.getAccessibleRepositories( getPrincipal() );
518 }
519 catch ( ArchivaSecurityException e )
520 {
521 throw new ArchivaRestServiceException( "repositories.read.observable.error",
522 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
523 }
524 }
525
526 @Override
527 public List<ManagedRepository> getUserManagableRepositories() throws ArchivaRestServiceException {
528 try
529 {
530 return userRepositories.getManagableRepositories( getPrincipal() );
531 }
532 catch ( ArchivaSecurityException e )
533 {
534 throw new ArchivaRestServiceException( "repositories.read.managable.error",
535 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
536 }
537 }
538
539 @Override
540 public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
541 throws ArchivaRestServiceException
542 {
543 List<ProjectVersionReference> references = new ArrayList<>();
544
545 RepositorySession repositorySession = null;
546 try
547 {
548 repositorySession = repositorySessionFactory.createSession();
549 }
550 catch ( MetadataRepositoryException e )
551 {
552 e.printStackTrace( );
553 }
554 try
555 {
556 MetadataResolver metadataResolver = repositorySession.getResolver();
557 for ( String repoId : getObservableRepos() )
558 {
559
560 references.addAll(
561 metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
562 version ) );
563 }
564 }
565 catch ( MetadataResolutionException e )
566 {
567 throw new ArchivaRestServiceException( e.getMessage(),
568 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
569 }
570 finally
571 {
572 repositorySession.close();
573 }
574
575 List<Artifact> artifacts = new ArrayList<>( references.size() );
576
577 for ( ProjectVersionReference projectVersionReference : references )
578 {
579 artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
580 projectVersionReference.getProjectVersion() ) );
581 }
582 return artifacts;
583 }
584
585 @Override
586 public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
587 throws ArchivaRestServiceException
588 {
589 ProjectVersionMetadata projectVersionMetadata =
590 getProjectMetadata( groupId, artifactId, version, repositoryId );
591 if ( projectVersionMetadata == null )
592 {
593 return Collections.emptyList();
594 }
595 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
596
597 if ( metadataFacet == null )
598 {
599 return Collections.emptyList();
600 }
601 Map<String, String> map = metadataFacet.toProperties();
602 List<Entry> entries = new ArrayList<>( map.size() );
603
604 for ( Map.Entry<String, String> entry : map.entrySet() )
605 {
606 entries.add( new Entry( entry.getKey(), entry.getValue() ) );
607 }
608
609 return entries;
610 }
611
612 @Override
613 public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
614 String repositoryId )
615 throws ArchivaRestServiceException
616 {
617 ProjectVersionMetadata projectVersionMetadata =
618 getProjectMetadata( groupId, artifactId, version, repositoryId );
619
620 if ( projectVersionMetadata == null )
621 {
622 return Boolean.FALSE;
623 }
624
625 Map<String, String> properties = new HashMap<>();
626
627 MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
628
629 if ( metadataFacet != null && metadataFacet.toProperties() != null )
630 {
631 properties.putAll( metadataFacet.toProperties() );
632 }
633 else
634 {
635 metadataFacet = new GenericMetadataFacet();
636 }
637
638 properties.put( key, value );
639
640 metadataFacet.fromProperties( properties );
641
642 projectVersionMetadata.addFacet( metadataFacet );
643
644 RepositorySession repositorySession = null;
645 try
646 {
647 repositorySession = repositorySessionFactory.createSession();
648 }
649 catch ( MetadataRepositoryException e )
650 {
651 e.printStackTrace( );
652 }
653
654 try
655 {
656 MetadataRepository metadataRepository = repositorySession.getRepository();
657
658 metadataRepository.updateProjectVersion(repositorySession , repositoryId, groupId, artifactId, projectVersionMetadata );
659
660 repositorySession.save();
661 }
662 catch (MetadataRepositoryException | MetadataSessionException e )
663 {
664 log.error( e.getMessage(), e );
665 throw new ArchivaRestServiceException( e.getMessage(),
666 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
667 }
668 finally
669 {
670 repositorySession.close();
671 }
672 return Boolean.TRUE;
673 }
674
675 @Override
676 public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
677 throws ArchivaRestServiceException
678 {
679 ProjectVersionMetadata projectVersionMetadata =
680 getProjectMetadata( groupId, artifactId, version, repositoryId );
681
682 if ( projectVersionMetadata == null )
683 {
684 return Boolean.FALSE;
685 }
686
687 GenericMetadataFacet metadataFacet =
688 (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
689
690 if ( metadataFacet != null && metadataFacet.toProperties() != null )
691 {
692 Map<String, String> properties = metadataFacet.toProperties();
693 properties.remove( key );
694 metadataFacet.setAdditionalProperties( properties );
695 }
696 else
697 {
698 return Boolean.TRUE;
699 }
700
701 RepositorySession repositorySession = null;
702 try
703 {
704 repositorySession = repositorySessionFactory.createSession();
705 }
706 catch ( MetadataRepositoryException e )
707 {
708 e.printStackTrace( );
709 }
710
711 try
712 {
713 MetadataRepository metadataRepository = repositorySession.getRepository();
714
715 metadataRepository.updateProjectVersion(repositorySession , repositoryId, groupId, artifactId, projectVersionMetadata );
716
717 repositorySession.save();
718 }
719 catch (MetadataRepositoryException | MetadataSessionException e )
720 {
721 log.error( e.getMessage(), e );
722 throw new ArchivaRestServiceException( e.getMessage(),
723 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
724 }
725 finally
726 {
727 repositorySession.close();
728 }
729 return Boolean.TRUE;
730 }
731
732 @Override
733 public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
734 String classifier, String type, String path,
735 String repositoryId )
736 throws ArchivaRestServiceException
737 {
738 List<String> selectedRepos = getSelectedRepos( repositoryId );
739 try
740 {
741 for ( String repoId : selectedRepos )
742 {
743
744 ManagedRepositoryContent managedRepositoryContent =
745 getManagedRepositoryContent( repoId );
746 ArchivaArtifactml#ArchivaArtifact">ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
747 StringUtils.isEmpty( type ) ? "jar" : type,
748 repoId );
749 StorageAsset file = managedRepositoryContent.toFile( archivaArtifact );
750 if ( file.exists() )
751 {
752 return readFileEntries( file, path, repoId );
753 }
754 }
755 }
756 catch ( IOException e )
757 {
758 log.error( e.getMessage(), e );
759 throw new ArchivaRestServiceException( e.getMessage(),
760 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
761 }
762 catch ( RepositoryNotFoundException e )
763 {
764 log.error( e.getMessage(), e );
765 throw new ArchivaRestServiceException( e.getMessage(),
766 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
767 }
768 catch ( RepositoryException e )
769 {
770 log.error( e.getMessage(), e );
771 throw new ArchivaRestServiceException( e.getMessage(),
772 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
773 }
774 return Collections.emptyList();
775 }
776
777 @Override
778 public List<Artifact> getArtifactDownloadInfos( String groupId, String artifactId, String version,
779 String repositoryId )
780 throws ArchivaRestServiceException
781 {
782 List<String> selectedRepos = getSelectedRepos( repositoryId );
783
784 List<Artifact> artifactDownloadInfos = new ArrayList<>();
785
786 try (RepositorySession session = repositorySessionFactory.createSession())
787 {
788 MetadataResolver metadataResolver = session.getResolver();
789 for ( String repoId : selectedRepos )
790 {
791 List<ArtifactMetadata> artifacts = new ArrayList<>(
792 metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
793 Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
794 if ( artifacts != null && !artifacts.isEmpty() )
795 {
796 return buildArtifacts( artifacts, repoId );
797 }
798 }
799 }
800 catch ( MetadataResolutionException e )
801 {
802 log.error( e.getMessage(), e );
803 throw new ArchivaRestServiceException( e.getMessage(),
804 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
805 }
806 catch ( MetadataRepositoryException e )
807 {
808 e.printStackTrace( );
809 }
810
811 return artifactDownloadInfos;
812 }
813
814 @Override
815 public ArtifactContent getArtifactContentText( String groupId, String artifactId, String version, String classifier,
816 String type, String path, String repositoryId )
817 throws ArchivaRestServiceException
818 {
819 List<String> selectedRepos = getSelectedRepos( repositoryId );
820 try
821 {
822 for ( String repoId : selectedRepos )
823 {
824
825 ManagedRepositoryContent managedRepositoryContent = null;
826 try
827 {
828 managedRepositoryContent = getManagedRepositoryContent( repoId );
829 }
830 catch ( RepositoryException e )
831 {
832 log.error("No repository content found for "+repoId);
833 continue;
834 }
835 ArchivaArtifactml#ArchivaArtifact">ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
836 StringUtils.isEmpty( type ) ? "jar" : type,
837 repoId );
838 StorageAsset file = managedRepositoryContent.toFile( archivaArtifact );
839 if ( !file.exists() )
840 {
841 log.debug( "file: {} not exists for repository: {} try next repository", file, repoId );
842 continue;
843 }
844 if ( StringUtils.isNotBlank( path ) )
845 {
846
847 StorageUtil.PathInformation pathInfo = StorageUtil.getAssetDataAsPath(file);
848 JarFile jarFile = new JarFile( pathInfo.getPath().toFile());
849 ZipEntry zipEntry = jarFile.getEntry( path );
850 try (InputStream inputStream = jarFile.getInputStream( zipEntry ))
851 {
852 return new ArtifactContent( IOUtils.toString( inputStream, ARTIFACT_CONTENT_ENCODING ), repoId );
853 }
854 finally
855 {
856 closeQuietly( jarFile );
857 if (pathInfo.isTmpFile()) {
858 Files.deleteIfExists(pathInfo.getPath());
859 }
860 }
861 }
862 try(InputStream readStream = file.getReadStream()) {
863 return new ArtifactContent(IOUtils.toString(readStream, ARTIFACT_CONTENT_ENCODING), repoId);
864 }
865 }
866 }
867 catch ( IOException e )
868 {
869 log.error( e.getMessage(), e );
870 throw new ArchivaRestServiceException( e.getMessage(),
871 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
872 }
873 log.debug( "artifact: {}:{}:{}:{}:{} not found", groupId, artifactId, version, classifier, type );
874
875 return new ArtifactContent();
876 }
877
878 @Override
879 public Boolean artifactAvailable( String groupId, String artifactId, String version, String classifier,
880 String repositoryId )
881 throws ArchivaRestServiceException
882 {
883 List<String> selectedRepos = getSelectedRepos( repositoryId );
884
885 boolean snapshot = VersionUtil.isSnapshot( version );
886
887 try
888 {
889 for ( String repoId : selectedRepos )
890 {
891
892 org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository(repoId);
893 if (!proxyRegistry.hasHandler(managedRepo.getType())) {
894 throw new RepositoryException( "No proxy handler found for repository type "+managedRepo.getType());
895 }
896 RepositoryProxyHandler proxyHandler = proxyRegistry.getHandler(managedRepo.getType()).get(0);
897 if ( ( snapshot && !managedRepo.getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT) ) || ( !snapshot
898 && managedRepo.getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT) ) )
899 {
900 continue;
901 }
902 ManagedRepositoryContent managedRepositoryContent = getManagedRepositoryContent( repoId );
903
904
905 ArchivaArtifactml#ArchivaArtifact">ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version,
906 StringUtils.isEmpty( classifier )
907 ? ""
908 : classifier, "jar", repoId );
909 StorageAsset file = managedRepositoryContent.toFile( archivaArtifact );
910
911 if ( file != null && file.exists() )
912 {
913 return true;
914 }
915
916
917 if ( StringUtils.endsWith( version, VersionUtil.SNAPSHOT ) )
918 {
919 StorageAsset metadataFile = file.getStorage().getAsset(file.getParent().getPath()+"/"+MetadataTools.MAVEN_METADATA );
920 if ( metadataFile.exists() )
921 {
922 try
923 {
924 ArchivaRepositoryMetadata archivaRepositoryMetadata =
925 MavenMetadataReader.read( metadataFile );
926 int buildNumber = archivaRepositoryMetadata.getSnapshotVersion().getBuildNumber();
927 String timeStamp = archivaRepositoryMetadata.getSnapshotVersion().getTimestamp();
928
929 String timeStampFileName = new StringBuilder( artifactId ).append( '-' )
930 .append( StringUtils.remove( version, "-" + VersionUtil.SNAPSHOT ) )
931 .append( '-' ).append( timeStamp )
932 .append( '-' ).append( Integer.toString( buildNumber ) )
933 .append( ( StringUtils.isEmpty( classifier ) ? "" : "-" + classifier ) )
934 .append( ".jar" ).toString();
935
936 StorageAsset timeStampFile = file.getStorage().getAsset(file.getParent().getPath() + "/" + timeStampFileName );
937 log.debug( "try to find timestamped snapshot version file: {}", timeStampFile.getPath() );
938 if ( timeStampFile.exists() )
939 {
940 return true;
941 }
942 }
943 catch (XMLException | IOException e )
944 {
945 log.warn( "skip fail to find timestamped snapshot file: {}", e.getMessage() );
946 }
947 }
948 }
949
950 String path = managedRepositoryContent.toPath( archivaArtifact );
951
952 file = proxyHandler.fetchFromProxies( managedRepositoryContent.getRepository(), path );
953
954 if ( file != null && file.exists() )
955 {
956
957 String pomPath = StringUtils.substringBeforeLast( path, ".jar" ) + ".pom";
958 proxyHandler.fetchFromProxies( managedRepositoryContent.getRepository(), pomPath );
959 return true;
960 }
961 }
962 } catch ( RepositoryException e )
963 {
964 log.error( e.getMessage(), e );
965 throw new ArchivaRestServiceException( e.getMessage(),
966 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
967 }
968
969 return false;
970 }
971
972 @Override
973 public Boolean artifactAvailable( String groupId, String artifactId, String version, String repositoryId )
974 throws ArchivaRestServiceException
975 {
976 return artifactAvailable( groupId, artifactId, version, null, repositoryId );
977 }
978
979 @Override
980 public List<Artifact> getArtifacts( String repositoryId )
981 throws ArchivaRestServiceException
982 {
983 RepositorySession repositorySession = null;
984 try
985 {
986 repositorySession = repositorySessionFactory.createSession();
987 }
988 catch ( MetadataRepositoryException e )
989 {
990 e.printStackTrace( );
991 }
992 try
993 {
994 List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifacts(repositorySession , repositoryId );
995 return buildArtifacts( artifactMetadatas, repositoryId );
996 }
997 catch ( MetadataRepositoryException e )
998 {
999 throw new ArchivaRestServiceException( e.getMessage(), e );
1000 }
1001 finally
1002 {
1003 repositorySession.close();
1004 }
1005 }
1006
1007 @Override
1008 public List<Artifact> getArtifactsByProjectVersionMetadata( String key, String value, String repositoryId )
1009 throws ArchivaRestServiceException
1010 {
1011 RepositorySession repositorySession = null;
1012 try
1013 {
1014 repositorySession = repositorySessionFactory.createSession();
1015 }
1016 catch ( MetadataRepositoryException e )
1017 {
1018 e.printStackTrace( );
1019 }
1020 try
1021 {
1022 List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifactsByProjectVersionFacet(repositorySession , key, value, repositoryId );
1023 return buildArtifacts( artifactMetadatas, repositoryId );
1024 }
1025 catch ( MetadataRepositoryException e )
1026 {
1027 throw new ArchivaRestServiceException( e.getMessage(), e );
1028 }
1029 finally
1030 {
1031 repositorySession.close();
1032 }
1033 }
1034
1035 @Override
1036 public List<Artifact> getArtifactsByMetadata( String key, String value, String repositoryId )
1037 throws ArchivaRestServiceException
1038 {
1039 RepositorySession repositorySession = null;
1040 try
1041 {
1042 repositorySession = repositorySessionFactory.createSession();
1043 }
1044 catch ( MetadataRepositoryException e )
1045 {
1046 e.printStackTrace( );
1047 }
1048 try
1049 {
1050 List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifactsByAttribute(repositorySession , key, value, repositoryId );
1051 return buildArtifacts( artifactMetadatas, repositoryId );
1052 }
1053 catch ( MetadataRepositoryException e )
1054 {
1055 throw new ArchivaRestServiceException( e.getMessage(), e );
1056 }
1057 finally
1058 {
1059 repositorySession.close();
1060 }
1061 }
1062
1063 @Override
1064 public List<Artifact> getArtifactsByProperty( String key, String value, String repositoryId )
1065 throws ArchivaRestServiceException
1066 {
1067 RepositorySession repositorySession = null;
1068 try
1069 {
1070 repositorySession = repositorySessionFactory.createSession();
1071 }
1072 catch ( MetadataRepositoryException e )
1073 {
1074 e.printStackTrace( );
1075 }
1076 try
1077 {
1078 List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifactsByProjectVersionAttribute(repositorySession , key, value, repositoryId );
1079 return buildArtifacts( artifactMetadatas, repositoryId );
1080 }
1081 catch ( MetadataRepositoryException e )
1082 {
1083 throw new ArchivaRestServiceException( e.getMessage(), e );
1084 }
1085 finally
1086 {
1087 repositorySession.close();
1088 }
1089 }
1090
1091 @Override
1092 public Boolean importMetadata( MetadataAddRequest metadataAddRequest, String repositoryId )
1093 throws ArchivaRestServiceException
1094 {
1095 boolean result = true;
1096 for ( Map.Entry<String, String> metadata : metadataAddRequest.getMetadatas().entrySet() )
1097 {
1098 result = addMetadata( metadataAddRequest.getGroupId(), metadataAddRequest.getArtifactId(),
1099 metadataAddRequest.getVersion(), metadata.getKey(), metadata.getValue(),
1100 repositoryId );
1101 if ( !result )
1102 {
1103 break;
1104 }
1105 }
1106 return result;
1107 }
1108
1109 @Override
1110 public List<Artifact> searchArtifacts( String text, String repositoryId, Boolean exact )
1111 throws ArchivaRestServiceException
1112 {
1113 try(RepositorySession repositorySession = repositorySessionFactory.createSession())
1114 {
1115 List<ArtifactMetadata> artifactMetadatas =
1116 repositorySession.getRepository().searchArtifacts(repositorySession , repositoryId, text, exact == null ? false : exact );
1117 return buildArtifacts( artifactMetadatas, repositoryId );
1118 }
1119 catch ( MetadataRepositoryException e )
1120 {
1121 throw new ArchivaRestServiceException( e.getMessage(), e );
1122 }
1123 }
1124
1125 @Override
1126 public List<Artifact> searchArtifacts( String key, String text, String repositoryId, Boolean exact )
1127 throws ArchivaRestServiceException
1128 {
1129 RepositorySession repositorySession = null;
1130 try
1131 {
1132 repositorySession = repositorySessionFactory.createSession();
1133 }
1134 catch ( MetadataRepositoryException e )
1135 {
1136 e.printStackTrace( );
1137 }
1138 try
1139 {
1140 List<ArtifactMetadata> artifactMetadatas =
1141 repositorySession.getRepository().searchArtifacts(repositorySession , repositoryId, key, text, exact == null ? false : exact );
1142 return buildArtifacts( artifactMetadatas, repositoryId );
1143 }
1144 catch ( MetadataRepositoryException e )
1145 {
1146 throw new ArchivaRestServiceException( e.getMessage(), e );
1147 }
1148 finally
1149 {
1150 repositorySession.close();
1151 }
1152 }
1153
1154
1155
1156
1157
1158 private void closeQuietly( JarFile jarFile )
1159 {
1160 if ( jarFile != null )
1161 {
1162 try
1163 {
1164 jarFile.close();
1165 }
1166 catch ( IOException e )
1167 {
1168 log.warn( "ignore error closing jarFile {}", jarFile.getName() );
1169 }
1170 }
1171 }
1172
1173 protected List<ArtifactContentEntry> readFileEntries(final StorageAsset file, final String filterPath, final String repoId )
1174 throws IOException
1175 {
1176 String cleanedfilterPath = filterPath==null ? "" : (StringUtils.startsWith(filterPath, "/") ?
1177 StringUtils.substringAfter(filterPath, "/") : filterPath);
1178 Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<>();
1179 int filterDepth = StringUtils.countMatches( cleanedfilterPath, "/" );
1180 if (!StringUtils.endsWith(cleanedfilterPath,"/") && !StringUtils.isEmpty(cleanedfilterPath)) {
1181 filterDepth++;
1182 }
1183
1184 StorageUtil.PathInformation pathInfo = StorageUtil.getAssetDataAsPath(file);
1185 JarFile jarFile = new JarFile(pathInfo.getPath().toFile());
1186 try
1187 {
1188 Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
1189 while ( jarEntryEnumeration.hasMoreElements() )
1190 {
1191 JarEntry currentEntry = jarEntryEnumeration.nextElement();
1192 String cleanedEntryName = StringUtils.endsWith( currentEntry.getName(), "/" ) ?
1193 StringUtils.substringBeforeLast( currentEntry.getName(), "/" ) : currentEntry.getName();
1194 String entryRootPath = getRootPath( cleanedEntryName );
1195 int depth = StringUtils.countMatches( cleanedEntryName, "/" );
1196 if ( StringUtils.isEmpty( cleanedfilterPath )
1197 && !artifactContentEntryMap.containsKey( entryRootPath )
1198 && depth == filterDepth )
1199 {
1200
1201 artifactContentEntryMap.put( entryRootPath,
1202 new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
1203 depth, repoId ) );
1204 }
1205 else
1206 {
1207 if ( StringUtils.startsWith( cleanedEntryName, cleanedfilterPath )
1208 && ( depth == filterDepth || ( !currentEntry.isDirectory() && depth == filterDepth ) ) )
1209 {
1210 artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
1211 !currentEntry.isDirectory(),
1212 depth, repoId ) );
1213 }
1214 }
1215 }
1216
1217 if ( StringUtils.isNotEmpty( cleanedfilterPath ) )
1218 {
1219 Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap = new HashMap<>();
1220
1221 for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
1222 {
1223 filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
1224 }
1225
1226 List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
1227 if ( sorted == null )
1228 {
1229 return Collections.emptyList();
1230 }
1231 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
1232 return sorted;
1233 }
1234 }
1235 finally
1236 {
1237 if ( jarFile != null )
1238 {
1239 jarFile.close();
1240 }
1241 if (pathInfo.isTmpFile()) {
1242 Files.deleteIfExists(pathInfo.getPath());
1243 }
1244 }
1245 List<ArtifactContentEntry> sorted = new ArrayList<>( artifactContentEntryMap.values() );
1246 Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
1247 return sorted;
1248 }
1249
1250 private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
1251 {
1252 int smallestDepth = Integer.MAX_VALUE;
1253 Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<>();
1254 for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
1255 {
1256
1257 ArtifactContentEntry current = entry.getValue();
1258
1259 if ( current.getDepth() < smallestDepth )
1260 {
1261 smallestDepth = current.getDepth();
1262 }
1263
1264 List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
1265
1266 if ( currentList == null )
1267 {
1268 currentList = new ArrayList<>();
1269 currentList.add( current );
1270 perDepthList.put( current.getDepth(), currentList );
1271 }
1272 else
1273 {
1274 currentList.add( current );
1275 }
1276
1277 }
1278
1279 return perDepthList.get( smallestDepth );
1280 }
1281
1282
1283
1284
1285
1286 private String getRootPath( String path )
1287 {
1288 if ( StringUtils.contains( path, '/' ) )
1289 {
1290 return StringUtils.substringBefore( path, "/" );
1291 }
1292 return path;
1293 }
1294
1295 private List<String> getSelectedRepos( String repositoryId )
1296 throws ArchivaRestServiceException
1297 {
1298
1299 List<String> selectedRepos = getObservableRepos();
1300
1301 if ( CollectionUtils.isEmpty( selectedRepos ) )
1302 {
1303 return Collections.emptyList();
1304 }
1305
1306 if ( StringUtils.isNotEmpty( repositoryId ) )
1307 {
1308
1309 if ( !selectedRepos.contains( repositoryId ) )
1310 {
1311 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
1312 Response.Status.FORBIDDEN.getStatusCode(), null );
1313 }
1314 selectedRepos = Collections.singletonList( repositoryId );
1315 }
1316 return selectedRepos;
1317 }
1318
1319
1320 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
1321 Collection<String> repoIds, String n )
1322 throws MetadataResolutionException
1323 {
1324 Set<String> subNamespaces = new LinkedHashSet<String>();
1325 for ( String repoId : repoIds )
1326 {
1327 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
1328 }
1329 if ( subNamespaces.size() != 1 )
1330 {
1331 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
1332 return n;
1333 }
1334 else
1335 {
1336 for ( String repoId : repoIds )
1337 {
1338 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
1339 if ( projects != null && !projects.isEmpty() )
1340 {
1341 log.debug( "{} is not collapsible as it has projects", n );
1342 return n;
1343 }
1344 }
1345 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
1346 n + "." + subNamespaces.iterator().next() );
1347 }
1348 }
1349
1350 public Cache<String, ProjectVersionMetadata> getVersionMetadataCache()
1351 {
1352 return versionMetadataCache;
1353 }
1354
1355 public void setVersionMetadataCache( Cache<String, ProjectVersionMetadata> versionMetadataCache )
1356 {
1357 this.versionMetadataCache = versionMetadataCache;
1358 }
1359 }