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