1 package org.apache.maven.repository.converter;
4 * Copyright 2005-2006 The Apache Software Foundation.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 import org.apache.maven.artifact.Artifact;
20 import org.apache.maven.artifact.factory.ArtifactFactory;
21 import org.apache.maven.artifact.repository.ArtifactRepository;
22 import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;
23 import org.apache.maven.artifact.repository.metadata.Metadata;
24 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
25 import org.apache.maven.artifact.repository.metadata.Snapshot;
26 import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
27 import org.apache.maven.artifact.repository.metadata.Versioning;
28 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
29 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
30 import org.apache.maven.model.DistributionManagement;
31 import org.apache.maven.model.Model;
32 import org.apache.maven.model.Relocation;
33 import org.apache.maven.model.converter.ArtifactPomRewriter;
34 import org.apache.maven.model.converter.ModelConverter;
35 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
36 import org.apache.maven.model.v3_0_0.io.xpp3.MavenXpp3Reader;
37 import org.apache.maven.repository.converter.transaction.FileTransaction;
38 import org.apache.maven.repository.digest.Digester;
39 import org.apache.maven.repository.reporting.ArtifactReporter;
40 import org.codehaus.plexus.i18n.I18N;
41 import org.codehaus.plexus.util.FileUtils;
42 import org.codehaus.plexus.util.IOUtil;
43 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
46 import java.io.FileReader;
47 import java.io.IOException;
48 import java.io.StringReader;
49 import java.io.StringWriter;
50 import java.security.NoSuchAlgorithmException;
51 import java.util.Iterator;
52 import java.util.List;
53 import java.util.Locale;
54 import java.util.Properties;
55 import java.util.regex.Matcher;
58 * Implementation of repository conversion class.
60 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
61 * @plexus.component role="org.apache.maven.repository.converter.RepositoryConverter" role-hint="default"
63 public class DefaultRepositoryConverter
64 implements RepositoryConverter
69 private Digester digester;
74 private ArtifactFactory artifactFactory;
79 private ArtifactPomRewriter rewriter;
84 private ModelConverter translator;
87 * @plexus.configuration default-value="false"
89 private boolean force;
92 * @plexus.configuration default-value="false"
94 private boolean dryrun;
101 public void convert( Artifact artifact, ArtifactRepository targetRepository, ArtifactReporter reporter )
102 throws RepositoryConversionException
104 if ( artifact.getRepository().getUrl().equals( targetRepository.getUrl() ) )
106 throw new RepositoryConversionException( getI18NString( "exception.repositories.match" ) );
109 if ( validateMetadata( artifact, reporter ) )
111 FileTransaction transaction = new FileTransaction();
113 if ( copyPom( artifact, targetRepository, reporter, transaction ) )
115 if ( copyArtifact( artifact, targetRepository, reporter, transaction ) )
117 Metadata metadata = createBaseMetadata( artifact );
118 Versioning versioning = new Versioning();
119 versioning.addVersion( artifact.getBaseVersion() );
120 metadata.setVersioning( versioning );
121 updateMetadata( new ArtifactRepositoryMetadata( artifact ), targetRepository, metadata,
124 metadata = createBaseMetadata( artifact );
125 metadata.setVersion( artifact.getBaseVersion() );
126 versioning = new Versioning();
128 Matcher matcher = Artifact.VERSION_FILE_PATTERN.matcher( artifact.getVersion() );
129 if ( matcher.matches() )
131 Snapshot snapshot = new Snapshot();
132 snapshot.setBuildNumber( Integer.valueOf( matcher.group( 3 ) ).intValue() );
133 snapshot.setTimestamp( matcher.group( 2 ) );
134 versioning.setSnapshot( snapshot );
137 // TODO: merge latest/release/snapshot from source instead
138 metadata.setVersioning( versioning );
139 updateMetadata( new SnapshotArtifactRepositoryMetadata( artifact ), targetRepository, metadata,
144 transaction.commit();
146 reporter.addSuccess( artifact );
152 private static Metadata createBaseMetadata( Artifact artifact )
154 Metadata metadata = new Metadata();
155 metadata.setArtifactId( artifact.getArtifactId() );
156 metadata.setGroupId( artifact.getGroupId() );
160 private void updateMetadata( RepositoryMetadata artifactMetadata, ArtifactRepository targetRepository,
161 Metadata newMetadata, FileTransaction transaction )
162 throws RepositoryConversionException
164 File file = new File( targetRepository.getBasedir(),
165 targetRepository.pathOfRemoteRepositoryMetadata( artifactMetadata ) );
172 metadata = readMetadata( file );
173 changed = metadata.merge( newMetadata );
178 metadata = newMetadata;
183 StringWriter writer = null;
186 writer = new StringWriter();
188 MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer();
190 mappingWriter.write( writer, metadata );
192 transaction.createFile( writer.toString(), file );
194 catch ( IOException e )
196 throw new RepositoryConversionException( "Error writing target metadata", e );
200 IOUtil.close( writer );
205 private Metadata readMetadata( File file )
206 throws RepositoryConversionException
209 MetadataXpp3Reader reader = new MetadataXpp3Reader();
210 FileReader fileReader = null;
213 fileReader = new FileReader( file );
214 metadata = reader.read( fileReader );
216 catch ( IOException e )
218 throw new RepositoryConversionException( "Error reading target metadata", e );
220 catch ( XmlPullParserException e )
222 throw new RepositoryConversionException( "Error reading target metadata", e );
226 IOUtil.close( fileReader );
231 private boolean validateMetadata( Artifact artifact, ArtifactReporter reporter )
232 throws RepositoryConversionException
234 ArtifactRepository repository = artifact.getRepository();
236 boolean result = true;
238 RepositoryMetadata repositoryMetadata = new ArtifactRepositoryMetadata( artifact );
240 new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ) );
243 Metadata metadata = readMetadata( file );
244 result = validateMetadata( metadata, repositoryMetadata, artifact, reporter );
247 repositoryMetadata = new SnapshotArtifactRepositoryMetadata( artifact );
248 file = new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ) );
251 Metadata metadata = readMetadata( file );
252 result = result && validateMetadata( metadata, repositoryMetadata, artifact, reporter );
258 private boolean validateMetadata( Metadata metadata, RepositoryMetadata repositoryMetadata, Artifact artifact,
259 ArtifactReporter reporter )
261 String key = "failure.incorrect.";
263 if ( repositoryMetadata.storedInGroupDirectory() )
265 key += "groupMetadata.";
267 else if ( repositoryMetadata.storedInArtifactVersionDirectory() )
269 key += "snapshotMetadata.";
273 key += "artifactMetadata.";
276 boolean result = true;
278 if ( !metadata.getGroupId().equals( artifact.getGroupId() ) )
280 reporter.addFailure( artifact, getI18NString( key + "groupId" ) );
283 if ( !repositoryMetadata.storedInGroupDirectory() )
285 if ( !metadata.getArtifactId().equals( artifact.getArtifactId() ) )
287 reporter.addFailure( artifact, getI18NString( key + "artifactId" ) );
290 if ( !repositoryMetadata.storedInArtifactVersionDirectory() )
294 boolean foundVersion = false;
295 if ( metadata.getVersioning() != null )
297 for ( Iterator i = metadata.getVersioning().getVersions().iterator();
298 i.hasNext() && !foundVersion; )
300 String version = (String) i.next();
301 if ( version.equals( artifact.getBaseVersion() ) )
310 reporter.addFailure( artifact, getI18NString( key + "versions" ) );
317 if ( !artifact.getBaseVersion().equals( metadata.getVersion() ) )
319 reporter.addFailure( artifact, getI18NString( key + "version" ) );
323 if ( artifact.isSnapshot() )
325 Matcher matcher = Artifact.VERSION_FILE_PATTERN.matcher( artifact.getVersion() );
326 if ( matcher.matches() )
328 boolean correct = false;
329 if ( metadata.getVersioning() != null && metadata.getVersioning().getSnapshot() != null )
331 Snapshot snapshot = metadata.getVersioning().getSnapshot();
332 int build = Integer.valueOf( matcher.group( 3 ) ).intValue();
333 String ts = matcher.group( 2 );
334 if ( build == snapshot.getBuildNumber() && ts.equals( snapshot.getTimestamp() ) )
342 reporter.addFailure( artifact, getI18NString( key + "snapshot" ) );
352 private boolean copyPom( Artifact artifact, ArtifactRepository targetRepository, ArtifactReporter reporter,
353 FileTransaction transaction )
354 throws RepositoryConversionException
356 Artifact pom = artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(),
357 artifact.getVersion() );
358 pom.setBaseVersion( artifact.getBaseVersion() );
359 ArtifactRepository repository = artifact.getRepository();
360 File file = new File( repository.getBasedir(), repository.pathOf( pom ) );
362 boolean result = true;
365 // TODO: utility methods in the model converter
366 File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( pom ) );
368 String contents = null;
369 boolean checksumsValid = false;
372 if ( testChecksums( artifact, file, reporter ) )
374 checksumsValid = true;
375 contents = FileUtils.fileRead( file );
378 catch ( IOException e )
380 throw new RepositoryConversionException( "Unable to read source POM: " + e.getMessage(), e );
383 if ( checksumsValid && contents.indexOf( "modelVersion" ) >= 0 )
388 boolean matching = false;
389 if ( !force && targetFile.exists() )
391 String targetContents = FileUtils.fileRead( targetFile );
392 matching = targetContents.equals( contents );
394 if ( force || !matching )
396 transaction.createFile( contents, targetFile );
399 catch ( IOException e )
401 throw new RepositoryConversionException( "Unable to write target POM: " + e.getMessage(), e );
407 StringReader stringReader = new StringReader( contents );
408 StringWriter writer = null;
411 MavenXpp3Reader v3Reader = new MavenXpp3Reader();
412 org.apache.maven.model.v3_0_0.Model v3Model = v3Reader.read( stringReader );
414 if ( doRelocation( artifact, v3Model, targetRepository, transaction ) )
416 Artifact relocatedPom = artifactFactory.createProjectArtifact( artifact.getGroupId(),
417 artifact.getArtifactId(),
418 artifact.getVersion() );
419 targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( relocatedPom ) );
422 Model v4Model = translator.translate( v3Model );
424 translator.validateV4Basics( v4Model, v3Model.getGroupId(), v3Model.getArtifactId(),
425 v3Model.getVersion(), v3Model.getPackage() );
427 writer = new StringWriter();
428 MavenXpp3Writer Xpp3Writer = new MavenXpp3Writer();
429 Xpp3Writer.write( writer, v4Model );
431 transaction.createFile( writer.toString(), targetFile );
433 List warnings = translator.getWarnings();
435 for ( Iterator i = warnings.iterator(); i.hasNext(); )
437 String message = (String) i.next();
438 reporter.addWarning( artifact, message );
441 catch ( XmlPullParserException e )
443 reporter.addFailure( artifact, getI18NString( "failure.invalid.source.pom", e.getMessage() ) );
446 catch ( Exception e )
448 throw new RepositoryConversionException( "Unable to write converted POM", e );
452 IOUtil.close( writer );
458 reporter.addWarning( artifact, getI18NString( "warning.missing.pom" ) );
463 private boolean doRelocation( Artifact artifact, org.apache.maven.model.v3_0_0.Model v3Model,
464 ArtifactRepository repository, FileTransaction transaction )
467 Properties properties = v3Model.getProperties();
468 if ( properties.containsKey( "relocated.groupId" ) || properties.containsKey( "relocated.artifactId" ) ||
469 properties.containsKey( "relocated.version" ) )
471 String newGroupId = v3Model.getGroupId();
472 if ( properties.containsKey( "relocated.groupId" ) )
474 newGroupId = properties.getProperty( "relocated.groupId" );
475 properties.remove( "relocated.groupId" );
478 String newArtifactId = v3Model.getArtifactId();
479 if ( properties.containsKey( "relocated.artifactId" ) )
481 newArtifactId = properties.getProperty( "relocated.artifactId" );
482 properties.remove( "relocated.artifactId" );
485 String newVersion = v3Model.getVersion();
486 if ( properties.containsKey( "relocated.version" ) )
488 newVersion = properties.getProperty( "relocated.version" );
489 properties.remove( "relocated.version" );
493 if ( properties.containsKey( "relocated.message" ) )
495 message = properties.getProperty( "relocated.message" );
496 properties.remove( "relocated.message" );
499 if ( properties.isEmpty() )
501 v3Model.setProperties( null );
504 writeRelocationPom( v3Model.getGroupId(), v3Model.getArtifactId(), v3Model.getVersion(), newGroupId,
505 newArtifactId, newVersion, message, repository, transaction );
507 v3Model.setGroupId( newGroupId );
508 v3Model.setArtifactId( newArtifactId );
509 v3Model.setVersion( newVersion );
511 artifact.setGroupId( newGroupId );
512 artifact.setArtifactId( newArtifactId );
513 artifact.setVersion( newVersion );
523 private void writeRelocationPom( String groupId, String artifactId, String version, String newGroupId,
524 String newArtifactId, String newVersion, String message,
525 ArtifactRepository repository, FileTransaction transaction )
528 Model pom = new Model();
529 pom.setGroupId( groupId );
530 pom.setArtifactId( artifactId );
531 pom.setVersion( version );
533 DistributionManagement dMngt = new DistributionManagement();
535 Relocation relocation = new Relocation();
536 relocation.setGroupId( newGroupId );
537 relocation.setArtifactId( newArtifactId );
538 relocation.setVersion( newVersion );
539 if ( message != null && message.length() > 0 )
541 relocation.setMessage( message );
544 dMngt.setRelocation( relocation );
546 pom.setDistributionManagement( dMngt );
548 Artifact artifact = artifactFactory.createBuildArtifact( groupId, artifactId, version, "pom" );
549 File pomFile = new File( repository.getBasedir(), repository.pathOf( artifact ) );
551 StringWriter strWriter = new StringWriter();
552 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
553 pomWriter.write( strWriter, pom );
555 transaction.createFile( strWriter.toString(), pomFile );
558 private String getI18NString( String key, String arg0 )
560 return i18n.format( getClass().getName(), Locale.getDefault(), key, arg0 );
563 private String getI18NString( String key )
565 return i18n.getString( getClass().getName(), Locale.getDefault(), key );
568 private boolean testChecksums( Artifact artifact, File file, ArtifactReporter reporter )
569 throws IOException, RepositoryConversionException
571 boolean result = true;
575 File md5 = new File( file.getParentFile(), file.getName() + ".md5" );
578 String checksum = FileUtils.fileRead( md5 );
579 if ( !digester.verifyChecksum( file, checksum, Digester.MD5 ) )
581 reporter.addFailure( artifact, getI18NString( "failure.incorrect.md5" ) );
586 File sha1 = new File( file.getParentFile(), file.getName() + ".sha1" );
589 String checksum = FileUtils.fileRead( sha1 );
590 if ( !digester.verifyChecksum( file, checksum, Digester.SHA1 ) )
592 reporter.addFailure( artifact, getI18NString( "failure.incorrect.sha1" ) );
597 catch ( NoSuchAlgorithmException e )
599 throw new RepositoryConversionException( "Error copying artifact: " + e.getMessage(), e );
604 private boolean copyArtifact( Artifact artifact, ArtifactRepository targetRepository, ArtifactReporter reporter,
605 FileTransaction transaction )
606 throws RepositoryConversionException
608 File sourceFile = artifact.getFile();
610 File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( artifact ) );
612 boolean result = true;
615 boolean matching = false;
616 if ( !force && targetFile.exists() )
618 matching = FileUtils.contentEquals( sourceFile, targetFile );
621 reporter.addFailure( artifact, getI18NString( "failure.target.already.exists" ) );
627 if ( force || !matching )
629 if ( testChecksums( artifact, sourceFile, reporter ) )
631 transaction.copyFile( sourceFile, targetFile );
640 catch ( IOException e )
642 throw new RepositoryConversionException( "Error copying artifact", e );
647 public void convert( List artifacts, ArtifactRepository targetRepository, ArtifactReporter reporter )
648 throws RepositoryConversionException
650 for ( Iterator i = artifacts.iterator(); i.hasNext(); )
652 Artifact artifact = (Artifact) i.next();
653 convert( artifact, targetRepository, reporter );