001 package 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 022 import org.apache.archiva.admin.model.RepositoryAdminException; 023 import org.apache.archiva.admin.model.beans.ManagedRepository; 024 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 025 import org.apache.archiva.metadata.repository.MetadataRepository; 026 import org.apache.archiva.metadata.repository.MetadataRepositoryException; 027 import org.apache.archiva.metadata.repository.RepositorySession; 028 import org.apache.archiva.metadata.repository.RepositorySessionFactory; 029 import org.apache.archiva.metadata.repository.stats.RepositoryStatistics; 030 import org.apache.archiva.metadata.repository.stats.RepositoryStatisticsManager; 031 import org.apache.archiva.repository.scanner.RepositoryContentConsumers; 032 import org.apache.archiva.repository.scanner.RepositoryScanStatistics; 033 import org.apache.archiva.repository.scanner.RepositoryScanner; 034 import org.apache.archiva.repository.scanner.RepositoryScannerException; 035 import org.apache.archiva.scheduler.repository.model.RepositoryTask; 036 import org.apache.commons.lang.StringUtils; 037 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; 038 import org.apache.archiva.redback.components.taskqueue.Task; 039 import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutionException; 040 import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutor; 041 import org.slf4j.Logger; 042 import org.slf4j.LoggerFactory; 043 import org.springframework.stereotype.Service; 044 045 import javax.annotation.PostConstruct; 046 import javax.inject.Inject; 047 import java.util.Date; 048 049 /** 050 * ArchivaRepositoryScanningTaskExecutor 051 * 052 * 053 */ 054 @Service( "taskExecutor#repository-scanning" ) 055 public class ArchivaRepositoryScanningTaskExecutor 056 implements TaskExecutor 057 { 058 private Logger log = LoggerFactory.getLogger( ArchivaRepositoryScanningTaskExecutor.class ); 059 060 /** 061 * 062 */ 063 @Inject 064 private ManagedRepositoryAdmin managedRepositoryAdmin; 065 066 /** 067 * The repository scanner component. 068 */ 069 @Inject 070 private RepositoryScanner repoScanner; 071 072 /** 073 * 074 */ 075 @Inject 076 private RepositoryContentConsumers consumers; 077 078 private Task task; 079 080 /** 081 * 082 */ 083 @Inject 084 private RepositoryStatisticsManager repositoryStatisticsManager; 085 086 /** 087 * FIXME: this could be multiple implementations and needs to be configured. 088 */ 089 @Inject 090 private RepositorySessionFactory repositorySessionFactory; 091 092 @PostConstruct 093 public void initialize() 094 throws InitializationException 095 { 096 log.info( "Initialized {}", this.getClass().getName() ); 097 } 098 099 @SuppressWarnings( "unchecked" ) 100 public void executeTask( Task task ) 101 throws TaskExecutionException 102 { 103 try 104 { 105 // TODO: replace this whole class with the prescribed content scanning service/action 106 // - scan repository for artifacts that do not have corresponding metadata or have been updated and 107 // send events for each 108 // - scan metadata for artifacts that have been removed and send events for each 109 // - scan metadata for missing plugin data 110 // - store information so that it can restart upon failure (publish event on the server recovery 111 // queue, remove it on successful completion) 112 113 this.task = task; 114 115 RepositoryTask repoTask = (RepositoryTask) task; 116 117 String repoId = repoTask.getRepositoryId(); 118 if ( StringUtils.isBlank( repoId ) ) 119 { 120 throw new TaskExecutionException( "Unable to execute RepositoryTask with blank repository Id." ); 121 } 122 123 ManagedRepository arepo = managedRepositoryAdmin.getManagedRepository( repoId ); 124 125 // execute consumers on resource file if set 126 if ( repoTask.getResourceFile() != null ) 127 { 128 log.debug( "Executing task from queue with job name: {}", repoTask ); 129 consumers.executeConsumers( arepo, repoTask.getResourceFile(), repoTask.isUpdateRelatedArtifacts() ); 130 } 131 else 132 { 133 log.info( "Executing task from queue with job name: {}", repoTask ); 134 135 // otherwise, execute consumers on whole repository 136 if ( arepo == null ) 137 { 138 throw new TaskExecutionException( 139 "Unable to execute RepositoryTask with invalid repository id: " + repoId ); 140 } 141 142 long sinceWhen = RepositoryScanner.FRESH_SCAN; 143 long previousFileCount = 0; 144 145 RepositorySession repositorySession = repositorySessionFactory.createSession(); 146 MetadataRepository metadataRepository = repositorySession.getRepository(); 147 try 148 { 149 if ( !repoTask.isScanAll() ) 150 { 151 RepositoryStatistics previousStats = 152 repositoryStatisticsManager.getLastStatistics( metadataRepository, repoId ); 153 if ( previousStats != null ) 154 { 155 sinceWhen = previousStats.getScanStartTime().getTime(); 156 previousFileCount = previousStats.getTotalFileCount(); 157 } 158 } 159 160 RepositoryScanStatistics stats; 161 try 162 { 163 stats = repoScanner.scan( arepo, sinceWhen ); 164 } 165 catch ( RepositoryScannerException e ) 166 { 167 throw new TaskExecutionException( "Repository error when executing repository job.", e ); 168 } 169 170 log.info( "Finished first scan: {}", stats.toDump( arepo ) ); 171 172 // further statistics will be populated by the following method 173 Date endTime = new Date( stats.getWhenGathered().getTime() + stats.getDuration() ); 174 175 log.info( "Gathering repository statistics" ); 176 177 repositoryStatisticsManager.addStatisticsAfterScan( metadataRepository, repoId, 178 stats.getWhenGathered(), endTime, 179 stats.getTotalFileCount(), 180 stats.getTotalFileCount() - previousFileCount ); 181 repositorySession.save(); 182 } 183 catch ( MetadataRepositoryException e ) 184 { 185 throw new TaskExecutionException( "Unable to store updated statistics: " + e.getMessage(), e ); 186 } 187 finally 188 { 189 repositorySession.close(); 190 } 191 192 // log.info( "Scanning for removed repository content" ); 193 194 // metadataRepository.findAllProjects(); 195 // FIXME: do something 196 197 log.info( "Finished repository task: {}", repoTask ); 198 199 this.task = null; 200 } 201 } 202 catch ( RepositoryAdminException e ) 203 { 204 log.error( e.getMessage(), e ); 205 throw new TaskExecutionException( e.getMessage(), e ); 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 }