1 package org.apache.maven.plugin.antrun;
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 import java.io.IOException;
24 import java.io.LineNumberReader;
25 import java.io.StringWriter;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Properties;
32 import java.util.Set;
33
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.DependencyResolutionRequiredException;
36 import org.apache.maven.artifact.repository.ArtifactRepository;
37 import org.apache.maven.plugin.AbstractMojo;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.project.MavenProject;
40 import org.apache.maven.project.MavenProjectHelper;
41 import org.apache.tools.ant.BuildException;
42 import org.apache.tools.ant.DefaultLogger;
43 import org.apache.tools.ant.Project;
44 import org.apache.tools.ant.ProjectHelper;
45 import org.apache.tools.ant.taskdefs.Typedef;
46 import org.apache.tools.ant.types.Path;
47 import org.codehaus.plexus.configuration.PlexusConfiguration;
48 import org.codehaus.plexus.configuration.PlexusConfigurationException;
49 import org.codehaus.plexus.util.FileUtils;
50 import org.codehaus.plexus.util.IOUtil;
51 import org.codehaus.plexus.util.ReaderFactory;
52 import org.codehaus.plexus.util.StringUtils;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class AntRunMojo
71 extends AbstractMojo
72 {
73
74
75
76 public final static String DEFAULT_MAVEN_PROJECT_REFID = "maven.project";
77
78
79
80
81 public final static String DEFAULT_MAVEN_PROJECT_HELPER_REFID = "maven.project.helper";
82
83
84
85
86 public final static String DEFAULT_ANT_TARGET_NAME = "main";
87
88
89
90
91 public final static String UTF_8 = "UTF-8";
92
93
94
95
96 private String antTargetName;
97
98
99
100
101 public final static String ANTLIB = "org/apache/maven/ant/tasks/antlib.xml";
102
103
104
105
106 public final static String TASK_URI = "antlib:org.apache.maven.ant.tasks";
107
108
109
110
111
112
113
114 private MavenProject project;
115
116
117
118
119
120
121 private MavenProjectHelper projectHelper;
122
123
124
125
126
127
128
129
130 private List pluginArtifacts;
131
132
133
134
135
136
137
138 protected ArtifactRepository localRepository;
139
140
141
142
143
144
145
146 private String propertyPrefix;
147
148
149
150
151
152
153
154
155
156 private String customTaskPrefix = "";
157
158
159
160
161
162
163
164 private String versionsPropertyName;
165
166
167
168
169
170
171
172
173 private PlexusConfiguration tasks;
174
175
176
177
178
179
180
181
182 private PlexusConfiguration target;
183
184
185
186
187
188
189
190
191 private File sourceRoot;
192
193
194
195
196
197
198
199
200 private File testSourceRoot;
201
202
203
204
205
206
207
208 private boolean skip;
209
210
211
212
213
214
215
216 private boolean exportAntProperties;
217
218
219
220
221
222
223
224
225
226
227 private boolean failOnError;
228
229
230
231
232 public void execute()
233 throws MojoExecutionException
234 {
235 if ( skip )
236 {
237 getLog().info( "Skipping Antrun execution" );
238 return;
239 }
240
241 MavenProject mavenProject = getMavenProject();
242
243 if ( tasks != null )
244 {
245 getLog().warn( "Parameter tasks is deprecated, use target instead" );
246 target = tasks;
247 }
248
249 if ( target == null )
250 {
251 getLog().info( "No ant target defined - SKIPPED" );
252 return;
253 }
254
255 if ( propertyPrefix == null )
256 {
257 propertyPrefix = "";
258 }
259
260 try
261 {
262 Project antProject = new Project();
263 File antBuildFile = this.writeTargetToProjectFile( );
264 ProjectHelper.configureProject( antProject, antBuildFile );
265 antProject.init();
266
267 DefaultLogger antLogger = new DefaultLogger();
268 antLogger.setOutputPrintStream( System.out );
269 antLogger.setErrorPrintStream( System.err );
270
271 if ( getLog().isDebugEnabled() )
272 {
273 antLogger.setMessageOutputLevel( Project.MSG_DEBUG );
274 }
275 else if ( getLog().isInfoEnabled() )
276 {
277 antLogger.setMessageOutputLevel( Project.MSG_INFO );
278 }
279 else if ( getLog().isWarnEnabled() )
280 {
281 antLogger.setMessageOutputLevel( Project.MSG_WARN );
282 }
283 else if ( getLog().isErrorEnabled() )
284 {
285 antLogger.setMessageOutputLevel( Project.MSG_ERR );
286 }
287 else
288 {
289 antLogger.setMessageOutputLevel( Project.MSG_VERBOSE );
290 }
291
292 antProject.addBuildListener( antLogger );
293 antProject.setBaseDir( mavenProject.getBasedir() );
294
295 Path p = new Path( antProject );
296 p.setPath( StringUtils.join( mavenProject.getCompileClasspathElements().iterator(), File.pathSeparator ) );
297
298
299 antProject.addReference( "maven.dependency.classpath", p );
300 antProject.addReference( "maven.compile.classpath", p );
301
302 p = new Path( antProject );
303 p.setPath( StringUtils.join( mavenProject.getRuntimeClasspathElements().iterator(), File.pathSeparator ) );
304 antProject.addReference( "maven.runtime.classpath", p );
305
306 p = new Path( antProject );
307 p.setPath( StringUtils.join( mavenProject.getTestClasspathElements().iterator(), File.pathSeparator ) );
308 antProject.addReference( "maven.test.classpath", p );
309
310
311 antProject.addReference( "maven.plugin.classpath", getPathFromArtifacts( pluginArtifacts, antProject ) );
312
313 antProject.addReference( DEFAULT_MAVEN_PROJECT_REFID, getMavenProject() );
314 antProject.addReference( DEFAULT_MAVEN_PROJECT_HELPER_REFID, projectHelper );
315 antProject.addReference( "maven.local.repository", localRepository );
316 initMavenTasks( antProject );
317
318
319
320 copyProperties( mavenProject, antProject );
321
322 if ( getLog().isInfoEnabled() )
323 {
324 getLog().info( "Executing tasks" );
325 }
326
327 antProject.executeTarget( antTargetName );
328
329 if ( getLog().isInfoEnabled() )
330 {
331 getLog().info( "Executed tasks" );
332 }
333
334 copyProperties( antProject, mavenProject );
335 }
336 catch ( DependencyResolutionRequiredException e )
337 {
338 throw new MojoExecutionException( "DependencyResolutionRequiredException: " + e.getMessage(), e );
339 }
340 catch ( BuildException e )
341 {
342 StringBuffer sb = new StringBuffer();
343 sb.append( "An Ant BuildException has occured: " + e.getMessage() );
344 String fragment = findFragment( e );
345 if ( fragment != null )
346 {
347 sb.append( "\n" ).append( fragment );
348 }
349 if ( !failOnError )
350 {
351 getLog().info( sb.toString(), e );
352 return;
353 } else
354 {
355 throw new MojoExecutionException( sb.toString(), e );
356 }
357 }
358 catch ( Throwable e )
359 {
360 throw new MojoExecutionException( "Error executing ant tasks: " + e.getMessage(), e );
361 }
362
363 if ( sourceRoot != null )
364 {
365 getLog().info( "Registering compile source root " + sourceRoot );
366 getMavenProject().addCompileSourceRoot( sourceRoot.toString() );
367 }
368
369 if ( testSourceRoot != null )
370 {
371 getLog().info( "Registering compile test source root " + testSourceRoot );
372 getMavenProject().addTestCompileSourceRoot( testSourceRoot.toString() );
373 }
374 }
375
376
377
378
379
380
381
382 public Path getPathFromArtifacts( Collection artifacts, Project antProject )
383 throws DependencyResolutionRequiredException
384 {
385 if ( artifacts == null )
386 {
387 return new Path( antProject );
388 }
389
390 List list = new ArrayList( artifacts.size() );
391 for ( Iterator i = artifacts.iterator(); i.hasNext(); )
392 {
393 Artifact a = (Artifact) i.next();
394 File file = a.getFile();
395 if ( file == null )
396 {
397 throw new DependencyResolutionRequiredException( a );
398 }
399 list.add( file.getPath() );
400 }
401
402 Path p = new Path( antProject );
403 p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) );
404
405 return p;
406 }
407
408
409
410
411
412
413
414 public void copyProperties( MavenProject mavenProject, Project antProject )
415 {
416 Properties mavenProps = mavenProject.getProperties();
417 Iterator iter = mavenProps.keySet().iterator();
418 while ( iter.hasNext() )
419 {
420 String key = (String) iter.next();
421 antProject.setProperty( key, mavenProps.getProperty( key ) );
422 }
423
424
425 antProject.setProperty( "ant.file", mavenProject.getFile().getAbsolutePath() );
426
427
428 getLog().debug("Setting properties with prefix: " + propertyPrefix );
429 antProject.setProperty( ( propertyPrefix + "project.groupId" ), mavenProject.getGroupId() );
430 antProject.setProperty( ( propertyPrefix + "project.artifactId" ), mavenProject.getArtifactId() );
431 antProject.setProperty( ( propertyPrefix + "project.name" ), mavenProject.getName() );
432 if ( mavenProject.getDescription() != null)
433 {
434 antProject.setProperty( ( propertyPrefix + "project.description" ), mavenProject.getDescription() );
435 }
436 antProject.setProperty( ( propertyPrefix + "project.version" ), mavenProject.getVersion() );
437 antProject.setProperty( ( propertyPrefix + "project.packaging" ), mavenProject.getPackaging() );
438 antProject.setProperty( ( propertyPrefix + "project.build.directory" ), mavenProject.getBuild().getDirectory() );
439 antProject.setProperty( ( propertyPrefix + "project.build.outputDirectory" ),
440 mavenProject.getBuild().getOutputDirectory() );
441 antProject.setProperty( ( propertyPrefix + "project.build.testOutputDirectory" ),
442 mavenProject.getBuild().getTestOutputDirectory() );
443 antProject.setProperty( ( propertyPrefix + "project.build.sourceDirectory" ),
444 mavenProject.getBuild().getSourceDirectory() );
445 antProject.setProperty( ( propertyPrefix + "project.build.testSourceDirectory" ),
446 mavenProject.getBuild().getTestSourceDirectory() );
447 antProject.setProperty( ( propertyPrefix + "localRepository" ), localRepository.toString() );
448 antProject.setProperty( ( propertyPrefix + "settings.localRepository" ), localRepository.getBasedir() );
449
450
451 Set depArtifacts = mavenProject.getArtifacts();
452 for ( Iterator it = depArtifacts.iterator(); it.hasNext(); )
453 {
454 Artifact artifact = (Artifact) it.next();
455
456 String propName = artifact.getDependencyConflictId();
457
458 antProject.setProperty( propertyPrefix + propName, artifact.getFile().getPath() );
459 }
460
461
462 StringBuffer versionsBuffer = new StringBuffer();
463 for ( Iterator it = depArtifacts.iterator(); it.hasNext(); )
464 {
465 Artifact artifact = (Artifact) it.next();
466
467 versionsBuffer.append( artifact.getVersion() + File.pathSeparator );
468 }
469 antProject.setProperty( versionsPropertyName, versionsBuffer.toString() );
470
471
472
473 for ( Iterator it = depArtifacts.iterator(); it.hasNext(); )
474 {
475 Artifact artifact = (Artifact) it.next();
476
477 String propName = getDependencyArtifactPropertyName( artifact );
478
479 antProject.setProperty( propName, artifact.getFile().getPath() );
480 }
481 }
482
483
484
485
486
487
488
489
490 public void copyProperties( Project antProject, MavenProject mavenProject )
491 {
492 if ( !exportAntProperties )
493 {
494 return;
495 }
496
497 getLog().debug( "Propagated Ant properties to Maven properties" );
498 Hashtable antProps = antProject.getProperties();
499
500 Iterator iter = antProps.keySet().iterator();
501 while ( iter.hasNext() )
502 {
503 String key = (String) iter.next();
504
505 Properties mavenProperties = mavenProject.getProperties();
506 if ( mavenProperties.getProperty( key ) != null )
507 {
508 getLog().debug( "Ant property '" + key +"=" +mavenProperties.getProperty( key )
509 + "' clashs with an existing Maven property, SKIPPING this Ant property propagation." );
510 continue;
511 }
512 mavenProperties.setProperty( key, antProps.get( key ).toString() );
513 }
514 }
515
516
517
518
519
520 public static final String DEPENDENCY_PREFIX = "maven.dependency.";
521
522
523
524
525
526
527
528
529
530 public static String getDependencyArtifactPropertyName( Artifact artifact )
531 {
532 String key = DEPENDENCY_PREFIX + artifact.getGroupId() + "." + artifact.getArtifactId()
533 + ( artifact.getClassifier() != null ? "." + artifact.getClassifier() : "" )
534 + ( artifact.getType() != null ? "." + artifact.getType() : "" ) + ".path";
535 return key;
536 }
537
538
539
540
541
542
543 public MavenProject getMavenProject()
544 {
545 return this.project;
546 }
547
548 public void initMavenTasks( Project antProject )
549 {
550 getLog().debug( "Initialize Maven Ant Tasks" );
551 Typedef typedef = new Typedef();
552 typedef.setProject( antProject );
553 typedef.setResource( ANTLIB );
554 if ( ! customTaskPrefix.equals( "" ) )
555 {
556 typedef.setURI( TASK_URI );
557 }
558 typedef.execute();
559 }
560
561
562
563
564
565
566 private File writeTargetToProjectFile()
567 throws IOException, PlexusConfigurationException
568 {
569
570 StringWriter writer = new StringWriter();
571 AntrunXmlPlexusConfigurationWriter xmlWriter = new AntrunXmlPlexusConfigurationWriter();
572 xmlWriter.write( target, writer );
573
574 StringBuffer antProjectConfig = writer.getBuffer();
575
576
577 stringReplace( antProjectConfig, "<tasks", "<target" );
578 stringReplace( antProjectConfig, "</tasks", "</target" );
579
580 antTargetName = target.getAttribute( "name" );
581
582 if ( antTargetName == null )
583 {
584 antTargetName = DEFAULT_ANT_TARGET_NAME;
585 stringReplace( antProjectConfig, "<target", "<target name=\"" + antTargetName + "\"" );
586 }
587
588 String xmlns = "";
589 if ( ! customTaskPrefix.trim().equals( "" ) )
590 {
591 xmlns = "xmlns:" + customTaskPrefix + "=\"" + TASK_URI + "\"";
592 }
593
594 final String xmlHeader = "<?xml version=\"1.0\" encoding=\"" + UTF_8 + "\" ?>\n";
595 antProjectConfig.insert( 0, xmlHeader );
596 final String projectOpen = "<project name=\"maven-antrun-\" default=\"" + antTargetName + "\" " + xmlns +" >\n";
597 int index = antProjectConfig.indexOf( "<target" );
598 antProjectConfig.insert( index, projectOpen );
599
600 final String projectClose = "\n</project>";
601 antProjectConfig.append( projectClose );
602
603
604 String fileName = "build-" + antTargetName + ".xml";
605 File buildFile = new File( project.getBuild().getDirectory(), "/antrun/" + fileName );
606
607 buildFile.getParentFile().mkdirs();
608 FileUtils.fileWrite( buildFile.getAbsolutePath(), UTF_8, antProjectConfig.toString() );
609 return buildFile;
610 }
611
612
613
614
615
616
617
618
619
620 public void stringReplace( StringBuffer text, String match, String with )
621 {
622 int index = text.indexOf( match );
623 if ( index != -1 )
624 {
625 text.replace( index, index + match.length(), with );
626 }
627 }
628
629 public String checkTargetName( PlexusConfiguration antTargetConfig )
630 throws PlexusConfigurationException
631 {
632 String targetName = antTargetConfig.getAttribute( "name" );
633 if ( targetName == null )
634 {
635 targetName = DEFAULT_ANT_TARGET_NAME;
636 }
637 return targetName;
638 }
639
640
641
642
643
644
645 private String findFragment( BuildException buildException )
646 {
647 if ( buildException == null || buildException.getLocation() == null
648 || buildException.getLocation().getFileName() == null )
649 {
650 return null;
651 }
652
653 File antFile = new File( buildException.getLocation().getFileName() );
654 if ( !antFile.exists() )
655 {
656 return null;
657 }
658
659 LineNumberReader reader = null;
660 try
661 {
662 reader = new LineNumberReader( ReaderFactory.newXmlReader( antFile ) );
663 String line = "";
664 while ( ( line = reader.readLine() ) != null )
665 {
666 if ( reader.getLineNumber() == buildException.getLocation().getLineNumber() )
667 {
668 return "around Ant part ..." + line.trim() + "... @ " + buildException.getLocation().getLineNumber() + ":"
669 + buildException.getLocation().getColumnNumber() + " in " + antFile.getAbsolutePath();
670 }
671 }
672 }
673 catch ( Exception e )
674 {
675 getLog().debug( e.getMessage(), e );
676 return null;
677 }
678 finally
679 {
680 IOUtil.close( reader );
681 }
682
683 return null;
684 }
685 }