]> source.dussan.org Git - archiva.git/blob
892a461ba4ff22abad0421468508c1c192b3ec0c
[archiva.git] /
1 package org.apache.archiva.stagerepository.merge;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import org.apache.archiva.common.utils.VersionComparator;
23 import org.apache.archiva.common.utils.VersionUtil;
24 import org.apache.archiva.configuration.ArchivaConfiguration;
25 import org.apache.archiva.configuration.Configuration;
26 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
27 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
28 import org.apache.archiva.metadata.model.ArtifactMetadata;
29 import org.apache.archiva.metadata.repository.MetadataRepository;
30 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
31 import org.apache.archiva.metadata.repository.filter.Filter;
32 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
33 import org.apache.archiva.model.ArchivaRepositoryMetadata;
34 import org.apache.archiva.repository.RepositoryException;
35 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
36 import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
37 import org.apache.archiva.xml.XMLException;
38 import org.apache.commons.io.FileUtils;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.stereotype.Service;
42
43 import javax.inject.Inject;
44 import javax.inject.Named;
45 import java.io.File;
46 import java.io.IOException;
47 import java.text.DateFormat;
48 import java.text.SimpleDateFormat;
49 import java.util.ArrayList;
50 import java.util.Calendar;
51 import java.util.Collections;
52 import java.util.Date;
53 import java.util.List;
54 import java.util.TimeZone;
55 import java.util.regex.Pattern;
56
57 /**
58  *
59  */
60 @Service ("repositoryMerger#maven2")
61 public class Maven2RepositoryMerger
62     implements RepositoryMerger
63 {
64
65     private Logger log = LoggerFactory.getLogger( getClass() );
66
67     /**
68      *
69      */
70     private ArchivaConfiguration configuration;
71
72     /**
73      *
74      */
75     private RepositoryPathTranslator pathTranslator;
76
77     private static final String METADATA_FILENAME = "maven-metadata.xml";
78
79     @Inject
80     public Maven2RepositoryMerger(
81         @Named (value = "archivaConfiguration#default") ArchivaConfiguration archivaConfiguration,
82         @Named (value = "repositoryPathTranslator#maven2") RepositoryPathTranslator repositoryPathTranslator )
83     {
84         this.configuration = archivaConfiguration;
85         this.pathTranslator = repositoryPathTranslator;
86     }
87
88     public void setConfiguration( ArchivaConfiguration configuration )
89     {
90         this.configuration = configuration;
91     }
92
93     @Override
94     public void merge( MetadataRepository metadataRepository, String sourceRepoId, String targetRepoId )
95         throws RepositoryMergerException
96     {
97
98         try
99         {
100             List<ArtifactMetadata> artifactsInSourceRepo = metadataRepository.getArtifacts( sourceRepoId );
101             for ( ArtifactMetadata artifactMetadata : artifactsInSourceRepo )
102             {
103                 artifactMetadata.setRepositoryId( targetRepoId );
104                 createFolderStructure( sourceRepoId, targetRepoId, artifactMetadata );
105             }
106         }
107         catch ( MetadataRepositoryException e )
108         {
109             throw new RepositoryMergerException( e.getMessage(), e );
110         }
111         catch ( IOException e )
112         {
113             throw new RepositoryMergerException( e.getMessage(), e );
114         }
115         catch ( RepositoryException e )
116         {
117             throw new RepositoryMergerException( e.getMessage(), e );
118         }
119     }
120
121     // TODO when UI needs a subset to merge
122     @Override
123     public void merge( MetadataRepository metadataRepository, String sourceRepoId, String targetRepoId,
124                        Filter<ArtifactMetadata> filter )
125         throws RepositoryMergerException
126     {
127         try
128         {
129             List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts( sourceRepoId );
130             for ( ArtifactMetadata metadata : sourceArtifacts )
131             {
132                 if ( filter.accept( metadata ) )
133                 {
134                     createFolderStructure( sourceRepoId, targetRepoId, metadata );
135                 }
136             }
137         }
138         catch ( MetadataRepositoryException e )
139         {
140             throw new RepositoryMergerException( e.getMessage(), e );
141         }
142         catch ( IOException e )
143         {
144             throw new RepositoryMergerException( e.getMessage(), e );
145         }
146         catch ( RepositoryException e )
147         {
148             throw new RepositoryMergerException( e.getMessage(), e );
149         }
150     }
151
152     private void createFolderStructure( String sourceRepoId, String targetRepoId, ArtifactMetadata artifactMetadata )
153         throws IOException, RepositoryException
154     {
155         Configuration config = configuration.getConfiguration();
156
157         ManagedRepositoryConfiguration targetRepoConfig = config.findManagedRepositoryById( targetRepoId );
158
159         ManagedRepositoryConfiguration sourceRepoConfig = config.findManagedRepositoryById( sourceRepoId );
160
161         Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
162
163         TimeZone timezone = TimeZone.getTimeZone( "UTC" );
164
165         DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
166
167         fmt.setTimeZone( timezone );
168
169         String timestamp = fmt.format( lastUpdatedTimestamp );
170
171         String targetRepoPath = targetRepoConfig.getLocation();
172
173         String sourceRepoPath = sourceRepoConfig.getLocation();
174
175         String artifactPath = pathTranslator.toPath( artifactMetadata.getNamespace(), artifactMetadata.getProject(),
176                                                      artifactMetadata.getProjectVersion(), artifactMetadata.getId() );
177
178         File sourceArtifactFile = new File( sourceRepoPath, artifactPath );
179
180         File targetArtifactFile = new File( targetRepoPath, artifactPath );
181
182         log.debug( "artifactPath {}", artifactPath );
183
184         int lastIndex = artifactPath.lastIndexOf( RepositoryPathTranslator.PATH_SEPARATOR );
185
186         File targetFile = new File( targetRepoPath, artifactPath.substring( 0, lastIndex ) );
187
188         if ( !targetFile.exists() )
189         {
190             // create the folder structure when it does not exist
191             targetFile.mkdirs();
192         }
193         // artifact copying
194         copyFile( sourceArtifactFile, targetArtifactFile );
195
196         // pom file copying
197         String fileName = artifactMetadata.getProject() + "-" + artifactMetadata.getVersion() + ".pom";
198
199         // pom file copying
200         // TODO need to use path translator to get the pom file path
201 //        String fileName = artifactMetadata.getProject() + "-" + artifactMetadata.getVersion() + ".pom";
202 //
203 //        File sourcePomFile =
204 //            pathTranslator.toFile( new File( sourceRepoPath ), artifactMetadata.getId(), artifactMetadata.getProject(),
205 //                                   artifactMetadata.getVersion(), fileName );
206 //
207 //        String relativePathToPomFile = sourcePomFile.getAbsolutePath().split( sourceRepoPath )[1];
208 //        File targetPomFile = new File( targetRepoPath, relativePathToPomFile );
209
210         //pom file copying  (file path is taken with out using path translator)
211
212         String index = artifactPath.substring( lastIndex + 1 );
213         int last = index.lastIndexOf( '.' );
214         File sourcePomFile = new File( sourceRepoPath,
215                                        artifactPath.substring( 0, lastIndex ) + "/" + artifactPath.substring(
216                                            lastIndex + 1 ).substring( 0, last ) + ".pom" );
217         File targetPomFile = new File( targetRepoPath,
218                                        artifactPath.substring( 0, lastIndex ) + "/" + artifactPath.substring(
219                                            lastIndex + 1 ).substring( 0, last ) + ".pom" );
220
221         if ( !targetPomFile.exists() && sourcePomFile.exists() )
222         {
223             copyFile( sourcePomFile, targetPomFile );
224         }
225
226         // explicitly update only if metadata-updater consumer is not enabled!
227         if ( !config.getRepositoryScanning().getKnownContentConsumers().contains( "metadata-updater" ) )
228         {
229
230             // updating version metadata files
231             File versionMetaDataFileInSourceRepo =
232                 pathTranslator.toFile( new File( sourceRepoPath ), artifactMetadata.getNamespace(),
233                                        artifactMetadata.getProject(), artifactMetadata.getVersion(),
234                                        METADATA_FILENAME );
235
236             if ( versionMetaDataFileInSourceRepo.exists() )
237             {//Pattern quote for windows path
238                 String relativePathToVersionMetadataFile =
239                     versionMetaDataFileInSourceRepo.getAbsolutePath().split( Pattern.quote( sourceRepoPath ) )[1];
240                 File versionMetaDataFileInTargetRepo = new File( targetRepoPath, relativePathToVersionMetadataFile );
241
242                 if ( !versionMetaDataFileInTargetRepo.exists() )
243                 {
244                     copyFile( versionMetaDataFileInSourceRepo, versionMetaDataFileInTargetRepo );
245                 }
246                 else
247                 {
248                     updateVersionMetadata( versionMetaDataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp );
249
250                 }
251             }
252
253             // updating project meta data file
254             String projectDirectoryInSourceRepo = new File( versionMetaDataFileInSourceRepo.getParent() ).getParent();
255             File projectMetadataFileInSourceRepo = new File( projectDirectoryInSourceRepo, METADATA_FILENAME );
256
257             if ( projectMetadataFileInSourceRepo.exists() )
258             {
259                 String relativePathToProjectMetadataFile =
260                     projectMetadataFileInSourceRepo.getAbsolutePath().split( Pattern.quote( sourceRepoPath ) )[1];
261                 File projectMetadataFileInTargetRepo = new File( targetRepoPath, relativePathToProjectMetadataFile );
262
263                 if ( !projectMetadataFileInTargetRepo.exists() )
264                 {
265
266                     copyFile( projectMetadataFileInSourceRepo, projectMetadataFileInTargetRepo );
267                 }
268                 else
269                 {
270                     updateProjectMetadata( projectMetadataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp,
271                                            timestamp );
272                 }
273             }
274         }
275
276     }
277
278     private void copyFile( File sourceFile, File targetFile )
279         throws IOException
280     {
281
282         FileUtils.copyFile( sourceFile, targetFile );
283
284     }
285
286     private void updateProjectMetadata( File projectMetaDataFileIntargetRepo, ArtifactMetadata artifactMetadata,
287                                         Date lastUpdatedTimestamp, String timestamp )
288         throws RepositoryMetadataException
289     {
290         ArrayList<String> availableVersions = new ArrayList<>();
291         String latestVersion = artifactMetadata.getProjectVersion();
292
293         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetaDataFileIntargetRepo );
294
295         if ( projectMetaDataFileIntargetRepo.exists() )
296         {
297             availableVersions = (ArrayList<String>) projectMetadata.getAvailableVersions();
298
299             Collections.sort( availableVersions, VersionComparator.getInstance() );
300
301             if ( !availableVersions.contains( artifactMetadata.getVersion() ) )
302             {
303                 availableVersions.add( artifactMetadata.getVersion() );
304             }
305
306             latestVersion = availableVersions.get( availableVersions.size() - 1 );
307         }
308         else
309         {
310             availableVersions.add( artifactMetadata.getProjectVersion() );
311             projectMetadata.setGroupId( artifactMetadata.getNamespace() );
312             projectMetadata.setArtifactId( artifactMetadata.getProject() );
313         }
314
315         if ( projectMetadata.getGroupId() == null )
316         {
317             projectMetadata.setGroupId( artifactMetadata.getNamespace() );
318         }
319
320         if ( projectMetadata.getArtifactId() == null )
321         {
322             projectMetadata.setArtifactId( artifactMetadata.getProject() );
323         }
324
325         projectMetadata.setLatestVersion( latestVersion );
326         projectMetadata.setAvailableVersions( availableVersions );
327         projectMetadata.setLastUpdated( timestamp );
328         projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
329
330         if ( !VersionUtil.isSnapshot( artifactMetadata.getVersion() ) )
331         {
332             projectMetadata.setReleasedVersion( latestVersion );
333         }
334
335         RepositoryMetadataWriter.write( projectMetadata, projectMetaDataFileIntargetRepo );
336
337     }
338
339     private void updateVersionMetadata( File versionMetaDataFileInTargetRepo, ArtifactMetadata artifactMetadata,
340                                         Date lastUpdatedTimestamp )
341         throws RepositoryMetadataException
342     {
343         ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetaDataFileInTargetRepo );
344         if ( !versionMetaDataFileInTargetRepo.exists() )
345         {
346             versionMetadata.setGroupId( artifactMetadata.getNamespace() );
347             versionMetadata.setArtifactId( artifactMetadata.getProject() );
348             versionMetadata.setVersion( artifactMetadata.getProjectVersion() );
349         }
350
351         versionMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
352         RepositoryMetadataWriter.write( versionMetadata, versionMetaDataFileInTargetRepo );
353     }
354
355     private ArchivaRepositoryMetadata getMetadata( File metadataFile )
356         throws RepositoryMetadataException
357     {
358         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
359         if ( metadataFile.exists() )
360         {
361             try
362             {
363                 metadata = MavenMetadataReader.read( metadataFile );
364             }
365             catch ( XMLException e )
366             {
367                 throw new RepositoryMetadataException( e.getMessage(), e );
368             }
369         }
370         return metadata;
371     }
372
373     @Override
374     public List<ArtifactMetadata> getConflictingArtifacts( MetadataRepository metadataRepository, String sourceRepo,
375                                                            String targetRepo )
376         throws RepositoryMergerException
377     {
378         try
379         {
380             List<ArtifactMetadata> targetArtifacts = metadataRepository.getArtifacts( targetRepo );
381             List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts( sourceRepo );
382             List<ArtifactMetadata> conflictsArtifacts = new ArrayList<>();
383
384             for ( ArtifactMetadata targetArtifact : targetArtifacts )
385             {
386                 for ( ArtifactMetadata sourceArtifact : sourceArtifacts )
387                 {
388                     if ( isEquals( targetArtifact, sourceArtifact ) )
389                     {
390                         if ( !conflictsArtifacts.contains( sourceArtifact ) )
391                         {
392                             conflictsArtifacts.add( sourceArtifact );
393                         }
394                     }
395                 }
396             }
397
398             sourceArtifacts.removeAll( conflictsArtifacts );
399
400             return conflictsArtifacts;
401         }
402         catch ( MetadataRepositoryException e )
403         {
404             throw new RepositoryMergerException( e.getMessage(), e );
405         }
406     }
407
408     private boolean isEquals( ArtifactMetadata sourceArtifact, ArtifactMetadata targetArtifact )
409     {
410         boolean isSame = false;
411
412         if ( ( sourceArtifact.getNamespace().equals( targetArtifact.getNamespace() ) )
413             && ( sourceArtifact.getProject().equals( targetArtifact.getProject() ) ) && ( sourceArtifact.getId().equals(
414             targetArtifact.getId() ) ) && ( sourceArtifact.getProjectVersion().equals(
415             targetArtifact.getProjectVersion() ) ) )
416
417         {
418             isSame = true;
419
420         }
421
422         return isSame;
423     }
424 }