1   package org.apache.maven.plugins.site;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  import java.io.File;
23  
24  import java.util.List;
25  import java.util.Locale;
26  
27  import org.apache.maven.artifact.manager.WagonConfigurationException;
28  import org.apache.maven.artifact.manager.WagonManager;
29  import org.apache.maven.model.DistributionManagement;
30  import org.apache.maven.model.Site;
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.plugin.logging.Log;
33  import org.apache.maven.project.MavenProject;
34  import org.apache.maven.settings.Server;
35  import org.apache.maven.settings.Settings;
36  import org.apache.maven.wagon.CommandExecutionException;
37  import org.apache.maven.wagon.CommandExecutor;
38  import org.apache.maven.wagon.ConnectionException;
39  import org.apache.maven.wagon.ResourceDoesNotExistException;
40  import org.apache.maven.wagon.TransferFailedException;
41  import org.apache.maven.wagon.UnsupportedProtocolException;
42  import org.apache.maven.wagon.Wagon;
43  import org.apache.maven.wagon.authentication.AuthenticationException;
44  import org.apache.maven.wagon.authentication.AuthenticationInfo;
45  import org.apache.maven.wagon.authorization.AuthorizationException;
46  import org.apache.maven.wagon.observers.Debug;
47  import org.apache.maven.wagon.proxy.ProxyInfo;
48  import org.apache.maven.wagon.repository.Repository;
49  
50  import org.codehaus.plexus.PlexusConstants;
51  import org.codehaus.plexus.PlexusContainer;
52  import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
53  import org.codehaus.plexus.component.configurator.ComponentConfigurator;
54  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
55  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
56  import org.codehaus.plexus.configuration.PlexusConfiguration;
57  import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
58  import org.codehaus.plexus.context.Context;
59  import org.codehaus.plexus.context.ContextException;
60  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
61  import org.codehaus.plexus.util.StringUtils;
62  import org.codehaus.plexus.util.xml.Xpp3Dom;
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  public abstract class AbstractDeployMojo
73      extends AbstractSiteMojo implements Contextualizable
74  {
75      
76  
77  
78  
79  
80  
81      private File inputDirectory;
82  
83      
84  
85  
86  
87  
88  
89  
90      private boolean chmod;
91  
92      
93  
94  
95  
96  
97  
98  
99      private String chmodMode;
100 
101     
102 
103 
104 
105 
106 
107 
108     private String chmodOptions;
109 
110     
111 
112 
113     private WagonManager wagonManager;
114 
115     
116 
117 
118 
119 
120 
121 
122     private Settings settings;
123 
124     private PlexusContainer container;
125 
126     
127 
128 
129     protected static final String DEFAULT_STAGING_DIRECTORY = "staging/";
130 
131     
132     public void execute()
133         throws MojoExecutionException
134     {
135         deployTo( new org.apache.maven.plugins.site.wagon.repository.Repository(
136             getDeployRepositoryID(),
137             appendSlash( getDeployRepositoryURL() ) ) );
138     }
139 
140     
141 
142 
143 
144 
145 
146 
147 
148     protected static String appendSlash( final String url )
149     {
150         if ( url.endsWith( "/" ) )
151         {
152             return url;
153         }
154         else
155         {
156             return url + "/";
157         }
158     }
159 
160     
161 
162 
163 
164 
165 
166 
167 
168     protected abstract String getDeployRepositoryID()
169         throws MojoExecutionException;
170 
171     
172 
173 
174 
175 
176 
177 
178 
179 
180     protected abstract String getDeployRepositoryURL()
181         throws MojoExecutionException;
182 
183     
184 
185 
186 
187 
188 
189 
190     private String getDeployModuleDirectory()
191         throws MojoExecutionException
192     {
193         String relative = siteTool.getRelativePath( getSite( project ).getUrl(),
194             getRootSite( project ).getUrl() );
195 
196         
197         
198         relative = relative.replace( '\\', '/' );
199 
200         return ( "".equals( relative ) ) ? "./" : relative;
201     }
202 
203     
204 
205 
206 
207 
208 
209 
210 
211 
212 
213     private void deployTo( final Repository repository )
214         throws MojoExecutionException
215     {
216         if ( !inputDirectory.exists() )
217         {
218             throw new MojoExecutionException( "The site does not exist, please run site:site first" );
219         }
220 
221         if ( getLog().isDebugEnabled() )
222         {
223             getLog().debug( "Deploying to '" + repository.getUrl()
224                 + "',\n    Using credentials from server id '" + repository.getId() + "'" );
225         }
226 
227         deploy( inputDirectory, repository );
228     }
229 
230     private void deploy( final File directory, final Repository repository )
231         throws MojoExecutionException
232     {
233         
234         final Wagon wagon = getWagon( repository, wagonManager );
235 
236         try
237         {
238             configureWagon( wagon, repository.getId(), settings, container, getLog() );
239         }
240         catch ( WagonConfigurationException e )
241         {
242             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
243         }
244 
245         try
246         {
247             final ProxyInfo proxyInfo = getProxyInfo( repository, wagonManager );
248 
249             push( directory, repository, wagonManager, wagon, proxyInfo,
250                 siteTool.getAvailableLocales( locales ), getDeployModuleDirectory(), getLog() );
251 
252             if ( chmod )
253             {
254                 chmod( wagon, repository, chmodOptions, chmodMode );
255             }
256         }
257         finally
258         {
259             try
260             {
261                 wagon.disconnect();
262             }
263             catch ( ConnectionException e )
264             {
265                 getLog().error( "Error disconnecting wagon - ignored", e );
266             }
267         }
268     }
269 
270     
271 
272 
273 
274 
275 
276     protected File getTopLevelBuildDirectory()
277     {
278         
279         final MavenProject topLevelProject = getTopLevelProject( reactorProjects );
280 
281         
282         final File buildDirectory;
283 
284         if ( topLevelProject == null )
285         {
286             getLog().debug( "No top level project found in the reactor, using the current project." );
287 
288             buildDirectory = new File( project.getBuild().getDirectory() );
289         }
290         else
291         {
292             getLog().debug( "Using the top level project found in the reactor." );
293 
294             buildDirectory = new File( topLevelProject.getBuild().getDirectory() );
295         }
296 
297         return buildDirectory;
298     }
299 
300     private static Wagon getWagon( final Repository repository, final WagonManager manager )
301         throws MojoExecutionException
302     {
303         final Wagon wagon;
304 
305         try
306         {
307             wagon = manager.getWagon( repository );
308         }
309         catch ( UnsupportedProtocolException e )
310         {
311             throw new MojoExecutionException( "Unsupported protocol: '" + repository.getProtocol() + "'", e );
312         }
313         catch ( WagonConfigurationException e )
314         {
315             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
316         }
317 
318         if ( !wagon.supportsDirectoryCopy() )
319         {
320             throw new MojoExecutionException(
321                 "Wagon protocol '" + repository.getProtocol() + "' doesn't support directory copying" );
322         }
323 
324         return wagon;
325     }
326 
327     private static void push( final File inputDirectory, final Repository repository, final WagonManager manager,
328                               final Wagon wagon, final ProxyInfo proxyInfo, final List<Locale> localesList,
329                               final String relativeDir, final Log log )
330         throws MojoExecutionException
331     {
332         AuthenticationInfo authenticationInfo = manager.getAuthenticationInfo( repository.getId() );
333         log.debug( "authenticationInfo with id '" + repository.getId() + "': "
334             + ( ( authenticationInfo == null ) ? "-" : authenticationInfo.getUserName() ) );
335 
336         try
337         {
338             Debug debug = new Debug();
339 
340             wagon.addSessionListener( debug );
341 
342             wagon.addTransferListener( debug );
343 
344             if ( proxyInfo != null )
345             {
346                 log.debug( "connect with proxyInfo" );
347                 wagon.connect( repository, authenticationInfo, proxyInfo );
348             }
349             else if ( proxyInfo == null && authenticationInfo != null )
350             {
351                 log.debug( "connect with authenticationInfo and without proxyInfo" );
352                 wagon.connect( repository, authenticationInfo );
353             }
354             else
355             {
356                 log.debug( "connect without authenticationInfo and without proxyInfo" );
357                 wagon.connect( repository );
358             }
359 
360             log.info( "Pushing " + inputDirectory );
361 
362             
363             final String defaultLocale = localesList.get( 0 ).getLanguage();
364 
365             for ( Locale locale : localesList )
366             {
367                 if ( locale.getLanguage().equals( defaultLocale ) )
368                 {
369                     
370                     
371                     log.info( "   >>> to " + repository.getUrl() + relativeDir );
372 
373                     wagon.putDirectory( inputDirectory, relativeDir );
374                 }
375                 else
376                 {
377                     log.info( "   >>> to " + repository.getUrl() + locale.getLanguage() + "/" + relativeDir );
378 
379                     wagon.putDirectory( new File( inputDirectory, locale.getLanguage() ),
380                         locale.getLanguage() + "/" + relativeDir );
381                 }
382             }
383         }
384         catch ( ResourceDoesNotExistException e )
385         {
386             throw new MojoExecutionException( "Error uploading site", e );
387         }
388         catch ( TransferFailedException e )
389         {
390             throw new MojoExecutionException( "Error uploading site", e );
391         }
392         catch ( AuthorizationException e )
393         {
394             throw new MojoExecutionException( "Error uploading site", e );
395         }
396         catch ( ConnectionException e )
397         {
398             throw new MojoExecutionException( "Error uploading site", e );
399         }
400         catch ( AuthenticationException e )
401         {
402             throw new MojoExecutionException( "Error uploading site", e );
403         }
404     }
405 
406     private static void chmod( final Wagon wagon, final Repository repository,
407         final String chmodOptions, final String chmodMode )
408         throws MojoExecutionException
409     {
410         try
411         {
412             if ( wagon instanceof CommandExecutor )
413             {
414                 CommandExecutor exec = (CommandExecutor) wagon;
415                 exec.executeCommand( "chmod " + chmodOptions + " " + chmodMode + " " + repository.getBasedir() );
416             }
417             
418         }
419         catch ( CommandExecutionException e )
420         {
421             throw new MojoExecutionException( "Error uploading site", e );
422         }
423     }
424 
425     
426 
427 
428 
429 
430 
431 
432 
433 
434 
435 
436 
437 
438 
439 
440 
441 
442 
443     public static ProxyInfo getProxyInfo( Repository repository, WagonManager wagonManager )
444     {
445         ProxyInfo proxyInfo = wagonManager.getProxy( repository.getProtocol() );
446 
447         if ( proxyInfo == null )
448         {
449             return null;
450         }
451 
452         String host = repository.getHost();
453         String nonProxyHostsAsString = proxyInfo.getNonProxyHosts();
454         String[] nonProxyHosts = StringUtils.split( nonProxyHostsAsString, ",;|" );
455         for ( int i = 0; i < nonProxyHosts.length; i++ )
456         {
457             String nonProxyHost = nonProxyHosts[i];
458             if ( StringUtils.contains( nonProxyHost, "*" ) )
459             {
460                 
461                 final int pos = nonProxyHost.indexOf( '*' );
462                 String nonProxyHostPrefix = nonProxyHost.substring( 0, pos );
463                 String nonProxyHostSuffix = nonProxyHost.substring( pos + 1 );
464                 
465                 if ( StringUtils.isNotEmpty( nonProxyHostPrefix ) && host.startsWith( nonProxyHostPrefix )
466                     && StringUtils.isEmpty( nonProxyHostSuffix ) )
467                 {
468                     return null;
469                 }
470                 
471                 if ( StringUtils.isEmpty( nonProxyHostPrefix )
472                     && StringUtils.isNotEmpty( nonProxyHostSuffix ) && host.endsWith( nonProxyHostSuffix ) )
473                 {
474                     return null;
475                 }
476                 
477                 if ( StringUtils.isNotEmpty( nonProxyHostPrefix ) && host.startsWith( nonProxyHostPrefix )
478                     && StringUtils.isNotEmpty( nonProxyHostSuffix ) && host.endsWith( nonProxyHostSuffix ) )
479                 {
480                     return null;
481                 }
482             }
483             else if ( host.equals( nonProxyHost ) )
484             {
485                 return null;
486             }
487         }
488         return proxyInfo;
489     }
490 
491     
492 
493 
494 
495 
496 
497 
498 
499 
500 
501 
502     private static void configureWagon( Wagon wagon, String repositoryId, Settings settings, PlexusContainer container,
503                                         Log log )
504         throws WagonConfigurationException
505     {
506         log.debug( " configureWagon " );
507 
508         
509         for ( int i = 0; i < settings.getServers().size(); i++ )
510         {
511             Server server = settings.getServers().get( i );
512             String id = server.getId();
513 
514             log.debug( "configureWagon server " + id );
515 
516             if ( id != null && id.equals( repositoryId ) )
517             {
518                 if ( server.getConfiguration() != null )
519                 {
520                     final PlexusConfiguration plexusConf =
521                         new XmlPlexusConfiguration( (Xpp3Dom) server.getConfiguration() );
522 
523                     ComponentConfigurator componentConfigurator = null;
524                     try
525                     {
526                         componentConfigurator = (ComponentConfigurator) container.lookup( ComponentConfigurator.ROLE );
527                         componentConfigurator.configureComponent( wagon, plexusConf, container.getContainerRealm() );
528                     }
529                     catch ( final ComponentLookupException e )
530                     {
531                         throw new WagonConfigurationException( repositoryId, "Unable to lookup wagon configurator."
532                             + " Wagon configuration cannot be applied.", e );
533                     }
534                     catch ( ComponentConfigurationException e )
535                     {
536                         throw new WagonConfigurationException( repositoryId, "Unable to apply wagon configuration.",
537                             e );
538                     }
539                     finally
540                     {
541                         if ( componentConfigurator != null )
542                         {
543                             try
544                             {
545                                 container.release( componentConfigurator );
546                             }
547                             catch ( ComponentLifecycleException e )
548                             {
549                                 log.error( "Problem releasing configurator - ignoring: " + e.getMessage() );
550                             }
551                         }
552                     }
553                 }
554             }
555         }
556     }
557 
558     
559     public void contextualize( Context context )
560         throws ContextException
561     {
562         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
563     }
564 
565     
566 
567 
568 
569 
570 
571 
572     private static MavenProject getTopLevelProject( List<MavenProject> reactorProjects )
573     {
574         if ( reactorProjects == null )
575         {
576             return null;
577         }
578 
579         for ( MavenProject reactorProject : reactorProjects )
580         {
581             if ( reactorProject.isExecutionRoot() )
582             {
583                 return reactorProject;
584             }
585         }
586 
587         return null;
588     }
589 
590     
591 
592 
593 
594 
595 
596 
597 
598 
599 
600     protected static Site getSite( final MavenProject project )
601         throws MojoExecutionException
602     {
603         final String name = project.getName() + " ("
604             + project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion() + ")";
605 
606         final DistributionManagement distributionManagement = project.getDistributionManagement();
607 
608         if ( distributionManagement == null )
609         {
610             throw new MojoExecutionException( "Missing distribution management in project " + name );
611         }
612 
613         final Site site = distributionManagement.getSite();
614 
615         if ( site == null )
616         {
617             throw new MojoExecutionException(
618                 "Missing site information in the distribution management of the project " + name );
619         }
620 
621         if ( site.getUrl() == null || site.getId() == null )
622         {
623             throw new MojoExecutionException( "Missing site data: specify url and id for project " + name );
624         }
625 
626         return site;
627     }
628 
629     
630 
631 
632 
633 
634 
635 
636 
637 
638 
639 
640 
641     protected static Site getRootSite( MavenProject project )
642         throws MojoExecutionException
643     {
644         Site site = getSite( project );
645 
646         MavenProject parent = project;
647 
648         while ( parent.getParent() != null )
649         {
650             parent = parent.getParent();
651 
652             try
653             {
654                 site = getSite( parent );
655             }
656             catch ( MojoExecutionException e )
657             {
658                 break;
659             }
660         }
661 
662         return site;
663     }
664 }