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 }