]> source.dussan.org Git - archiva.git/blob
1d8da4b7562ed69c86523360745f5bbf1238d905
[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.metadata.model.ArtifactMetadata;
23 import org.apache.archiva.metadata.repository.MetadataRepository;
24 import org.apache.archiva.metadata.repository.filter.Filter;
25 import org.apache.archiva.metadata.repository.filter.IncludesFilter;
26 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.maven.archiva.common.utils.VersionComparator;
29 import org.apache.maven.archiva.common.utils.VersionUtil;
30 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
31 import org.apache.maven.archiva.configuration.Configuration;
32 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
33 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
34 import org.apache.maven.archiva.repository.RepositoryException;
35 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
36 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
37 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
38 import org.springframework.stereotype.Service;
39
40 import java.io.File;
41 import java.io.FileInputStream;
42 import java.io.FileOutputStream;
43 import java.io.IOException;
44 import java.text.DateFormat;
45 import java.text.SimpleDateFormat;
46 import java.util.ArrayList;
47 import java.util.Calendar;
48 import java.util.Collections;
49 import java.util.Date;
50 import java.util.List;
51 import java.util.TimeZone;
52 import javax.inject.Inject;
53 import javax.inject.Named;
54
55 /**
56  * plexus.component role="org.apache.archiva.stagerepository.merge.RepositoryMerger" role-hint="maven2"
57  */
58 @Service( "repositoryMerger#maven2" )
59 public class Maven2RepositoryMerger
60     implements RepositoryMerger
61 {
62     /**
63      * plexus.requirement role-hint="default"
64      */
65     private ArchivaConfiguration configuration;
66
67     /**
68      * plexus.requirement role-hint="maven2"
69      */
70     private RepositoryPathTranslator pathTranslator;
71
72     private static final String METADATA_FILENAME = "maven-metadata.xml";
73
74     @Inject
75     public Maven2RepositoryMerger(
76         @Named( value = "archivaConfiguration#default" ) ArchivaConfiguration archivaConfiguration,
77         @Named( value = "repositoryPathTranslator#maven2") RepositoryPathTranslator repositoryPathTranslator )
78     {
79         this.configuration = archivaConfiguration;
80         this.pathTranslator = repositoryPathTranslator;
81     }
82
83     public void setConfiguration( ArchivaConfiguration configuration )
84     {
85         this.configuration = configuration;
86     }
87
88     public void merge( MetadataRepository metadataRepository, String sourceRepoId, String targetRepoId )
89         throws Exception
90     {
91
92         List<ArtifactMetadata> artifactsInSourceRepo = metadataRepository.getArtifacts( sourceRepoId );
93         for ( ArtifactMetadata artifactMetadata : artifactsInSourceRepo )
94         {
95             artifactMetadata.setRepositoryId( targetRepoId );
96             createFolderStructure( sourceRepoId, targetRepoId, artifactMetadata );
97         }
98     }
99
100     // TODO when UI needs a subset to merge
101     public void merge( MetadataRepository metadataRepository, String sourceRepoId, String targetRepoId,
102                        Filter<ArtifactMetadata> filter )
103         throws Exception
104     {
105         List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts( sourceRepoId );
106         for ( ArtifactMetadata metadata : sourceArtifacts )
107         {
108             if ( filter.accept( metadata ) )
109             {
110                 createFolderStructure( sourceRepoId, targetRepoId, metadata );
111             }
112         }
113     }
114
115     private void createFolderStructure( String sourceRepoId, String targetRepoId, ArtifactMetadata artifactMetadata )
116         throws IOException, RepositoryException
117     {
118         Configuration config = configuration.getConfiguration();
119
120         ManagedRepositoryConfiguration targetRepoConfig = config.findManagedRepositoryById( targetRepoId );
121
122         ManagedRepositoryConfiguration sourceRepoConfig = config.findManagedRepositoryById( sourceRepoId );
123
124         Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
125
126         TimeZone timezone = TimeZone.getTimeZone( "UTC" );
127
128         DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
129
130         fmt.setTimeZone( timezone );
131
132         String timestamp = fmt.format( lastUpdatedTimestamp );
133
134         String targetRepoPath = targetRepoConfig.getLocation();
135
136         String sourceRepoPath = sourceRepoConfig.getLocation();
137
138         String artifactPath = pathTranslator.toPath( artifactMetadata.getNamespace(), artifactMetadata.getProject(),
139                                                      artifactMetadata.getProjectVersion(), artifactMetadata.getId() );
140
141         File sourceArtifactFile = new File( sourceRepoPath, artifactPath );
142
143         File targetArtifactFile = new File( targetRepoPath, artifactPath );
144
145         int lastIndex = artifactPath.lastIndexOf( '/' );
146
147         File targetFile = new File( targetRepoPath, artifactPath.substring( 0, lastIndex ) );
148
149         if ( !targetFile.exists() )
150         {
151             // create the folder structure when it does not exist
152             targetFile.mkdirs();
153         }
154         // artifact copying
155         copyFile( sourceArtifactFile, targetArtifactFile );
156
157         // pom file copying
158         String fileName = artifactMetadata.getProject() + "-" + artifactMetadata.getVersion() + ".pom";
159
160         // pom file copying
161         // TODO need to use path translator to get the pom file path
162 //        String fileName = artifactMetadata.getProject() + "-" + artifactMetadata.getVersion() + ".pom";
163 //
164 //        File sourcePomFile =
165 //            pathTranslator.toFile( new File( sourceRepoPath ), artifactMetadata.getId(), artifactMetadata.getProject(),
166 //                                   artifactMetadata.getVersion(), fileName );
167 //
168 //        String relativePathToPomFile = sourcePomFile.getAbsolutePath().split( sourceRepoPath )[1];
169 //        File targetPomFile = new File( targetRepoPath, relativePathToPomFile );
170
171         //pom file copying  (file path is taken with out using path translator)
172
173         String index = artifactPath.substring( lastIndex + 1 );
174         int last = index.lastIndexOf( '.' );
175         File sourcePomFile = new File( sourceRepoPath, artifactPath.substring( 0, lastIndex ) + "/"
176             + artifactPath.substring( lastIndex + 1 ).substring( 0, last ) + ".pom" );
177         File targetPomFile = new File( targetRepoPath, artifactPath.substring( 0, lastIndex ) + "/"
178             + artifactPath.substring( lastIndex + 1 ).substring( 0, last ) + ".pom" );
179
180         if ( !targetPomFile.exists() && sourcePomFile.exists() )
181         {
182             copyFile( sourcePomFile, targetPomFile );
183         }
184
185         // explicitly update only if metadata-updater consumer is not enabled!
186         if ( !config.getRepositoryScanning().getKnownContentConsumers().contains( "metadata-updater" ) )
187         {
188
189             // updating version metadata files
190             File versionMetaDataFileInSourceRepo =
191                 pathTranslator.toFile( new File( sourceRepoPath ), artifactMetadata.getNamespace(),
192                                        artifactMetadata.getProject(), artifactMetadata.getVersion(),
193                                        METADATA_FILENAME );
194
195             if ( versionMetaDataFileInSourceRepo.exists() )
196             {
197                 String relativePathToVersionMetadataFile =
198                     versionMetaDataFileInSourceRepo.getAbsolutePath().split( sourceRepoPath )[1];
199                 File versionMetaDataFileInTargetRepo = new File( targetRepoPath, relativePathToVersionMetadataFile );
200
201                 if ( !versionMetaDataFileInTargetRepo.exists() )
202                 {
203                     copyFile( versionMetaDataFileInSourceRepo, versionMetaDataFileInTargetRepo );
204                 }
205                 else
206                 {
207                     updateVersionMetadata( versionMetaDataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp );
208
209                 }
210             }
211
212             // updating project meta data file
213             String projectDirectoryInSourceRepo = new File( versionMetaDataFileInSourceRepo.getParent() ).getParent();
214             File projectMetadataFileInSourceRepo = new File( projectDirectoryInSourceRepo, METADATA_FILENAME );
215
216             if ( projectMetadataFileInSourceRepo.exists() )
217             {
218                 String relativePathToProjectMetadataFile =
219                     projectMetadataFileInSourceRepo.getAbsolutePath().split( sourceRepoPath )[1];
220                 File projectMetadataFileInTargetRepo = new File( targetRepoPath, relativePathToProjectMetadataFile );
221
222                 if ( !projectMetadataFileInTargetRepo.exists() )
223                 {
224
225                     copyFile( projectMetadataFileInSourceRepo, projectMetadataFileInSourceRepo );
226                 }
227                 else
228                 {
229                     updateProjectMetadata( projectMetadataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp,
230                                            timestamp );
231                 }
232             }
233         }
234
235     }
236
237     private void copyFile( File sourceFile, File targetFile )
238         throws IOException
239     {
240         FileOutputStream out = new FileOutputStream( targetFile );
241         FileInputStream input = new FileInputStream( sourceFile );
242
243         // IOUtils internally buffers the streams
244         try
245         {
246             IOUtils.copy( input, out );
247         }
248         finally
249         {
250             IOUtils.closeQuietly( out );
251             IOUtils.closeQuietly( input );
252         }
253     }
254
255     private void updateProjectMetadata( File projectMetaDataFileIntargetRepo, ArtifactMetadata artifactMetadata,
256                                         Date lastUpdatedTimestamp, String timestamp )
257         throws RepositoryMetadataException
258     {
259         ArrayList<String> availableVersions = new ArrayList<String>();
260         String latestVersion = artifactMetadata.getProjectVersion();
261
262         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetaDataFileIntargetRepo );
263
264         if ( projectMetaDataFileIntargetRepo.exists() )
265         {
266             availableVersions = (ArrayList<String>) projectMetadata.getAvailableVersions();
267
268             Collections.sort( availableVersions, VersionComparator.getInstance() );
269
270             if ( !availableVersions.contains( artifactMetadata.getVersion() ) )
271             {
272                 availableVersions.add( artifactMetadata.getVersion() );
273             }
274
275             latestVersion = availableVersions.get( availableVersions.size() - 1 );
276         }
277         else
278         {
279             availableVersions.add( artifactMetadata.getProjectVersion() );
280             projectMetadata.setGroupId( artifactMetadata.getNamespace() );
281             projectMetadata.setArtifactId( artifactMetadata.getProject() );
282         }
283
284         if ( projectMetadata.getGroupId() == null )
285         {
286             projectMetadata.setGroupId( artifactMetadata.getNamespace() );
287         }
288
289         if ( projectMetadata.getArtifactId() == null )
290         {
291             projectMetadata.setArtifactId( artifactMetadata.getProject() );
292         }
293
294         projectMetadata.setLatestVersion( latestVersion );
295         projectMetadata.setAvailableVersions( availableVersions );
296         projectMetadata.setLastUpdated( timestamp );
297         projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
298
299         if ( !VersionUtil.isSnapshot( artifactMetadata.getVersion() ) )
300         {
301             projectMetadata.setReleasedVersion( latestVersion );
302         }
303
304         RepositoryMetadataWriter.write( projectMetadata, projectMetaDataFileIntargetRepo );
305
306     }
307
308     private void updateVersionMetadata( File versionMetaDataFileInTargetRepo, ArtifactMetadata artifactMetadata,
309                                         Date lastUpdatedTimestamp )
310         throws RepositoryMetadataException
311     {
312         ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetaDataFileInTargetRepo );
313         if ( !versionMetaDataFileInTargetRepo.exists() )
314         {
315             versionMetadata.setGroupId( artifactMetadata.getNamespace() );
316             versionMetadata.setArtifactId( artifactMetadata.getProject() );
317             versionMetadata.setVersion( artifactMetadata.getProjectVersion() );
318         }
319
320         versionMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
321         RepositoryMetadataWriter.write( versionMetadata, versionMetaDataFileInTargetRepo );
322     }
323
324     private ArchivaRepositoryMetadata getMetadata( File metadataFile )
325         throws RepositoryMetadataException
326     {
327         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
328         if ( metadataFile.exists() )
329         {
330             metadata = RepositoryMetadataReader.read( metadataFile );
331         }
332         return metadata;
333     }
334
335     public List<ArtifactMetadata> getConflictingArtifacts( MetadataRepository metadataRepository, String sourceRepo,
336                                                            String targetRepo )
337         throws Exception
338     {
339         List<ArtifactMetadata> targetArtifacts = metadataRepository.getArtifacts( targetRepo );
340         List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts( sourceRepo );
341         List<ArtifactMetadata> conflictsArtifacts = new ArrayList<ArtifactMetadata>();
342
343         for ( ArtifactMetadata targetArtifact : targetArtifacts )
344         {
345             for ( ArtifactMetadata sourceArtifact : sourceArtifacts )
346             {
347                 if ( isEquals( targetArtifact, sourceArtifact ) )
348                 {
349                     if ( !conflictsArtifacts.contains( sourceArtifact ) )
350                     {
351                         conflictsArtifacts.add( sourceArtifact );
352                     }
353                 }
354             }
355         }
356
357         sourceArtifacts.removeAll( conflictsArtifacts );
358         Filter<ArtifactMetadata> artifactsWithOutConflicts = new IncludesFilter<ArtifactMetadata>( sourceArtifacts );
359 //        merge( sourceRepo, targetRepo, artifactsWithOutConflicts );
360         return conflictsArtifacts;
361     }
362
363     private boolean isEquals( ArtifactMetadata sourceArtifact, ArtifactMetadata targetArtifact )
364     {
365         boolean isSame = false;
366
367         if ( ( sourceArtifact.getNamespace().equals( targetArtifact.getNamespace() ) )
368             && ( sourceArtifact.getProject().equals( targetArtifact.getProject() ) )
369             && ( sourceArtifact.getId().equals( targetArtifact.getId() ) )
370             && ( sourceArtifact.getProjectVersion().equals( targetArtifact.getProjectVersion() ) ) )
371
372         {
373             isSame = true;
374
375         }
376
377         return isSame;
378     }
379 }