You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MetadataUpdaterConsumer.java 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. package org.apache.archiva.consumers.core;
  2. /*
  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
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  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
  18. * under the License.
  19. */
  20. import org.apache.archiva.configuration.ArchivaConfiguration;
  21. import org.apache.archiva.configuration.FileTypes;
  22. import org.apache.archiva.consumers.AbstractMonitoredConsumer;
  23. import org.apache.archiva.consumers.ConsumerException;
  24. import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
  25. import org.apache.archiva.model.ArtifactReference;
  26. import org.apache.archiva.model.ProjectReference;
  27. import org.apache.archiva.model.VersionedReference;
  28. import org.apache.archiva.repository.LayoutException;
  29. import org.apache.archiva.repository.ManagedRepository;
  30. import org.apache.archiva.repository.ManagedRepositoryContent;
  31. import org.apache.archiva.repository.RepositoryException;
  32. import org.apache.archiva.repository.RepositoryNotFoundException;
  33. import org.apache.archiva.repository.RepositoryRegistry;
  34. import org.apache.archiva.repository.metadata.base.MetadataTools;
  35. import org.apache.archiva.repository.metadata.RepositoryMetadataException;
  36. import org.slf4j.Logger;
  37. import org.slf4j.LoggerFactory;
  38. import org.springframework.context.annotation.Scope;
  39. import org.springframework.stereotype.Service;
  40. import javax.annotation.PostConstruct;
  41. import javax.inject.Inject;
  42. import java.io.IOException;
  43. import java.nio.file.Files;
  44. import java.nio.file.Path;
  45. import java.nio.file.Paths;
  46. import java.util.ArrayList;
  47. import java.util.Date;
  48. import java.util.List;
  49. /**
  50. * MetadataUpdaterConsumer will create and update the metadata present within the repository.
  51. */
  52. @Service( "knownRepositoryContentConsumer#metadata-updater" )
  53. @Scope( "prototype" )
  54. public class MetadataUpdaterConsumer
  55. extends AbstractMonitoredConsumer
  56. implements KnownRepositoryContentConsumer
  57. // it's prototype bean so we assume configuration won't change during a run
  58. //, RegistryListener
  59. {
  60. private Logger log = LoggerFactory.getLogger( MetadataUpdaterConsumer.class );
  61. /**
  62. * default-value="metadata-updater"
  63. */
  64. private String id = "metadata-updater";
  65. private String description = "Update / Create maven-metadata.xml files";
  66. @Inject
  67. private RepositoryRegistry repositoryRegistry;
  68. @Inject
  69. private MetadataTools metadataTools;
  70. @Inject
  71. private ArchivaConfiguration configuration;
  72. @Inject
  73. private FileTypes filetypes;
  74. private static final String TYPE_METADATA_BAD_INTERNAL_REF = "metadata-bad-internal-ref";
  75. private static final String TYPE_METADATA_WRITE_FAILURE = "metadata-write-failure";
  76. private static final String TYPE_METADATA_IO = "metadata-io-warning";
  77. private ManagedRepositoryContent repository;
  78. private Path repositoryDir;
  79. private List<String> includes = new ArrayList<>( 0 );
  80. private long scanStartTimestamp = 0;
  81. @Override
  82. public String getDescription( )
  83. {
  84. return description;
  85. }
  86. @Override
  87. public String getId( )
  88. {
  89. return id;
  90. }
  91. public void setIncludes( List<String> includes )
  92. {
  93. this.includes = includes;
  94. }
  95. @Override
  96. public void beginScan( ManagedRepository repoConfig, Date whenGathered )
  97. throws ConsumerException
  98. {
  99. try
  100. {
  101. ManagedRepository repo = repositoryRegistry.getManagedRepository( repoConfig.getId( ) );
  102. if (repo==null) {
  103. throw new RepositoryNotFoundException( "Repository not found: "+repoConfig.getId() );
  104. }
  105. this.repository = repo.getContent();
  106. if (this.repository==null) {
  107. throw new RepositoryNotFoundException( "Repository content not found: "+repoConfig.getId() );
  108. }
  109. this.repositoryDir = Paths.get( repository.getRepoRoot( ) );
  110. this.scanStartTimestamp = System.currentTimeMillis( );
  111. }
  112. catch ( RepositoryException e )
  113. {
  114. throw new ConsumerException( e.getMessage( ), e );
  115. }
  116. }
  117. @Override
  118. public void beginScan( ManagedRepository repository, Date whenGathered, boolean executeOnEntireRepo )
  119. throws ConsumerException
  120. {
  121. beginScan( repository, whenGathered );
  122. }
  123. @Override
  124. public void completeScan( )
  125. {
  126. /* do nothing here */
  127. }
  128. @Override
  129. public void completeScan( boolean executeOnEntireRepo )
  130. {
  131. completeScan( );
  132. }
  133. @Override
  134. public List<String> getExcludes( )
  135. {
  136. return getDefaultArtifactExclusions( );
  137. }
  138. @Override
  139. public List<String> getIncludes( )
  140. {
  141. return this.includes;
  142. }
  143. @Override
  144. public void processFile( String path )
  145. throws ConsumerException
  146. {
  147. // Ignore paths like .index etc
  148. if ( !path.startsWith( "." ) )
  149. {
  150. try
  151. {
  152. ArtifactReference artifact = repository.toArtifactReference( path );
  153. updateVersionMetadata( artifact, path );
  154. updateProjectMetadata( artifact, path );
  155. }
  156. catch ( LayoutException e )
  157. {
  158. log.info( "Not processing path that is not an artifact: {} ({})", path, e.getMessage( ) );
  159. }
  160. }
  161. }
  162. @Override
  163. public void processFile( String path, boolean executeOnEntireRepo )
  164. throws Exception
  165. {
  166. processFile( path );
  167. }
  168. private void updateProjectMetadata( ArtifactReference artifact, String path )
  169. {
  170. ProjectReference projectRef = new ProjectReference( );
  171. projectRef.setGroupId( artifact.getGroupId( ) );
  172. projectRef.setArtifactId( artifact.getArtifactId( ) );
  173. try
  174. {
  175. String metadataPath = this.metadataTools.toPath( projectRef );
  176. Path projectMetadata = this.repositoryDir.resolve( metadataPath );
  177. if ( Files.exists(projectMetadata) && ( Files.getLastModifiedTime( projectMetadata).toMillis() >= this.scanStartTimestamp ) )
  178. {
  179. // This metadata is up to date. skip it.
  180. log.debug( "Skipping uptodate metadata: {}", this.metadataTools.toPath( projectRef ) );
  181. return;
  182. }
  183. metadataTools.updateMetadata( this.repository, metadataPath );
  184. log.debug( "Updated metadata: {}", this.metadataTools.toPath( projectRef ) );
  185. }
  186. catch ( RepositoryMetadataException e )
  187. {
  188. log.error( "Unable to write project metadat for artifact [{}]:", path, e );
  189. triggerConsumerError( TYPE_METADATA_WRITE_FAILURE,
  190. "Unable to write project metadata for artifact [" + path + "]: " + e.getMessage( ) );
  191. }
  192. catch ( IOException e )
  193. {
  194. log.warn( "Project metadata not written due to IO warning: ", e );
  195. triggerConsumerWarning( TYPE_METADATA_IO,
  196. "Project metadata not written due to IO warning: " + e.getMessage( ) );
  197. }
  198. }
  199. private void updateVersionMetadata( ArtifactReference artifact, String path )
  200. {
  201. VersionedReference versionRef = new VersionedReference( );
  202. versionRef.setGroupId( artifact.getGroupId( ) );
  203. versionRef.setArtifactId( artifact.getArtifactId( ) );
  204. versionRef.setVersion( artifact.getVersion( ) );
  205. try
  206. {
  207. String metadataPath = this.metadataTools.toPath( versionRef );
  208. Path projectMetadata = this.repositoryDir.resolve( metadataPath );
  209. if ( Files.exists(projectMetadata) && ( Files.getLastModifiedTime( projectMetadata ).toMillis() >= this.scanStartTimestamp ) )
  210. {
  211. // This metadata is up to date. skip it.
  212. log.debug( "Skipping uptodate metadata: {}", this.metadataTools.toPath( versionRef ) );
  213. return;
  214. }
  215. metadataTools.updateMetadata( this.repository, metadataPath );
  216. log.debug( "Updated metadata: {}", this.metadataTools.toPath( versionRef ) );
  217. }
  218. catch ( RepositoryMetadataException e )
  219. {
  220. log.error( "Unable to write version metadata for artifact [{}]: ", path, e );
  221. triggerConsumerError( TYPE_METADATA_WRITE_FAILURE,
  222. "Unable to write version metadata for artifact [" + path + "]: " + e.getMessage( ) );
  223. }
  224. catch ( IOException e )
  225. {
  226. log.warn( "Version metadata not written due to IO warning: ", e );
  227. triggerConsumerWarning( TYPE_METADATA_IO,
  228. "Version metadata not written due to IO warning: " + e.getMessage( ) );
  229. }
  230. }
  231. /*
  232. @Override
  233. public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
  234. {
  235. if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
  236. {
  237. initIncludes();
  238. }
  239. }
  240. @Override
  241. public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
  242. {
  243. // do nothing here
  244. }
  245. */
  246. private void initIncludes( )
  247. {
  248. includes = new ArrayList<>( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
  249. }
  250. @PostConstruct
  251. public void initialize( )
  252. {
  253. //configuration.addChangeListener( this );
  254. initIncludes( );
  255. }
  256. }