Coverage Report - org.apache.maven.artifact.manager.DefaultWagonManager
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultWagonManager
71 %
313/442
69 %
119/172
0
DefaultWagonManager$1
50 %
1/2
N/A
0
DefaultWagonManager$2
50 %
1/2
N/A
0
 
 1  
 package org.apache.maven.artifact.manager;
 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.maven.artifact.Artifact;
 23  
 import org.apache.maven.artifact.metadata.ArtifactMetadata;
 24  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 25  
 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
 26  
 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
 27  
 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
 28  
 import org.apache.maven.wagon.ConnectionException;
 29  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 30  
 import org.apache.maven.wagon.TransferFailedException;
 31  
 import org.apache.maven.wagon.UnsupportedProtocolException;
 32  
 import org.apache.maven.wagon.Wagon;
 33  
 import org.apache.maven.wagon.authentication.AuthenticationException;
 34  
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 35  
 import org.apache.maven.wagon.authorization.AuthorizationException;
 36  
 import org.apache.maven.wagon.events.TransferListener;
 37  
 import org.apache.maven.wagon.observers.ChecksumObserver;
 38  
 import org.apache.maven.wagon.proxy.ProxyInfo;
 39  
 import org.apache.maven.wagon.proxy.ProxyInfoProvider;
 40  
 import org.apache.maven.wagon.repository.Repository;
 41  
 import org.apache.maven.wagon.repository.RepositoryPermissions;
 42  
 import org.codehaus.plexus.PlexusConstants;
 43  
 import org.codehaus.plexus.PlexusContainer;
 44  
 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
 45  
 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
 46  
 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
 47  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 48  
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 49  
 import org.codehaus.plexus.configuration.PlexusConfigurationException;
 50  
 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
 51  
 import org.codehaus.plexus.context.Context;
 52  
 import org.codehaus.plexus.context.ContextException;
 53  
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 54  
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 55  
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 56  
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
 57  
 import org.codehaus.plexus.util.FileUtils;
 58  
 import org.codehaus.plexus.util.IOUtil;
 59  
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 60  
 
 61  
 import java.io.File;
 62  
 import java.io.IOException;
 63  
 import java.io.InputStream;
 64  
 import java.net.MalformedURLException;
 65  
 import java.net.URL;
 66  
 import java.security.NoSuchAlgorithmException;
 67  
 import java.util.Collection;
 68  
 import java.util.HashMap;
 69  
 import java.util.Iterator;
 70  
 import java.util.LinkedHashMap;
 71  
 import java.util.List;
 72  
 import java.util.Map;
 73  
 import java.util.Properties;
 74  
 import java.util.Set;
 75  
 
 76  30
 public class DefaultWagonManager
 77  
     extends AbstractLogEnabled
 78  
     implements WagonManager, Contextualizable, Initializable
 79  
 {
 80  
     private static final String WILDCARD = "*";
 81  
 
 82  
     private static final String EXTERNAL_WILDCARD = "external:*";
 83  
 
 84  
     private static final String MAVEN_ARTIFACT_PROPERTIES = "META-INF/maven/org.apache.maven/maven-artifact/pom.properties";
 85  
 
 86  
     private static final String WAGON_PROVIDER_CONFIGURATION = "wagonProvider";
 87  
 
 88  1
     private static int anonymousMirrorIdSeed = 0;
 89  
     
 90  
     private PlexusContainer container;
 91  
 
 92  
     // TODO: proxies, authentication and mirrors are via settings, and should come in via an alternate method - perhaps
 93  
     // attached to ArtifactRepository before the method is called (so AR would be composed of WR, not inherit it)
 94  30
     private Map proxies = new HashMap();
 95  
 
 96  30
     private Map authenticationInfoMap = new HashMap();
 97  
 
 98  30
     private Map serverPermissionsMap = new HashMap();
 99  
 
 100  
     //used LinkedMap to preserve the order.
 101  30
     private Map mirrors = new LinkedHashMap();
 102  
 
 103  
     /** Map( String, XmlPlexusConfiguration ) with the repository id and the wagon configuration */
 104  30
     private Map<String, XmlPlexusConfiguration> serverConfigurationMap = new HashMap<String, XmlPlexusConfiguration>();
 105  
 
 106  30
     private Map<String, String> serverWagonProviderMap = new HashMap<String, String>();
 107  
 
 108  
     private TransferListener downloadMonitor;
 109  
 
 110  30
     private boolean online = true;
 111  
 
 112  
     private ArtifactRepositoryFactory repositoryFactory;
 113  
 
 114  30
     private boolean interactive = true;
 115  
 
 116  30
     private Map<String, PlexusContainer> availableWagons = new HashMap<String, PlexusContainer>();
 117  
 
 118  
     private RepositoryPermissions defaultRepositoryPermissions;
 119  
 
 120  
     private String httpUserAgent;
 121  
     
 122  30
     private WagonProviderMapping providerMapping = new DefaultWagonProviderMapping();
 123  
 
 124  
     // TODO: this leaks the component in the public api - it is never released back to the container
 125  
     public Wagon getWagon( Repository repository )
 126  
         throws UnsupportedProtocolException, WagonConfigurationException
 127  
     {
 128  2008
         String protocol = repository.getProtocol();
 129  
 
 130  2008
         if ( protocol == null )
 131  
         {
 132  1
             throw new UnsupportedProtocolException( "The repository " + repository + " does not specify a protocol" );
 133  
         }
 134  
 
 135  2007
         Wagon wagon = getWagon( protocol, repository.getId() );
 136  
 
 137  2006
         configureWagon( wagon, repository.getId(), protocol );
 138  
 
 139  2006
         return wagon;
 140  
     }
 141  
     
 142  
     public Wagon getWagon( String protocol )
 143  
         throws UnsupportedProtocolException
 144  
     {
 145  8
         return getWagon( protocol, null );
 146  
     }
 147  
     
 148  
     private Wagon getWagon( String protocol, String repositoryId )
 149  
         throws UnsupportedProtocolException
 150  
     {
 151  2033
         String hint = getWagonHint( protocol, repositoryId );
 152  2033
         PlexusContainer container = getWagonContainer( hint );
 153  
 
 154  
         Wagon wagon;
 155  
         try
 156  
         {
 157  2033
             wagon = (Wagon) container.lookup( Wagon.ROLE, hint );
 158  
         }
 159  2
         catch ( ComponentLookupException e1 )
 160  
         {
 161  2
             throw new UnsupportedProtocolException(
 162  
                 "Cannot find wagon which supports the requested protocol: " + protocol, e1 );
 163  2031
         }
 164  
 
 165  2031
         wagon.setInteractive( interactive );
 166  
 
 167  2031
         return wagon;
 168  
     }
 169  
     
 170  
     private String getWagonHint( String protocol, String repositoryId )
 171  
     {
 172  
         // TODO: Implement a better way to get the hint, via settings.xml or something.
 173  2051
         String impl = null;
 174  
         
 175  2051
         if ( repositoryId != null && serverWagonProviderMap.containsKey( repositoryId ) )
 176  
         {
 177  2
             impl = serverWagonProviderMap.get( repositoryId );
 178  2
             getLogger().debug( "Using Wagon implementation " + impl + " from settings for server " + repositoryId );
 179  
         }
 180  
         else
 181  
         {
 182  2049
             impl = providerMapping.getWagonProvider( protocol );
 183  2049
             if ( impl != null )
 184  
             {
 185  0
                 getLogger().debug( "Using Wagon implementation " + impl + " from default mapping for protocol " + protocol );
 186  
             }
 187  
         }
 188  
         
 189  
         String hint;
 190  2051
         if ( impl != null )
 191  
         {
 192  2
             hint = protocol + "-" + impl;
 193  2
             PlexusContainer container = getWagonContainer( hint );
 194  2
             if ( container == null || !container.hasComponent( Wagon.ROLE, hint ) )
 195  
             {
 196  0
                 getLogger().debug(
 197  
                                    "Cannot find wagon for protocol-provider hint: '" + hint
 198  
                                        + "', configured for repository: '" + repositoryId + "'. Using protocol hint: '"
 199  
                                        + protocol + "' instead." );
 200  0
                 hint = protocol;
 201  
             }
 202  2
         }
 203  
         else
 204  
         {
 205  2049
             hint = protocol;
 206  
         }
 207  
         
 208  2051
         return hint;
 209  
     }
 210  
 
 211  
     private PlexusContainer getWagonContainer( String hint )
 212  
     {
 213  2053
         PlexusContainer container = this.container;
 214  2053
         if ( availableWagons.containsKey( hint ) )
 215  
         {
 216  0
             container = availableWagons.get( hint );
 217  
         }
 218  
         
 219  2053
         return container;
 220  
     }
 221  
 
 222  
     public void putArtifact( File source,
 223  
                              Artifact artifact,
 224  
                              ArtifactRepository deploymentRepository )
 225  
         throws TransferFailedException
 226  
     {
 227  1
         putRemoteFile( deploymentRepository, source, deploymentRepository.pathOf( artifact ), downloadMonitor );
 228  1
     }
 229  
 
 230  
     public void putArtifactMetadata( File source,
 231  
                                      ArtifactMetadata artifactMetadata,
 232  
                                      ArtifactRepository repository )
 233  
         throws TransferFailedException
 234  
     {
 235  1
         getLogger().info( "Uploading " + artifactMetadata );
 236  1
         putRemoteFile( repository, source, repository.pathOfRemoteRepositoryMetadata( artifactMetadata ), null );
 237  1
     }
 238  
 
 239  
     private void putRemoteFile( ArtifactRepository repository,
 240  
                                 File source,
 241  
                                 String remotePath,
 242  
                                 TransferListener downloadMonitor )
 243  
         throws TransferFailedException
 244  
     {
 245  2
         failIfNotOnline();
 246  
 
 247  2
         String protocol = repository.getProtocol();
 248  
 
 249  
         Wagon wagon;
 250  
         try
 251  
         {
 252  2
             wagon = getWagon( protocol, repository.getId() );
 253  
 
 254  2
             configureWagon( wagon, repository );
 255  
         }
 256  0
         catch ( UnsupportedProtocolException e )
 257  
         {
 258  0
             throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e );
 259  2
         }
 260  
 
 261  2
         if ( downloadMonitor != null )
 262  
         {
 263  0
             wagon.addTransferListener( downloadMonitor );
 264  
         }
 265  
 
 266  2
         Map checksums = new HashMap( 2 );
 267  2
         Map sums = new HashMap( 2 );
 268  
 
 269  
         // TODO: configure these on the repository
 270  
         try
 271  
         {
 272  2
             ChecksumObserver checksumObserver = new ChecksumObserver( "MD5" );
 273  2
             wagon.addTransferListener( checksumObserver );
 274  2
             checksums.put( "md5", checksumObserver );
 275  2
             checksumObserver = new ChecksumObserver( "SHA-1" );
 276  2
             wagon.addTransferListener( checksumObserver );
 277  2
             checksums.put( "sha1", checksumObserver );
 278  
         }
 279  0
         catch ( NoSuchAlgorithmException e )
 280  
         {
 281  0
             throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e );
 282  2
         }
 283  
 
 284  
         try
 285  
         {
 286  2
             Repository artifactRepository = new Repository( repository.getId(), repository.getUrl() );
 287  
 
 288  2
             if ( serverPermissionsMap.containsKey( repository.getId() ) )
 289  
             {
 290  0
                 RepositoryPermissions perms = (RepositoryPermissions) serverPermissionsMap.get( repository.getId() );
 291  
 
 292  0
                 getLogger().debug(
 293  
                     "adding permissions to wagon connection: " + perms.getFileMode() + " " + perms.getDirectoryMode() );
 294  
 
 295  0
                 artifactRepository.setPermissions( perms );
 296  0
             }
 297  
             else
 298  
             {
 299  2
                 if ( defaultRepositoryPermissions != null )
 300  
                 {
 301  0
                     artifactRepository.setPermissions( defaultRepositoryPermissions );
 302  
                 }
 303  
                 else
 304  
                 {
 305  2
                     getLogger().debug( "not adding permissions to wagon connection" );
 306  
                 }
 307  
             }
 308  
 
 309  2
             wagon.connect( artifactRepository, getAuthenticationInfo( repository.getId() ), new ProxyInfoProvider()
 310  
             {
 311  2
                 public ProxyInfo getProxyInfo( String protocol )
 312  
                 {
 313  0
                     return getProxy( protocol );
 314  
                 }
 315  
             });
 316  
 
 317  2
             wagon.put( source, remotePath );
 318  
 
 319  2
             wagon.removeTransferListener( downloadMonitor );
 320  
 
 321  
             // Pre-store the checksums as any future puts will overwrite them
 322  2
             for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); )
 323  
             {
 324  4
                 String extension = (String) i.next();
 325  4
                 ChecksumObserver observer = (ChecksumObserver) checksums.get( extension );
 326  4
                 sums.put( extension, observer.getActualChecksum() );
 327  4
             }
 328  
 
 329  
             // We do this in here so we can checksum the artifact metadata too, otherwise it could be metadata itself
 330  2
             for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); )
 331  
             {
 332  4
                 String extension = (String) i.next();
 333  
 
 334  
                 // TODO: shouldn't need a file intermediatary - improve wagon to take a stream
 335  4
                 File temp = File.createTempFile( "maven-artifact", null );
 336  4
                 temp.deleteOnExit();
 337  4
                 FileUtils.fileWrite( temp.getAbsolutePath(), "UTF-8", (String) sums.get( extension ) );
 338  
 
 339  4
                 wagon.put( temp, remotePath + "." + extension );
 340  4
             }
 341  
         }
 342  0
         catch ( ConnectionException e )
 343  
         {
 344  0
             throw new TransferFailedException( "Connection failed: " + e.getMessage(), e );
 345  
         }
 346  0
         catch ( AuthenticationException e )
 347  
         {
 348  0
             throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e );
 349  
         }
 350  0
         catch ( AuthorizationException e )
 351  
         {
 352  0
             throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e );
 353  
         }
 354  0
         catch ( ResourceDoesNotExistException e )
 355  
         {
 356  0
             throw new TransferFailedException( "Resource to deploy not found: " + e.getMessage(), e );
 357  
         }
 358  0
         catch ( IOException e )
 359  
         {
 360  0
             throw new TransferFailedException( "Error creating temporary file for deployment: " + e.getMessage(), e );
 361  
         }
 362  
         finally
 363  
         {
 364  2
             disconnectWagon( wagon );
 365  
 
 366  2
             releaseWagon( protocol, wagon, repository.getId() );
 367  2
         }
 368  2
     }
 369  
 
 370  
     public void getArtifact( Artifact artifact,
 371  
                              List remoteRepositories )
 372  
         throws TransferFailedException, ResourceDoesNotExistException
 373  
     {
 374  
         // TODO [BP]: The exception handling here needs some work
 375  8
         boolean successful = false;
 376  8
         for ( Iterator iter = remoteRepositories.iterator(); iter.hasNext() && !successful; )
 377  
         {
 378  8
             ArtifactRepository repository = (ArtifactRepository) iter.next();
 379  
 
 380  
             try
 381  
             {
 382  8
                 getArtifact( artifact, repository );
 383  
 
 384  4
                 successful = artifact.isResolved();
 385  
             }
 386  4
             catch ( ResourceDoesNotExistException e )
 387  
             {
 388  
                 // This one we will eat when looking through remote repositories
 389  
                 // because we want to cycle through them all before squawking.
 390  
 
 391  4
                 getLogger().info( "Unable to find resource '" + artifact.getId() + "' in repository " +
 392  
                     repository.getId() + " (" + repository.getUrl() + ")" );
 393  
             }
 394  0
             catch ( TransferFailedException e )
 395  
             {
 396  0
                 getLogger().warn( "Unable to get resource '" + artifact.getId() + "' from repository " +
 397  
                     repository.getId() + " (" + repository.getUrl() + "): " + e.getMessage() );
 398  8
             }
 399  8
         }
 400  
 
 401  
         // if it already exists locally we were just trying to force it - ignore the update
 402  8
         if ( !successful && !artifact.getFile().exists() )
 403  
         {
 404  4
             throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" );
 405  
         }
 406  4
     }
 407  
 
 408  
     public void getArtifact( Artifact artifact,
 409  
                              ArtifactRepository repository )
 410  
         throws TransferFailedException, ResourceDoesNotExistException
 411  
     {
 412  15
         String remotePath = repository.pathOf( artifact );
 413  
 
 414  15
         ArtifactRepositoryPolicy policy = artifact.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
 415  
 
 416  15
         if ( !policy.isEnabled() )
 417  
         {
 418  0
             getLogger().debug( "Skipping disabled repository " + repository.getId() );
 419  
         }
 420  15
         else if ( repository.isBlacklisted() )
 421  
         {
 422  0
             getLogger().debug( "Skipping blacklisted repository " + repository.getId() );
 423  
         }
 424  
         else
 425  
         {
 426  15
             getLogger().debug( "Trying repository " + repository.getId() );
 427  15
             getRemoteFile( getMirrorRepository( repository ), artifact.getFile(), remotePath, downloadMonitor,
 428  
                                    policy.getChecksumPolicy(), false );
 429  9
             getLogger().debug( "  Artifact resolved" );
 430  
 
 431  9
             artifact.setResolved( true );
 432  
         }
 433  9
     }
 434  
 
 435  
     public void getArtifactMetadata( ArtifactMetadata metadata,
 436  
                                      ArtifactRepository repository,
 437  
                                      File destination,
 438  
                                      String checksumPolicy )
 439  
         throws TransferFailedException, ResourceDoesNotExistException
 440  
     {
 441  0
         String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata );
 442  
 
 443  0
         getRemoteFile( getMirrorRepository( repository ), destination, remotePath, null, checksumPolicy, true );
 444  0
     }
 445  
 
 446  
     public void getArtifactMetadataFromDeploymentRepository( ArtifactMetadata metadata, ArtifactRepository repository,
 447  
                                                              File destination, String checksumPolicy )
 448  
         throws TransferFailedException, ResourceDoesNotExistException
 449  
     {
 450  1
         String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata );
 451  
 
 452  1
         getRemoteFile( repository, destination, remotePath, null, checksumPolicy, true );
 453  1
     }
 454  
 
 455  
     private void getRemoteFile( ArtifactRepository repository,
 456  
                                 File destination,
 457  
                                 String remotePath,
 458  
                                 TransferListener downloadMonitor,
 459  
                                 String checksumPolicy,
 460  
                                 boolean force )
 461  
         throws TransferFailedException, ResourceDoesNotExistException
 462  
     {
 463  
         // TODO: better excetpions - transfer failed is not enough?
 464  
 
 465  16
         failIfNotOnline();
 466  
 
 467  16
         String protocol = repository.getProtocol();
 468  
         Wagon wagon;
 469  
         try
 470  
         {
 471  16
             wagon = getWagon( protocol, repository.getId() );
 472  
 
 473  16
             configureWagon( wagon, repository );
 474  
         }
 475  0
         catch ( UnsupportedProtocolException e )
 476  
         {
 477  0
             throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e );
 478  16
         }
 479  
 
 480  16
         if ( downloadMonitor != null )
 481  
         {
 482  0
             wagon.addTransferListener( downloadMonitor );
 483  
         }
 484  
 
 485  16
         File temp = new File( destination + ".tmp" );
 486  16
         temp.deleteOnExit();
 487  
 
 488  16
         boolean downloaded = false;
 489  
 
 490  
         try
 491  
         {
 492  16
             getLogger().debug( "Connecting to repository: \'" + repository.getId() + "\' with url: \'" + repository.getUrl() + "\'." );
 493  
             
 494  16
             wagon.connect( new Repository( repository.getId(), repository.getUrl() ),
 495  
                            getAuthenticationInfo( repository.getId() ), new ProxyInfoProvider()
 496  
             {
 497  16
                 public ProxyInfo getProxyInfo( String protocol )
 498  
                 {
 499  0
                     return getProxy( protocol );
 500  
                 }
 501  
             });
 502  
 
 503  16
             boolean firstRun = true;
 504  16
             boolean retry = true;
 505  
 
 506  
             // this will run at most twice. The first time, the firstRun flag is turned off, and if the retry flag
 507  
             // is set on the first run, it will be turned off and not re-set on the second try. This is because the
 508  
             // only way the retry flag can be set is if ( firstRun == true ).
 509  29
             while ( firstRun || retry )
 510  
             {
 511  
                 // reset the retry flag.
 512  19
                 retry = false;
 513  
 
 514  
                 // TODO: configure on repository
 515  19
                 ChecksumObserver md5ChecksumObserver = null;
 516  19
                 ChecksumObserver sha1ChecksumObserver = null;
 517  
                 try
 518  
                 {
 519  19
                     md5ChecksumObserver = new ChecksumObserver( "MD5" );
 520  19
                     wagon.addTransferListener( md5ChecksumObserver );
 521  
 
 522  19
                     sha1ChecksumObserver = new ChecksumObserver( "SHA-1" );
 523  19
                     wagon.addTransferListener( sha1ChecksumObserver );
 524  
 
 525  
                     // This should take care of creating destination directory now on
 526  19
                     if ( destination.exists() && !force )
 527  
                     {
 528  
                         try
 529  
                         {
 530  0
                             downloaded = wagon.getIfNewer( remotePath, temp, destination.lastModified() );
 531  0
                             if ( !downloaded )
 532  
                             {
 533  
                                 // prevent additional checks of this artifact until it expires again
 534  0
                                 destination.setLastModified( System.currentTimeMillis() );
 535  
                             }
 536  
                         }
 537  0
                         catch ( UnsupportedOperationException e )
 538  
                         {
 539  
                             // older wagons throw this. Just get() instead
 540  0
                             wagon.get( remotePath, temp );
 541  0
                             downloaded = true;
 542  0
                         }
 543  
                     }
 544  
                     else
 545  
                     {
 546  19
                         wagon.get( remotePath, temp );
 547  15
                         downloaded = true;
 548  
                     }
 549  
                 }
 550  0
                 catch ( NoSuchAlgorithmException e )
 551  
                 {
 552  0
                     throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e );
 553  
                 }
 554  
                 finally
 555  
                 {
 556  19
                     if ( md5ChecksumObserver != null )
 557  
                     {
 558  19
                         wagon.removeTransferListener( md5ChecksumObserver );
 559  
                     }
 560  19
                     if ( sha1ChecksumObserver != null )
 561  
                     {
 562  19
                         wagon.removeTransferListener( sha1ChecksumObserver );
 563  
                     }
 564  
                 }
 565  
 
 566  15
                 if ( downloaded )
 567  
                 {
 568  
                     // keep the checksum files from showing up on the download monitor...
 569  15
                     if ( downloadMonitor != null )
 570  
                     {
 571  0
                         wagon.removeTransferListener( downloadMonitor );
 572  
                     }
 573  
 
 574  
                     // try to verify the SHA-1 checksum for this file.
 575  
                     try
 576  
                     {
 577  15
                         verifyChecksum( sha1ChecksumObserver, destination, temp, remotePath, ".sha1", wagon );
 578  
                     }
 579  2
                     catch ( ChecksumFailedException e )
 580  
                     {
 581  
                         // if we catch a ChecksumFailedException, it means the transfer/read succeeded, but the checksum
 582  
                         // doesn't match. This could be a problem with the server (ibiblio HTTP-200 error page), so we'll
 583  
                         // try this up to two times. On the second try, we'll handle it as a bona-fide error, based on the
 584  
                         // repository's checksum checking policy.
 585  2
                         if ( firstRun )
 586  
                         {
 587  1
                             getLogger().warn( "*** CHECKSUM FAILED - " + e.getMessage() + " - RETRYING" );
 588  1
                             retry = true;
 589  
                         }
 590  
                         else
 591  
                         {
 592  1
                             handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() );
 593  
                         }
 594  
                     }
 595  10
                     catch ( ResourceDoesNotExistException sha1TryException )
 596  
                     {
 597  10
                         getLogger().debug( "SHA1 not found, trying MD5", sha1TryException );
 598  
 
 599  
                         // if this IS NOT a ChecksumFailedException, it was a problem with transfer/read of the checksum
 600  
                         // file...we'll try again with the MD5 checksum.
 601  
                         try
 602  
                         {
 603  10
                             verifyChecksum( md5ChecksumObserver, destination, temp, remotePath, ".md5", wagon );
 604  
                         }
 605  4
                         catch ( ChecksumFailedException e )
 606  
                         {
 607  
                             // if we also fail to verify based on the MD5 checksum, and the checksum transfer/read
 608  
                             // succeeded, then we need to determine whether to retry or handle it as a failure.
 609  4
                             if ( firstRun )
 610  
                             {
 611  2
                                 retry = true;
 612  
                             }
 613  
                             else
 614  
                             {
 615  2
                                 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() );
 616  
                             }
 617  
                         }
 618  4
                         catch ( ResourceDoesNotExistException md5TryException )
 619  
                         {
 620  
                             // this was a failed transfer, and we don't want to retry.
 621  4
                             handleChecksumFailure( checksumPolicy, "Error retrieving checksum file for " + remotePath,
 622  
                                 md5TryException );
 623  5
                         }
 624  4
                     }
 625  
 
 626  
                     // reinstate the download monitor...
 627  13
                     if ( downloadMonitor != null )
 628  
                     {
 629  0
                         wagon.addTransferListener( downloadMonitor );
 630  
                     }
 631  
                 }
 632  
 
 633  
                 // unset the firstRun flag, so we don't get caught in an infinite loop...
 634  13
                 firstRun = false;
 635  13
             }
 636  
         }
 637  0
         catch ( ConnectionException e )
 638  
         {
 639  0
             throw new TransferFailedException( "Connection failed: " + e.getMessage(), e );
 640  
         }
 641  0
         catch ( AuthenticationException e )
 642  
         {
 643  0
             throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e );
 644  
         }
 645  0
         catch ( AuthorizationException e )
 646  
         {
 647  0
             throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e );
 648  
         }
 649  
         finally
 650  
         {
 651  16
             disconnectWagon( wagon );
 652  
 
 653  16
             releaseWagon( protocol, wagon, repository.getId() );
 654  10
         }
 655  
 
 656  10
         if ( downloaded )
 657  
         {
 658  10
             if ( !temp.exists() )
 659  
             {
 660  0
                 throw new ResourceDoesNotExistException( "Downloaded file does not exist: " + temp );
 661  
             }
 662  
 
 663  
             // The temporary file is named destination + ".tmp" and is done this way to ensure
 664  
             // that the temporary file is in the same file system as the destination because the
 665  
             // File.renameTo operation doesn't really work across file systems.
 666  
             // So we will attempt to do a File.renameTo for efficiency and atomicity, if this fails
 667  
             // then we will use a brute force copy and delete the temporary file.
 668  
 
 669  10
             if ( !temp.renameTo( destination ) )
 670  
             {
 671  
                 try
 672  
                 {
 673  0
                     FileUtils.copyFile( temp, destination );
 674  
 
 675  0
                     temp.delete();
 676  
                 }
 677  0
                 catch ( IOException e )
 678  
                 {
 679  0
                     throw new TransferFailedException(
 680  
                         "Error copying temporary file to the final destination: " + e.getMessage(), e );
 681  0
                 }
 682  
             }
 683  
         }
 684  10
     }
 685  
 
 686  
     public ArtifactRepository getMirrorRepository( ArtifactRepository repository )
 687  
     {
 688  32
         ArtifactRepository mirror = getMirror( repository );
 689  32
         if ( mirror != null )
 690  
         {
 691  13
             String id = mirror.getId();
 692  13
             if ( id == null )
 693  
             {
 694  
                 // TODO: this should be illegal in settings.xml
 695  0
                 id = repository.getId();
 696  
             }
 697  
             
 698  13
             getLogger().debug( "Using mirror: " + mirror.getUrl() + " (id: " + id + ")" );
 699  
 
 700  13
             repository = repositoryFactory.createArtifactRepository( id, mirror.getUrl(),
 701  
                                                                      repository.getLayout(), repository.getSnapshots(),
 702  
                                                                      repository.getReleases() );
 703  
         }
 704  32
         return repository;
 705  
     }
 706  
 
 707  
     private void failIfNotOnline()
 708  
         throws TransferFailedException
 709  
     {
 710  18
         if ( !isOnline() )
 711  
         {
 712  0
             throw new TransferFailedException( "System is offline." );
 713  
         }
 714  18
     }
 715  
 
 716  
     private void handleChecksumFailure( String checksumPolicy,
 717  
                                         String message,
 718  
                                         Throwable cause )
 719  
         throws ChecksumFailedException
 720  
     {
 721  7
         if ( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
 722  
         {
 723  2
             throw new ChecksumFailedException( message, cause );
 724  
         }
 725  5
         else if ( !ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) )
 726  
         {
 727  
             // warn if it is set to anything other than ignore
 728  4
             getLogger().warn( "*** CHECKSUM FAILED - " + message + " - IGNORING" );
 729  
         }
 730  
         // otherwise it is ignore
 731  5
     }
 732  
 
 733  
     private void verifyChecksum( ChecksumObserver checksumObserver,
 734  
                                  File destination,
 735  
                                  File tempDestination,
 736  
                                  String remotePath,
 737  
                                  String checksumFileExtension,
 738  
                                  Wagon wagon )
 739  
         throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException
 740  
     {
 741  
         try
 742  
         {
 743  
             // grab it first, because it's about to change...
 744  25
             String actualChecksum = checksumObserver.getActualChecksum();
 745  
 
 746  25
             File tempChecksumFile = new File( tempDestination + checksumFileExtension + ".tmp" );
 747  25
             tempChecksumFile.deleteOnExit();
 748  25
             wagon.get( remotePath + checksumFileExtension, tempChecksumFile );
 749  
 
 750  11
             String expectedChecksum = FileUtils.fileRead( tempChecksumFile, "UTF-8" );
 751  
 
 752  
             // remove whitespaces at the end
 753  11
             expectedChecksum = expectedChecksum.trim();
 754  
 
 755  
             // check for 'ALGO (name) = CHECKSUM' like used by openssl
 756  11
             if ( expectedChecksum.regionMatches( true, 0, "MD", 0, 2 )
 757  
                 || expectedChecksum.regionMatches( true, 0, "SHA", 0, 3 ) )
 758  
             {
 759  0
                 int lastSpacePos = expectedChecksum.lastIndexOf( ' ' );
 760  0
                 expectedChecksum = expectedChecksum.substring( lastSpacePos + 1 );
 761  0
             }
 762  
             else
 763  
             {
 764  
                 // remove everything after the first space (if available)
 765  11
                 int spacePos = expectedChecksum.indexOf( ' ' );
 766  
 
 767  11
                 if ( spacePos != -1 )
 768  
                 {
 769  0
                     expectedChecksum = expectedChecksum.substring( 0, spacePos );
 770  
                 }
 771  
             }
 772  11
             if ( expectedChecksum.equalsIgnoreCase( actualChecksum ) )
 773  
             {
 774  5
                 File checksumFile = new File( destination + checksumFileExtension );
 775  5
                 if ( checksumFile.exists() )
 776  
                 {
 777  2
                     checksumFile.delete();
 778  
                 }
 779  5
                 FileUtils.copyFile( tempChecksumFile, checksumFile );
 780  5
             }
 781  
             else
 782  
             {
 783  6
                 throw new ChecksumFailedException( "Checksum failed on download: local = '" + actualChecksum +
 784  
                     "'; remote = '" + expectedChecksum + "'" );
 785  
             }
 786  
         }
 787  0
         catch ( IOException e )
 788  
         {
 789  0
             throw new ChecksumFailedException( "Invalid checksum file", e );
 790  5
         }
 791  5
     }
 792  
 
 793  
 
 794  
     private void disconnectWagon( Wagon wagon )
 795  
     {
 796  
         try
 797  
         {
 798  18
             wagon.disconnect();
 799  
         }
 800  0
         catch ( ConnectionException e )
 801  
         {
 802  0
             getLogger().error( "Problem disconnecting from wagon - ignoring: " + e.getMessage() );
 803  18
         }
 804  18
     }
 805  
 
 806  
     private void releaseWagon( String protocol,
 807  
                                Wagon wagon, String repositoryId )
 808  
     {
 809  18
         String hint = getWagonHint( protocol, repositoryId );
 810  
         
 811  18
         PlexusContainer container = getWagonContainer( hint );
 812  
         try
 813  
         {
 814  18
             container.release( wagon );
 815  
         }
 816  0
         catch ( ComponentLifecycleException e )
 817  
         {
 818  0
             getLogger().error( "Problem releasing wagon - ignoring: " + e.getMessage() );
 819  18
         }
 820  18
     }
 821  
 
 822  
     public ProxyInfo getProxy( String protocol )
 823  
     {
 824  0
         ProxyInfo info = (ProxyInfo) proxies.get( protocol );
 825  
         
 826  0
         if ( info != null )
 827  
         {
 828  0
             getLogger().debug( "Using Proxy: " + info.getHost() );
 829  
         }
 830  
         
 831  0
         return info;
 832  
     }
 833  
 
 834  
     public AuthenticationInfo getAuthenticationInfo( String id )
 835  
     {
 836  18
         return (AuthenticationInfo) authenticationInfoMap.get( id );
 837  
     }
 838  
 
 839  
     /**
 840  
      * This method finds a matching mirror for the selected repository. If there is an exact match, this will be used.
 841  
      * If there is no exact match, then the list of mirrors is examined to see if a pattern applies.
 842  
      *
 843  
      * @param originalRepository See if there is a mirror for this repository.
 844  
      * @return the selected mirror or null if none are found.
 845  
      */
 846  
     public ArtifactRepository getMirror( ArtifactRepository originalRepository )
 847  
     {
 848  32
         ArtifactRepository selectedMirror = (ArtifactRepository) mirrors.get( originalRepository.getId() );
 849  32
         if ( null == selectedMirror )
 850  
         {
 851  
             // Process the patterns in order. First one that matches wins.
 852  24
             Set keySet = mirrors.keySet();
 853  24
             if ( keySet != null )
 854  
             {
 855  24
                 Iterator iter = keySet.iterator();
 856  42
                 while ( iter.hasNext() )
 857  
                 {
 858  23
                     String pattern = (String) iter.next();
 859  23
                     if ( matchPattern( originalRepository, pattern ) )
 860  
                     {
 861  5
                         selectedMirror = (ArtifactRepository) mirrors.get( pattern );
 862  5
                         break;
 863  
                     }
 864  18
                 }
 865  
             }
 866  
 
 867  
         }
 868  32
         return selectedMirror;
 869  
     }
 870  
 
 871  
     /**
 872  
      * This method checks if the pattern matches the originalRepository.
 873  
      * Valid patterns:
 874  
      * * = everything
 875  
      * external:* = everything not on the localhost and not file based.
 876  
      * repo,repo1 = repo or repo1
 877  
      * *,!repo1 = everything except repo1
 878  
      *
 879  
      * @param originalRepository to compare for a match.
 880  
      * @param pattern used for match. Currently only '*' is supported.
 881  
      * @return true if the repository is a match to this pattern.
 882  
      */
 883  
     public boolean matchPattern( ArtifactRepository originalRepository, String pattern )
 884  
     {
 885  55
         boolean result = false;
 886  55
         String originalId = originalRepository.getId();
 887  
 
 888  
         // simple checks first to short circuit processing below.
 889  55
         if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
 890  
         {
 891  7
             result = true;
 892  
         }
 893  
         else
 894  
         {
 895  
             // process the list
 896  48
             String[] repos = pattern.split( "," );
 897  106
             for ( int i = 0; i < repos.length; i++ )
 898  
             {
 899  72
                 String repo = repos[i];
 900  
 
 901  
                 // see if this is a negative match
 902  72
                 if ( repo.length() > 1 && repo.startsWith( "!" ) )
 903  
                 {
 904  13
                     if ( originalId.equals( repo.substring( 1 ) ) )
 905  
                     {
 906  
                         // explicitly exclude. Set result and stop processing.
 907  5
                         result = false;
 908  5
                         break;
 909  
                     }
 910  
                 }
 911  
                 // check for exact match
 912  59
                 else if ( originalId.equals( repo ) )
 913  
                 {
 914  9
                     result = true;
 915  9
                     break;
 916  
                 }
 917  
                 // check for external:*
 918  50
                 else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
 919  
                 {
 920  1
                     result = true;
 921  
                     // don't stop processing in case a future segment explicitly excludes this repo
 922  
                 }
 923  49
                 else if ( WILDCARD.equals( repo ) )
 924  
                 {
 925  8
                     result = true;
 926  
                     // don't stop processing in case a future segment explicitly excludes this repo
 927  
                 }
 928  
             }
 929  
         }
 930  55
         return result;
 931  
     }
 932  
 
 933  
     /**
 934  
      * Checks the URL to see if this repository refers to an external repository
 935  
      *
 936  
      * @param originalRepository
 937  
      * @return true if external.
 938  
      */
 939  
     public boolean isExternalRepo( ArtifactRepository originalRepository )
 940  
     {
 941  
         try
 942  
         {
 943  20
             URL url = new URL( originalRepository.getUrl() );
 944  18
             return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" ) || url.getProtocol().equals(
 945  
                                                                                                                               "file" ) );
 946  
         }
 947  2
         catch ( MalformedURLException e )
 948  
         {
 949  
             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
 950  2
             return false;
 951  
         }
 952  
     }
 953  
 
 954  
     /**
 955  
      * Set the proxy used for a particular protocol.
 956  
      *
 957  
      * @param protocol the protocol (required)
 958  
      * @param host the proxy host name (required)
 959  
      * @param port the proxy port (required)
 960  
      * @param username the username for the proxy, or null if there is none
 961  
      * @param password the password for the proxy, or null if there is none
 962  
      * @param nonProxyHosts the set of hosts not to use the proxy for. Follows Java system property format:
 963  
      *            <code>*.foo.com|localhost</code>.
 964  
      * @todo [BP] would be nice to configure this via plexus in some way
 965  
      */
 966  
     public void addProxy( String protocol,
 967  
                           String host,
 968  
                           int port,
 969  
                           String username,
 970  
                           String password,
 971  
                           String nonProxyHosts )
 972  
     {
 973  0
         ProxyInfo proxyInfo = new ProxyInfo();
 974  0
         proxyInfo.setHost( host );
 975  0
         proxyInfo.setType( protocol );
 976  0
         proxyInfo.setPort( port );
 977  0
         proxyInfo.setNonProxyHosts( nonProxyHosts );
 978  0
         proxyInfo.setUserName( username );
 979  0
         proxyInfo.setPassword( password );
 980  
 
 981  0
         proxies.put( protocol, proxyInfo );
 982  0
     }
 983  
 
 984  
     public void contextualize( Context context )
 985  
         throws ContextException
 986  
     {
 987  27
         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
 988  27
     }
 989  
 
 990  
     /** @todo I'd rather not be setting this explicitly. */
 991  
     public void setDownloadMonitor( TransferListener downloadMonitor )
 992  
     {
 993  0
         this.downloadMonitor = downloadMonitor;
 994  0
     }
 995  
 
 996  
     public void addAuthenticationInfo( String repositoryId,
 997  
                                        String username,
 998  
                                        String password,
 999  
                                        String privateKey,
 1000  
                                        String passphrase )
 1001  
     {
 1002  0
         AuthenticationInfo authInfo = new AuthenticationInfo();
 1003  
 
 1004  0
         authInfo.setUserName( username );
 1005  
 
 1006  0
         authInfo.setPassword( password );
 1007  
 
 1008  0
         authInfo.setPrivateKey( privateKey );
 1009  
 
 1010  0
         authInfo.setPassphrase( passphrase );
 1011  
 
 1012  0
         authenticationInfoMap.put( repositoryId, authInfo );
 1013  0
     }
 1014  
 
 1015  
     public void addPermissionInfo( String repositoryId,
 1016  
                                    String filePermissions,
 1017  
                                    String directoryPermissions )
 1018  
     {
 1019  
 
 1020  0
         RepositoryPermissions permissions = new RepositoryPermissions();
 1021  0
         boolean addPermissions = false;
 1022  
 
 1023  0
         if ( filePermissions != null )
 1024  
         {
 1025  0
             permissions.setFileMode( filePermissions );
 1026  0
             addPermissions = true;
 1027  
         }
 1028  
 
 1029  0
         if ( directoryPermissions != null )
 1030  
         {
 1031  0
             permissions.setDirectoryMode( directoryPermissions );
 1032  0
             addPermissions = true;
 1033  
         }
 1034  
 
 1035  0
         if ( addPermissions )
 1036  
         {
 1037  0
             serverPermissionsMap.put( repositoryId, permissions );
 1038  
         }
 1039  0
     }
 1040  
 
 1041  
     public void addMirror( String id,
 1042  
                            String mirrorOf,
 1043  
                            String url )
 1044  
     {
 1045  14
         if ( id == null )
 1046  
         {
 1047  1
             id = "mirror-" + anonymousMirrorIdSeed++;
 1048  1
             getLogger().warn( "You are using a mirror that doesn't declare an <id/> element. Using \'" + id + "\' instead:\nId: " + id + "\nmirrorOf: " + mirrorOf + "\nurl: " + url + "\n" );
 1049  
         }
 1050  
         
 1051  14
         ArtifactRepository mirror = new DefaultArtifactRepository( id, url, null );
 1052  
 
 1053  
         //to preserve first wins, don't add repeated mirrors.
 1054  14
         if (!mirrors.containsKey( mirrorOf ))
 1055  
         {
 1056  13
             mirrors.put( mirrorOf, mirror );
 1057  
         }
 1058  14
     }
 1059  
 
 1060  
     public void setOnline( boolean online )
 1061  
     {
 1062  0
         this.online = online;
 1063  0
     }
 1064  
 
 1065  
     public boolean isOnline()
 1066  
     {
 1067  28
         return online;
 1068  
     }
 1069  
 
 1070  
     public void setInteractive( boolean interactive )
 1071  
     {
 1072  0
         this.interactive = interactive;
 1073  0
     }
 1074  
 
 1075  
     @SuppressWarnings( "unchecked" )
 1076  
     public void registerWagons( Collection wagons,
 1077  
                                 PlexusContainer extensionContainer )
 1078  
     {
 1079  0
         for ( Iterator<String> i = wagons.iterator(); i.hasNext(); )
 1080  
         {
 1081  0
             availableWagons.put( i.next(), extensionContainer );
 1082  
         }
 1083  0
     }
 1084  
 
 1085  
     /**
 1086  
      * Applies the server configuration to the wagon
 1087  
      *
 1088  
      * @param wagon      the wagon to configure
 1089  
      * @param repository the repository that has the configuration
 1090  
      * @throws WagonConfigurationException wraps any error given during configuration of the wagon instance
 1091  
      */
 1092  
     private void configureWagon( Wagon wagon,
 1093  
                                  ArtifactRepository repository )
 1094  
         throws WagonConfigurationException
 1095  
     {
 1096  18
         configureWagon( wagon, repository.getId(), repository.getProtocol() );
 1097  18
     }
 1098  
 
 1099  
     private void configureWagon( Wagon wagon, String repositoryId, String protocol )
 1100  
         throws WagonConfigurationException
 1101  
     {
 1102  2024
         PlexusConfiguration config = (PlexusConfiguration) serverConfigurationMap.get( repositoryId ); 
 1103  2024
         if ( protocol.startsWith( "http" ) || protocol.startsWith( "dav" ) )
 1104  
         {
 1105  2000
             config = updateUserAgentForHttp( wagon, config );
 1106  
         }
 1107  
         
 1108  2024
         if ( config != null )
 1109  
         {
 1110  2006
             ComponentConfigurator componentConfigurator = null;
 1111  
             try
 1112  
             {
 1113  2006
                 componentConfigurator = (ComponentConfigurator) container.lookup( ComponentConfigurator.ROLE, "wagon" );
 1114  2006
                 componentConfigurator.configureComponent( wagon, config, container.getContainerRealm() );
 1115  
             }
 1116  0
             catch ( final ComponentLookupException e )
 1117  
             {
 1118  0
                 throw new WagonConfigurationException( repositoryId,
 1119  
                                                        "Unable to lookup wagon configurator. Wagon configuration cannot be applied.",
 1120  
                                                        e );
 1121  
             }
 1122  0
             catch ( ComponentConfigurationException e )
 1123  
             {
 1124  0
                 throw new WagonConfigurationException( repositoryId, "Unable to apply wagon configuration.", e );
 1125  
             }
 1126  
             finally
 1127  
             {
 1128  2006
                 if ( componentConfigurator != null )
 1129  
                 {
 1130  
                     try
 1131  
                     {
 1132  2006
                         container.release( componentConfigurator );
 1133  
                     }
 1134  0
                     catch ( ComponentLifecycleException e )
 1135  
                     {
 1136  0
                         getLogger().error( "Problem releasing configurator - ignoring: " + e.getMessage() );
 1137  2006
                     }
 1138  
                 }
 1139  
 
 1140  
             }
 1141  
         }
 1142  2024
     }
 1143  
 
 1144  
     // TODO: Remove this, once the maven-shade-plugin 1.2 release is out, allowing configuration of httpHeaders in the components.xml
 1145  
     private PlexusConfiguration updateUserAgentForHttp( Wagon wagon, PlexusConfiguration config )
 1146  
     {
 1147  2000
         if ( config == null )
 1148  
         {
 1149  2000
             config = new XmlPlexusConfiguration( "configuration" );
 1150  
         }
 1151  
         
 1152  2000
         if ( httpUserAgent != null )
 1153  
         {
 1154  
             try
 1155  
             {
 1156  2000
                 wagon.getClass().getMethod( "setHttpHeaders", new Class[]{ Properties.class } );
 1157  
                 
 1158  2000
                 PlexusConfiguration headerConfig = config.getChild( "httpHeaders", true );
 1159  2000
                 PlexusConfiguration[] children = headerConfig.getChildren( "property" );
 1160  2000
                 boolean found = false;
 1161  
                 
 1162  2000
                 getLogger().debug( "Checking for pre-existing User-Agent configuration." );
 1163  2000
                 for ( int i = 0; i < children.length; i++ )
 1164  
                 {
 1165  0
                     PlexusConfiguration c = children[i].getChild( "name", false );
 1166  0
                     if ( c != null && "User-Agent".equals( c.getValue( null ) ) )
 1167  
                     {
 1168  0
                         found = true;
 1169  0
                         break;
 1170  
                     }
 1171  
                 }
 1172  
                 
 1173  2000
                 if ( !found )
 1174  
                 {
 1175  2000
                     getLogger().debug( "Adding User-Agent configuration." );
 1176  2000
                     XmlPlexusConfiguration propertyConfig = new XmlPlexusConfiguration( "property" );
 1177  2000
                     headerConfig.addChild( propertyConfig );
 1178  
                     
 1179  2000
                     XmlPlexusConfiguration nameConfig = new XmlPlexusConfiguration( "name" );
 1180  2000
                     nameConfig.setValue( "User-Agent" );
 1181  2000
                     propertyConfig.addChild( nameConfig );
 1182  
                     
 1183  2000
                     XmlPlexusConfiguration versionConfig = new XmlPlexusConfiguration( "value" );
 1184  2000
                     versionConfig.setValue( httpUserAgent );
 1185  2000
                     propertyConfig.addChild( versionConfig );
 1186  2000
                 }
 1187  
                 else
 1188  
                 {
 1189  0
                     getLogger().debug( "User-Agent configuration found." );
 1190  
                 }
 1191  
             }
 1192  0
             catch ( SecurityException e )
 1193  
             {
 1194  0
                 getLogger().debug( "setHttpHeaders method not accessible on wagon: " + wagon + "; skipping User-Agent configuration." );
 1195  
                 // forget it. this method is public, if it exists.
 1196  
             }
 1197  0
             catch ( NoSuchMethodException e )
 1198  
             {
 1199  0
                 getLogger().debug( "setHttpHeaders method not found on wagon: " + wagon + "; skipping User-Agent configuration." );
 1200  
                 // forget it.
 1201  2000
             }
 1202  
         }
 1203  
         
 1204  2000
         return config;
 1205  
     }
 1206  
 
 1207  
     public void addConfiguration( String repositoryId,
 1208  
                                   Xpp3Dom configuration )
 1209  
     {
 1210  6
         if ( repositoryId == null || configuration == null )
 1211  
         {
 1212  0
             throw new IllegalArgumentException( "arguments can't be null" );
 1213  
         }
 1214  
 
 1215  6
         final XmlPlexusConfiguration xmlConf = new XmlPlexusConfiguration( configuration );
 1216  
 
 1217  11
         for ( int i = 0; i < configuration.getChildCount(); i++ )
 1218  
         {
 1219  6
             Xpp3Dom domChild = configuration.getChild( i );
 1220  6
             if ( WAGON_PROVIDER_CONFIGURATION.equals( domChild.getName() ) )
 1221  
             {
 1222  1
                 serverWagonProviderMap.put( repositoryId, domChild.getValue() );
 1223  1
                 configuration.removeChild( i );
 1224  1
                 break;
 1225  
             }
 1226  
             
 1227  5
             i++;
 1228  
         }
 1229  
 
 1230  6
         serverConfigurationMap.put( repositoryId, xmlConf );
 1231  6
     }
 1232  
     
 1233  
     public void setDefaultRepositoryPermissions( RepositoryPermissions defaultRepositoryPermissions )
 1234  
     {
 1235  0
         this.defaultRepositoryPermissions = defaultRepositoryPermissions;
 1236  0
     }
 1237  
 
 1238  
     // TODO: Remove this, once the maven-shade-plugin 1.2 release is out, allowing configuration of httpHeaders in the components.xml
 1239  
     public void initialize()
 1240  
         throws InitializationException
 1241  
     {
 1242  27
         if ( httpUserAgent == null )
 1243  
         {
 1244  27
             InputStream resourceAsStream = null;
 1245  
             try
 1246  
             {
 1247  27
                 Properties properties = new Properties();
 1248  27
                 resourceAsStream = getClass().getClassLoader().getResourceAsStream( MAVEN_ARTIFACT_PROPERTIES );
 1249  
 
 1250  27
                 if ( resourceAsStream != null )
 1251  
                 {
 1252  
                     try
 1253  
                     {
 1254  27
                         properties.load( resourceAsStream );
 1255  
 
 1256  27
                         httpUserAgent =
 1257  
                             "maven-artifact/" + properties.getProperty( "version" ) + " (Java "
 1258  
                                 + System.getProperty( "java.version" ) + "; " + System.getProperty( "os.name" ) + " "
 1259  
                                 + System.getProperty( "os.version" ) + ")";
 1260  
                     }
 1261  0
                     catch ( IOException e )
 1262  
                     {
 1263  0
                         getLogger().warn(
 1264  
                                           "Failed to load Maven artifact properties from:\n" + MAVEN_ARTIFACT_PROPERTIES
 1265  
                                               + "\n\nUser-Agent HTTP header may be incorrect for artifact resolution." );
 1266  27
                     }
 1267  
                 }
 1268  
             }
 1269  
             finally
 1270  
             {
 1271  27
                 IOUtil.close( resourceAsStream );
 1272  27
             }
 1273  
         }
 1274  27
     }
 1275  
     
 1276  
     /**
 1277  
      * {@inheritDoc}
 1278  
      */
 1279  
     public void setHttpUserAgent( String userAgent )
 1280  
     {
 1281  1
         this.httpUserAgent = userAgent;
 1282  1
     }
 1283  
     
 1284  
     /**
 1285  
      * {@inheritDoc}
 1286  
      */
 1287  
     public String getHttpUserAgent()
 1288  
     {
 1289  1
         return httpUserAgent;
 1290  
     }
 1291  
 }