1 package org.apache.maven.plugins.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.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Hashtable;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Properties;
31 import java.util.Set;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.artifact.DependencyResolutionRequiredException;
35 import org.apache.maven.artifact.repository.ArtifactRepository;
36 import org.apache.maven.execution.MavenSession;
37 import org.apache.maven.plugin.AbstractMojo;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugin.MojoFailureException;
40 import org.apache.maven.plugins.annotations.Component;
41 import org.apache.maven.plugins.annotations.Mojo;
42 import org.apache.maven.plugins.annotations.Parameter;
43 import org.apache.maven.plugins.annotations.ResolutionScope;
44 import org.apache.maven.project.MavenProject;
45 import org.apache.maven.project.MavenProjectHelper;
46 import org.apache.tools.ant.BuildException;
47 import org.apache.tools.ant.DefaultLogger;
48 import org.apache.tools.ant.Project;
49 import org.apache.tools.ant.ProjectHelper;
50 import org.apache.tools.ant.taskdefs.Typedef;
51 import org.apache.tools.ant.types.Path;
52 import org.codehaus.plexus.configuration.PlexusConfiguration;
53 import org.codehaus.plexus.util.ReaderFactory;
54 import org.codehaus.plexus.util.StringUtils;
55
56
57
58
59
60
61
62
63
64
65
66
67 @Mojo( name = "run", threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST )
68 public class AntRunMojo
69 extends AbstractMojo
70 {
71
72
73
74
75 public static final String MAVEN_REFID_PREFIX = "maven.";
76
77
78
79
80
81
82 public static final String DEFAULT_MAVEN_PROJECT_REFID = MAVEN_REFID_PREFIX + "project";
83
84
85
86
87
88
89
90 public static final String DEFAULT_MAVEN_PROJECT_REF_REFID = MAVEN_REFID_PREFIX + "project.ref";
91
92
93
94
95 public static final String DEFAULT_MAVEN_PROJECT_HELPER_REFID = MAVEN_REFID_PREFIX + "project.helper";
96
97
98
99
100 public static final String DEFAULT_ANT_TARGET_NAME = "main";
101
102
103
104
105 public static final String UTF_8 = "UTF-8";
106
107
108
109
110 public static final String ANTLIB = "org/apache/maven/ant/tasks/antlib.xml";
111
112
113
114
115 public static final String TASK_URI = "antlib:org.apache.maven.ant.tasks";
116
117
118
119
120 @Parameter( defaultValue = "${project}", readonly = true, required = true )
121 private MavenProject mavenProject;
122
123
124
125
126 @Parameter( defaultValue = "${session}", readonly = true, required = true )
127 private MavenSession session;
128
129
130
131
132 @Component
133 private MavenProjectHelper projectHelper;
134
135
136
137
138 @Parameter( property = "plugin.artifacts", required = true, readonly = true )
139 private List<Artifact> pluginArtifacts;
140
141
142
143
144 @Parameter( property = "localRepository", readonly = true )
145 protected ArtifactRepository localRepository;
146
147
148
149
150
151
152 @Parameter( defaultValue = "" )
153 private String propertyPrefix;
154
155
156
157
158
159
160
161
162 @Parameter( defaultValue = "" )
163 private String customTaskPrefix = "";
164
165
166
167
168
169 @Parameter( defaultValue = "maven.project.dependencies.versions" )
170 private String versionsPropertyName;
171
172
173
174
175
176
177
178
179 @Deprecated
180 @Parameter
181 private PlexusConfiguration tasks;
182
183
184
185
186
187
188
189 @Parameter
190 private PlexusConfiguration target;
191
192
193
194
195
196
197
198
199 @SuppressWarnings( "DeprecatedIsStillUsed" )
200 @Deprecated
201 @Parameter( property = "sourceRoot" )
202 private File sourceRoot;
203
204
205
206
207
208
209
210
211 @SuppressWarnings( "DeprecatedIsStillUsed" )
212 @Deprecated
213 @Parameter( property = "testSourceRoot" )
214 private File testSourceRoot;
215
216
217
218
219
220
221 @Parameter( property = "maven.antrun.skip", defaultValue = "false" )
222 private boolean skip;
223
224
225
226
227
228
229 @Parameter( defaultValue = "false" )
230 private boolean exportAntProperties;
231
232
233
234
235
236
237
238
239 @Parameter( defaultValue = "true" )
240 private boolean failOnError;
241
242 @Override
243 public void execute()
244 throws MojoExecutionException, MojoFailureException
245 {
246 checkDeprecatedParameterUsage( tasks, "tasks", "target" );
247 checkDeprecatedParameterUsage( sourceRoot, "sourceRoot", "the build-helper-maven-plugin" );
248 checkDeprecatedParameterUsage( testSourceRoot, "testSourceRoot", "the build-helper-maven-plugin" );
249 if ( skip )
250 {
251 getLog().info( "Skipping Antrun execution" );
252 return;
253 }
254
255 if ( target == null )
256 {
257 getLog().info( "No Ant target defined - SKIPPED" );
258 return;
259 }
260
261 if ( propertyPrefix == null )
262 {
263 propertyPrefix = "";
264 }
265
266 String antTargetName = target.getAttribute( "name", DEFAULT_ANT_TARGET_NAME );
267 target.setAttribute( "name", antTargetName );
268
269 Project antProject = new Project();
270 antProject.addBuildListener( getConfiguredBuildLogger() );
271 try
272 {
273 File antBuildFile = writeTargetToProjectFile( antTargetName );
274 ProjectHelper.configureProject( antProject, antBuildFile );
275 antProject.init();
276
277 antProject.setBaseDir( mavenProject.getBasedir() );
278
279 addAntProjectReferences( mavenProject, antProject );
280 initMavenTasks( antProject );
281
282
283
284 copyProperties( mavenProject, antProject );
285
286 getLog().info( "Executing tasks" );
287 antProject.executeTarget( antTargetName );
288 getLog().info( "Executed tasks" );
289
290 copyProperties( antProject, mavenProject );
291 }
292 catch ( BuildException e )
293 {
294 StringBuilder sb = new StringBuilder();
295 sb.append( "An Ant BuildException has occured: " ).append( e.getMessage() );
296 String fragment = findFragment( e );
297 if ( fragment != null )
298 {
299 sb.append( "\n" ).append( fragment );
300 }
301 if ( !failOnError )
302 {
303 getLog().info( sb.toString(), e );
304 return;
305 }
306 else
307 {
308 throw new MojoExecutionException( sb.toString(), e );
309 }
310 }
311 catch ( Throwable e )
312 {
313 throw new MojoExecutionException( "Error executing Ant tasks: " + e.getMessage(), e );
314 }
315 }
316
317 private void checkDeprecatedParameterUsage( Object parameter, String name, String replacement )
318 throws MojoFailureException
319 {
320 if ( parameter != null )
321 {
322 throw new MojoFailureException( "You are using '" + name + "' which has been removed"
323 + " from the maven-antrun-plugin. Please use '" + replacement
324 + "' and refer to the >>Major Version Upgrade to version 3.0.0<< " + "on the plugin site." );
325 }
326 }
327
328 private DefaultLogger getConfiguredBuildLogger()
329 {
330 DefaultLogger antLogger = new MavenLogger( getLog() );
331 if ( getLog().isDebugEnabled() )
332 {
333 antLogger.setMessageOutputLevel( Project.MSG_DEBUG );
334 }
335 else if ( getLog().isInfoEnabled() )
336 {
337 antLogger.setMessageOutputLevel( Project.MSG_INFO );
338 }
339 else if ( getLog().isWarnEnabled() )
340 {
341 antLogger.setMessageOutputLevel( Project.MSG_WARN );
342 }
343 else if ( getLog().isErrorEnabled() )
344 {
345 antLogger.setMessageOutputLevel( Project.MSG_ERR );
346 }
347 else
348 {
349 antLogger.setMessageOutputLevel( Project.MSG_VERBOSE );
350 }
351 return antLogger;
352 }
353
354 private void addAntProjectReferences( MavenProject mavenProject, Project antProject )
355 throws DependencyResolutionRequiredException
356 {
357 Path p = new Path( antProject );
358 p.setPath( StringUtils.join( mavenProject.getCompileClasspathElements().iterator(), File.pathSeparator ) );
359
360
361 antProject.addReference( MAVEN_REFID_PREFIX + "dependency.classpath", p );
362 antProject.addReference( MAVEN_REFID_PREFIX + "compile.classpath", p );
363
364 p = new Path( antProject );
365 p.setPath( StringUtils.join( mavenProject.getRuntimeClasspathElements().iterator(), File.pathSeparator ) );
366 antProject.addReference( MAVEN_REFID_PREFIX + "runtime.classpath", p );
367
368 p = new Path( antProject );
369 p.setPath( StringUtils.join( mavenProject.getTestClasspathElements().iterator(), File.pathSeparator ) );
370 antProject.addReference( MAVEN_REFID_PREFIX + "test.classpath", p );
371
372
373 antProject.addReference( MAVEN_REFID_PREFIX + "plugin.classpath",
374 getPathFromArtifacts( pluginArtifacts, antProject ) );
375
376 antProject.addReference( DEFAULT_MAVEN_PROJECT_REFID, mavenProject );
377 antProject.addReference( DEFAULT_MAVEN_PROJECT_REF_REFID, new MavenAntRunProject( mavenProject ) );
378 antProject.addReference( DEFAULT_MAVEN_PROJECT_HELPER_REFID, projectHelper );
379 antProject.addReference( MAVEN_REFID_PREFIX + "local.repository", localRepository );
380 }
381
382
383
384
385
386
387
388 private Path getPathFromArtifacts( Collection<Artifact> artifacts, Project antProject )
389 throws DependencyResolutionRequiredException
390 {
391 if ( artifacts == null )
392 {
393 return new Path( antProject );
394 }
395
396 List<String> list = new ArrayList<>( artifacts.size() );
397 for ( Artifact a : artifacts )
398 {
399 File file = a.getFile();
400 if ( file == null )
401 {
402 throw new DependencyResolutionRequiredException( a );
403 }
404 list.add( file.getPath() );
405 }
406
407 Path p = new Path( antProject );
408 p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) );
409
410 return p;
411 }
412
413
414
415
416
417
418
419 public void copyProperties( MavenProject mavenProject, Project antProject )
420 {
421 Properties mavenProps = mavenProject.getProperties();
422 Properties userProps = session.getUserProperties();
423 List<String> allPropertyKeys = new ArrayList<>( mavenProps.stringPropertyNames() );
424 allPropertyKeys.addAll( userProps.stringPropertyNames() );
425 for ( String key : allPropertyKeys )
426 {
427 String value = userProps.getProperty( key, mavenProps.getProperty( key ) );
428 antProject.setProperty( key, value );
429 }
430
431
432 antProject.setProperty( "ant.file", mavenProject.getFile().getAbsolutePath() );
433
434
435 getLog().debug( "Setting properties with prefix: " + propertyPrefix );
436 antProject.setProperty( ( propertyPrefix + "project.groupId" ), mavenProject.getGroupId() );
437 antProject.setProperty( ( propertyPrefix + "project.artifactId" ), mavenProject.getArtifactId() );
438 antProject.setProperty( ( propertyPrefix + "project.name" ), mavenProject.getName() );
439 if ( mavenProject.getDescription() != null )
440 {
441 antProject.setProperty( ( propertyPrefix + "project.description" ), mavenProject.getDescription() );
442 }
443 antProject.setProperty( ( propertyPrefix + "project.version" ), mavenProject.getVersion() );
444 antProject.setProperty( ( propertyPrefix + "project.packaging" ), mavenProject.getPackaging() );
445 antProject.setProperty( ( propertyPrefix + "project.build.directory" ),
446 mavenProject.getBuild().getDirectory() );
447 antProject.setProperty( ( propertyPrefix + "project.build.outputDirectory" ),
448 mavenProject.getBuild().getOutputDirectory() );
449 antProject.setProperty( ( propertyPrefix + "project.build.testOutputDirectory" ),
450 mavenProject.getBuild().getTestOutputDirectory() );
451 antProject.setProperty( ( propertyPrefix + "project.build.sourceDirectory" ),
452 mavenProject.getBuild().getSourceDirectory() );
453 antProject.setProperty( ( propertyPrefix + "project.build.testSourceDirectory" ),
454 mavenProject.getBuild().getTestSourceDirectory() );
455 antProject.setProperty( ( propertyPrefix + "localRepository" ), localRepository.toString() );
456 antProject.setProperty( ( propertyPrefix + "settings.localRepository" ), localRepository.getBasedir() );
457
458
459 Set<Artifact> depArtifacts = mavenProject.getArtifacts();
460 for ( Artifact artifact : depArtifacts )
461 {
462 String propName = artifact.getDependencyConflictId();
463
464 antProject.setProperty( propertyPrefix + propName, artifact.getFile().getPath() );
465 }
466
467
468 StringBuilder versionsBuffer = new StringBuilder();
469 for ( Artifact artifact : depArtifacts )
470 {
471 versionsBuffer.append( artifact.getVersion() ).append( File.pathSeparator );
472 }
473 antProject.setProperty( versionsPropertyName, versionsBuffer.toString() );
474 }
475
476
477
478
479
480
481
482
483 public void copyProperties( Project antProject, MavenProject mavenProject )
484 {
485 if ( !exportAntProperties )
486 {
487 return;
488 }
489
490 getLog().debug( "Propagated Ant properties to Maven properties" );
491 Hashtable<String, Object> antProps = antProject.getProperties();
492 Properties mavenProperties = mavenProject.getProperties();
493
494 for ( Map.Entry<String, Object> entry : antProps.entrySet() )
495 {
496 String key = entry.getKey();
497 if ( mavenProperties.getProperty( key ) != null )
498 {
499 getLog().debug( "Ant property '" + key + "=" + mavenProperties.getProperty( key )
500 + "' clashs with an existing Maven property, SKIPPING this Ant property propagation." );
501 continue;
502 }
503
504 mavenProperties.setProperty( key, entry.getValue().toString() );
505 }
506 }
507
508
509
510
511 public void initMavenTasks( Project antProject )
512 {
513 getLog().debug( "Initialize Maven Ant Tasks" );
514 Typedef typedef = new Typedef();
515 typedef.setProject( antProject );
516 typedef.setResource( ANTLIB );
517 if ( !customTaskPrefix.isEmpty() )
518 {
519 typedef.setURI( TASK_URI );
520 }
521 typedef.execute();
522 }
523
524
525
526
527
528
529 private File writeTargetToProjectFile( String targetName )
530 throws IOException
531 {
532
533 File buildFile = new File( mavenProject.getBuild().getDirectory(), "antrun/build-" + targetName + ".xml" );
534
535 buildFile.getParentFile().mkdirs();
536
537 AntrunXmlPlexusConfigurationWriter xmlWriter = new AntrunXmlPlexusConfigurationWriter();
538 xmlWriter.write( target, buildFile, customTaskPrefix, targetName );
539
540 return buildFile;
541 }
542
543
544
545
546
547
548 private String findFragment( BuildException buildException )
549 {
550 if ( buildException == null || buildException.getLocation() == null
551 || buildException.getLocation().getFileName() == null )
552 {
553 return null;
554 }
555
556 File antFile = new File( buildException.getLocation().getFileName() );
557 if ( !antFile.exists() )
558 {
559 return null;
560 }
561
562 try ( LineNumberReader reader = new LineNumberReader( ReaderFactory.newXmlReader( antFile ) ) )
563 {
564 for ( String line = reader.readLine(); line != null; line = reader.readLine() )
565 {
566 if ( reader.getLineNumber() == buildException.getLocation().getLineNumber() )
567 {
568 return "around Ant part ..." + line.trim() + "... @ " + buildException.getLocation().getLineNumber()
569 + ":" + buildException.getLocation().getColumnNumber() + " in " + antFile.getAbsolutePath();
570
571 }
572 }
573 }
574 catch ( Exception e )
575 {
576 getLog().debug( e.getMessage(), e );
577 }
578
579 return null;
580 }
581 }