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.beans.ManagedRepository; 024import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 025import org.apache.archiva.metadata.repository.MetadataRepository; 026import org.apache.archiva.metadata.repository.MetadataRepositoryException; 027import org.apache.archiva.metadata.repository.RepositorySession; 028import org.apache.archiva.metadata.repository.RepositorySessionFactory; 029import org.apache.archiva.metadata.repository.stats.RepositoryStatistics; 030import org.apache.archiva.metadata.repository.stats.RepositoryStatisticsManager; 031import org.apache.archiva.repository.scanner.RepositoryContentConsumers; 032import org.apache.archiva.repository.scanner.RepositoryScanStatistics; 033import org.apache.archiva.repository.scanner.RepositoryScanner; 034import org.apache.archiva.repository.scanner.RepositoryScannerException; 035import org.apache.archiva.scheduler.repository.model.RepositoryTask; 036import org.apache.commons.lang.StringUtils; 037import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; 038import org.apache.archiva.redback.components.taskqueue.Task; 039import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutionException; 040import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutor; 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 private ManagedRepositoryAdmin managedRepositoryAdmin; 062 063 @Inject 064 private RepositoryScanner repoScanner; 065 066 @Inject 067 private RepositoryContentConsumers consumers; 068 069 private Task task; 070 071 @Inject 072 private RepositoryStatisticsManager repositoryStatisticsManager; 073 074 /** 075 * FIXME: this could be multiple implementations and needs to be configured. 076 */ 077 @Inject 078 private RepositorySessionFactory repositorySessionFactory; 079 080 @PostConstruct 081 public void initialize() 082 throws InitializationException 083 { 084 log.info( "Initialized {}", this.getClass().getName() ); 085 } 086 087 @SuppressWarnings( "unchecked" ) 088 @Override 089 public void executeTask( RepositoryTask task ) 090 throws TaskExecutionException 091 { 092 try 093 { 094 // TODO: replace this whole class with the prescribed content scanning service/action 095 // - scan repository for artifacts that do not have corresponding metadata or have been updated and 096 // send events for each 097 // - scan metadata for artifacts that have been removed and send events for each 098 // - scan metadata for missing plugin data 099 // - store information so that it can restart upon failure (publish event on the server recovery 100 // queue, remove it on successful completion) 101 102 this.task = task; 103 104 String repoId = task.getRepositoryId(); 105 if ( StringUtils.isBlank( repoId ) ) 106 { 107 throw new TaskExecutionException( "Unable to execute RepositoryTask with blank repository Id." ); 108 } 109 110 ManagedRepository arepo = managedRepositoryAdmin.getManagedRepository( repoId ); 111 112 // execute consumers on resource file if set 113 if ( task.getResourceFile() != null ) 114 { 115 log.debug( "Executing task from queue with job name: {}", task ); 116 consumers.executeConsumers( arepo, task.getResourceFile(), task.isUpdateRelatedArtifacts() ); 117 } 118 else 119 { 120 log.info( "Executing task from queue with job name: {}", task ); 121 122 // otherwise, execute consumers on whole repository 123 if ( arepo == null ) 124 { 125 throw new TaskExecutionException( 126 "Unable to execute RepositoryTask with invalid repository id: " + repoId ); 127 } 128 129 long sinceWhen = RepositoryScanner.FRESH_SCAN; 130 long previousFileCount = 0; 131 132 RepositorySession repositorySession = repositorySessionFactory.createSession(); 133 MetadataRepository metadataRepository = repositorySession.getRepository(); 134 try 135 { 136 if ( !task.isScanAll() ) 137 { 138 RepositoryStatistics previousStats = 139 repositoryStatisticsManager.getLastStatistics( metadataRepository, repoId ); 140 if ( previousStats != null ) 141 { 142 sinceWhen = previousStats.getScanStartTime().getTime(); 143 previousFileCount = previousStats.getTotalFileCount(); 144 } 145 } 146 147 RepositoryScanStatistics stats; 148 try 149 { 150 stats = repoScanner.scan( arepo, sinceWhen ); 151 } 152 catch ( RepositoryScannerException e ) 153 { 154 throw new TaskExecutionException( "Repository error when executing repository job.", e ); 155 } 156 157 log.info( "Finished first scan: {}", stats.toDump( arepo ) ); 158 159 // further statistics will be populated by the following method 160 Date endTime = new Date( stats.getWhenGathered().getTime() + stats.getDuration() ); 161 162 log.info( "Gathering repository statistics" ); 163 164 repositoryStatisticsManager.addStatisticsAfterScan( metadataRepository, repoId, 165 stats.getWhenGathered(), endTime, 166 stats.getTotalFileCount(), 167 stats.getTotalFileCount() - previousFileCount ); 168 repositorySession.save(); 169 } 170 catch ( MetadataRepositoryException e ) 171 { 172 throw new TaskExecutionException( "Unable to store updated statistics: " + e.getMessage(), e ); 173 } 174 finally 175 { 176 repositorySession.close(); 177 } 178 179// log.info( "Scanning for removed repository content" ); 180 181// metadataRepository.findAllProjects(); 182 // FIXME: do something 183 184 log.info( "Finished repository task: {}", task ); 185 186 this.task = null; 187 } 188 } 189 catch ( RepositoryAdminException e ) 190 { 191 log.error( e.getMessage(), e ); 192 throw new TaskExecutionException( e.getMessage(), e ); 193 } 194 } 195 196 public Task getCurrentTaskInExecution() 197 { 198 return task; 199 } 200 201 public RepositoryScanner getRepoScanner() 202 { 203 return repoScanner; 204 } 205 206 public void setRepoScanner( RepositoryScanner repoScanner ) 207 { 208 this.repoScanner = repoScanner; 209 } 210 211 public RepositoryContentConsumers getConsumers() 212 { 213 return consumers; 214 } 215 216 public void setConsumers( RepositoryContentConsumers consumers ) 217 { 218 this.consumers = consumers; 219 } 220 221 public RepositorySessionFactory getRepositorySessionFactory() 222 { 223 return repositorySessionFactory; 224 } 225 226 public void setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory ) 227 { 228 this.repositorySessionFactory = repositorySessionFactory; 229 } 230 231 public RepositoryStatisticsManager getRepositoryStatisticsManager() 232 { 233 return repositoryStatisticsManager; 234 } 235 236 public void setRepositoryStatisticsManager( RepositoryStatisticsManager repositoryStatisticsManager ) 237 { 238 this.repositoryStatisticsManager = repositoryStatisticsManager; 239 } 240 241 public ManagedRepositoryAdmin getManagedRepositoryAdmin() 242 { 243 return managedRepositoryAdmin; 244 } 245 246 public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin ) 247 { 248 this.managedRepositoryAdmin = managedRepositoryAdmin; 249 } 250}