]> source.dussan.org Git - archiva.git/blob
aa5e4f7dcaf2efa0ac22fbdbc173486d8e2eb079
[archiva.git] /
1 package org.apache.archiva.rest.services;
2 /*
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
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
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
18  * under the License.
19  */
20
21 import org.apache.archiva.admin.model.beans.ManagedRepository;
22 import org.apache.archiva.common.utils.VersionComparator;
23 import org.apache.archiva.dependency.tree.maven2.DependencyTreeBuilder;
24 import org.apache.archiva.metadata.generic.GenericMetadataFacet;
25 import org.apache.archiva.metadata.model.MetadataFacet;
26 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
27 import org.apache.archiva.metadata.model.ProjectVersionReference;
28 import org.apache.archiva.metadata.repository.MetadataRepository;
29 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
30 import org.apache.archiva.metadata.repository.MetadataResolutionException;
31 import org.apache.archiva.metadata.repository.MetadataResolver;
32 import org.apache.archiva.metadata.repository.RepositorySession;
33 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
34 import org.apache.archiva.rest.api.model.Artifact;
35 import org.apache.archiva.rest.api.model.ArtifactContentEntry;
36 import org.apache.archiva.rest.api.model.BrowseResult;
37 import org.apache.archiva.rest.api.model.BrowseResultEntry;
38 import org.apache.archiva.rest.api.model.Entry;
39 import org.apache.archiva.rest.api.model.TreeEntry;
40 import org.apache.archiva.rest.api.model.VersionsList;
41 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
42 import org.apache.archiva.rest.api.services.BrowseService;
43 import org.apache.archiva.rest.services.utils.TreeDependencyNodeVisitor;
44 import org.apache.archiva.security.ArchivaSecurityException;
45 import org.apache.commons.collections.CollectionUtils;
46 import org.apache.commons.lang.StringUtils;
47 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
48 import org.springframework.stereotype.Service;
49
50 import javax.inject.Inject;
51 import javax.ws.rs.core.Response;
52 import java.util.ArrayList;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.HashMap;
56 import java.util.LinkedHashSet;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.Set;
60
61 /**
62  * @author Olivier Lamy
63  * @since 1.4-M3
64  */
65 @Service( "browseService#rest" )
66 public class DefaultBrowseService
67     extends AbstractRestService
68     implements BrowseService
69 {
70
71     @Inject
72     private DependencyTreeBuilder dependencyTreeBuilder;
73
74     public BrowseResult getRootGroups( String repositoryId )
75         throws ArchivaRestServiceException
76     {
77         List<String> selectedRepos = getObservableRepos();
78         if ( CollectionUtils.isEmpty( selectedRepos ) )
79         {
80             // FIXME 403 ???
81             return new BrowseResult();
82         }
83
84         if ( StringUtils.isNotEmpty( repositoryId ) )
85         {
86             // check user has karma on the repository
87             if ( !selectedRepos.contains( repositoryId ) )
88             {
89                 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
90                                                        Response.Status.FORBIDDEN.getStatusCode() );
91             }
92             selectedRepos = Collections.singletonList( repositoryId );
93         }
94
95         Set<String> namespaces = new LinkedHashSet<String>();
96
97         // TODO: this logic should be optional, particularly remembering we want to keep this code simple
98         //       it is located here to avoid the content repository implementation needing to do too much for what
99         //       is essentially presentation code
100         Set<String> namespacesToCollapse;
101         RepositorySession repositorySession = repositorySessionFactory.createSession();
102         try
103         {
104             MetadataResolver metadataResolver = repositorySession.getResolver();
105             namespacesToCollapse = new LinkedHashSet<String>();
106
107             for ( String repoId : selectedRepos )
108             {
109                 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
110             }
111             for ( String n : namespacesToCollapse )
112             {
113                 // TODO: check performance of this
114                 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
115             }
116         }
117         catch ( MetadataResolutionException e )
118         {
119             throw new ArchivaRestServiceException( e.getMessage(),
120                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
121         }
122         finally
123         {
124             repositorySession.close();
125         }
126
127         List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
128         for ( String namespace : namespaces )
129         {
130             browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
131         }
132
133         Collections.sort( browseGroupResultEntries );
134         return new BrowseResult( browseGroupResultEntries );
135     }
136
137     public BrowseResult browseGroupId( String groupId, String repositoryId )
138         throws ArchivaRestServiceException
139     {
140
141         List<String> selectedRepos = getObservableRepos();
142         if ( CollectionUtils.isEmpty( selectedRepos ) )
143         {
144             // FIXME 403 ???
145             return new BrowseResult();
146         }
147
148         if ( StringUtils.isNotEmpty( repositoryId ) )
149         {
150             // check user has karma on the repository
151             if ( !selectedRepos.contains( repositoryId ) )
152             {
153                 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
154                                                        Response.Status.FORBIDDEN.getStatusCode() );
155             }
156             selectedRepos = Collections.singletonList( repositoryId );
157         }
158
159         Set<String> projects = new LinkedHashSet<String>();
160
161         RepositorySession repositorySession = repositorySessionFactory.createSession();
162         Set<String> namespaces;
163         try
164         {
165             MetadataResolver metadataResolver = repositorySession.getResolver();
166
167             Set<String> namespacesToCollapse = new LinkedHashSet<String>();
168             for ( String repoId : selectedRepos )
169             {
170                 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
171
172                 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
173             }
174
175             // TODO: this logic should be optional, particularly remembering we want to keep this code simple
176             // it is located here to avoid the content repository implementation needing to do too much for what
177             // is essentially presentation code
178             namespaces = new LinkedHashSet<String>();
179             for ( String n : namespacesToCollapse )
180             {
181                 // TODO: check performance of this
182                 namespaces.add(
183                     collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
184             }
185         }
186         catch ( MetadataResolutionException e )
187         {
188             throw new ArchivaRestServiceException( e.getMessage(),
189                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
190         }
191         finally
192         {
193             repositorySession.close();
194         }
195         List<BrowseResultEntry> browseGroupResultEntries =
196             new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
197         for ( String namespace : namespaces )
198         {
199             browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
200         }
201         for ( String project : projects )
202         {
203             browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
204         }
205         Collections.sort( browseGroupResultEntries );
206         return new BrowseResult( browseGroupResultEntries );
207
208     }
209
210     public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
211         throws ArchivaRestServiceException
212     {
213         List<String> selectedRepos = getObservableRepos();
214         if ( CollectionUtils.isEmpty( selectedRepos ) )
215         {
216             // FIXME 403 ???
217             return new VersionsList();
218         }
219
220         if ( StringUtils.isNotEmpty( repositoryId ) )
221         {
222             // check user has karma on the repository
223             if ( !selectedRepos.contains( repositoryId ) )
224             {
225                 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
226                                                        Response.Status.FORBIDDEN.getStatusCode() );
227             }
228             selectedRepos = Collections.singletonList( repositoryId );
229         }
230
231         try
232         {
233             return new VersionsList( new ArrayList<String>( getVersions( selectedRepos, groupId, artifactId ) ) );
234         }
235         catch ( MetadataResolutionException e )
236         {
237             throw new ArchivaRestServiceException( e.getMessage(),
238                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
239         }
240
241     }
242
243     private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
244         throws MetadataResolutionException
245
246     {
247         RepositorySession repositorySession = repositorySessionFactory.createSession();
248         try
249         {
250             MetadataResolver metadataResolver = repositorySession.getResolver();
251
252             Set<String> versions = new LinkedHashSet<String>();
253
254             for ( String repoId : selectedRepos )
255             {
256                 versions.addAll(
257                     metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
258             }
259
260             List<String> sortedVersions = new ArrayList<String>( versions );
261
262             Collections.sort( sortedVersions, VersionComparator.getInstance() );
263
264             return sortedVersions;
265         }
266         finally
267         {
268             repositorySession.close();
269         }
270     }
271
272     public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
273                                                       String repositoryId )
274         throws ArchivaRestServiceException
275     {
276         List<String> selectedRepos = getObservableRepos();
277
278         if ( CollectionUtils.isEmpty( selectedRepos ) )
279         {
280             // FIXME 403 ???
281             return null;
282         }
283
284         if ( StringUtils.isNotEmpty( repositoryId ) )
285         {
286             // check user has karma on the repository
287             if ( !selectedRepos.contains( repositoryId ) )
288             {
289                 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
290                                                        Response.Status.FORBIDDEN.getStatusCode() );
291             }
292             selectedRepos = Collections.singletonList( repositoryId );
293         }
294
295         RepositorySession repositorySession = null;
296         try
297         {
298             repositorySession = repositorySessionFactory.createSession();
299
300             MetadataResolver metadataResolver = repositorySession.getResolver();
301
302             ProjectVersionMetadata versionMetadata = null;
303             for ( String repoId : selectedRepos )
304             {
305                 if ( versionMetadata == null || versionMetadata.isIncomplete() )
306                 {
307                     try
308                     {
309                         versionMetadata =
310                             metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
311                                                                     version );
312                     }
313                     catch ( MetadataResolutionException e )
314                     {
315                         log.error(
316                             "Skipping invalid metadata while compiling shared model for " + groupId + ":" + artifactId
317                                 + " in repo " + repoId + ": " + e.getMessage() );
318                     }
319                 }
320             }
321
322             return versionMetadata;
323         }
324         finally
325         {
326             if ( repositorySession != null )
327             {
328                 repositorySession.close();
329             }
330         }
331
332     }
333
334     public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
335         throws ArchivaRestServiceException
336     {
337
338         List<String> selectedRepos = getObservableRepos();
339
340         if ( CollectionUtils.isEmpty( selectedRepos ) )
341         {
342             // FIXME 403 ???
343             return null;
344         }
345
346         if ( StringUtils.isNotEmpty( repositoryId ) )
347         {
348             // check user has karma on the repository
349             if ( !selectedRepos.contains( repositoryId ) )
350             {
351                 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
352                                                        Response.Status.FORBIDDEN.getStatusCode() );
353             }
354             selectedRepos = Collections.singletonList( repositoryId );
355         }
356
357         RepositorySession repositorySession = null;
358         try
359         {
360
361             Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
362
363             repositorySession = repositorySessionFactory.createSession();
364
365             MetadataResolver metadataResolver = repositorySession.getResolver();
366
367             ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
368
369             MavenProjectFacet mavenFacet = new MavenProjectFacet();
370             mavenFacet.setGroupId( groupId );
371             mavenFacet.setArtifactId( artifactId );
372             sharedModel.addFacet( mavenFacet );
373
374             boolean isFirstVersion = true;
375
376             for ( String version : projectVersions )
377             {
378                 ProjectVersionMetadata versionMetadata = null;
379                 for ( String repoId : selectedRepos )
380                 {
381                     if ( versionMetadata == null || versionMetadata.isIncomplete() )
382                     {
383                         try
384                         {
385                             versionMetadata =
386                                 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
387                                                                         version );
388                         }
389                         catch ( MetadataResolutionException e )
390                         {
391                             log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
392                                            + artifactId + " in repo " + repoId + ": " + e.getMessage() );
393                         }
394                     }
395                 }
396
397                 if ( versionMetadata == null )
398                 {
399                     continue;
400                 }
401
402                 if ( isFirstVersion )
403                 {
404                     sharedModel = versionMetadata;
405                     sharedModel.setId( null );
406                 }
407                 else
408                 {
409                     MavenProjectFacet versionMetadataMavenFacet =
410                         (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
411                     if ( versionMetadataMavenFacet != null )
412                     {
413                         if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
414                             mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
415                         {
416                             mavenFacet.setPackaging( null );
417                         }
418                     }
419
420                     if ( StringUtils.isEmpty( sharedModel.getName() ) && !StringUtils.isEmpty(
421                         versionMetadata.getName() ) )
422                     {
423                         sharedModel.setName( versionMetadata.getName() );
424                     }
425
426                     if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
427                         sharedModel.getDescription(), versionMetadata.getDescription() ) )
428                     {
429                         sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
430                                                         ? versionMetadata.getDescription()
431                                                         : "" );
432                     }
433
434                     if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
435                         && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
436                                                           versionMetadata.getIssueManagement().getUrl() ) )
437                     {
438                         sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
439                     }
440
441                     if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
442                         && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
443                                                           versionMetadata.getCiManagement().getUrl() ) )
444                     {
445                         sharedModel.setCiManagement( versionMetadata.getCiManagement() );
446                     }
447
448                     if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
449                         && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
450                                                           versionMetadata.getOrganization().getName() ) )
451                     {
452                         sharedModel.setOrganization( versionMetadata.getOrganization() );
453                     }
454
455                     if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
456                                                                                         versionMetadata.getUrl() ) )
457                     {
458                         sharedModel.setUrl( versionMetadata.getUrl() );
459                     }
460                 }
461
462                 isFirstVersion = false;
463             }
464             return sharedModel;
465         }
466         catch ( MetadataResolutionException e )
467         {
468             throw new ArchivaRestServiceException( e.getMessage(),
469                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
470         }
471         finally
472         {
473             if ( repositorySession != null )
474             {
475                 repositorySession.close();
476             }
477         }
478     }
479
480     public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
481         throws ArchivaRestServiceException
482     {
483         List<String> selectedRepos = getObservableRepos();
484
485         if ( CollectionUtils.isEmpty( selectedRepos ) )
486         {
487             // FIXME 403 ???
488             return null;
489         }
490
491         if ( StringUtils.isNotEmpty( repositoryId ) )
492         {
493             // check user has karma on the repository
494             if ( !selectedRepos.contains( repositoryId ) )
495             {
496                 throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
497                                                        Response.Status.FORBIDDEN.getStatusCode() );
498             }
499             selectedRepos = Collections.singletonList( repositoryId );
500         }
501
502         List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
503         TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
504         try
505         {
506             dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version,
507                                                        treeDependencyNodeVisitor );
508         }
509         catch ( DependencyTreeBuilderException e )
510         {
511             throw new ArchivaRestServiceException( e.getMessage(),
512                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
513         }
514         return treeEntries;
515     }
516
517     public List<ManagedRepository> getUserRepositories()
518         throws ArchivaRestServiceException
519     {
520         try
521         {
522             return userRepositories.getAccessibleRepositories( getPrincipal() );
523         }
524         catch ( ArchivaSecurityException e )
525         {
526             throw new ArchivaRestServiceException( "repositories.read.observable.error",
527                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
528         }
529     }
530
531     public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
532         throws ArchivaRestServiceException
533     {
534         List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
535         // TODO: what if we get duplicates across repositories?
536         RepositorySession repositorySession = repositorySessionFactory.createSession();
537         try
538         {
539             MetadataResolver metadataResolver = repositorySession.getResolver();
540             for ( String repoId : getObservableRepos() )
541             {
542                 // TODO: what about if we want to see this irrespective of version?
543                 references.addAll(
544                     metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
545                                                                version ) );
546             }
547         }
548         catch ( MetadataResolutionException e )
549         {
550             throw new ArchivaRestServiceException( e.getMessage(),
551                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
552         }
553         finally
554         {
555             repositorySession.close();
556         }
557
558         List<Artifact> artifacts = new ArrayList<Artifact>( references.size() );
559
560         for ( ProjectVersionReference projectVersionReference : references )
561         {
562             artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
563                                          projectVersionReference.getProjectVersion() ) );
564         }
565         return artifacts;
566     }
567
568     public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
569         throws ArchivaRestServiceException
570     {
571         ProjectVersionMetadata projectVersionMetadata =
572             getProjectMetadata( groupId, artifactId, version, repositoryId );
573         if ( projectVersionMetadata == null )
574         {
575             return Collections.emptyList();
576         }
577         MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
578
579         if ( metadataFacet == null )
580         {
581             return Collections.emptyList();
582         }
583         Map<String, String> map = metadataFacet.toProperties();
584         List<Entry> entries = new ArrayList<Entry>( map.size() );
585
586         for ( Map.Entry<String, String> entry : map.entrySet() )
587         {
588             entries.add( new Entry( entry.getKey(), entry.getValue() ) );
589         }
590
591         return entries;
592     }
593
594     public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
595                                 String repositoryId )
596         throws ArchivaRestServiceException
597     {
598         ProjectVersionMetadata projectVersionMetadata =
599             getProjectMetadata( groupId, artifactId, version, repositoryId );
600
601         if ( projectVersionMetadata == null )
602         {
603             return Boolean.FALSE;
604         }
605
606         Map<String, String> properties = new HashMap<String, String>();
607
608         MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
609
610         if ( metadataFacet != null && metadataFacet.toProperties() != null )
611         {
612             properties.putAll( metadataFacet.toProperties() );
613         }
614         else
615         {
616             metadataFacet = new GenericMetadataFacet();
617         }
618
619         properties.put( key, value );
620
621         metadataFacet.fromProperties( properties );
622
623         projectVersionMetadata.addFacet( metadataFacet );
624
625         RepositorySession repositorySession = repositorySessionFactory.createSession();
626
627         try
628         {
629             MetadataRepository metadataRepository = repositorySession.getRepository();
630
631             metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
632
633             repositorySession.save();
634         }
635         catch ( MetadataRepositoryException e )
636         {
637             log.error( e.getMessage(), e );
638             throw new ArchivaRestServiceException( e.getMessage(),
639                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
640         }
641         finally
642         {
643             repositorySession.close();
644         }
645         return Boolean.TRUE;
646     }
647
648     public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
649         throws ArchivaRestServiceException
650     {
651         ProjectVersionMetadata projectVersionMetadata =
652             getProjectMetadata( groupId, artifactId, version, repositoryId );
653
654         if ( projectVersionMetadata == null )
655         {
656             return Boolean.FALSE;
657         }
658
659         GenericMetadataFacet metadataFacet =
660             (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
661
662         if ( metadataFacet != null && metadataFacet.toProperties() != null )
663         {
664             Map<String, String> properties = metadataFacet.toProperties();
665             properties.remove( key );
666             metadataFacet.setAdditionalProperties( properties );
667         }
668         else
669         {
670             return Boolean.TRUE;
671         }
672
673         RepositorySession repositorySession = repositorySessionFactory.createSession();
674
675         try
676         {
677             MetadataRepository metadataRepository = repositorySession.getRepository();
678
679             metadataRepository.updateProjectVersion( repositoryId, groupId, artifactId, projectVersionMetadata );
680
681             repositorySession.save();
682         }
683         catch ( MetadataRepositoryException e )
684         {
685             log.error( e.getMessage(), e );
686             throw new ArchivaRestServiceException( e.getMessage(),
687                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
688         }
689         finally
690         {
691             repositorySession.close();
692         }
693         return Boolean.TRUE;
694     }
695
696     public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
697                                                                  String path, String repositoryId )
698         throws ArchivaRestServiceException
699     {
700         return null;
701     }
702
703     //---------------------------
704     // internals
705     //---------------------------
706
707     private List<String> getSortedList( Set<String> set )
708     {
709         List<String> list = new ArrayList<String>( set );
710         Collections.sort( list );
711         return list;
712     }
713
714     private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
715                                        Collection<String> repoIds, String n )
716         throws MetadataResolutionException
717     {
718         Set<String> subNamespaces = new LinkedHashSet<String>();
719         for ( String repoId : repoIds )
720         {
721             subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
722         }
723         if ( subNamespaces.size() != 1 )
724         {
725             log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
726             return n;
727         }
728         else
729         {
730             for ( String repoId : repoIds )
731             {
732                 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
733                 if ( projects != null && !projects.isEmpty() )
734                 {
735                     log.debug( "{} is not collapsible as it has projects", n );
736                     return n;
737                 }
738             }
739             return collapseNamespaces( repositorySession, metadataResolver, repoIds,
740                                        n + "." + subNamespaces.iterator().next() );
741         }
742     }
743 }