1 package org.apache.archiva.rest.services.v2;
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
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
20 import org.apache.archiva.admin.model.RepositoryAdminException;
21 import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration;
22 import org.apache.archiva.components.rest.model.PagedResult;
23 import org.apache.archiva.components.rest.util.QueryHelper;
24 import org.apache.archiva.components.rest.util.RestUtil;
25 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
26 import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
27 import org.apache.archiva.repository.RemoteRepository;
28 import org.apache.archiva.repository.RepositoryRegistry;
29 import org.apache.archiva.repository.scanner.RepositoryScanner;
30 import org.apache.archiva.repository.scanner.RepositoryScannerException;
31 import org.apache.archiva.rest.api.model.v2.Repository;
32 import org.apache.archiva.rest.api.model.v2.RepositoryStatistics;
33 import org.apache.archiva.rest.api.model.v2.ScanStatus;
34 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
35 import org.apache.archiva.rest.api.services.v2.ErrorKeys;
36 import org.apache.archiva.rest.api.services.v2.ErrorMessage;
37 import org.apache.archiva.rest.api.services.v2.RepositoryService;
38 import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException;
39 import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
40 import org.apache.commons.lang3.StringUtils;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.springframework.stereotype.Service;
45 import javax.inject.Named;
46 import javax.ws.rs.core.Response;
47 import javax.ws.rs.core.UriInfo;
48 import java.util.Comparator;
49 import java.util.List;
50 import java.util.Locale;
51 import java.util.function.Predicate;
52 import java.util.stream.Collectors;
55 * @author Martin Stockhammer <martin_s@apache.org>
58 @Service( "v2.repositoryService#rest" )
59 public class DefaultRepositoryService implements RepositoryService
63 RepositoryRegistry repositoryRegistry;
66 RepositoryStatisticsManager repositoryStatisticsManager;
68 private final RepositoryTaskAdministration repositoryTaskAdministration;
70 private final RepositoryScanner repoScanner;
72 private final DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;
74 private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryService.class );
75 private static final QueryHelper<org.apache.archiva.repository.Repository> QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
79 QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.Repository::getId );
80 QUERY_HELPER.addStringFilter( "name", org.apache.archiva.repository.Repository::getName );
81 QUERY_HELPER.addStringFilter( "description", org.apache.archiva.repository.Repository::getDescription );
82 QUERY_HELPER.addStringFilter( "type", repo -> repo.getType( ).name( ) );
83 QUERY_HELPER.addBooleanFilter( "scanned", org.apache.archiva.repository.Repository::isScanned );
84 QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.Repository::getId );
85 QUERY_HELPER.addNullsafeFieldComparator( "name", org.apache.archiva.repository.Repository::getName );
86 QUERY_HELPER.addNullsafeFieldComparator( "type", repo -> repo.getType( ).name( ) );
87 QUERY_HELPER.addNullsafeFieldComparator( "boolean", org.apache.archiva.repository.Repository::isScanned );
90 public DefaultRepositoryService( RepositoryRegistry repositoryRegistry, RepositoryStatisticsManager repositoryStatisticsManager,
91 @Named( value = "repositoryTaskAdministration#default") RepositoryTaskAdministration repositoryTaskAdministration,
92 RepositoryScanner repoScanner, DownloadRemoteIndexScheduler downloadRemoteIndexScheduler )
94 this.repositoryRegistry = repositoryRegistry;
95 this.repositoryStatisticsManager = repositoryStatisticsManager;
96 this.repoScanner = repoScanner;
97 this.repositoryTaskAdministration = repositoryTaskAdministration;
98 this.downloadRemoteIndexScheduler = downloadRemoteIndexScheduler;
101 private void handleAdminException( RepositoryAdminException e ) throws ArchivaRestServiceException
103 log.error( "Repository admin error: {}", e.getMessage( ), e );
104 if ( e.keyExists( ) )
106 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PREFIX + e.getKey( ), e.getParameters( ) ) );
110 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
116 public PagedResult<Repository> getRepositories( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order,
117 String localeString ) throws ArchivaRestServiceException
119 final Locale locale = StringUtils.isNotEmpty( localeString ) ? Locale.forLanguageTag( localeString ) : Locale.getDefault( );
120 boolean isAscending = QUERY_HELPER.isAscending( order );
121 Predicate<org.apache.archiva.repository.Repository> filter = QUERY_HELPER.getQueryFilter( searchTerm );
122 Comparator<org.apache.archiva.repository.Repository> comparator = QUERY_HELPER.getComparator( orderBy, isAscending );
125 int totalCount = Math.toIntExact( repositoryRegistry.getRepositories( ).stream( ).filter( filter ).count( ) );
126 return new PagedResult<>( totalCount, offset, limit, repositoryRegistry.getRepositories( ).stream( )
127 .filter( filter ).skip( offset ).limit( limit ).sorted( comparator ).map( repo -> Repository.of( repo, locale ) )
128 .collect( Collectors.toList( ) ) );
130 catch ( ArithmeticException e )
132 log.error( "Invalid integer conversion for totalCount" );
133 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
138 public RepositoryStatistics getManagedRepositoryStatistics( String repositoryId ) throws ArchivaRestServiceException
140 if ( repositoryRegistry.getManagedRepository( repositoryId ) == null )
142 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_MANAGED_NOT_FOUND, repositoryId ), 404 );
146 return RepositoryStatistics.of( repositoryStatisticsManager.getLastStatistics( repositoryId ) );
148 catch ( MetadataRepositoryException e )
150 log.error( "Metadata error: {} ", e.getMessage( ), e );
151 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_METADATA_ERROR, e.getMessage( ) ) );
156 public Response scheduleRepositoryScan( String repositoryId, boolean fullScan ) throws ArchivaRestServiceException
160 repositoryTaskAdministration.scheduleFullScan( repositoryId );
161 return Response.ok( ).build( );
163 catch ( RepositoryAdminException e )
165 handleAdminException( e );
166 return Response.serverError( ).build( );
171 public RepositoryStatistics scanRepositoryImmediately( String repositoryId ) throws ArchivaRestServiceException
173 long sinceWhen = RepositoryScanner.FRESH_SCAN;
176 return RepositoryStatistics.of( repoScanner.scan( repositoryRegistry.getManagedRepository( repositoryId ), sinceWhen ) );
178 catch ( RepositoryScannerException e )
180 log.error( e.getMessage( ), e );
181 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage( ) ) );
186 public ScanStatus getScanStatus( String repositoryId ) throws ArchivaRestServiceException
190 return ScanStatus.of( repositoryTaskAdministration.getCurrentScanStatus( ) );
192 catch ( RepositoryAdminException e )
194 handleAdminException( e );
195 return new ScanStatus();
200 public Response removeScanningTaskFromQueue( String repositoryId ) throws ArchivaRestServiceException
204 repositoryTaskAdministration.cancelTasks( repositoryId );
205 return Response.ok( ).build( );
207 catch ( RepositoryAdminException e )
209 handleAdminException( e );
210 return Response.serverError( ).build( );
216 public Response scheduleDownloadRemoteIndex( String repositoryId, boolean immediately, boolean full,
217 UriInfo uriInfo ) throws ArchivaRestServiceException
219 boolean immediateSet = RestUtil.isFlagSet( uriInfo, "immediate" );
220 boolean fullSet = RestUtil.isFlagSet( uriInfo, "full" );
221 RemoteRepository repo = repositoryRegistry.getRemoteRepository( repositoryId );
223 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_NOT_FOUND, repositoryId ), 404 );
227 downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, immediateSet, fullSet );
228 return Response.ok( ).build( );
230 catch ( DownloadRemoteIndexException e )
232 log.error( "Could not schedule index download for repository {}: {}", repositoryId, e.getMessage(), e );
233 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED, e.getMessage( ) ) );
240 public List<String> getRunningRemoteDownloads( )
242 return downloadRemoteIndexScheduler.getRunningRemoteDownloadIds( );