Coverage Report - org.apache.maven.plugins.site.AbstractDeployMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractDeployMojo
43%
96/222
31%
36/114
6,429
AbstractDeployMojo$URIEncoder
0%
0/9
0%
0/18
6,429
 
 1  
 package org.apache.maven.plugins.site;
 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.manager.WagonManager;
 23  
 import org.apache.maven.doxia.site.decoration.inheritance.URIPathDescriptor;
 24  
 import org.apache.maven.execution.MavenExecutionRequest;
 25  
 import org.apache.maven.execution.MavenSession;
 26  
 import org.apache.maven.model.DistributionManagement;
 27  
 import org.apache.maven.model.Site;
 28  
 import org.apache.maven.plugin.MojoExecutionException;
 29  
 import org.apache.maven.plugin.logging.Log;
 30  
 import org.apache.maven.project.MavenProject;
 31  
 import org.apache.maven.settings.Proxy;
 32  
 import org.apache.maven.settings.Server;
 33  
 import org.apache.maven.settings.Settings;
 34  
 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
 35  
 import org.apache.maven.settings.crypto.SettingsDecrypter;
 36  
 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
 37  
 import org.apache.maven.wagon.CommandExecutionException;
 38  
 import org.apache.maven.wagon.CommandExecutor;
 39  
 import org.apache.maven.wagon.ConnectionException;
 40  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 41  
 import org.apache.maven.wagon.TransferFailedException;
 42  
 import org.apache.maven.wagon.UnsupportedProtocolException;
 43  
 import org.apache.maven.wagon.Wagon;
 44  
 import org.apache.maven.wagon.authentication.AuthenticationException;
 45  
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 46  
 import org.apache.maven.wagon.authorization.AuthorizationException;
 47  
 import org.apache.maven.wagon.observers.Debug;
 48  
 import org.apache.maven.wagon.proxy.ProxyInfo;
 49  
 import org.apache.maven.wagon.repository.Repository;
 50  
 import org.codehaus.classworlds.ClassRealm;
 51  
 import org.codehaus.plexus.PlexusConstants;
 52  
 import org.codehaus.plexus.PlexusContainer;
 53  
 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
 54  
 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
 55  
 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
 56  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 57  
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 58  
 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
 59  
 import org.codehaus.plexus.context.Context;
 60  
 import org.codehaus.plexus.context.ContextException;
 61  
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 62  
 import org.codehaus.plexus.util.StringUtils;
 63  
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 64  
 
 65  
 import java.io.File;
 66  
 import java.lang.reflect.Method;
 67  
 import java.net.MalformedURLException;
 68  
 import java.net.URL;
 69  
 import java.util.List;
 70  
 import java.util.Locale;
 71  
 import java.util.Set;
 72  
 
 73  
 /**
 74  
  * Abstract base class for deploy mojos.
 75  
  * Since 2.3 this includes {@link SiteStageMojo} and {@link SiteStageDeployMojo}.
 76  
  *
 77  
  * @author ltheussl
 78  
  * @since 2.3
 79  
  */
 80  3
 public abstract class AbstractDeployMojo
 81  
     extends AbstractSiteMojo
 82  
     implements Contextualizable
 83  
 {
 84  
     /**
 85  
      * Directory containing the generated project sites and report distributions.
 86  
      *
 87  
      * @parameter alias="outputDirectory" expression="${project.reporting.outputDirectory}"
 88  
      * @required
 89  
      */
 90  
     private File inputDirectory;
 91  
 
 92  
     /**
 93  
      * Whether to run the "chmod" command on the remote site after the deploy.
 94  
      * Defaults to "true".
 95  
      *
 96  
      * @parameter expression="${maven.site.chmod}" default-value="true"
 97  
      * @since 2.1
 98  
      */
 99  
     private boolean chmod;
 100  
 
 101  
     /**
 102  
      * The mode used by the "chmod" command. Only used if chmod = true.
 103  
      * Defaults to "g+w,a+rX".
 104  
      *
 105  
      * @parameter expression="${maven.site.chmod.mode}" default-value="g+w,a+rX"
 106  
      * @since 2.1
 107  
      */
 108  
     private String chmodMode;
 109  
 
 110  
     /**
 111  
      * The options used by the "chmod" command. Only used if chmod = true.
 112  
      * Defaults to "-Rf".
 113  
      *
 114  
      * @parameter expression="${maven.site.chmod.options}" default-value="-Rf"
 115  
      * @since 2.1
 116  
      */
 117  
     private String chmodOptions;
 118  
 
 119  
     /**
 120  
      * Set this to 'true' to skip site deployment.
 121  
      *
 122  
      * @parameter expression="${maven.site.deploy.skip}" default-value="false"
 123  
      * @since 3.0
 124  
      */
 125  
     private boolean skipDeploy;
 126  
 
 127  
     /**
 128  
      * @component
 129  
      */
 130  
     private WagonManager wagonManager;
 131  
 
 132  
     /**
 133  
      * The current user system settings for use in Maven.
 134  
      *
 135  
      * @parameter expression="${settings}"
 136  
      * @required
 137  
      * @readonly
 138  
      */
 139  
     private Settings settings;
 140  
 
 141  
     /**
 142  
      * @parameter expression="${session}"
 143  
      * @required
 144  
      * @readonly
 145  
      * @since 3.0-beta-2
 146  
      */
 147  
     protected MavenSession mavenSession;
 148  
 
 149  
     private PlexusContainer container;
 150  
 
 151  
     /**
 152  
      * The String "staging/".
 153  
      */
 154  
     protected static final String DEFAULT_STAGING_DIRECTORY = "staging/";
 155  
 
 156  
     /**
 157  
      * {@inheritDoc}
 158  
      */
 159  
     public void execute()
 160  
         throws MojoExecutionException
 161  
     {
 162  3
         if ( skipDeploy )
 163  
         {
 164  0
             getLog().info( "maven.site.deploy.skip = true: Skipping site deployment" );
 165  0
             return;
 166  
         }
 167  
 
 168  3
         deployTo( new org.apache.maven.plugins.site.wagon.repository.Repository( getDeployRepositoryID(), appendSlash(
 169  
             getDeployRepositoryURL() ) ) );
 170  3
     }
 171  
 
 172  
     /**
 173  
      * Make sure the given url ends with a slash.
 174  
      *
 175  
      * @param url a String.
 176  
      * @return if url already ends with '/' it is returned unchanged,
 177  
      *         otherwise a '/' character is appended.
 178  
      */
 179  
     protected static String appendSlash( final String url )
 180  
     {
 181  3
         if ( url.endsWith( "/" ) )
 182  
         {
 183  3
             return url;
 184  
         }
 185  
         else
 186  
         {
 187  0
             return url + "/";
 188  
         }
 189  
     }
 190  
 
 191  
     /**
 192  
      * Specifies the id to look up credential settings.
 193  
      *
 194  
      * @return the id to look up credentials for the deploy. Not null.
 195  
      * @throws MojoExecutionException if the ID cannot be determined
 196  
      */
 197  
     protected abstract String getDeployRepositoryID()
 198  
         throws MojoExecutionException;
 199  
 
 200  
     /**
 201  
      * Specifies the target URL for the deploy.
 202  
      * This should be the top-level URL, ie above modules and locale sub-directories.
 203  
      *
 204  
      * @return the url to deploy to. Not null.
 205  
      * @throws MojoExecutionException if the URL cannot be constructed
 206  
      */
 207  
     protected abstract String getDeployRepositoryURL()
 208  
         throws MojoExecutionException;
 209  
 
 210  
     /**
 211  
      * Find the relative path between the distribution URLs of the top parent and the current project.
 212  
      *
 213  
      * @return the relative path or "./" if the two URLs are the same.
 214  
      * @throws MojoExecutionException
 215  
      */
 216  
     protected String getDeployModuleDirectory()
 217  
         throws MojoExecutionException
 218  
     {
 219  3
         String relative = siteTool.getRelativePath( getSite( project ).getUrl(), getRootSite( project ).getUrl() );
 220  
 
 221  
         // SiteTool.getRelativePath() uses File.separatorChar,
 222  
         // so we need to convert '\' to '/' in order for the URL to be valid for Windows users
 223  3
         relative = relative.replace( '\\', '/' );
 224  
 
 225  3
         return ( "".equals( relative ) ) ? "./" : relative;
 226  
     }
 227  
 
 228  
     /**
 229  
      * Use wagon to deploy the generated site to a given repository.
 230  
      *
 231  
      * @param repository the repository to deply to.
 232  
      *                   This needs to contain a valid, non-null {@link Repository#getId() id}
 233  
      *                   to look up credentials for the deploy, and a valid, non-null
 234  
      *                   {@link Repository#getUrl() scm url} to deploy to.
 235  
      * @throws MojoExecutionException if the deploy fails.
 236  
      */
 237  
     private void deployTo( final Repository repository )
 238  
         throws MojoExecutionException
 239  
     {
 240  3
         if ( !inputDirectory.exists() )
 241  
         {
 242  0
             throw new MojoExecutionException( "The site does not exist, please run site:site first" );
 243  
         }
 244  
 
 245  3
         if ( getLog().isDebugEnabled() )
 246  
         {
 247  0
             getLog().debug( "Deploying to '" + repository.getUrl() + "',\n    Using credentials from server id '"
 248  
                                 + repository.getId() + "'" );
 249  
         }
 250  
 
 251  3
         deploy( inputDirectory, repository );
 252  3
     }
 253  
 
 254  
     private void deploy( final File directory, final Repository repository )
 255  
         throws MojoExecutionException
 256  
     {
 257  
         // TODO: work on moving this into the deployer like the other deploy methods
 258  3
         final Wagon wagon = getWagon( repository, wagonManager );
 259  
 
 260  
         try
 261  
         {
 262  3
             configureWagon( wagon, repository.getId(), settings, container, getLog() );
 263  
         }
 264  0
         catch ( TransferFailedException e )
 265  
         {
 266  0
             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
 267  3
         }
 268  
 
 269  
         try
 270  
         {
 271  
             final ProxyInfo proxyInfo;
 272  3
             if ( !isMaven3OrMore() )
 273  
             {
 274  0
                 proxyInfo = getProxyInfo( repository, wagonManager );
 275  
             }
 276  
             else
 277  
             {
 278  
                 try
 279  
                 {
 280  3
                     SettingsDecrypter settingsDecrypter = container.lookup( SettingsDecrypter.class );
 281  
 
 282  3
                     proxyInfo = getProxy( repository, settingsDecrypter );
 283  
                 }
 284  0
                 catch ( ComponentLookupException cle )
 285  
                 {
 286  0
                     throw new MojoExecutionException( "Unable to lookup SettingsDecrypter: " + cle.getMessage(), cle );
 287  3
                 }
 288  
             }
 289  
 
 290  3
             push( directory, repository, wagon, proxyInfo, siteTool.getAvailableLocales( locales ),
 291  
                   getDeployModuleDirectory() );
 292  
 
 293  3
             if ( chmod )
 294  
             {
 295  0
                 chmod( wagon, repository, chmodOptions, chmodMode );
 296  
             }
 297  
         }
 298  
         finally
 299  
         {
 300  0
             try
 301  
             {
 302  3
                 wagon.disconnect();
 303  
             }
 304  0
             catch ( ConnectionException e )
 305  
             {
 306  0
                 getLog().error( "Error disconnecting wagon - ignored", e );
 307  3
             }
 308  0
         }
 309  3
     }
 310  
 
 311  
     /**
 312  
      * Find the build directory of the top level project in the reactor.
 313  
      * If no top level project is found, the build directory of the current project is returned.
 314  
      *
 315  
      * @return the build directory of the top level project.
 316  
      */
 317  
     protected File getTopLevelBuildDirectory()
 318  
     {
 319  
         // Find the top level project in the reactor
 320  0
         final MavenProject topLevelProject = getTopLevelProject( reactorProjects );
 321  
 
 322  
         // Use the top level project's build directory if there is one, otherwise use this project's build directory
 323  
         final File buildDirectory;
 324  
 
 325  0
         if ( topLevelProject == null )
 326  
         {
 327  0
             getLog().debug( "No top level project found in the reactor, using the current project." );
 328  
 
 329  0
             buildDirectory = new File( project.getBuild().getDirectory() );
 330  
         }
 331  
         else
 332  
         {
 333  0
             getLog().debug( "Using the top level project found in the reactor." );
 334  
 
 335  0
             buildDirectory = new File( topLevelProject.getBuild().getDirectory() );
 336  
         }
 337  
 
 338  0
         return buildDirectory;
 339  
     }
 340  
 
 341  
     private Wagon getWagon( final Repository repository, final WagonManager manager )
 342  
         throws MojoExecutionException
 343  
     {
 344  
         final Wagon wagon;
 345  
 
 346  
         try
 347  
         {
 348  3
             wagon = manager.getWagon( repository );
 349  
         }
 350  0
         catch ( UnsupportedProtocolException e )
 351  
         {
 352  0
             String shortMessage = "Unsupported protocol: '" + repository.getProtocol() + "' for site deployment to "
 353  
                 + "distributionManagement.site.url=" + repository.getUrl() + ".";
 354  0
             String longMessage =
 355  
                 "\n" + shortMessage + "\n" + "Currently supported protocols are: " + getSupportedProtocols() + ".\n"
 356  
                     + "    Protocols may be added through wagon providers.\n" + "    For more information, see "
 357  
                     + "http://maven.apache.org/plugins/maven-site-plugin/examples/adding-deploy-protocol.html";
 358  
 
 359  0
             getLog().error( longMessage );
 360  
 
 361  0
             throw new MojoExecutionException( shortMessage );
 362  
         }
 363  0
         catch ( TransferFailedException e )
 364  
         {
 365  0
             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
 366  3
         }
 367  
 
 368  3
         if ( !wagon.supportsDirectoryCopy() )
 369  
         {
 370  0
             throw new MojoExecutionException(
 371  
                 "Wagon protocol '" + repository.getProtocol() + "' doesn't support directory copying" );
 372  
         }
 373  
 
 374  3
         return wagon;
 375  
     }
 376  
 
 377  
     private String getSupportedProtocols()
 378  
     {
 379  
         try
 380  
         {
 381  0
             Set<String> protocols = container.lookupMap( Wagon.class ).keySet();
 382  
 
 383  0
             return StringUtils.join( protocols.iterator(), ", " );
 384  
         }
 385  0
         catch ( ComponentLookupException e )
 386  
         {
 387  
             // in the unexpected case there is a problem when instantiating a wagon provider
 388  0
             getLog().error( e );
 389  
         }
 390  0
         return "";
 391  
     }
 392  
 
 393  
     private void push( final File inputDirectory, final Repository repository, final Wagon wagon,
 394  
                        final ProxyInfo proxyInfo, final List<Locale> localesList, final String relativeDir )
 395  
         throws MojoExecutionException
 396  
     {
 397  3
         AuthenticationInfo authenticationInfo = wagonManager.getAuthenticationInfo( repository.getId() );
 398  3
         getLog().debug( "authenticationInfo with id '" + repository.getId() + "': " + ( ( authenticationInfo == null )
 399  
             ? "-"
 400  
             : authenticationInfo.getUserName() ) );
 401  
 
 402  
         try
 403  
         {
 404  3
             Debug debug = new Debug();
 405  
 
 406  3
             wagon.addSessionListener( debug );
 407  
 
 408  3
             wagon.addTransferListener( debug );
 409  
 
 410  3
             if ( proxyInfo != null )
 411  
             {
 412  2
                 getLog().debug( "connect with proxyInfo" );
 413  2
                 wagon.connect( repository, authenticationInfo, proxyInfo );
 414  
             }
 415  1
             else if ( proxyInfo == null && authenticationInfo != null )
 416  
             {
 417  1
                 getLog().debug( "connect with authenticationInfo and without proxyInfo" );
 418  1
                 wagon.connect( repository, authenticationInfo );
 419  
             }
 420  
             else
 421  
             {
 422  0
                 getLog().debug( "connect without authenticationInfo and without proxyInfo" );
 423  0
                 wagon.connect( repository );
 424  
             }
 425  
 
 426  3
             getLog().info( "Pushing " + inputDirectory );
 427  
 
 428  
             // Default is first in the list
 429  3
             final String defaultLocale = localesList.get( 0 ).getLanguage();
 430  
 
 431  3
             for ( Locale locale : localesList )
 432  
             {
 433  3
                 if ( locale.getLanguage().equals( defaultLocale ) )
 434  
                 {
 435  
                     // TODO: this also uploads the non-default locales,
 436  
                     // is there a way to exclude directories in wagon?
 437  3
                     getLog().info( "   >>> to " + repository.getUrl() + relativeDir );
 438  
 
 439  3
                     wagon.putDirectory( inputDirectory, relativeDir );
 440  
                 }
 441  
                 else
 442  
                 {
 443  0
                     getLog().info( "   >>> to " + repository.getUrl() + locale.getLanguage() + "/" + relativeDir );
 444  
 
 445  0
                     wagon.putDirectory( new File( inputDirectory, locale.getLanguage() ),
 446  
                                         locale.getLanguage() + "/" + relativeDir );
 447  
                 }
 448  
             }
 449  
         }
 450  0
         catch ( ResourceDoesNotExistException e )
 451  
         {
 452  0
             throw new MojoExecutionException( "Error uploading site", e );
 453  
         }
 454  0
         catch ( TransferFailedException e )
 455  
         {
 456  0
             throw new MojoExecutionException( "Error uploading site", e );
 457  
         }
 458  0
         catch ( AuthorizationException e )
 459  
         {
 460  0
             throw new MojoExecutionException( "Error uploading site", e );
 461  
         }
 462  0
         catch ( ConnectionException e )
 463  
         {
 464  0
             throw new MojoExecutionException( "Error uploading site", e );
 465  
         }
 466  0
         catch ( AuthenticationException e )
 467  
         {
 468  0
             throw new MojoExecutionException( "Error uploading site", e );
 469  3
         }
 470  3
     }
 471  
 
 472  
     private static void chmod( final Wagon wagon, final Repository repository, final String chmodOptions,
 473  
                                final String chmodMode )
 474  
         throws MojoExecutionException
 475  
     {
 476  
         try
 477  
         {
 478  0
             if ( wagon instanceof CommandExecutor )
 479  
             {
 480  0
                 CommandExecutor exec = (CommandExecutor) wagon;
 481  0
                 exec.executeCommand( "chmod " + chmodOptions + " " + chmodMode + " " + repository.getBasedir() );
 482  
             }
 483  
             // else ? silently ignore, FileWagon is not a CommandExecutor!
 484  
         }
 485  0
         catch ( CommandExecutionException e )
 486  
         {
 487  0
             throw new MojoExecutionException( "Error uploading site", e );
 488  0
         }
 489  0
     }
 490  
 
 491  
     /**
 492  
      * <p>
 493  
      * Get the <code>ProxyInfo</code> of the proxy associated with the <code>host</code>
 494  
      * and the <code>protocol</code> of the given <code>repository</code>.
 495  
      * </p>
 496  
      * <p>
 497  
      * Extract from <a href="http://java.sun.com/j2se/1.5.0/docs/guide/net/properties.html">
 498  
      * J2SE Doc : Networking Properties - nonProxyHosts</a> : "The value can be a list of hosts,
 499  
      * each separated by a |, and in addition a wildcard character (*) can be used for matching"
 500  
      * </p>
 501  
      * <p>
 502  
      * Defensively support for comma (",") and semi colon (";") in addition to pipe ("|") as separator.
 503  
      * </p>
 504  
      *
 505  
      * @param repository   the Repository to extract the ProxyInfo from.
 506  
      * @param wagonManager the WagonManager used to connect to the Repository.
 507  
      * @return a ProxyInfo object instantiated or <code>null</code> if no matching proxy is found
 508  
      */
 509  
     public static ProxyInfo getProxyInfo( Repository repository, WagonManager wagonManager )
 510  
     {
 511  0
         ProxyInfo proxyInfo = wagonManager.getProxy( repository.getProtocol() );
 512  
 
 513  0
         if ( proxyInfo == null )
 514  
         {
 515  0
             return null;
 516  
         }
 517  
 
 518  0
         String host = repository.getHost();
 519  0
         String nonProxyHostsAsString = proxyInfo.getNonProxyHosts();
 520  0
         for ( String nonProxyHost : StringUtils.split( nonProxyHostsAsString, ",;|" ) )
 521  
         {
 522  0
             if ( StringUtils.contains( nonProxyHost, "*" ) )
 523  
             {
 524  
                 // Handle wildcard at the end, beginning or middle of the nonProxyHost
 525  0
                 final int pos = nonProxyHost.indexOf( '*' );
 526  0
                 String nonProxyHostPrefix = nonProxyHost.substring( 0, pos );
 527  0
                 String nonProxyHostSuffix = nonProxyHost.substring( pos + 1 );
 528  
                 // prefix*
 529  0
                 if ( StringUtils.isNotEmpty( nonProxyHostPrefix ) && host.startsWith( nonProxyHostPrefix )
 530  
                     && StringUtils.isEmpty( nonProxyHostSuffix ) )
 531  
                 {
 532  0
                     return null;
 533  
                 }
 534  
                 // *suffix
 535  0
                 if ( StringUtils.isEmpty( nonProxyHostPrefix ) && StringUtils.isNotEmpty( nonProxyHostSuffix )
 536  
                     && host.endsWith( nonProxyHostSuffix ) )
 537  
                 {
 538  0
                     return null;
 539  
                 }
 540  
                 // prefix*suffix
 541  0
                 if ( StringUtils.isNotEmpty( nonProxyHostPrefix ) && host.startsWith( nonProxyHostPrefix )
 542  
                     && StringUtils.isNotEmpty( nonProxyHostSuffix ) && host.endsWith( nonProxyHostSuffix ) )
 543  
                 {
 544  0
                     return null;
 545  
                 }
 546  0
             }
 547  0
             else if ( host.equals( nonProxyHost ) )
 548  
             {
 549  0
                 return null;
 550  
             }
 551  
         }
 552  0
         return proxyInfo;
 553  
     }
 554  
 
 555  
     /**
 556  
      * Get proxy information for Maven 3.
 557  
      *
 558  
      * @param repository
 559  
      * @param settingsDecrypter
 560  
      * @return
 561  
      */
 562  
     private ProxyInfo getProxy( Repository repository, SettingsDecrypter settingsDecrypter )
 563  
     {
 564  3
         String protocol = repository.getProtocol();
 565  3
         String url = repository.getUrl();
 566  
 
 567  3
         getLog().debug( "repository protocol " + protocol );
 568  
 
 569  3
         String originalProtocol = protocol;
 570  
         // olamy: hackish here protocol (wagon hint in fact !) is dav
 571  
         // but the real protocol (transport layer) is http(s)
 572  
         // and it's the one use in wagon to find the proxy arghhh
 573  
         // so we will check both
 574  3
         if ( StringUtils.equalsIgnoreCase( "dav", protocol ) && url.startsWith( "dav:" ) )
 575  
         {
 576  3
             url = url.substring( 4 );
 577  3
             if ( url.startsWith( "http" ) )
 578  
             {
 579  
                 try
 580  
                 {
 581  3
                     URL urlSite = new URL( url );
 582  3
                     protocol = urlSite.getProtocol();
 583  3
                     getLog().debug( "found dav protocol so transform to real transport protocol " + protocol );
 584  
                 }
 585  0
                 catch ( MalformedURLException e )
 586  
                 {
 587  0
                     getLog().warn( "fail to build URL with " + url );
 588  3
                 }
 589  
 
 590  
             }
 591  
         }
 592  
         else
 593  
         {
 594  0
             getLog().debug( "getProxy 'protocol': " + protocol );
 595  
         }
 596  3
         if ( mavenSession != null && protocol != null )
 597  
         {
 598  2
             MavenExecutionRequest request = mavenSession.getRequest();
 599  
 
 600  2
             if ( request != null )
 601  
             {
 602  2
                 List<Proxy> proxies = request.getProxies();
 603  
 
 604  2
                 if ( proxies != null )
 605  
                 {
 606  2
                     for ( Proxy proxy : proxies )
 607  
                     {
 608  2
                         if ( proxy.isActive() && ( protocol.equalsIgnoreCase( proxy.getProtocol() )
 609  
                             || originalProtocol.equalsIgnoreCase( proxy.getProtocol() ) ) )
 610  
                         {
 611  2
                             SettingsDecryptionResult result =
 612  
                                 settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( proxy ) );
 613  2
                             proxy = result.getProxy();
 614  
 
 615  2
                             ProxyInfo proxyInfo = new ProxyInfo();
 616  2
                             proxyInfo.setHost( proxy.getHost() );
 617  
                             // so hackish for wagon the protocol is https for site dav : dav:https://dav.codehaus.org/mojo/
 618  2
                             proxyInfo.setType( protocol );//proxy.getProtocol() );
 619  2
                             proxyInfo.setPort( proxy.getPort() );
 620  2
                             proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
 621  2
                             proxyInfo.setUserName( proxy.getUsername() );
 622  2
                             proxyInfo.setPassword( proxy.getPassword() );
 623  
 
 624  2
                             getLog().debug( "found proxyInfo " + ( proxyInfo == null
 625  
                                 ? "null"
 626  
                                 : "host:port " + proxyInfo.getHost() + ":" + proxyInfo.getPort() + ", "
 627  
                                     + proxyInfo.getUserName() ) );
 628  
 
 629  2
                             return proxyInfo;
 630  
                         }
 631  
                     }
 632  
                 }
 633  
             }
 634  
         }
 635  1
         getLog().debug( "getProxy 'protocol': " + protocol + " no ProxyInfo found" );
 636  1
         return null;
 637  
     }
 638  
 
 639  
     /**
 640  
      * Configure the Wagon with the information from serverConfigurationMap ( which comes from settings.xml )
 641  
      *
 642  
      * @param wagon
 643  
      * @param repositoryId
 644  
      * @param settings
 645  
      * @param container
 646  
      * @param log
 647  
      * @throws TransferFailedException
 648  
      * @todo Remove when {@link WagonManager#getWagon(Repository) is available}. It's available in Maven 2.0.5.
 649  
      */
 650  
     private static void configureWagon( Wagon wagon, String repositoryId, Settings settings, PlexusContainer container,
 651  
                                         Log log )
 652  
         throws TransferFailedException
 653  
     {
 654  3
         log.debug( " configureWagon " );
 655  
 
 656  
         // MSITE-25: Make sure that the server settings are inserted
 657  3
         for ( Server server : settings.getServers() )
 658  
         {
 659  0
             String id = server.getId();
 660  
 
 661  0
             log.debug( "configureWagon server " + id );
 662  
 
 663  0
             if ( id != null && id.equals( repositoryId ) && ( server.getConfiguration() != null ) )
 664  
             {
 665  0
                 final PlexusConfiguration plexusConf =
 666  
                     new XmlPlexusConfiguration( (Xpp3Dom) server.getConfiguration() );
 667  
 
 668  0
                 ComponentConfigurator componentConfigurator = null;
 669  
                 try
 670  
                 {
 671  0
                     componentConfigurator =
 672  
                         (ComponentConfigurator) container.lookup( ComponentConfigurator.ROLE, "basic" );
 673  0
                     if ( isMaven3OrMore() )
 674  
                     {
 675  0
                         componentConfigurator.configureComponent( wagon, plexusConf,
 676  
                                                                   container.getContainerRealm() );
 677  
                     }
 678  
                     else
 679  
                     {
 680  0
                         configureWagonWithMaven2( componentConfigurator, wagon, plexusConf, container );
 681  
                     }
 682  
                 }
 683  0
                 catch ( final ComponentLookupException e )
 684  
                 {
 685  0
                     throw new TransferFailedException(
 686  
                         "While configuring wagon for \'" + repositoryId + "\': Unable to lookup wagon configurator."
 687  
                             + " Wagon configuration cannot be applied.", e );
 688  
                 }
 689  0
                 catch ( ComponentConfigurationException e )
 690  
                 {
 691  0
                     throw new TransferFailedException( "While configuring wagon for \'" + repositoryId
 692  
                                                            + "\': Unable to apply wagon configuration.", e );
 693  
                 }
 694  
                 finally
 695  
                 {
 696  0
                     if ( componentConfigurator != null )
 697  
                     {
 698  
                         try
 699  
                         {
 700  0
                             container.release( componentConfigurator );
 701  
                         }
 702  0
                         catch ( ComponentLifecycleException e )
 703  
                         {
 704  0
                             log.error( "Problem releasing configurator - ignoring: " + e.getMessage() );
 705  0
                         }
 706  
                     }
 707  
                 }
 708  
             }
 709  0
         }
 710  3
     }
 711  
 
 712  
     private static void configureWagonWithMaven2( ComponentConfigurator componentConfigurator, Wagon wagon,
 713  
                                                   PlexusConfiguration plexusConf, PlexusContainer container )
 714  
         throws ComponentConfigurationException
 715  
     {
 716  
         // in maven 2.x   :
 717  
         // * container.getContainerRealm() -> org.codehaus.classworlds.ClassRealm
 718  
         // * componentConfiguration 3rd param is org.codehaus.classworlds.ClassRealm
 719  
         // so use some reflection see MSITE-609
 720  
         try
 721  
         {
 722  0
             Method methodContainerRealm = container.getClass().getMethod( "getContainerRealm" );
 723  0
             ClassRealm realm = (ClassRealm) methodContainerRealm.invoke( container, null );
 724  
 
 725  0
             Method methodConfigure = componentConfigurator.getClass().getMethod( "configureComponent",
 726  
                                                                                  new Class[]{ Object.class,
 727  
                                                                                      PlexusConfiguration.class,
 728  
                                                                                      ClassRealm.class } );
 729  
 
 730  0
             methodConfigure.invoke( componentConfigurator, wagon, plexusConf, realm );
 731  
         }
 732  0
         catch ( Exception e )
 733  
         {
 734  0
             throw new ComponentConfigurationException(
 735  
                 "fail to configure wagon component for a maven2 use " + e.getMessage(), e );
 736  0
         }
 737  0
     }
 738  
 
 739  
     /**
 740  
      * {@inheritDoc}
 741  
      */
 742  
     public void contextualize( Context context )
 743  
         throws ContextException
 744  
     {
 745  3
         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
 746  3
     }
 747  
 
 748  
     /**
 749  
      * Find the top level parent in the reactor, i.e. the execution root.
 750  
      *
 751  
      * @param reactorProjects The projects in the reactor. May be null in which case null is returned.
 752  
      * @return The top level project in the reactor, or <code>null</code> if none can be found
 753  
      */
 754  
     private static MavenProject getTopLevelProject( List<MavenProject> reactorProjects )
 755  
     {
 756  0
         if ( reactorProjects == null )
 757  
         {
 758  0
             return null;
 759  
         }
 760  
 
 761  0
         for ( MavenProject reactorProject : reactorProjects )
 762  
         {
 763  0
             if ( reactorProject.isExecutionRoot() )
 764  
             {
 765  0
                 return reactorProject;
 766  
             }
 767  
         }
 768  
 
 769  0
         return null;
 770  
     }
 771  
 
 772  
     /**
 773  
      * Extract the distributionManagement site from the given MavenProject.
 774  
      *
 775  
      * @param project the MavenProject. Not null.
 776  
      * @return the project site. Not null.
 777  
      *         Also site.getUrl() and site.getId() are guaranteed to be not null.
 778  
      * @throws MojoExecutionException if any of the site info is missing.
 779  
      */
 780  
     protected static Site getSite( final MavenProject project )
 781  
         throws MojoExecutionException
 782  
     {
 783  9
         final String name =
 784  
             project.getName() + " (" + project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion()
 785  
                 + ")";
 786  
 
 787  9
         final DistributionManagement distributionManagement = project.getDistributionManagement();
 788  
 
 789  9
         if ( distributionManagement == null )
 790  
         {
 791  0
             throw new MojoExecutionException( "Missing distribution management in project " + name );
 792  
         }
 793  
 
 794  9
         final Site site = distributionManagement.getSite();
 795  
 
 796  9
         if ( site == null )
 797  
         {
 798  0
             throw new MojoExecutionException(
 799  
                 "Missing site information in the distribution management of the project " + name );
 800  
         }
 801  
 
 802  9
         if ( site.getUrl() == null || site.getId() == null )
 803  
         {
 804  0
             throw new MojoExecutionException( "Missing site data: specify url and id for project " + name );
 805  
         }
 806  
 
 807  9
         return site;
 808  
     }
 809  
 
 810  
     /**
 811  
      * Extract the distributionManagement site of the top level parent of the given MavenProject.
 812  
      * This climbs up the project hierarchy and returns the site of the last project
 813  
      * for which {@link #getSite(org.apache.maven.project.MavenProject)} returns a site.
 814  
      *
 815  
      * @param project the MavenProject. Not null.
 816  
      * @return the top level site. Not null.
 817  
      *         Also site.getUrl() and site.getId() are guaranteed to be not null.
 818  
      * @throws MojoExecutionException if no site info is found in the tree.
 819  
      */
 820  
     protected Site getRootSite( MavenProject project )
 821  
         throws MojoExecutionException
 822  
     {
 823  6
         Site site = getSite( project );
 824  
 
 825  6
         MavenProject parent = project;
 826  
 
 827  6
         while ( parent.getParent() != null )
 828  
         {
 829  
             // MSITE-585, MNG-1943
 830  0
             parent = siteTool.getParentProject( parent, reactorProjects, localRepository );
 831  
 
 832  0
             Site oldSite = site;
 833  
 
 834  
             try
 835  
             {
 836  0
                 site = getSite( parent );
 837  
             }
 838  0
             catch ( MojoExecutionException e )
 839  
             {
 840  0
                 break;
 841  0
             }
 842  
 
 843  
             // MSITE-600
 844  0
             URIPathDescriptor siteURI = new URIPathDescriptor( URIEncoder.encodeURI( site.getUrl() ), "" );
 845  0
             URIPathDescriptor oldSiteURI = new URIPathDescriptor( URIEncoder.encodeURI( oldSite.getUrl() ), "" );
 846  
 
 847  0
             if ( !siteURI.sameSite( oldSiteURI.getBaseURI() ) )
 848  
             {
 849  0
                 return oldSite;
 850  
             }
 851  0
         }
 852  
 
 853  6
         return site;
 854  
     }
 855  
 
 856  3
     private static class URIEncoder
 857  
     {
 858  
         private static final String mark = "-_.!~*'()";
 859  
         private static final String reserved = ";/?:@&=+$,";
 860  
 
 861  
         public static String encodeURI( final String uriString )
 862  
         {
 863  0
             final char[] chars = uriString.toCharArray();
 864  0
             final StringBuilder uri = new StringBuilder( chars.length );
 865  
 
 866  0
             for ( char c : chars )
 867  
             {
 868  0
                 if ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' )
 869  
                         || mark.indexOf( c ) != -1  || reserved.indexOf( c ) != -1 )
 870  
                 {
 871  0
                     uri.append( c );
 872  
                 }
 873  
                 else
 874  
                 {
 875  0
                     uri.append( '%' );
 876  0
                     uri.append( Integer.toHexString( (int) c ) );
 877  
                 }
 878  
             }
 879  0
             return uri.toString();
 880  
         }
 881  
     }
 882  
 }