1 package org.apache.maven.artifact.manager; 2 3 18 19 import org.apache.maven.artifact.Artifact; 20 import org.apache.maven.artifact.metadata.ArtifactMetadata; 21 import org.apache.maven.artifact.repository.ArtifactRepository; 22 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; 23 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; 24 import org.apache.maven.artifact.repository.DefaultArtifactRepository; 25 import org.apache.maven.wagon.ConnectionException; 26 import org.apache.maven.wagon.ResourceDoesNotExistException; 27 import org.apache.maven.wagon.TransferFailedException; 28 import org.apache.maven.wagon.UnsupportedProtocolException; 29 import org.apache.maven.wagon.Wagon; 30 import org.apache.maven.wagon.authentication.AuthenticationException; 31 import org.apache.maven.wagon.authentication.AuthenticationInfo; 32 import org.apache.maven.wagon.authorization.AuthorizationException; 33 import org.apache.maven.wagon.events.TransferListener; 34 import org.apache.maven.wagon.observers.ChecksumObserver; 35 import org.apache.maven.wagon.proxy.ProxyInfo; 36 import org.apache.maven.wagon.repository.Repository; 37 import org.apache.maven.wagon.repository.RepositoryPermissions; 38 import org.codehaus.plexus.PlexusConstants; 39 import org.codehaus.plexus.PlexusContainer; 40 import org.codehaus.plexus.component.configurator.ComponentConfigurationException; 41 import org.codehaus.plexus.component.configurator.ComponentConfigurator; 42 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; 43 import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 44 import org.codehaus.plexus.configuration.PlexusConfiguration; 45 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; 46 import org.codehaus.plexus.context.Context; 47 import org.codehaus.plexus.context.ContextException; 48 import org.codehaus.plexus.logging.AbstractLogEnabled; 49 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; 50 import org.codehaus.plexus.util.FileUtils; 51 import org.codehaus.plexus.util.xml.Xpp3Dom; 52 53 import java.io.File ; 54 import java.io.IOException ; 55 import java.security.NoSuchAlgorithmException ; 56 import java.util.HashMap ; 57 import java.util.Iterator ; 58 import java.util.List ; 59 import java.util.Map ; 60 61 public class DefaultWagonManager 62 extends AbstractLogEnabled 63 implements WagonManager, Contextualizable 64 { 65 private PlexusContainer container; 66 67 private Map proxies = new HashMap (); 70 71 private Map authenticationInfoMap = new HashMap (); 72 73 private Map serverPermissionsMap = new HashMap (); 74 75 private Map mirrors = new HashMap (); 76 77 private Map serverConfigurationMap = new HashMap (); 78 79 private TransferListener downloadMonitor; 80 81 private boolean online = true; 82 83 private ArtifactRepositoryFactory repositoryFactory; 84 85 private boolean interactive = true; 86 87 public Wagon getWagon( String protocol ) 88 throws UnsupportedProtocolException 89 { 90 Wagon wagon; 91 92 try 93 { 94 wagon = (Wagon) container.lookup( Wagon.ROLE, protocol ); 95 wagon.setInteractive( interactive ); 96 } 97 catch ( ComponentLookupException e ) 98 { 99 throw new UnsupportedProtocolException( 100 "Cannot find wagon which supports the requested protocol: " + protocol, e ); 101 } 102 103 return wagon; 104 } 105 106 public void putArtifact( File source, Artifact artifact, ArtifactRepository repository ) 107 throws TransferFailedException 108 { 109 putRemoteFile( repository, source, repository.pathOf( artifact ), downloadMonitor ); 110 } 111 112 public void putArtifactMetadata( File source, ArtifactMetadata artifactMetadata, ArtifactRepository repository ) 113 throws TransferFailedException 114 { 115 getLogger().info( "Uploading " + artifactMetadata ); 116 putRemoteFile( repository, source, repository.pathOfRemoteRepositoryMetadata( artifactMetadata ), null ); 117 } 118 119 private void putRemoteFile( ArtifactRepository repository, File source, String remotePath, 120 TransferListener downloadMonitor ) 121 throws TransferFailedException 122 { 123 failIfNotOnline(); 124 125 String protocol = repository.getProtocol(); 126 127 Wagon wagon; 128 try 129 { 130 wagon = getWagon( protocol ); 131 132 configureWagon( wagon, repository ); 133 } 134 catch ( UnsupportedProtocolException e ) 135 { 136 throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e ); 137 } 138 139 if ( downloadMonitor != null ) 140 { 141 wagon.addTransferListener( downloadMonitor ); 142 } 143 144 Map checksums = new HashMap ( 2 ); 145 Map sums = new HashMap ( 2 ); 146 147 try 149 { 150 ChecksumObserver checksumObserver = new ChecksumObserver( "MD5" ); 151 wagon.addTransferListener( checksumObserver ); 152 checksums.put( "md5", checksumObserver ); 153 checksumObserver = new ChecksumObserver( "SHA-1" ); 154 wagon.addTransferListener( checksumObserver ); 155 checksums.put( "sha1", checksumObserver ); 156 } 157 catch ( NoSuchAlgorithmException e ) 158 { 159 throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e ); 160 } 161 162 try 163 { 164 Repository artifactRepository = new Repository( repository.getId(), repository.getUrl() ); 165 166 if ( serverPermissionsMap.containsKey( repository.getId() ) ) 167 { 168 RepositoryPermissions perms = (RepositoryPermissions) serverPermissionsMap.get( repository.getId() ); 169 getLogger().debug( 170 "adding permissions to wagon connection: " + perms.getFileMode() + " " + perms.getDirectoryMode() ); 171 artifactRepository.setPermissions( perms ); 172 } 173 else 174 { 175 getLogger().debug( "not adding permissions to wagon connection" ); 176 } 177 178 wagon.connect( artifactRepository, getAuthenticationInfo( repository.getId() ), getProxy( protocol ) ); 179 180 wagon.put( source, remotePath ); 181 182 wagon.removeTransferListener( downloadMonitor ); 183 184 for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); ) 186 { 187 String extension = (String ) i.next(); 188 ChecksumObserver observer = (ChecksumObserver) checksums.get( extension ); 189 sums.put( extension, observer.getActualChecksum() ); 190 } 191 192 for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); ) 194 { 195 String extension = (String ) i.next(); 196 197 File temp = File.createTempFile( "maven-artifact", null ); 199 temp.deleteOnExit(); 200 FileUtils.fileWrite( temp.getAbsolutePath(), (String ) sums.get( extension ) ); 201 202 wagon.put( temp, remotePath + "." + extension ); 203 } 204 } 205 catch ( ConnectionException e ) 206 { 207 throw new TransferFailedException( "Connection failed: " + e.getMessage(), e ); 208 } 209 catch ( AuthenticationException e ) 210 { 211 throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e ); 212 } 213 catch ( AuthorizationException e ) 214 { 215 throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e ); 216 } 217 catch ( ResourceDoesNotExistException e ) 218 { 219 throw new TransferFailedException( "Resource to deploy not found: " + e.getMessage(), e ); 220 } 221 catch ( IOException e ) 222 { 223 throw new TransferFailedException( "Error creating temporary file for deployment: " + e.getMessage(), e ); 224 } 225 finally 226 { 227 disconnectWagon( wagon ); 228 229 releaseWagon( wagon ); 230 } 231 } 232 233 public void getArtifact( Artifact artifact, List remoteRepositories ) 234 throws TransferFailedException, ResourceDoesNotExistException 235 { 236 boolean successful = false; 238 for ( Iterator iter = remoteRepositories.iterator(); iter.hasNext() && !successful; ) 239 { 240 ArtifactRepository repository = (ArtifactRepository) iter.next(); 241 242 try 243 { 244 getArtifact( artifact, repository ); 245 246 successful = artifact.isResolved(); 247 } 248 catch ( ResourceDoesNotExistException e ) 249 { 250 253 getLogger().warn( 254 "Unable to get resource from repository " + repository.getId() + " (" + repository.getUrl() + ")" ); 255 } 256 } 257 258 if ( !successful ) 259 { 260 throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" ); 261 } 262 } 263 264 public void getArtifact( Artifact artifact, ArtifactRepository repository ) 265 throws TransferFailedException, ResourceDoesNotExistException 266 { 267 String remotePath = repository.pathOf( artifact ); 268 269 ArtifactRepositoryPolicy policy = artifact.isSnapshot() ? repository.getSnapshots() : repository.getReleases(); 270 271 if ( !policy.isEnabled() ) 272 { 273 getLogger().debug( "Skipping disabled repository " + repository.getId() ); 274 } 275 else if ( repository.isBlacklisted() ) 276 { 277 getLogger().debug( "Skipping blacklisted repository " + repository.getId() ); 278 } 279 else 280 { 281 getLogger().debug( "Trying repository " + repository.getId() ); 282 getRemoteFile( repository, artifact.getFile(), remotePath, downloadMonitor, policy.getChecksumPolicy() ); 283 getLogger().debug( " Artifact resolved" ); 284 285 artifact.setResolved( true ); 286 } 287 } 288 289 public void getArtifactMetadata( ArtifactMetadata metadata, ArtifactRepository repository, File destination, 290 String checksumPolicy ) 291 throws TransferFailedException, ResourceDoesNotExistException 292 { 293 String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata ); 294 295 getRemoteFile( repository, destination, remotePath, null, checksumPolicy ); 296 } 297 298 private void getRemoteFile( ArtifactRepository repository, File destination, String remotePath, 299 TransferListener downloadMonitor, String checksumPolicy ) 300 throws TransferFailedException, ResourceDoesNotExistException, ChecksumFailedException 301 { 302 304 failIfNotOnline(); 305 306 Wagon wagon; 307 308 ArtifactRepository mirror = getMirror( repository.getId() ); 309 if ( mirror != null ) 310 { 311 repository = repositoryFactory.createArtifactRepository( mirror.getId(), mirror.getUrl(), 312 repository.getLayout(), repository.getSnapshots(), 313 repository.getReleases() ); 314 } 315 316 String protocol = repository.getProtocol(); 317 try 318 { 319 wagon = getWagon( protocol ); 320 321 configureWagon( wagon, repository ); 322 } 323 catch ( UnsupportedProtocolException e ) 324 { 325 throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e ); 326 } 327 328 if ( downloadMonitor != null ) 329 { 330 wagon.addTransferListener( downloadMonitor ); 331 } 332 333 ChecksumObserver md5ChecksumObserver; 335 ChecksumObserver sha1ChecksumObserver; 336 try 337 { 338 md5ChecksumObserver = new ChecksumObserver( "MD5" ); 339 wagon.addTransferListener( md5ChecksumObserver ); 340 341 sha1ChecksumObserver = new ChecksumObserver( "SHA-1" ); 342 wagon.addTransferListener( sha1ChecksumObserver ); 343 } 344 catch ( NoSuchAlgorithmException e ) 345 { 346 throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e ); 347 } 348 349 File temp = new File ( destination + ".tmp" ); 350 temp.deleteOnExit(); 351 352 try 353 { 354 wagon.connect( new Repository( repository.getId(), repository.getUrl() ), 355 getAuthenticationInfo( repository.getId() ), getProxy( protocol ) ); 356 357 boolean firstRun = true; 358 boolean retry = true; 359 360 while ( firstRun || retry ) 364 { 365 retry = false; 367 368 wagon.get( remotePath, temp ); 370 371 if ( downloadMonitor != null ) 373 { 374 wagon.removeTransferListener( downloadMonitor ); 375 } 376 377 try 379 { 380 verifyChecksum( sha1ChecksumObserver, destination, temp, remotePath, ".sha1", wagon ); 381 } 382 catch ( ChecksumFailedException e ) 383 { 384 if ( firstRun ) 389 { 390 getLogger().warn( "*** CHECKSUM FAILED - " + e.getMessage() + " - RETRYING" ); 391 retry = true; 392 } 393 else 394 { 395 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() ); 396 } 397 } 398 catch ( ResourceDoesNotExistException sha1TryException ) 399 { 400 getLogger().debug( "SHA1 not found, trying MD5", sha1TryException ); 401 402 try 405 { 406 verifyChecksum( md5ChecksumObserver, destination, temp, remotePath, ".md5", wagon ); 407 } 408 catch ( ChecksumFailedException e ) 409 { 410 if ( firstRun ) 413 { 414 retry = true; 415 } 416 else 417 { 418 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() ); 419 } 420 } 421 catch ( ResourceDoesNotExistException md5TryException ) 422 { 423 handleChecksumFailure( checksumPolicy, "Error retrieving checksum file for " + remotePath, 425 md5TryException ); 426 } 427 } 428 429 if ( downloadMonitor != null ) 431 { 432 wagon.addTransferListener( downloadMonitor ); 433 } 434 435 firstRun = false; 437 } 438 } 439 catch ( ConnectionException e ) 440 { 441 throw new TransferFailedException( "Connection failed: " + e.getMessage(), e ); 442 } 443 catch ( AuthenticationException e ) 444 { 445 throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e ); 446 } 447 catch ( AuthorizationException e ) 448 { 449 throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e ); 450 } 451 finally 452 { 453 disconnectWagon( wagon ); 454 455 releaseWagon( wagon ); 456 } 457 458 if ( !temp.exists() ) 459 { 460 throw new ResourceDoesNotExistException( "Downloaded file does not exist: " + temp ); 461 } 462 463 469 if ( !temp.renameTo( destination ) ) 470 { 471 try 472 { 473 FileUtils.copyFile( temp, destination ); 474 475 temp.delete(); 476 } 477 catch ( IOException e ) 478 { 479 throw new TransferFailedException( 480 "Error copying temporary file to the final destination: " + e.getMessage(), e ); 481 } 482 } 483 } 484 485 private void failIfNotOnline() 486 throws TransferFailedException 487 { 488 if ( !isOnline() ) 489 { 490 throw new TransferFailedException( "System is offline." ); 491 } 492 } 493 494 private void handleChecksumFailure( String checksumPolicy, String message, Throwable cause ) 495 throws ChecksumFailedException 496 { 497 if ( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) ) 498 { 499 throw new ChecksumFailedException( message, cause ); 500 } 501 else if ( !ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) ) 502 { 503 getLogger().warn( "*** CHECKSUM FAILED - " + message + " - IGNORING" ); 505 } 506 } 508 509 private void verifyChecksum( ChecksumObserver checksumObserver, File destination, File tempDestination, String remotePath, 510 String checksumFileExtension, Wagon wagon ) 511 throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException 512 { 513 try 514 { 515 String actualChecksum = checksumObserver.getActualChecksum(); 517 518 File tempChecksumFile = new File ( tempDestination + checksumFileExtension + ".tmp" ); 519 tempChecksumFile.deleteOnExit(); 520 wagon.get( remotePath + checksumFileExtension, tempChecksumFile ); 521 522 String expectedChecksum = FileUtils.fileRead( tempChecksumFile ); 523 524 expectedChecksum = expectedChecksum.trim(); 526 527 if ( expectedChecksum.startsWith( "MD5" ) ) 529 { 530 int lastSpacePos = expectedChecksum.lastIndexOf( ' ' ); 531 expectedChecksum = expectedChecksum.substring( lastSpacePos + 1 ); 532 } 533 else 534 { 535 int spacePos = expectedChecksum.indexOf( ' ' ); 537 538 if ( spacePos != -1 ) 539 { 540 expectedChecksum = expectedChecksum.substring( 0, spacePos ); 541 } 542 } 543 if ( expectedChecksum.equals( actualChecksum ) ) 544 { 545 File checksumFile = new File ( destination + checksumFileExtension ); 546 if ( checksumFile.exists() ) checksumFile.delete(); 547 FileUtils.copyFile( tempChecksumFile, checksumFile ); 548 } 549 else 550 { 551 throw new ChecksumFailedException( "Checksum failed on download: local = '" + actualChecksum + 552 "'; remote = '" + expectedChecksum + "'" ); 553 } 554 } 555 catch ( IOException e ) 556 { 557 throw new ChecksumFailedException( "Invalid checksum file", e ); 558 } 559 } 560 561 private void disconnectWagon( Wagon wagon ) 562 { 563 try 564 { 565 wagon.disconnect(); 566 } 567 catch ( ConnectionException e ) 568 { 569 getLogger().error( "Problem disconnecting from wagon - ignoring: " + e.getMessage() ); 570 } 571 } 572 573 private void releaseWagon( Wagon wagon ) 574 { 575 try 576 { 577 container.release( wagon ); 578 } 579 catch ( ComponentLifecycleException e ) 580 { 581 getLogger().error( "Problem releasing wagon - ignoring: " + e.getMessage() ); 582 } 583 } 584 585 public ProxyInfo getProxy( String protocol ) 586 { 587 return (ProxyInfo) proxies.get( protocol ); 588 } 589 590 public AuthenticationInfo getAuthenticationInfo( String id ) 591 { 592 return (AuthenticationInfo) authenticationInfoMap.get( id ); 593 } 594 595 public ArtifactRepository getMirror( String mirrorOf ) 596 { 597 return (ArtifactRepository) mirrors.get( mirrorOf ); 598 } 599 600 612 public void addProxy( String protocol, String host, int port, String username, String password, 613 String nonProxyHosts ) 614 { 615 ProxyInfo proxyInfo = new ProxyInfo(); 616 proxyInfo.setHost( host ); 617 proxyInfo.setType( protocol ); 618 proxyInfo.setPort( port ); 619 proxyInfo.setNonProxyHosts( nonProxyHosts ); 620 proxyInfo.setUserName( username ); 621 proxyInfo.setPassword( password ); 622 623 proxies.put( protocol, proxyInfo ); 624 } 625 626 public void contextualize( Context context ) 627 throws ContextException 628 { 629 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); 630 } 631 632 635 public void setDownloadMonitor( TransferListener downloadMonitor ) 636 { 637 this.downloadMonitor = downloadMonitor; 638 } 639 640 public void addAuthenticationInfo( String repositoryId, String username, String password, String privateKey, 641 String passphrase ) 642 { 643 AuthenticationInfo authInfo = new AuthenticationInfo(); 644 645 authInfo.setUserName( username ); 646 647 authInfo.setPassword( password ); 648 649 authInfo.setPrivateKey( privateKey ); 650 651 authInfo.setPassphrase( passphrase ); 652 653 authenticationInfoMap.put( repositoryId, authInfo ); 654 } 655 656 public void addPermissionInfo( String repositoryId, String filePermissions, String directoryPermissions ) 657 { 658 659 RepositoryPermissions permissions = new RepositoryPermissions(); 660 boolean addPermissions = false; 661 662 if ( filePermissions != null ) 663 { 664 permissions.setFileMode( filePermissions ); 665 addPermissions = true; 666 } 667 668 if ( directoryPermissions != null ) 669 { 670 permissions.setDirectoryMode( directoryPermissions ); 671 addPermissions = true; 672 } 673 674 if ( addPermissions ) 675 { 676 serverPermissionsMap.put( repositoryId, permissions ); 677 } 678 } 679 680 public void addMirror( String id, String mirrorOf, String url ) 681 { 682 ArtifactRepository mirror = new DefaultArtifactRepository( id, url, null ); 683 684 mirrors.put( mirrorOf, mirror ); 685 } 686 687 public void setOnline( boolean online ) 688 { 689 this.online = online; 690 } 691 692 public boolean isOnline() 693 { 694 return online; 695 } 696 697 public void setInteractive( boolean interactive ) 698 { 699 this.interactive = interactive; 700 } 701 702 703 710 private void configureWagon( Wagon wagon, ArtifactRepository repository ) 711 throws WagonConfigurationException 712 { 713 714 final String repositoryId = repository.getId(); 715 716 if ( serverConfigurationMap.containsKey( repositoryId ) ) 717 { 718 ComponentConfigurator componentConfigurator = null; 719 try 720 { 721 componentConfigurator = (ComponentConfigurator) container.lookup( ComponentConfigurator.ROLE ); 722 componentConfigurator.configureComponent( wagon, (PlexusConfiguration) serverConfigurationMap 723 .get( repositoryId ), container.getContainerRealm() ); 724 } 725 catch ( final ComponentLookupException e ) 726 { 727 throw new WagonConfigurationException( repositoryId, "Unable to lookup wagon configurator. Wagon configuration cannot be applied.", e ); 728 } 729 catch ( ComponentConfigurationException e ) 730 { 731 throw new WagonConfigurationException( repositoryId, "Unable to apply wagon configuration.", e ); 732 } 733 finally 734 { 735 if ( componentConfigurator != null ) 736 { 737 try 738 { 739 container.release( componentConfigurator ); 740 } 741 catch ( ComponentLifecycleException e ) 742 { 743 getLogger().error( "Problem releasing configurator - ignoring: " + e.getMessage() ); 744 } 745 } 746 747 } 748 } 749 } 750 751 752 public void addConfiguration( String repositoryId, Xpp3Dom configuration ) 753 { 754 755 if ( repositoryId == null || configuration == null ) 756 { 757 throw new IllegalArgumentException ( "arguments can't be null" ); 758 } 759 760 final XmlPlexusConfiguration xmlConf = new XmlPlexusConfiguration( configuration ); 761 762 serverConfigurationMap.put( repositoryId, xmlConf ); 763 } 764 } 765 | Popular Tags |