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.converter.ArtifactPomRewriter;
31 import org.apache.maven.repository.converter.transaction.FileTransaction;
32 import org.apache.maven.repository.digest.Digester;
33 import org.apache.maven.repository.reporting.ArtifactReporter;
34 import org.codehaus.plexus.i18n.I18N;
35 import org.codehaus.plexus.util.FileUtils;
36 import org.codehaus.plexus.util.IOUtil;
37 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
40 import java.io.FileReader;
41 import java.io.IOException;
42 import java.io.StringReader;
43 import java.io.StringWriter;
44 import java.security.NoSuchAlgorithmException;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Locale;
48 import java.util.regex.Matcher;
51 * Implementation of repository conversion class.
53 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
54 * @plexus.component role="org.apache.maven.repository.converter.RepositoryConverter" role-hint="default"
56 public class DefaultRepositoryConverter
57 implements RepositoryConverter
62 private Digester digester;
67 private ArtifactFactory artifactFactory;
72 private ArtifactPomRewriter rewriter;
75 * @plexus.configuration default-value="false"
77 private boolean force;
80 * @plexus.configuration default-value="false"
82 private boolean dryrun;
89 public void convert( Artifact artifact, ArtifactRepository targetRepository, ArtifactReporter reporter )
90 throws RepositoryConversionException
92 if ( artifact.getRepository().getUrl().equals( targetRepository.getUrl() ) )
94 throw new RepositoryConversionException( getI18NString( "exception.repositories.match" ) );
97 if ( validateMetadata( artifact, reporter ) )
99 FileTransaction transaction = new FileTransaction();
101 if ( copyArtifact( artifact, targetRepository, reporter, transaction ) )
103 if ( copyPom( artifact, targetRepository, reporter, transaction ) )
105 Metadata metadata = createBaseMetadata( artifact );
106 Versioning versioning = new Versioning();
107 versioning.addVersion( artifact.getBaseVersion() );
108 metadata.setVersioning( versioning );
109 updateMetadata( new ArtifactRepositoryMetadata( artifact ), targetRepository, metadata,
112 metadata = createBaseMetadata( artifact );
113 metadata.setVersion( artifact.getBaseVersion() );
114 versioning = new Versioning();
116 Matcher matcher = Artifact.VERSION_FILE_PATTERN.matcher( artifact.getVersion() );
117 if ( matcher.matches() )
119 Snapshot snapshot = new Snapshot();
120 snapshot.setBuildNumber( Integer.valueOf( matcher.group( 3 ) ).intValue() );
121 snapshot.setTimestamp( matcher.group( 2 ) );
122 versioning.setSnapshot( snapshot );
125 // TODO: merge latest/release/snapshot from source instead
126 metadata.setVersioning( versioning );
127 updateMetadata( new SnapshotArtifactRepositoryMetadata( artifact ), targetRepository, metadata,
132 transaction.commit();
134 reporter.addSuccess( artifact );
140 private static Metadata createBaseMetadata( Artifact artifact )
142 Metadata metadata = new Metadata();
143 metadata.setArtifactId( artifact.getArtifactId() );
144 metadata.setGroupId( artifact.getGroupId() );
148 private void updateMetadata( RepositoryMetadata artifactMetadata, ArtifactRepository targetRepository,
149 Metadata newMetadata, FileTransaction transaction )
150 throws RepositoryConversionException
152 File file = new File( targetRepository.getBasedir(),
153 targetRepository.pathOfRemoteRepositoryMetadata( artifactMetadata ) );
160 metadata = readMetadata( file );
161 changed = metadata.merge( newMetadata );
166 metadata = newMetadata;
171 StringWriter writer = null;
174 writer = new StringWriter();
176 MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer();
178 mappingWriter.write( writer, metadata );
180 transaction.createFile( writer.toString(), file );
182 catch ( IOException e )
184 throw new RepositoryConversionException( "Error writing target metadata", e );
188 IOUtil.close( writer );
193 private Metadata readMetadata( File file )
194 throws RepositoryConversionException
197 MetadataXpp3Reader reader = new MetadataXpp3Reader();
198 FileReader fileReader = null;
201 fileReader = new FileReader( file );
202 metadata = reader.read( fileReader );
204 catch ( IOException e )
206 throw new RepositoryConversionException( "Error reading target metadata", e );
208 catch ( XmlPullParserException e )
210 throw new RepositoryConversionException( "Error reading target metadata", e );
214 IOUtil.close( fileReader );
219 private boolean validateMetadata( Artifact artifact, ArtifactReporter reporter )
220 throws RepositoryConversionException
222 ArtifactRepository repository = artifact.getRepository();
224 boolean result = true;
226 RepositoryMetadata repositoryMetadata = new ArtifactRepositoryMetadata( artifact );
228 new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ) );
231 Metadata metadata = readMetadata( file );
232 result = validateMetadata( metadata, repositoryMetadata, artifact, reporter );
235 repositoryMetadata = new SnapshotArtifactRepositoryMetadata( artifact );
236 file = new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ) );
239 Metadata metadata = readMetadata( file );
240 result = result && validateMetadata( metadata, repositoryMetadata, artifact, reporter );
246 private boolean validateMetadata( Metadata metadata, RepositoryMetadata repositoryMetadata, Artifact artifact,
247 ArtifactReporter reporter )
249 String key = "failure.incorrect.";
251 if ( repositoryMetadata.storedInGroupDirectory() )
253 key += "groupMetadata.";
255 else if ( repositoryMetadata.storedInArtifactVersionDirectory() )
257 key += "snapshotMetadata.";
261 key += "artifactMetadata.";
264 boolean result = true;
266 if ( !metadata.getGroupId().equals( artifact.getGroupId() ) )
268 reporter.addFailure( artifact, getI18NString( key + "groupId" ) );
271 if ( !repositoryMetadata.storedInGroupDirectory() )
273 if ( !metadata.getArtifactId().equals( artifact.getArtifactId() ) )
275 reporter.addFailure( artifact, getI18NString( key + "artifactId" ) );
278 if ( !repositoryMetadata.storedInArtifactVersionDirectory() )
282 boolean foundVersion = false;
283 if ( metadata.getVersioning() != null )
285 for ( Iterator i = metadata.getVersioning().getVersions().iterator();
286 i.hasNext() && !foundVersion; )
288 String version = (String) i.next();
289 if ( version.equals( artifact.getBaseVersion() ) )
298 reporter.addFailure( artifact, getI18NString( key + "versions" ) );
305 if ( !artifact.getBaseVersion().equals( metadata.getVersion() ) )
307 reporter.addFailure( artifact, getI18NString( key + "version" ) );
311 if ( artifact.isSnapshot() )
313 Matcher matcher = Artifact.VERSION_FILE_PATTERN.matcher( artifact.getVersion() );
314 if ( matcher.matches() )
316 boolean correct = false;
317 if ( metadata.getVersioning() != null && metadata.getVersioning().getSnapshot() != null )
319 Snapshot snapshot = metadata.getVersioning().getSnapshot();
320 int build = Integer.valueOf( matcher.group( 3 ) ).intValue();
321 String ts = matcher.group( 2 );
322 if ( build == snapshot.getBuildNumber() && ts.equals( snapshot.getTimestamp() ) )
330 reporter.addFailure( artifact, getI18NString( key + "snapshot" ) );
340 private boolean copyPom( Artifact artifact, ArtifactRepository targetRepository, ArtifactReporter reporter,
341 FileTransaction transaction )
342 throws RepositoryConversionException
344 Artifact pom = artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(),
345 artifact.getVersion() );
346 pom.setBaseVersion( artifact.getBaseVersion() );
347 ArtifactRepository repository = artifact.getRepository();
348 File file = new File( repository.getBasedir(), repository.pathOf( pom ) );
350 boolean result = true;
353 // TODO: utility methods in the model converter
354 File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( pom ) );
356 String contents = null;
357 boolean checksumsValid = false;
360 if ( testChecksums( artifact, file, reporter ) )
362 checksumsValid = true;
363 contents = FileUtils.fileRead( file );
366 catch ( IOException e )
368 throw new RepositoryConversionException( "Unable to read source POM: " + e.getMessage(), e );
371 if ( checksumsValid && contents.indexOf( "modelVersion" ) >= 0 )
376 boolean matching = false;
377 if ( !force && targetFile.exists() )
379 String targetContents = FileUtils.fileRead( targetFile );
380 matching = targetContents.equals( contents );
382 if ( force || !matching )
384 transaction.createFile( contents, targetFile );
387 catch ( IOException e )
389 throw new RepositoryConversionException( "Unable to write target POM: " + e.getMessage(), e );
395 StringReader stringReader = new StringReader( contents );
396 StringWriter writer = null;
399 writer = new StringWriter();
401 // TODO: this api could be improved - is it worth having or go back to modelConverter?
402 rewriter.rewrite( stringReader, writer, false, artifact.getGroupId(), artifact.getArtifactId(),
403 artifact.getVersion(), artifact.getType() );
405 transaction.createFile( writer.toString(), targetFile );
407 List warnings = rewriter.getWarnings();
409 for ( Iterator i = warnings.iterator(); i.hasNext(); )
411 String message = (String) i.next();
412 reporter.addWarning( artifact, message );
415 catch ( XmlPullParserException e )
417 reporter.addFailure( artifact, getI18NString( "failure.invalid.source.pom", e.getMessage() ) );
420 catch ( Exception e )
422 throw new RepositoryConversionException( "Unable to write converted POM", e );
426 IOUtil.close( writer );
432 reporter.addWarning( artifact, getI18NString( "warning.missing.pom" ) );
437 private String getI18NString( String key, String arg0 )
439 return i18n.format( getClass().getName(), Locale.getDefault(), key, arg0 );
442 private String getI18NString( String key )
444 return i18n.getString( getClass().getName(), Locale.getDefault(), key );
447 private boolean testChecksums( Artifact artifact, File file, ArtifactReporter reporter )
448 throws IOException, RepositoryConversionException
450 boolean result = true;
454 File md5 = new File( file.getParentFile(), file.getName() + ".md5" );
457 String checksum = FileUtils.fileRead( md5 );
458 if ( !digester.verifyChecksum( file, checksum, Digester.MD5 ) )
460 reporter.addFailure( artifact, getI18NString( "failure.incorrect.md5" ) );
465 File sha1 = new File( file.getParentFile(), file.getName() + ".sha1" );
468 String checksum = FileUtils.fileRead( sha1 );
469 if ( !digester.verifyChecksum( file, checksum, Digester.SHA1 ) )
471 reporter.addFailure( artifact, getI18NString( "failure.incorrect.sha1" ) );
476 catch ( NoSuchAlgorithmException e )
478 throw new RepositoryConversionException( "Error copying artifact: " + e.getMessage(), e );
483 private boolean copyArtifact( Artifact artifact, ArtifactRepository targetRepository, ArtifactReporter reporter,
484 FileTransaction transaction )
485 throws RepositoryConversionException
487 File sourceFile = artifact.getFile();
489 File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( artifact ) );
491 boolean result = true;
494 boolean matching = false;
495 if ( !force && targetFile.exists() )
497 matching = FileUtils.contentEquals( sourceFile, targetFile );
500 reporter.addFailure( artifact, getI18NString( "failure.target.already.exists" ) );
506 if ( force || !matching )
508 if ( testChecksums( artifact, sourceFile, reporter ) )
510 transaction.copyFile( sourceFile, targetFile );
519 catch ( IOException e )
521 throw new RepositoryConversionException( "Error copying artifact", e );
526 public void convert( List artifacts, ArtifactRepository targetRepository, ArtifactReporter reporter )
527 throws RepositoryConversionException
529 for ( Iterator i = artifacts.iterator(); i.hasNext(); )
531 Artifact artifact = (Artifact) i.next();
532 convert( artifact, targetRepository, reporter );