This project has retired. For details please refer to its
Attic page.
Maven2RepositoryMerger xref
1 package org.apache.archiva.stagerepository.merge;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.archiva.common.filelock.DefaultFileLockManager;
23 import org.apache.archiva.common.utils.VersionComparator;
24 import org.apache.archiva.common.utils.VersionUtil;
25 import org.apache.archiva.configuration.ArchivaConfiguration;
26 import org.apache.archiva.configuration.Configuration;
27 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
28 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
29 import org.apache.archiva.metadata.model.ArtifactMetadata;
30 import org.apache.archiva.metadata.repository.MetadataRepository;
31 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
32 import org.apache.archiva.filter.Filter;
33 import org.apache.archiva.metadata.repository.RepositorySession;
34 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
35 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
36 import org.apache.archiva.model.ArchivaRepositoryMetadata;
37 import org.apache.archiva.repository.RepositoryException;
38 import org.apache.archiva.repository.RepositoryType;
39 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
40 import org.apache.archiva.repository.metadata.base.RepositoryMetadataWriter;
41 import org.apache.archiva.repository.storage.FilesystemAsset;
42 import org.apache.archiva.repository.storage.FilesystemStorage;
43 import org.apache.archiva.repository.storage.StorageAsset;
44 import org.apache.archiva.xml.XMLException;
45 import org.apache.commons.io.FileUtils;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.stereotype.Service;
49
50 import javax.inject.Inject;
51 import javax.inject.Named;
52 import java.io.BufferedWriter;
53 import java.io.IOException;
54 import java.nio.file.Files;
55 import java.nio.file.Path;
56 import java.nio.file.Paths;
57 import java.text.DateFormat;
58 import java.text.SimpleDateFormat;
59 import java.util.*;
60
61
62
63
64 @Service ("repositoryMerger#maven2")
65 public class Maven2RepositoryMerger
66 implements RepositoryMerger
67 {
68
69 private Logger log = LoggerFactory.getLogger( getClass() );
70
71 private static final Comparator<ArtifactMetadata> META_COMPARATOR = Comparator.comparing(ArtifactMetadata::getNamespace)
72 .thenComparing(ArtifactMetadata::getProject)
73 .thenComparing(ArtifactMetadata::getId)
74 .thenComparing(ArtifactMetadata::getVersion);
75
76
77
78
79 private ArchivaConfiguration configuration;
80
81
82
83
84 private RepositoryPathTranslator pathTranslator;
85
86 private static final String METADATA_FILENAME = "maven-metadata.xml";
87
88 @Inject
89 private RepositorySessionFactory repositorySessionFactory;
90
91 @Inject
92 public Maven2RepositoryMerger(
93 @Named (value = "archivaConfiguration#default") ArchivaConfiguration archivaConfiguration,
94 @Named (value = "repositoryPathTranslator#maven2") RepositoryPathTranslator repositoryPathTranslator )
95 {
96 this.configuration = archivaConfiguration;
97 this.pathTranslator = repositoryPathTranslator;
98 }
99
100 public void setConfiguration( ArchivaConfiguration configuration )
101 {
102 this.configuration = configuration;
103 }
104
105 @Override
106 public boolean supportsRepository( RepositoryType type )
107 {
108 return RepositoryType.MAVEN.equals( type );
109 }
110
111 @Override
112 public void merge( MetadataRepository metadataRepository, String sourceRepoId, String targetRepoId )
113 throws RepositoryMergerException
114 {
115
116 try(RepositorySession session = repositorySessionFactory.createSession())
117 {
118 List<ArtifactMetadata> artifactsInSourceRepo = metadataRepository.getArtifacts(session , sourceRepoId );
119 for ( ArtifactMetadata artifactMetadata : artifactsInSourceRepo )
120 {
121 artifactMetadata.setRepositoryId( targetRepoId );
122 createFolderStructure( sourceRepoId, targetRepoId, artifactMetadata );
123 }
124 }
125 catch ( MetadataRepositoryException e )
126 {
127 throw new RepositoryMergerException( e.getMessage(), e );
128 }
129 catch ( IOException e )
130 {
131 throw new RepositoryMergerException( e.getMessage(), e );
132 }
133 catch ( RepositoryException e )
134 {
135 throw new RepositoryMergerException( e.getMessage(), e );
136 }
137 }
138
139
140 @Override
141 public void merge( MetadataRepository metadataRepository, String sourceRepoId, String targetRepoId,
142 Filter<ArtifactMetadata> filter )
143 throws RepositoryMergerException
144 {
145 try(RepositorySession session = repositorySessionFactory.createSession())
146 {
147 List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts(session , sourceRepoId );
148 for ( ArtifactMetadata metadata : sourceArtifacts )
149 {
150 if ( filter.accept( metadata ) )
151 {
152 createFolderStructure( sourceRepoId, targetRepoId, metadata );
153 }
154 }
155 }
156 catch ( MetadataRepositoryException e )
157 {
158 throw new RepositoryMergerException( e.getMessage(), e );
159 }
160 catch ( IOException e )
161 {
162 throw new RepositoryMergerException( e.getMessage(), e );
163 }
164 catch ( RepositoryException e )
165 {
166 throw new RepositoryMergerException( e.getMessage(), e );
167 }
168 }
169
170 private void createFolderStructure( String sourceRepoId, String targetRepoId, ArtifactMetadata artifactMetadata )
171 throws IOException, RepositoryException
172 {
173 Configuration config = configuration.getConfiguration();
174
175 ManagedRepositoryConfiguration targetRepoConfig = config.findManagedRepositoryById( targetRepoId );
176
177 ManagedRepositoryConfiguration sourceRepoConfig = config.findManagedRepositoryById( sourceRepoId );
178
179 Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
180
181 TimeZone timezone = TimeZone.getTimeZone( "UTC" );
182
183 DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
184
185 fmt.setTimeZone( timezone );
186
187 String timestamp = fmt.format( lastUpdatedTimestamp );
188
189 String targetRepoPath = targetRepoConfig.getLocation();
190
191 String sourceRepoPath = sourceRepoConfig.getLocation();
192
193 String artifactPath = pathTranslator.toPath( artifactMetadata.getNamespace(), artifactMetadata.getProject(),
194 artifactMetadata.getProjectVersion(), artifactMetadata.getId() );
195
196 Path sourceArtifactFile = Paths.get( sourceRepoPath, artifactPath );
197
198 Path targetArtifactFile = Paths.get( targetRepoPath, artifactPath );
199
200 log.debug( "artifactPath {}", artifactPath );
201
202 int lastIndex = artifactPath.lastIndexOf( RepositoryPathTranslator.PATH_SEPARATOR );
203
204 Path targetFile = Paths.get( targetRepoPath, artifactPath.substring( 0, lastIndex ) );
205
206 if ( !Files.exists(targetFile) )
207 {
208
209 Files.createDirectories(targetFile);
210 }
211
212 copyFile( sourceArtifactFile, targetArtifactFile );
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 String index = artifactPath.substring( lastIndex + 1 );
228 int last = index.lastIndexOf( '.' );
229 Path sourcePomFile = Paths.get( sourceRepoPath,
230 artifactPath.substring( 0, lastIndex ) + "/" + artifactPath.substring(
231 lastIndex + 1 ).substring( 0, last ) + ".pom" );
232 Path targetPomFile = Paths.get( targetRepoPath,
233 artifactPath.substring( 0, lastIndex ) + "/" + artifactPath.substring(
234 lastIndex + 1 ).substring( 0, last ) + ".pom" );
235
236 if ( !Files.exists(targetPomFile) && Files.exists(sourcePomFile) )
237 {
238 copyFile( sourcePomFile, targetPomFile );
239 }
240
241
242 if ( !config.getRepositoryScanning().getKnownContentConsumers().contains( "metadata-updater" ) )
243 {
244
245
246 FilesystemStorageilesystemStorage.html#FilesystemStorage">FilesystemStorage fsStorage = new FilesystemStorage(Paths.get(sourceRepoPath), new DefaultFileLockManager());
247
248 StorageAsset versionMetaDataFileInSourceRepo =
249 pathTranslator.toFile( new FilesystemAsset(fsStorage, "", Paths.get(sourceRepoPath)), artifactMetadata.getNamespace(),
250 artifactMetadata.getProject(), artifactMetadata.getVersion(),
251 METADATA_FILENAME );
252
253 if ( versionMetaDataFileInSourceRepo.exists() )
254 {
255 String relativePathToVersionMetadataFile =
256 getRelativeAssetPath(versionMetaDataFileInSourceRepo);
257 Path versionMetaDataFileInTargetRepo = Paths.get( targetRepoPath, relativePathToVersionMetadataFile );
258
259 if ( !Files.exists(versionMetaDataFileInTargetRepo) )
260 {
261 copyFile( versionMetaDataFileInSourceRepo.getFilePath(), versionMetaDataFileInTargetRepo );
262 }
263 else
264 {
265 updateVersionMetadata( versionMetaDataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp );
266
267 }
268 }
269
270
271 StorageAsset projectDirectoryInSourceRepo = versionMetaDataFileInSourceRepo.getParent().getParent();
272 StorageAsset projectMetadataFileInSourceRepo = projectDirectoryInSourceRepo.resolve(METADATA_FILENAME );
273
274 if ( projectMetadataFileInSourceRepo.exists() )
275 {
276 String relativePathToProjectMetadataFile =
277 getRelativeAssetPath(projectMetadataFileInSourceRepo);
278 Path projectMetadataFileInTargetRepo = Paths.get( targetRepoPath, relativePathToProjectMetadataFile );
279
280 if ( !Files.exists(projectMetadataFileInTargetRepo) )
281 {
282
283 copyFile( projectMetadataFileInSourceRepo.getFilePath(), projectMetadataFileInTargetRepo );
284 }
285 else
286 {
287 updateProjectMetadata( projectMetadataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp,
288 timestamp );
289 }
290 }
291 }
292
293 }
294
295 private String getRelativeAssetPath(final StorageAsset asset) {
296 String relPath = asset.getPath();
297 while(relPath.startsWith("/")) {
298 relPath = relPath.substring(1);
299 }
300 return relPath;
301 }
302
303 private void copyFile( Path sourceFile, Path targetFile )
304 throws IOException
305 {
306
307 FileUtils.copyFile( sourceFile.toFile(), targetFile.toFile() );
308
309 }
310
311 private void updateProjectMetadata( Path projectMetaDataFileIntargetRepo, ArtifactMetadata artifactMetadata,
312 Date lastUpdatedTimestamp, String timestamp )
313 throws RepositoryMetadataException
314 {
315 ArrayList<String> availableVersions = new ArrayList<>();
316 String latestVersion = artifactMetadata.getProjectVersion();
317
318 ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetaDataFileIntargetRepo );
319
320 if ( Files.exists(projectMetaDataFileIntargetRepo) )
321 {
322 availableVersions = (ArrayList<String>) projectMetadata.getAvailableVersions();
323
324 Collections.sort( availableVersions, VersionComparator.getInstance() );
325
326 if ( !availableVersions.contains( artifactMetadata.getVersion() ) )
327 {
328 availableVersions.add( artifactMetadata.getVersion() );
329 }
330
331 latestVersion = availableVersions.get( availableVersions.size() - 1 );
332 }
333 else
334 {
335 availableVersions.add( artifactMetadata.getProjectVersion() );
336 projectMetadata.setGroupId( artifactMetadata.getNamespace() );
337 projectMetadata.setArtifactId( artifactMetadata.getProject() );
338 }
339
340 if ( projectMetadata.getGroupId() == null )
341 {
342 projectMetadata.setGroupId( artifactMetadata.getNamespace() );
343 }
344
345 if ( projectMetadata.getArtifactId() == null )
346 {
347 projectMetadata.setArtifactId( artifactMetadata.getProject() );
348 }
349
350 projectMetadata.setLatestVersion( latestVersion );
351 projectMetadata.setAvailableVersions( availableVersions );
352 projectMetadata.setLastUpdated( timestamp );
353 projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
354
355 if ( !VersionUtil.isSnapshot( artifactMetadata.getVersion() ) )
356 {
357 projectMetadata.setReleasedVersion( latestVersion );
358 }
359
360 try(BufferedWriter writer = Files.newBufferedWriter(projectMetaDataFileIntargetRepo)) {
361 RepositoryMetadataWriter.write( projectMetadata, writer );
362 } catch (IOException e) {
363 throw new RepositoryMetadataException(e);
364 }
365
366 }
367
368 private void updateVersionMetadata( Path versionMetaDataFileInTargetRepo, ArtifactMetadata artifactMetadata,
369 Date lastUpdatedTimestamp )
370 throws RepositoryMetadataException
371 {
372 ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetaDataFileInTargetRepo );
373 if ( !Files.exists(versionMetaDataFileInTargetRepo) )
374 {
375 versionMetadata.setGroupId( artifactMetadata.getNamespace() );
376 versionMetadata.setArtifactId( artifactMetadata.getProject() );
377 versionMetadata.setVersion( artifactMetadata.getProjectVersion() );
378 }
379
380 versionMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
381 try(BufferedWriter writer = Files.newBufferedWriter(versionMetaDataFileInTargetRepo) ) {
382 RepositoryMetadataWriter.write( versionMetadata, writer);
383 } catch (IOException e) {
384 throw new RepositoryMetadataException(e);
385 }
386 }
387
388 private ArchivaRepositoryMetadata getMetadata( Path metadataFile )
389 throws RepositoryMetadataException
390 {
391 ArchivaRepositoryMetadatadata.html#ArchivaRepositoryMetadata">ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
392 if ( Files.exists(metadataFile) )
393 {
394 try
395 {
396 metadata = MavenMetadataReader.read( metadataFile );
397 }
398 catch (XMLException e )
399 {
400 throw new RepositoryMetadataException( e.getMessage(), e );
401 }
402 }
403 return metadata;
404 }
405
406 @Override
407 public List<ArtifactMetadata> getConflictingArtifacts( MetadataRepository metadataRepository, String sourceRepo,
408 String targetRepo )
409 throws RepositoryMergerException
410 {
411 try(RepositorySession session = repositorySessionFactory.createSession())
412 {
413 TreeSet<ArtifactMetadata> targetArtifacts = new TreeSet<>(META_COMPARATOR);
414 targetArtifacts.addAll(metadataRepository.getArtifacts(session , targetRepo ));
415 TreeSet<ArtifactMetadata> sourceArtifacts = new TreeSet<>(META_COMPARATOR);
416 sourceArtifacts.addAll(metadataRepository.getArtifacts(session , sourceRepo ));
417 sourceArtifacts.retainAll(targetArtifacts);
418
419 return new ArrayList<>(sourceArtifacts);
420 }
421 catch ( MetadataRepositoryException e )
422 {
423 throw new RepositoryMergerException( e.getMessage(), e );
424 }
425 }
426
427 public RepositorySessionFactory getRepositorySessionFactory( )
428 {
429 return repositorySessionFactory;
430 }
431
432 public void setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory )
433 {
434 this.repositorySessionFactory = repositorySessionFactory;
435 }
436 }