001package org.apache.archiva.scheduler.repository; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.apache.archiva.admin.model.RepositoryAdminException; 023import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 024import org.apache.archiva.metadata.repository.MetadataRepository; 025import org.apache.archiva.metadata.repository.MetadataRepositoryException; 026import org.apache.archiva.metadata.repository.RepositorySession; 027import org.apache.archiva.metadata.repository.RepositorySessionFactory; 028import org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics; 029import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager; 030import org.apache.archiva.components.taskqueue.Task; 031import org.apache.archiva.components.taskqueue.execution.TaskExecutionException; 032import org.apache.archiva.components.taskqueue.execution.TaskExecutor; 033import org.apache.archiva.repository.ManagedRepository; 034import org.apache.archiva.repository.RepositoryRegistry; 035import org.apache.archiva.repository.scanner.RepositoryContentConsumers; 036import org.apache.archiva.repository.scanner.RepositoryScanStatistics; 037import org.apache.archiva.repository.scanner.RepositoryScanner; 038import org.apache.archiva.repository.scanner.RepositoryScannerException; 039import org.apache.archiva.scheduler.repository.model.RepositoryTask; 040import org.apache.commons.lang3.StringUtils; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043import org.springframework.stereotype.Service; 044 045import javax.annotation.PostConstruct; 046import javax.inject.Inject; 047import java.util.Date; 048 049/** 050 * ArchivaRepositoryScanningTaskExecutor 051 * 052 * 053 */ 054@Service( "taskExecutor#repository-scanning" ) 055public class ArchivaRepositoryScanningTaskExecutor 056 implements TaskExecutor<RepositoryTask> 057{ 058 private Logger log = LoggerFactory.getLogger( ArchivaRepositoryScanningTaskExecutor.class ); 059 060 @Inject 061 RepositoryRegistry repositoryRegistry; 062 063 @Inject 064 private ManagedRepositoryAdmin managedRepositoryAdmin; 065 066 @Inject 067 private RepositoryScanner repoScanner; 068 069 @Inject 070 private RepositoryContentConsumers consumers; 071 072 private Task task; 073 074 @Inject 075 private RepositoryStatisticsManager repositoryStatisticsManager; 076 077 /** 078 * FIXME: this could be multiple implementations and needs to be configured. 079 */ 080 @Inject 081 private RepositorySessionFactory repositorySessionFactory; 082 083 @PostConstruct 084 public void initialize() 085 { 086 log.info( "Initialized {}", this.getClass().getName() ); 087 } 088 089 @SuppressWarnings( "unchecked" ) 090 @Override 091 public void executeTask( RepositoryTask task ) 092 throws TaskExecutionException 093 { 094 try 095 { 096 // TODO: replace this whole class with the prescribed content scanning service/action 097 // - scan repository for artifacts that do not have corresponding metadata or have been updated and 098 // send events for each 099 // - scan metadata for artifacts that have been removed and send events for each 100 // - scan metadata for missing plugin data 101 // - store information so that it can restart upon failure (publish event on the server recovery 102 // queue, remove it on successful completion) 103 104 this.task = task; 105 106 String repoId = task.getRepositoryId(); 107 if ( StringUtils.isBlank( repoId ) ) 108 { 109 throw new TaskExecutionException( "Unable to execute RepositoryTask with blank repository Id." ); 110 } 111 112 ManagedRepository arepo = repositoryRegistry.getManagedRepository( repoId ); 113 114 // execute consumers on resource file if set 115 if ( task.getResourceFile() != null ) 116 { 117 log.debug( "Executing task from queue with job name: {}", task ); 118 if (task.getResourceFile().isFileBased()) 119 { 120 consumers.executeConsumers( arepo, task.getResourceFile( ).getFilePath(), task.isUpdateRelatedArtifacts( ) ); 121 } 122 } 123 else 124 { 125 log.info( "Executing task from queue with job name: {}", task ); 126 127 // otherwise, execute consumers on whole repository 128 if ( arepo == null ) 129 { 130 throw new TaskExecutionException( 131 "Unable to execute RepositoryTask with invalid repository id: " + repoId ); 132 } 133 134 long sinceWhen = RepositoryScanner.FRESH_SCAN; 135 long previousFileCount = 0; 136 137 RepositorySession repositorySession = repositorySessionFactory.createSession(); 138 MetadataRepository metadataRepository = repositorySession.getRepository(); 139 try 140 { 141 if ( !task.isScanAll() ) 142 { 143 RepositoryStatistics previousStats = 144 repositoryStatisticsManager.getLastStatistics( repoId ); 145 if ( previousStats != null ) 146 { 147 sinceWhen = previousStats.getScanStartTime().getTime(); 148 previousFileCount = previousStats.getTotalFileCount(); 149 } 150 } 151 152 RepositoryScanStatistics stats; 153 try 154 { 155 stats = repoScanner.scan( arepo, sinceWhen ); 156 } 157 catch ( RepositoryScannerException e ) 158 { 159 throw new TaskExecutionException( "Repository error when executing repository job.", e ); 160 } 161 162 log.info( "Finished first scan: {}", stats.toDump( arepo ) ); 163 164 // further statistics will be populated by the following method 165 Date endTime = new Date( stats.getWhenGathered().getTime() + stats.getDuration() ); 166 167 log.info( "Gathering repository statistics" ); 168 169 repositoryStatisticsManager.addStatisticsAfterScan( repoId, 170 stats.getWhenGathered(), endTime, 171 stats.getTotalFileCount(), 172 stats.getTotalFileCount() - previousFileCount ); 173 repositorySession.save(); 174 } 175 catch ( MetadataRepositoryException e ) 176 { 177 throw new TaskExecutionException( "Unable to store updated statistics: " + e.getMessage(), e ); 178 } 179 catch ( org.apache.archiva.metadata.repository.MetadataSessionException e ) 180 { 181 e.printStackTrace( ); 182 } 183 finally 184 { 185 repositorySession.close(); 186 } 187 188// log.info( "Scanning for removed repository content" ); 189 190// metadataRepository.findAllProjects(); 191 // FIXME: do something 192 193 log.info( "Finished repository task: {}", task ); 194 195 this.task = null; 196 } 197 } 198 catch ( RepositoryAdminException e ) 199 { 200 log.error( e.getMessage(), e ); 201 throw new TaskExecutionException( e.getMessage(), e ); 202 } 203 catch ( MetadataRepositoryException e ) 204 { 205 e.printStackTrace( ); 206 } 207 } 208 209 public Task getCurrentTaskInExecution() 210 { 211 return task; 212 } 213 214 public RepositoryScanner getRepoScanner() 215 { 216 return repoScanner; 217 } 218 219 public void setRepoScanner( RepositoryScanner repoScanner ) 220 { 221 this.repoScanner = repoScanner; 222 } 223 224 public RepositoryContentConsumers getConsumers() 225 { 226 return consumers; 227 } 228 229 public void setConsumers( RepositoryContentConsumers consumers ) 230 { 231 this.consumers = consumers; 232 } 233 234 public RepositorySessionFactory getRepositorySessionFactory() 235 { 236 return repositorySessionFactory; 237 } 238 239 public void setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory ) 240 { 241 this.repositorySessionFactory = repositorySessionFactory; 242 } 243 244 public RepositoryStatisticsManager getRepositoryStatisticsManager() 245 { 246 return repositoryStatisticsManager; 247 } 248 249 public void setRepositoryStatisticsManager( RepositoryStatisticsManager repositoryStatisticsManager ) 250 { 251 this.repositoryStatisticsManager = repositoryStatisticsManager; 252 } 253 254 public ManagedRepositoryAdmin getManagedRepositoryAdmin() 255 { 256 return managedRepositoryAdmin; 257 } 258 259 public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin ) 260 { 261 this.managedRepositoryAdmin = managedRepositoryAdmin; 262 } 263}