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.metadata.model.ProjectVersionMetadata;
22 import org.apache.archiva.metadata.repository.MetadataResolutionException;
23 import org.apache.archiva.metadata.repository.MetadataResolver;
24 import org.apache.archiva.metadata.repository.RepositorySession;
25 import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
26 import org.apache.archiva.rest.api.model.BrowseResult;
27 import org.apache.archiva.rest.api.model.BrowseResultEntry;
28 import org.apache.archiva.rest.api.model.VersionsList;
29 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
30 import org.apache.archiva.rest.api.services.BrowseService;
31 import org.apache.commons.collections.CollectionUtils;
32 import org.apache.commons.lang.StringUtils;
33 import org.springframework.stereotype.Service;
35 import javax.ws.rs.core.Response;
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.LinkedHashSet;
40 import java.util.List;
44 * @author Olivier Lamy
47 @Service( "browseService#rest" )
48 public class DefaultBrowseService
49 extends AbstractRestService
50 implements BrowseService
53 public BrowseResult getRootGroups()
54 throws ArchivaRestServiceException
56 List<String> selectedRepos = getObservableRepos();
57 if ( CollectionUtils.isEmpty( selectedRepos ) )
60 return new BrowseResult();
63 Set<String> namespaces = new LinkedHashSet<String>();
65 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
66 // it is located here to avoid the content repository implementation needing to do too much for what
67 // is essentially presentation code
68 Set<String> namespacesToCollapse;
69 RepositorySession repositorySession = repositorySessionFactory.createSession();
72 MetadataResolver metadataResolver = repositorySession.getResolver();
73 namespacesToCollapse = new LinkedHashSet<String>();
74 for ( String repoId : selectedRepos )
76 namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
78 for ( String n : namespacesToCollapse )
80 // TODO: check performance of this
81 namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
84 catch ( MetadataResolutionException e )
86 throw new ArchivaRestServiceException( e.getMessage(),
87 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
91 repositorySession.close();
94 List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<BrowseResultEntry>( namespaces.size() );
95 for ( String namespace : namespaces )
97 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
100 Collections.sort( browseGroupResultEntries );
101 return new BrowseResult( browseGroupResultEntries );
104 public BrowseResult browseGroupId( String groupId )
105 throws ArchivaRestServiceException
108 List<String> selectedRepos = getObservableRepos();
109 if ( CollectionUtils.isEmpty( selectedRepos ) )
112 return new BrowseResult();
115 Set<String> projects = new LinkedHashSet<String>();
117 RepositorySession repositorySession = repositorySessionFactory.createSession();
118 Set<String> namespaces;
121 MetadataResolver metadataResolver = repositorySession.getResolver();
123 Set<String> namespacesToCollapse = new LinkedHashSet<String>();
124 for ( String repoId : selectedRepos )
126 namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
128 projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
131 // TODO: this logic should be optional, particularly remembering we want to keep this code simple
132 // it is located here to avoid the content repository implementation needing to do too much for what
133 // is essentially presentation code
134 namespaces = new LinkedHashSet<String>();
135 for ( String n : namespacesToCollapse )
137 // TODO: check performance of this
139 collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
142 catch ( MetadataResolutionException e )
144 throw new ArchivaRestServiceException( e.getMessage(),
145 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
149 repositorySession.close();
151 List<BrowseResultEntry> browseGroupResultEntries =
152 new ArrayList<BrowseResultEntry>( namespaces.size() + projects.size() );
153 for ( String namespace : namespaces )
155 browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
157 for ( String project : projects )
159 browseGroupResultEntries.add( new BrowseResultEntry( groupId + '.' + project, true ) );
161 Collections.sort( browseGroupResultEntries );
162 return new BrowseResult( browseGroupResultEntries );
166 public VersionsList getVersionsList( String groupId, String artifactId )
167 throws ArchivaRestServiceException
169 List<String> selectedRepos = getObservableRepos();
170 if ( CollectionUtils.isEmpty( selectedRepos ) )
173 return new VersionsList();
178 return new VersionsList( new ArrayList<String>( getVersions( selectedRepos, groupId, artifactId ) ) );
180 catch ( MetadataResolutionException e )
182 throw new ArchivaRestServiceException( e.getMessage(),
183 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
188 private Set<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
189 throws MetadataResolutionException
192 RepositorySession repositorySession = repositorySessionFactory.createSession();
195 MetadataResolver metadataResolver = repositorySession.getResolver();
197 Set<String> versions = new LinkedHashSet<String>();
199 for ( String repoId : selectedRepos )
202 metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId ) );
209 repositorySession.close();
213 public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId )
214 throws ArchivaRestServiceException
217 List<String> selectedRepos = getObservableRepos();
219 if ( CollectionUtils.isEmpty( selectedRepos ) )
225 RepositorySession repositorySession = null;
229 Set<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
231 repositorySession = repositorySessionFactory.createSession();
233 MetadataResolver metadataResolver = repositorySession.getResolver();
235 ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
237 MavenProjectFacet mavenFacet = new MavenProjectFacet();
238 mavenFacet.setGroupId( groupId );
239 mavenFacet.setArtifactId( artifactId );
240 sharedModel.addFacet( mavenFacet );
242 boolean isFirstVersion = true;
244 for ( String version : projectVersions )
246 ProjectVersionMetadata versionMetadata = null;
247 for ( String repoId : selectedRepos )
249 if ( versionMetadata == null )
254 metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
257 catch ( MetadataResolutionException e )
259 log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
260 + artifactId + " in repo " + repoId + ": " + e.getMessage() );
265 if ( versionMetadata == null )
270 if ( isFirstVersion )
272 sharedModel = versionMetadata;
273 sharedModel.setId( null );
277 MavenProjectFacet versionMetadataMavenFacet =
278 (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
279 if ( versionMetadataMavenFacet != null )
281 if ( mavenFacet.getPackaging() != null && !StringUtils.equalsIgnoreCase(
282 mavenFacet.getPackaging(), versionMetadataMavenFacet.getPackaging() ) )
284 mavenFacet.setPackaging( null );
288 if ( sharedModel.getName() != null && !StringUtils.equalsIgnoreCase( sharedModel.getName(),
289 versionMetadata.getName() ) )
291 sharedModel.setName( "" );
294 if ( sharedModel.getDescription() != null && !StringUtils.equalsIgnoreCase(
295 sharedModel.getDescription(), versionMetadata.getDescription() ) )
297 sharedModel.setDescription( null );
300 if ( sharedModel.getIssueManagement() != null && versionMetadata.getIssueManagement() != null
301 && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
302 versionMetadata.getIssueManagement().getUrl() ) )
304 sharedModel.setIssueManagement( null );
307 if ( sharedModel.getCiManagement() != null && versionMetadata.getCiManagement() != null
308 && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
309 versionMetadata.getCiManagement().getUrl() ) )
311 sharedModel.setCiManagement( null );
314 if ( sharedModel.getOrganization() != null && versionMetadata.getOrganization() != null
315 && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
316 versionMetadata.getOrganization().getName() ) )
318 sharedModel.setOrganization( null );
321 if ( sharedModel.getUrl() != null && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(),
322 versionMetadata.getUrl() ) )
324 sharedModel.setUrl( null );
328 isFirstVersion = false;
332 catch ( MetadataResolutionException e )
334 throw new ArchivaRestServiceException( e.getMessage(),
335 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
339 if ( repositorySession != null )
341 repositorySession.close();
346 //---------------------------
348 //---------------------------
350 private List<String> getSortedList( Set<String> set )
352 List<String> list = new ArrayList<String>( set );
353 Collections.sort( list );
357 private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
358 Collection<String> repoIds, String n )
359 throws MetadataResolutionException
361 Set<String> subNamespaces = new LinkedHashSet<String>();
362 for ( String repoId : repoIds )
364 subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
366 if ( subNamespaces.size() != 1 )
368 log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
373 for ( String repoId : repoIds )
375 Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
376 if ( projects != null && !projects.isEmpty() )
378 log.debug( "{} is not collapsible as it has projects", n );
382 return collapseNamespaces( repositorySession, metadataResolver, repoIds,
383 n + "." + subNamespaces.iterator().next() );