001package org.apache.maven.repository.legacy; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.io.IOException; 024import java.lang.reflect.Method; 025import java.security.NoSuchAlgorithmException; 026import java.util.ArrayList; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Map; 030import java.util.Properties; 031 032import org.apache.maven.artifact.Artifact; 033import org.apache.maven.artifact.metadata.ArtifactMetadata; 034import org.apache.maven.artifact.repository.ArtifactRepository; 035import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; 036import org.apache.maven.plugin.LegacySupport; 037import org.apache.maven.wagon.ConnectionException; 038import org.apache.maven.wagon.ResourceDoesNotExistException; 039import org.apache.maven.wagon.TransferFailedException; 040import org.apache.maven.wagon.UnsupportedProtocolException; 041import org.apache.maven.wagon.Wagon; 042import org.apache.maven.wagon.authentication.AuthenticationException; 043import org.apache.maven.wagon.authentication.AuthenticationInfo; 044import org.apache.maven.wagon.authorization.AuthorizationException; 045import org.apache.maven.wagon.events.TransferListener; 046import org.apache.maven.wagon.observers.ChecksumObserver; 047import org.apache.maven.wagon.proxy.ProxyInfo; 048import org.apache.maven.wagon.repository.Repository; 049import org.codehaus.plexus.PlexusContainer; 050import org.codehaus.plexus.component.annotations.Component; 051import org.codehaus.plexus.component.annotations.Requirement; 052import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; 053import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 054import org.codehaus.plexus.logging.Logger; 055import org.codehaus.plexus.util.FileUtils; 056import org.eclipse.aether.ConfigurationProperties; 057import org.eclipse.aether.util.ConfigUtils; 058 059//TODO: remove the update check manager 060//TODO: separate into retriever and publisher 061//TODO: remove hardcoding of checksum logic 062@Component( role = WagonManager.class ) 063public class DefaultWagonManager 064 implements WagonManager 065{ 066 private static final String[] CHECKSUM_IDS = { "md5", "sha1" }; 067 068 /** have to match the CHECKSUM_IDS */ 069 private static final String[] CHECKSUM_ALGORITHMS = { "MD5", "SHA-1" }; 070 071 @Requirement 072 private Logger logger; 073 074 @Requirement 075 private PlexusContainer container; 076 077 @Requirement 078 private UpdateCheckManager updateCheckManager; 079 080 @Requirement 081 private LegacySupport legacySupport; 082 083 084 // 085 // Retriever 086 // 087 @Override 088 public void getArtifact( Artifact artifact, ArtifactRepository repository, TransferListener downloadMonitor, 089 boolean force ) 090 throws TransferFailedException, ResourceDoesNotExistException 091 { 092 String remotePath = repository.pathOf( artifact ); 093 094 ArtifactRepositoryPolicy policy = artifact.isSnapshot() ? repository.getSnapshots() : repository.getReleases(); 095 096 if ( !policy.isEnabled() ) 097 { 098 logger.debug( "Skipping disabled repository " + repository.getId() + " for resolution of " 099 + artifact.getId() ); 100 } 101 else if ( artifact.isSnapshot() || !artifact.getFile().exists() ) 102 { 103 if ( force || updateCheckManager.isUpdateRequired( artifact, repository ) ) 104 { 105 logger.debug( "Trying repository " + repository.getId() + " for resolution of " + artifact.getId() 106 + " from " + remotePath ); 107 108 try 109 { 110 getRemoteFile( repository, artifact.getFile(), remotePath, downloadMonitor, 111 policy.getChecksumPolicy(), false ); 112 113 updateCheckManager.touch( artifact, repository, null ); 114 } 115 catch ( ResourceDoesNotExistException e ) 116 { 117 updateCheckManager.touch( artifact, repository, null ); 118 throw e; 119 } 120 catch ( TransferFailedException e ) 121 { 122 String error = ( e.getMessage() != null ) ? e.getMessage() : e.getClass().getSimpleName(); 123 updateCheckManager.touch( artifact, repository, error ); 124 throw e; 125 } 126 127 logger.debug( " Artifact " + artifact.getId() + " resolved to " + artifact.getFile() ); 128 129 artifact.setResolved( true ); 130 } 131 else if ( !artifact.getFile().exists() ) 132 { 133 String error = updateCheckManager.getError( artifact, repository ); 134 if ( error != null ) 135 { 136 throw new TransferFailedException( "Failure to resolve " + remotePath + " from " 137 + repository.getUrl() + " was cached in the local repository. " 138 + "Resolution will not be reattempted until the update interval of " + repository.getId() 139 + " has elapsed or updates are forced. Original error: " + error ); 140 } 141 else 142 { 143 throw new ResourceDoesNotExistException( "Failure to resolve " + remotePath + " from " 144 + repository.getUrl() + " was cached in the local repository. " 145 + "Resolution will not be reattempted until the update interval of " + repository.getId() 146 + " has elapsed or updates are forced." ); 147 } 148 } 149 } 150 } 151 152 @Override 153 public void getArtifact( Artifact artifact, List<ArtifactRepository> remoteRepositories, 154 TransferListener downloadMonitor, boolean force ) 155 throws TransferFailedException, ResourceDoesNotExistException 156 { 157 TransferFailedException tfe = null; 158 159 for ( ArtifactRepository repository : remoteRepositories ) 160 { 161 try 162 { 163 getArtifact( artifact, repository, downloadMonitor, force ); 164 165 if ( artifact.isResolved() ) 166 { 167 artifact.setRepository( repository ); 168 break; 169 } 170 } 171 catch ( ResourceDoesNotExistException e ) 172 { 173 // This one we will eat when looking through remote repositories 174 // because we want to cycle through them all before squawking. 175 176 logger.debug( "Unable to find artifact " + artifact.getId() + " in repository " + repository.getId() 177 + " (" + repository.getUrl() + ")", e ); 178 } 179 catch ( TransferFailedException e ) 180 { 181 tfe = e; 182 183 String msg = 184 "Unable to get artifact " + artifact.getId() + " from repository " + repository.getId() + " (" 185 + repository.getUrl() + "): " + e.getMessage(); 186 if ( logger.isDebugEnabled() ) 187 { 188 logger.warn( msg, e ); 189 } 190 else 191 { 192 logger.warn( msg ); 193 } 194 } 195 } 196 197 // if it already exists locally we were just trying to force it - ignore the update 198 if ( !artifact.getFile().exists() ) 199 { 200 if ( tfe != null ) 201 { 202 throw tfe; 203 } 204 else 205 { 206 throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" ); 207 } 208 } 209 } 210 211 @Override 212 public void getArtifactMetadata( ArtifactMetadata metadata, ArtifactRepository repository, File destination, 213 String checksumPolicy ) 214 throws TransferFailedException, ResourceDoesNotExistException 215 { 216 String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata ); 217 218 getRemoteFile( repository, destination, remotePath, null, checksumPolicy, true ); 219 } 220 221 @Override 222 public void getArtifactMetadataFromDeploymentRepository( ArtifactMetadata metadata, ArtifactRepository repository, 223 File destination, String checksumPolicy ) 224 throws TransferFailedException, ResourceDoesNotExistException 225 { 226 String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata ); 227 228 getRemoteFile( repository, destination, remotePath, null, checksumPolicy, true ); 229 } 230 231 /** 232 * Deal with connecting to a wagon repository taking into account authentication and proxies. 233 * 234 * @param wagon 235 * @param repository 236 * @throws ConnectionException 237 * @throws AuthenticationException 238 */ 239 private void connectWagon( Wagon wagon, ArtifactRepository repository ) 240 throws ConnectionException, AuthenticationException 241 { 242 // MNG-5509 243 // See org.eclipse.aether.connector.wagon.WagonRepositoryConnector.connectWagon(Wagon) 244 if( legacySupport.getRepositorySession() != null ) 245 { 246 String userAgent = ConfigUtils.getString( legacySupport.getRepositorySession(), null, ConfigurationProperties.USER_AGENT ); 247 if( userAgent == null) 248 { 249 Properties headers = new Properties(); 250 251 headers.put( "User-Agent", ConfigUtils.getString( legacySupport.getRepositorySession(), "Maven", 252 ConfigurationProperties.USER_AGENT ) ); 253 try 254 { 255 Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class ); 256 setHttpHeaders.invoke( wagon, headers ); 257 } 258 catch ( NoSuchMethodException e ) 259 { 260 // normal for non-http wagons 261 } 262 catch ( Exception e ) 263 { 264 logger.debug( "Could not set user agent for wagon " + wagon.getClass().getName() + ": " + e ); 265 } 266 } 267 } 268 269 if ( repository.getProxy() != null && logger.isDebugEnabled() ) 270 { 271 logger.debug( "Using proxy " + repository.getProxy().getHost() + ":" + repository.getProxy().getPort() 272 + " for " + repository.getUrl() ); 273 } 274 275 if ( repository.getAuthentication() != null && repository.getProxy() != null ) 276 { 277 wagon.connect( new Repository( repository.getId(), repository.getUrl() ), authenticationInfo( repository ), 278 proxyInfo( repository ) ); 279 } 280 else if ( repository.getAuthentication() != null ) 281 { 282 wagon.connect( new Repository( repository.getId(), repository.getUrl() ), 283 authenticationInfo( repository ) ); 284 } 285 else if ( repository.getProxy() != null ) 286 { 287 wagon.connect( new Repository( repository.getId(), repository.getUrl() ), proxyInfo( repository ) ); 288 } 289 else 290 { 291 wagon.connect( new Repository( repository.getId(), repository.getUrl() ) ); 292 } 293 } 294 295 private AuthenticationInfo authenticationInfo( ArtifactRepository repository ) 296 { 297 AuthenticationInfo ai = new AuthenticationInfo(); 298 ai.setUserName( repository.getAuthentication().getUsername() ); 299 ai.setPassword( repository.getAuthentication().getPassword() ); 300 return ai; 301 } 302 303 private ProxyInfo proxyInfo( ArtifactRepository repository ) 304 { 305 ProxyInfo proxyInfo = new ProxyInfo(); 306 proxyInfo.setHost( repository.getProxy().getHost() ); 307 proxyInfo.setType( repository.getProxy().getProtocol() ); 308 proxyInfo.setPort( repository.getProxy().getPort() ); 309 proxyInfo.setNonProxyHosts( repository.getProxy().getNonProxyHosts() ); 310 proxyInfo.setUserName( repository.getProxy().getUserName() ); 311 proxyInfo.setPassword( repository.getProxy().getPassword() ); 312 return proxyInfo; 313 } 314 315 @Override 316 public void getRemoteFile( ArtifactRepository repository, File destination, String remotePath, 317 TransferListener downloadMonitor, String checksumPolicy, boolean force ) 318 throws TransferFailedException, ResourceDoesNotExistException 319 { 320 String protocol = repository.getProtocol(); 321 322 Wagon wagon; 323 324 try 325 { 326 wagon = getWagon( protocol ); 327 } 328 catch ( UnsupportedProtocolException e ) 329 { 330 throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e ); 331 } 332 333 if ( downloadMonitor != null ) 334 { 335 wagon.addTransferListener( downloadMonitor ); 336 } 337 338 File temp = new File( destination + ".tmp" ); 339 340 temp.deleteOnExit(); 341 342 boolean downloaded = false; 343 344 try 345 { 346 connectWagon( wagon, repository ); 347 348 boolean firstRun = true; 349 boolean retry = true; 350 351 // this will run at most twice. The first time, the firstRun flag is turned off, and if the retry flag 352 // is set on the first run, it will be turned off and not re-set on the second try. This is because the 353 // only way the retry flag can be set is if ( firstRun == true ). 354 while ( firstRun || retry ) 355 { 356 ChecksumObserver md5ChecksumObserver = null; 357 ChecksumObserver sha1ChecksumObserver = null; 358 try 359 { 360 // TODO: configure on repository 361 int i = 0; 362 363 md5ChecksumObserver = addChecksumObserver( wagon, CHECKSUM_ALGORITHMS[i++] ); 364 sha1ChecksumObserver = addChecksumObserver( wagon, CHECKSUM_ALGORITHMS[i++] ); 365 366 // reset the retry flag. 367 retry = false; 368 369 // This should take care of creating destination directory now on 370 if ( destination.exists() && !force ) 371 { 372 try 373 { 374 downloaded = wagon.getIfNewer( remotePath, temp, destination.lastModified() ); 375 376 if ( !downloaded ) 377 { 378 // prevent additional checks of this artifact until it expires again 379 destination.setLastModified( System.currentTimeMillis() ); 380 } 381 } 382 catch ( UnsupportedOperationException e ) 383 { 384 // older wagons throw this. Just get() instead 385 wagon.get( remotePath, temp ); 386 387 downloaded = true; 388 } 389 } 390 else 391 { 392 wagon.get( remotePath, temp ); 393 downloaded = true; 394 } 395 } 396 finally 397 { 398 wagon.removeTransferListener( md5ChecksumObserver ); 399 wagon.removeTransferListener( sha1ChecksumObserver ); 400 } 401 402 if ( downloaded ) 403 { 404 // keep the checksum files from showing up on the download monitor... 405 if ( downloadMonitor != null ) 406 { 407 wagon.removeTransferListener( downloadMonitor ); 408 } 409 410 // try to verify the SHA-1 checksum for this file. 411 try 412 { 413 verifyChecksum( sha1ChecksumObserver, destination, temp, remotePath, ".sha1", wagon ); 414 } 415 catch ( ChecksumFailedException e ) 416 { 417 // if we catch a ChecksumFailedException, it means the transfer/read succeeded, but the checksum 418 // doesn't match. This could be a problem with the server (ibiblio HTTP-200 error page), so we'll 419 // try this up to two times. On the second try, we'll handle it as a bona-fide error, based on the 420 // repository's checksum checking policy. 421 if ( firstRun ) 422 { 423 logger.warn( "*** CHECKSUM FAILED - " + e.getMessage() + " - RETRYING" ); 424 retry = true; 425 } 426 else 427 { 428 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() ); 429 } 430 } 431 catch ( ResourceDoesNotExistException sha1TryException ) 432 { 433 logger.debug( "SHA1 not found, trying MD5: " + sha1TryException.getMessage() ); 434 435 // if this IS NOT a ChecksumFailedException, it was a problem with transfer/read of the checksum 436 // file...we'll try again with the MD5 checksum. 437 try 438 { 439 verifyChecksum( md5ChecksumObserver, destination, temp, remotePath, ".md5", wagon ); 440 } 441 catch ( ChecksumFailedException e ) 442 { 443 // if we also fail to verify based on the MD5 checksum, and the checksum transfer/read 444 // succeeded, then we need to determine whether to retry or handle it as a failure. 445 if ( firstRun ) 446 { 447 retry = true; 448 } 449 else 450 { 451 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() ); 452 } 453 } 454 catch ( ResourceDoesNotExistException md5TryException ) 455 { 456 // this was a failed transfer, and we don't want to retry. 457 handleChecksumFailure( checksumPolicy, "Error retrieving checksum file for " + remotePath, 458 md5TryException ); 459 } 460 } 461 462 // reinstate the download monitor... 463 if ( downloadMonitor != null ) 464 { 465 wagon.addTransferListener( downloadMonitor ); 466 } 467 } 468 469 // unset the firstRun flag, so we don't get caught in an infinite loop... 470 firstRun = false; 471 } 472 } 473 catch ( ConnectionException e ) 474 { 475 throw new TransferFailedException( "Connection failed: " + e.getMessage(), e ); 476 } 477 catch ( AuthenticationException e ) 478 { 479 throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e ); 480 } 481 catch ( AuthorizationException e ) 482 { 483 throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e ); 484 } 485 finally 486 { 487 // Remove remaining TransferListener instances (checksum handlers removed in above finally clause) 488 if ( downloadMonitor != null ) 489 { 490 wagon.removeTransferListener( downloadMonitor ); 491 } 492 493 disconnectWagon( wagon ); 494 495 releaseWagon( protocol, wagon ); 496 } 497 498 if ( downloaded ) 499 { 500 if ( !temp.exists() ) 501 { 502 throw new ResourceDoesNotExistException( "Downloaded file does not exist: " + temp ); 503 } 504 505 // The temporary file is named destination + ".tmp" and is done this way to ensure 506 // that the temporary file is in the same file system as the destination because the 507 // File.renameTo operation doesn't really work across file systems. 508 // So we will attempt to do a File.renameTo for efficiency and atomicity, if this fails 509 // then we will use a brute force copy and delete the temporary file. 510 511 if ( !temp.renameTo( destination ) ) 512 { 513 try 514 { 515 FileUtils.copyFile( temp, destination ); 516 517 if ( !temp.delete() ) 518 { 519 temp.deleteOnExit(); 520 } 521 } 522 catch ( IOException e ) 523 { 524 throw new TransferFailedException( "Error copying temporary file to the final destination: " 525 + e.getMessage(), e ); 526 } 527 } 528 } 529 } 530 531 // 532 // Publisher 533 // 534 @Override 535 public void putArtifact( File source, Artifact artifact, ArtifactRepository deploymentRepository, 536 TransferListener downloadMonitor ) 537 throws TransferFailedException 538 { 539 putRemoteFile( deploymentRepository, source, deploymentRepository.pathOf( artifact ), downloadMonitor ); 540 } 541 542 @Override 543 public void putArtifactMetadata( File source, ArtifactMetadata artifactMetadata, ArtifactRepository repository ) 544 throws TransferFailedException 545 { 546 logger.info( "Uploading " + artifactMetadata ); 547 putRemoteFile( repository, source, repository.pathOfRemoteRepositoryMetadata( artifactMetadata ), null ); 548 } 549 550 @Override 551 public void putRemoteFile( ArtifactRepository repository, File source, String remotePath, 552 TransferListener downloadMonitor ) 553 throws TransferFailedException 554 { 555 String protocol = repository.getProtocol(); 556 557 Wagon wagon; 558 try 559 { 560 wagon = getWagon( protocol ); 561 } 562 catch ( UnsupportedProtocolException e ) 563 { 564 throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e ); 565 } 566 567 if ( downloadMonitor != null ) 568 { 569 wagon.addTransferListener( downloadMonitor ); 570 } 571 572 Map<String, ChecksumObserver> checksums = new HashMap<>( 2 ); 573 574 Map<String, String> sums = new HashMap<>( 2 ); 575 576 // TODO: configure these on the repository 577 for ( int i = 0; i < CHECKSUM_IDS.length; i++ ) 578 { 579 checksums.put( CHECKSUM_IDS[i], addChecksumObserver( wagon, CHECKSUM_ALGORITHMS[i] ) ); 580 } 581 582 List<File> temporaryFiles = new ArrayList<>(); 583 584 try 585 { 586 try 587 { 588 connectWagon( wagon, repository ); 589 590 wagon.put( source, remotePath ); 591 } 592 finally 593 { 594 if ( downloadMonitor != null ) 595 { 596 wagon.removeTransferListener( downloadMonitor ); 597 } 598 } 599 600 // Pre-store the checksums as any future puts will overwrite them 601 for ( String extension : checksums.keySet() ) 602 { 603 ChecksumObserver observer = checksums.get( extension ); 604 sums.put( extension, observer.getActualChecksum() ); 605 } 606 607 // We do this in here so we can checksum the artifact metadata too, otherwise it could be metadata itself 608 for ( String extension : checksums.keySet() ) 609 { 610 // TODO: shouldn't need a file intermediatary - improve wagon to take a stream 611 File temp = File.createTempFile( "maven-artifact", null ); 612 temp.deleteOnExit(); 613 FileUtils.fileWrite( temp.getAbsolutePath(), "UTF-8", sums.get( extension ) ); 614 615 temporaryFiles.add( temp ); 616 wagon.put( temp, remotePath + "." + extension ); 617 } 618 } 619 catch ( ConnectionException e ) 620 { 621 throw new TransferFailedException( "Connection failed: " + e.getMessage(), e ); 622 } 623 catch ( AuthenticationException e ) 624 { 625 throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e ); 626 } 627 catch ( AuthorizationException e ) 628 { 629 throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e ); 630 } 631 catch ( ResourceDoesNotExistException e ) 632 { 633 throw new TransferFailedException( "Resource to deploy not found: " + e.getMessage(), e ); 634 } 635 catch ( IOException e ) 636 { 637 throw new TransferFailedException( "Error creating temporary file for deployment: " + e.getMessage(), e ); 638 } 639 finally 640 { 641 // MNG-4543 642 cleanupTemporaryFiles( temporaryFiles ); 643 644 // Remove every checksum listener 645 for ( String aCHECKSUM_IDS : CHECKSUM_IDS ) 646 { 647 TransferListener checksumListener = checksums.get( aCHECKSUM_IDS ); 648 if ( checksumListener != null ) 649 { 650 wagon.removeTransferListener( checksumListener ); 651 } 652 } 653 654 disconnectWagon( wagon ); 655 656 releaseWagon( protocol, wagon ); 657 } 658 } 659 660 private void cleanupTemporaryFiles( List<File> files ) 661 { 662 for ( File file : files ) 663 { 664 // really don't care if it failed here only log warning 665 if ( !file.delete() ) 666 { 667 logger.warn( "skip failed to delete temporary file : " + file.getAbsolutePath() ); 668 file.deleteOnExit(); 669 } 670 } 671 672 } 673 674 private ChecksumObserver addChecksumObserver( Wagon wagon, String algorithm ) 675 throws TransferFailedException 676 { 677 try 678 { 679 ChecksumObserver checksumObserver = new ChecksumObserver( algorithm ); 680 wagon.addTransferListener( checksumObserver ); 681 return checksumObserver; 682 } 683 catch ( NoSuchAlgorithmException e ) 684 { 685 throw new TransferFailedException( "Unable to add checksum for unsupported algorithm " + algorithm, e ); 686 } 687 } 688 689 private void handleChecksumFailure( String checksumPolicy, String message, Throwable cause ) 690 throws ChecksumFailedException 691 { 692 if ( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) ) 693 { 694 throw new ChecksumFailedException( message, cause ); 695 } 696 else if ( !ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) ) 697 { 698 // warn if it is set to anything other than ignore 699 logger.warn( "*** CHECKSUM FAILED - " + message + " - IGNORING" ); 700 } 701 // otherwise it is ignore 702 } 703 704 private void verifyChecksum( ChecksumObserver checksumObserver, File destination, File tempDestination, 705 String remotePath, String checksumFileExtension, Wagon wagon ) 706 throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException 707 { 708 try 709 { 710 // grab it first, because it's about to change... 711 String actualChecksum = checksumObserver.getActualChecksum(); 712 713 File tempChecksumFile = new File( tempDestination + checksumFileExtension + ".tmp" ); 714 tempChecksumFile.deleteOnExit(); 715 wagon.get( remotePath + checksumFileExtension, tempChecksumFile ); 716 717 String expectedChecksum = FileUtils.fileRead( tempChecksumFile, "UTF-8" ); 718 719 // remove whitespaces at the end 720 expectedChecksum = expectedChecksum.trim(); 721 722 // check for 'ALGO (name) = CHECKSUM' like used by openssl 723 if ( expectedChecksum.regionMatches( true, 0, "MD", 0, 2 ) 724 || expectedChecksum.regionMatches( true, 0, "SHA", 0, 3 ) ) 725 { 726 int lastSpacePos = expectedChecksum.lastIndexOf( ' ' ); 727 expectedChecksum = expectedChecksum.substring( lastSpacePos + 1 ); 728 } 729 else 730 { 731 // remove everything after the first space (if available) 732 int spacePos = expectedChecksum.indexOf( ' ' ); 733 734 if ( spacePos != -1 ) 735 { 736 expectedChecksum = expectedChecksum.substring( 0, spacePos ); 737 } 738 } 739 if ( expectedChecksum.equalsIgnoreCase( actualChecksum ) ) 740 { 741 File checksumFile = new File( destination + checksumFileExtension ); 742 if ( checksumFile.exists() ) 743 { 744 checksumFile.delete(); // ignore if failed as we will overwrite 745 } 746 FileUtils.copyFile( tempChecksumFile, checksumFile ); 747 if ( !tempChecksumFile.delete() ) 748 { 749 tempChecksumFile.deleteOnExit(); 750 } 751 } 752 else 753 { 754 throw new ChecksumFailedException( "Checksum failed on download: local = '" + actualChecksum 755 + "'; remote = '" + expectedChecksum + "'" ); 756 } 757 } 758 catch ( IOException e ) 759 { 760 throw new ChecksumFailedException( "Invalid checksum file", e ); 761 } 762 } 763 764 private void disconnectWagon( Wagon wagon ) 765 { 766 try 767 { 768 wagon.disconnect(); 769 } 770 catch ( ConnectionException e ) 771 { 772 logger.error( "Problem disconnecting from wagon - ignoring: " + e.getMessage() ); 773 } 774 } 775 776 private void releaseWagon( String protocol, Wagon wagon ) 777 { 778 try 779 { 780 container.release( wagon ); 781 } 782 catch ( ComponentLifecycleException e ) 783 { 784 logger.error( "Problem releasing wagon - ignoring: " + e.getMessage() ); 785 logger.debug( "", e ); 786 } 787 } 788 789 @Override 790 @Deprecated 791 public Wagon getWagon( Repository repository ) 792 throws UnsupportedProtocolException 793 { 794 return getWagon( repository.getProtocol() ); 795 } 796 797 @Override 798 @Deprecated 799 public Wagon getWagon( String protocol ) 800 throws UnsupportedProtocolException 801 { 802 if ( protocol == null ) 803 { 804 throw new UnsupportedProtocolException( "Unspecified protocol" ); 805 } 806 807 String hint = protocol.toLowerCase( java.util.Locale.ENGLISH ); 808 809 Wagon wagon; 810 try 811 { 812 wagon = container.lookup( Wagon.class, hint ); 813 } 814 catch ( ComponentLookupException e ) 815 { 816 throw new UnsupportedProtocolException( "Cannot find wagon which supports the requested protocol: " 817 + protocol, e ); 818 } 819 820 return wagon; 821 } 822 823}