This project has retired. For details please refer to its Attic page.
Maven2RepositoryMerger xref
View Javadoc
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         // TODO need to use path translator to get the pom file path
198 //        String fileName = artifactMetadata.getProject() + "-" + artifactMetadata.getVersion() + ".pom";
199 //
200 //        File sourcePomFile =
201 //            pathTranslator.toFile( new File( sourceRepoPath ), artifactMetadata.getId(), artifactMetadata.getProject(),
202 //                                   artifactMetadata.getVersion(), fileName );
203 //
204 //        String relativePathToPomFile = sourcePomFile.getAbsolutePath().split( sourceRepoPath )[1];
205 //        File targetPomFile = new File( targetRepoPath, relativePathToPomFile );
206 
207         //pom file copying  (file path is taken with out using path translator)
208 
209         String index = artifactPath.substring( lastIndex + 1 );
210         int last = index.lastIndexOf( '.' );
211         File sourcePomFile = new File( sourceRepoPath,
212                                        artifactPath.substring( 0, lastIndex ) + "/" + artifactPath.substring(
213                                            lastIndex + 1 ).substring( 0, last ) + ".pom" );
214         File targetPomFile = new File( targetRepoPath,
215                                        artifactPath.substring( 0, lastIndex ) + "/" + artifactPath.substring(
216                                            lastIndex + 1 ).substring( 0, last ) + ".pom" );
217 
218         if ( !targetPomFile.exists() && sourcePomFile.exists() )
219         {
220             copyFile( sourcePomFile, targetPomFile );
221         }
222 
223         // explicitly update only if metadata-updater consumer is not enabled!
224         if ( !config.getRepositoryScanning().getKnownContentConsumers().contains( "metadata-updater" ) )
225         {
226 
227             // updating version metadata files
228             File versionMetaDataFileInSourceRepo =
229                 pathTranslator.toFile( new File( sourceRepoPath ), artifactMetadata.getNamespace(),
230                                        artifactMetadata.getProject(), artifactMetadata.getVersion(),
231                                        METADATA_FILENAME );
232 
233             if ( versionMetaDataFileInSourceRepo.exists() )
234             {//Pattern quote for windows path
235                 String relativePathToVersionMetadataFile =
236                     versionMetaDataFileInSourceRepo.getAbsolutePath().split( Pattern.quote( sourceRepoPath ) )[1];
237                 File versionMetaDataFileInTargetRepo = new File( targetRepoPath, relativePathToVersionMetadataFile );
238 
239                 if ( !versionMetaDataFileInTargetRepo.exists() )
240                 {
241                     copyFile( versionMetaDataFileInSourceRepo, versionMetaDataFileInTargetRepo );
242                 }
243                 else
244                 {
245                     updateVersionMetadata( versionMetaDataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp );
246 
247                 }
248             }
249 
250             // updating project meta data file
251             String projectDirectoryInSourceRepo = new File( versionMetaDataFileInSourceRepo.getParent() ).getParent();
252             File projectMetadataFileInSourceRepo = new File( projectDirectoryInSourceRepo, METADATA_FILENAME );
253 
254             if ( projectMetadataFileInSourceRepo.exists() )
255             {
256                 String relativePathToProjectMetadataFile =
257                     projectMetadataFileInSourceRepo.getAbsolutePath().split( Pattern.quote( sourceRepoPath ) )[1];
258                 File projectMetadataFileInTargetRepo = new File( targetRepoPath, relativePathToProjectMetadataFile );
259 
260                 if ( !projectMetadataFileInTargetRepo.exists() )
261                 {
262 
263                     copyFile( projectMetadataFileInSourceRepo, projectMetadataFileInTargetRepo );
264                 }
265                 else
266                 {
267                     updateProjectMetadata( projectMetadataFileInTargetRepo, artifactMetadata, lastUpdatedTimestamp,
268                                            timestamp );
269                 }
270             }
271         }
272 
273     }
274 
275     private void copyFile( File sourceFile, File targetFile )
276         throws IOException
277     {
278 
279         FileUtils.copyFile( sourceFile, targetFile );
280 
281     }
282 
283     private void updateProjectMetadata( File projectMetaDataFileIntargetRepo, ArtifactMetadata artifactMetadata,
284                                         Date lastUpdatedTimestamp, String timestamp )
285         throws RepositoryMetadataException
286     {
287         ArrayList<String> availableVersions = new ArrayList<>();
288         String latestVersion = artifactMetadata.getProjectVersion();
289 
290         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetaDataFileIntargetRepo );
291 
292         if ( projectMetaDataFileIntargetRepo.exists() )
293         {
294             availableVersions = (ArrayList<String>) projectMetadata.getAvailableVersions();
295 
296             Collections.sort( availableVersions, VersionComparator.getInstance() );
297 
298             if ( !availableVersions.contains( artifactMetadata.getVersion() ) )
299             {
300                 availableVersions.add( artifactMetadata.getVersion() );
301             }
302 
303             latestVersion = availableVersions.get( availableVersions.size() - 1 );
304         }
305         else
306         {
307             availableVersions.add( artifactMetadata.getProjectVersion() );
308             projectMetadata.setGroupId( artifactMetadata.getNamespace() );
309             projectMetadata.setArtifactId( artifactMetadata.getProject() );
310         }
311 
312         if ( projectMetadata.getGroupId() == null )
313         {
314             projectMetadata.setGroupId( artifactMetadata.getNamespace() );
315         }
316 
317         if ( projectMetadata.getArtifactId() == null )
318         {
319             projectMetadata.setArtifactId( artifactMetadata.getProject() );
320         }
321 
322         projectMetadata.setLatestVersion( latestVersion );
323         projectMetadata.setAvailableVersions( availableVersions );
324         projectMetadata.setLastUpdated( timestamp );
325         projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
326 
327         if ( !VersionUtil.isSnapshot( artifactMetadata.getVersion() ) )
328         {
329             projectMetadata.setReleasedVersion( latestVersion );
330         }
331 
332         RepositoryMetadataWriter.write( projectMetadata, projectMetaDataFileIntargetRepo );
333 
334     }
335 
336     private void updateVersionMetadata( File versionMetaDataFileInTargetRepo, ArtifactMetadata artifactMetadata,
337                                         Date lastUpdatedTimestamp )
338         throws RepositoryMetadataException
339     {
340         ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetaDataFileInTargetRepo );
341         if ( !versionMetaDataFileInTargetRepo.exists() )
342         {
343             versionMetadata.setGroupId( artifactMetadata.getNamespace() );
344             versionMetadata.setArtifactId( artifactMetadata.getProject() );
345             versionMetadata.setVersion( artifactMetadata.getProjectVersion() );
346         }
347 
348         versionMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
349         RepositoryMetadataWriter.write( versionMetadata, versionMetaDataFileInTargetRepo );
350     }
351 
352     private ArchivaRepositoryMetadata getMetadata( File metadataFile )
353         throws RepositoryMetadataException
354     {
355         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
356         if ( metadataFile.exists() )
357         {
358             try
359             {
360                 metadata = MavenMetadataReader.read( metadataFile );
361             }
362             catch ( XMLException e )
363             {
364                 throw new RepositoryMetadataException( e.getMessage(), e );
365             }
366         }
367         return metadata;
368     }
369 
370     @Override
371     public List<ArtifactMetadata> getConflictingArtifacts( MetadataRepository metadataRepository, String sourceRepo,
372                                                            String targetRepo )
373         throws RepositoryMergerException
374     {
375         try
376         {
377             List<ArtifactMetadata> targetArtifacts = metadataRepository.getArtifacts( targetRepo );
378             List<ArtifactMetadata> sourceArtifacts = metadataRepository.getArtifacts( sourceRepo );
379             List<ArtifactMetadata> conflictsArtifacts = new ArrayList<>();
380 
381             for ( ArtifactMetadata targetArtifact : targetArtifacts )
382             {
383                 for ( ArtifactMetadata sourceArtifact : sourceArtifacts )
384                 {
385                     if ( isEquals( targetArtifact, sourceArtifact ) )
386                     {
387                         if ( !conflictsArtifacts.contains( sourceArtifact ) )
388                         {
389                             conflictsArtifacts.add( sourceArtifact );
390                         }
391                     }
392                 }
393             }
394 
395             sourceArtifacts.removeAll( conflictsArtifacts );
396 
397             return conflictsArtifacts;
398         }
399         catch ( MetadataRepositoryException e )
400         {
401             throw new RepositoryMergerException( e.getMessage(), e );
402         }
403     }
404 
405     private boolean isEquals( ArtifactMetadata sourceArtifact, ArtifactMetadata targetArtifact )
406     {
407         boolean isSame = false;
408 
409         if ( ( sourceArtifact.getNamespace().equals( targetArtifact.getNamespace() ) )
410             && ( sourceArtifact.getProject().equals( targetArtifact.getProject() ) ) && ( sourceArtifact.getId().equals(
411             targetArtifact.getId() ) ) && ( sourceArtifact.getProjectVersion().equals(
412             targetArtifact.getProjectVersion() ) ) )
413 
414         {
415             isSame = true;
416 
417         }
418 
419         return isSame;
420     }
421 }