1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.nuxeo.build.maven;
19
20 import java.io.File;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Hashtable;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.apache.maven.artifact.DependencyResolutionRequiredException;
29 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
30 import org.apache.maven.artifact.repository.ArtifactRepository;
31 import org.apache.maven.model.Profile;
32 import org.apache.maven.plugin.AbstractMojo;
33 import org.apache.maven.plugin.MojoExecutionException;
34 import org.apache.maven.plugin.MojoFailureException;
35 import org.apache.maven.plugins.annotations.Component;
36 import org.apache.maven.plugins.annotations.LifecyclePhase;
37 import org.apache.maven.plugins.annotations.Mojo;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.annotations.ResolutionScope;
40 import org.apache.maven.project.MavenProject;
41 import org.apache.maven.project.MavenProjectHelper;
42 import org.apache.maven.settings.Settings;
43 import org.apache.tools.ant.BuildException;
44 import org.apache.tools.ant.ExitStatusException;
45 import org.apache.tools.ant.Project;
46 import org.apache.tools.ant.types.Path;
47 import org.codehaus.plexus.util.ReaderFactory;
48 import org.codehaus.plexus.util.StringUtils;
49 import org.eclipse.aether.DefaultRepositorySystemSession;
50 import org.eclipse.aether.RepositorySystem;
51 import org.eclipse.aether.RepositorySystemSession;
52 import org.eclipse.aether.collection.DependencySelector;
53 import org.eclipse.aether.repository.RemoteRepository;
54 import org.eclipse.aether.util.artifact.JavaScopes;
55 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
56 import org.eclipse.aether.util.graph.selector.AndDependencySelector;
57 import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
58 import org.eclipse.aether.util.graph.selector.OptionalDependencySelector;
59 import org.eclipse.aether.util.graph.transformer.ConflictResolver;
60
61 import org.nuxeo.build.ant.AntClient;
62 import org.nuxeo.build.ant.artifact.Expand;
63 import org.nuxeo.build.ant.profile.AntProfileManager;
64 import org.nuxeo.build.maven.filter.TrueFilter;
65 import org.nuxeo.build.maven.graph.Graph;
66
67
68
69
70
71
72 @Mojo(name = "build", threadSafe = true, defaultPhase = LifecyclePhase.PACKAGE,
73 requiresDependencyCollection = ResolutionScope.TEST,
74 requiresDependencyResolution = ResolutionScope.TEST)
75 public class AntBuildMojo extends AbstractMojo {
76
77 private static final ThreadLocal<AntBuildMojo> instance = new ThreadLocal<>();
78
79 protected Graph graph;
80
81 protected AntProfileManager antProfileManager;
82
83
84
85
86 @Parameter(property = "buildFile")
87 protected File buildFile;
88
89
90
91
92 @Parameter(property = "buildFiles")
93 protected File[] buildFiles;
94
95 public File[] getBuildFiles() throws MojoExecutionException {
96 if (buildFile != null && buildFiles != null && buildFiles.length > 0) {
97 throw new MojoExecutionException(
98 "The configuration parameters 'buildFile' and 'buildFiles' cannot both be used.");
99 }
100 if (buildFiles == null || buildFiles.length == 0) {
101 if (buildFile == null) {
102 buildFile = new File("build.xml");
103 }
104 buildFiles = new File[] { buildFile };
105 }
106 return buildFiles;
107 }
108
109
110
111
112 @Parameter(property = "target")
113 protected String target;
114
115
116
117
118
119
120 @Parameter(property = "targets")
121 protected String[] targets;
122
123
124
125
126 @Parameter(defaultValue = "0", property = "expand")
127 protected String expand;
128
129 @Component
130 protected RepositorySystem system;
131
132 public RepositorySystem getSystem() {
133 return system;
134 }
135
136 @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
137 protected RepositorySystemSession repositorySystemSession;
138
139 protected DefaultRepositorySystemSession session;
140
141 public DefaultRepositorySystemSession getSession() {
142 if (session == null) {
143 session = new DefaultRepositorySystemSession(repositorySystemSession);
144 DependencySelector depSelector = session.getDependencySelector();
145 getLog().debug("Replace DependencySelector " + depSelector);
146 DependencySelector depFilter = new AndDependencySelector(
147 new org.nuxeo.build.maven.graph.ScopeDependencySelector(JavaScopes.PROVIDED, JavaScopes.TEST),
148 new OptionalDependencySelector(), new ExclusionDependencySelector());
149 session.setDependencySelector(depFilter);
150 session.setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, false);
151 session.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true);
152 session.setReadOnly();
153 repositorySystemSession = session;
154 }
155 return session;
156 }
157
158 @Parameter(defaultValue = "${project}", readonly = true)
159 protected MavenProject project;
160
161 @Component
162 protected MavenProjectHelper projectHelper;
163
164 @Component
165 protected ArtifactHandlerManager artifactHandlerManager;
166
167 public ArtifactHandlerManager getArtifactHandlerManager() {
168 return artifactHandlerManager;
169 }
170
171
172
173
174
175
176 @Parameter(defaultValue = "maven.", property = "aamp.propertyPrefix")
177 protected String propertyPrefix;
178
179 @Parameter(defaultValue = "${localRepository}")
180 protected ArtifactRepository localRepository;
181
182
183
184
185
186
187 @Parameter(defaultValue = "false", property = "aamp.exportAntProperties")
188 protected boolean exportAntProperties;
189
190
191
192
193
194
195 @Parameter(property = "aamp.exportedAntProperties")
196 protected Set<String> exportedAntProperties;
197
198 @Parameter(defaultValue = "${project.remoteProjectRepositories}")
199 protected List<RemoteRepository> remoteRepositories;
200
201 public List<RemoteRepository> getRemoteRepositories() {
202 return remoteRepositories;
203 }
204
205
206
207
208 @Parameter(defaultValue = "${project.build.sourceEncoding}", property = "aamp.encoding")
209 protected String encoding;
210
211 public String getEncoding() {
212 if (StringUtils.isEmpty(encoding)) {
213 getLog().warn(
214 "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
215 + ", i.e. build is platform dependent!");
216 encoding = ReaderFactory.FILE_ENCODING;
217 }
218 return encoding;
219 }
220
221 @Parameter(defaultValue = "${settings}")
222 protected Settings settings;
223
224
225
226
227
228
229 @Parameter(defaultValue = "true", property = "failOnError", alias = "aamp.failOnError")
230 protected boolean failOnError;
231
232 @Override
233 public void execute() throws MojoExecutionException, MojoFailureException {
234 instance.set(this);
235 settings.setInteractiveMode(false);
236 AntClient ant = new AntClient(getLog());
237 ant.getProject().setBaseDir(project.getBasedir());
238 try {
239 setAntReferencesFromMaven(ant.getProject());
240 } catch (BuildException | DependencyResolutionRequiredException e) {
241 throw new MojoExecutionException(e.getMessage(), e);
242 }
243 setAntPropertiesFromMaven(ant.getProject());
244
245 if (target != null && targets != null && targets.length > 0) {
246 throw new MojoExecutionException("The configuration parameters 'target' and 'targets' cannot both be used.");
247 }
248 if ((targets == null || targets.length == 0) && target != null) {
249 targets = new String[] { target };
250 }
251 for (File file : getBuildFiles()) {
252 try {
253 if (targets != null && targets.length > 0) {
254 ant.run(file, Arrays.asList(targets));
255 } else {
256 ant.run(file);
257 }
258 if (exportAntProperties) {
259 setMavenPropertiesFromAnt(ant);
260 }
261 } catch (BuildException e) {
262 String errMsg = String.format("Error occurred while running %s@%d:%d\n%s", file.getPath(),
263 e.getLocation().getLineNumber(), e.getLocation().getColumnNumber(), e.getMessage());
264 if (failOnError) {
265 if (e instanceof ExitStatusException) {
266 throw new MojoFailureException(errMsg, e);
267 } else {
268 throw new MojoExecutionException(errMsg, e);
269 }
270 } else {
271 getLog().error(errMsg, e);
272 }
273 }
274 }
275 }
276
277
278
279
280 public Graph newGraph() {
281 graph = new Graph();
282 graph.addRootNode(project);
283 expandGraph(graph);
284 return graph;
285 }
286
287
288
289
290
291
292 public Graph newGraph(String key) {
293 graph = new Graph();
294 graph.addRootNode(key);
295 expandGraph(graph);
296 return graph;
297 }
298
299 protected void expandGraph(Graph newGraph) {
300 int depth = Expand.readExpand(expand);
301 if (depth > 0) {
302 newGraph.resolveDependencies(new TrueFilter(), depth);
303 }
304 }
305
306
307
308
309 protected void setMavenPropertiesFromAnt(AntClient ant) {
310 Hashtable<String, Object> antProps = ant.getProject().getUserProperties();
311 Set<String> keySet;
312 if (exportedAntProperties != null && exportedAntProperties.size() > 0) {
313 keySet = exportedAntProperties;
314 } else {
315 keySet = antProps.keySet();
316 }
317 for (String key : keySet) {
318 if (!(antProps.get(key) instanceof String)) {
319 continue;
320 }
321 project.getProperties().setProperty(key, (String) antProps.get(key));
322 }
323 }
324
325
326
327
328
329
330 protected void setAntReferencesFromMaven(Project antProject) throws BuildException,
331 DependencyResolutionRequiredException {
332 Path p = new Path(antProject);
333 p.setPath(StringUtils.join(project.getCompileClasspathElements().iterator(), File.pathSeparator));
334 antProject.addReference(propertyPrefix + "compile.classpath", p);
335
336 p = new Path(antProject);
337 p.setPath(StringUtils.join(project.getRuntimeClasspathElements().iterator(), File.pathSeparator));
338 antProject.addReference(propertyPrefix + "runtime.classpath", p);
339
340 p = new Path(antProject);
341 p.setPath(StringUtils.join(project.getTestClasspathElements().iterator(), File.pathSeparator));
342 antProject.addReference(propertyPrefix + "test.classpath", p);
343
344 antProject.addReference(propertyPrefix + "project", project);
345 antProject.addReference(propertyPrefix + "project.helper", projectHelper);
346 antProject.addReference(propertyPrefix + "local.repository", localRepository);
347 }
348
349
350
351
352 protected void setAntPropertiesFromMaven(Project antProject) {
353 for (String key : project.getProperties().stringPropertyNames()) {
354 antProject.setInheritedProperty(key, project.getProperties().getProperty(key));
355 }
356 antProject.setProperty(propertyPrefix + "basedir", project.getBasedir().getPath());
357 antProject.setProperty(propertyPrefix + "project.groupId", project.getGroupId());
358 antProject.setProperty(propertyPrefix + "project.artifactId", project.getArtifactId());
359 antProject.setProperty(propertyPrefix + "project.version", project.getVersion());
360 antProject.setProperty(propertyPrefix + "project.name", project.getName());
361 antProject.setProperty(propertyPrefix + "project.description", project.getDescription());
362 antProject.setProperty(propertyPrefix + "project.packaging", project.getPackaging());
363 antProject.setProperty(propertyPrefix + "project.id", project.getId());
364 antProject.setProperty(propertyPrefix + "project.build.directory", project.getBuild().getDirectory());
365 antProject.setProperty(propertyPrefix + "project.build.outputDirectory", project.getBuild()
366 .getOutputDirectory());
367 antProject.setProperty((propertyPrefix + "project.build.testOutputDirectory"), project.getBuild()
368 .getTestOutputDirectory());
369 antProject.setProperty((propertyPrefix + "project.build.sourceDirectory"), project.getBuild()
370 .getSourceDirectory());
371 antProject.setProperty((propertyPrefix + "project.build.testSourceDirectory"), project.getBuild()
372 .getTestSourceDirectory());
373 antProject.setProperty((propertyPrefix + "localRepository"), localRepository.toString());
374 antProject.setProperty((propertyPrefix + "settings.localRepository"), localRepository.getBasedir());
375 antProject.setProperty(propertyPrefix + "project.build.finalName", project.getBuild().getFinalName());
376 antProject.setProperty(propertyPrefix + "offline", settings.isOffline() ? "-o" : "");
377
378
379 antProfileManager = new AntProfileManager();
380 for (String profileId : getInjectedProfileIds()) {
381 antProfileManager.activateProfile(profileId, true);
382
383 antProject.setProperty(propertyPrefix + "profile." + profileId, "true");
384 }
385
386 for (String key : System.getProperties().stringPropertyNames()) {
387 antProject.setUserProperty(key, System.getProperty(key));
388 }
389 }
390
391 public List<Profile> getActiveProfiles() {
392 return project.getActiveProfiles();
393 }
394
395 public List<String> getInjectedProfileIds() {
396 List<String> profileIds = new ArrayList<>();
397 Map<String, List<String>> injectedProfileIds = project.getInjectedProfileIds();
398 if (injectedProfileIds.size() > 0) {
399 StringBuilder sb = new StringBuilder();
400 sb.append("Active Maven profiles:");
401 for (Map.Entry<String, List<String>> entry : injectedProfileIds.entrySet()) {
402 for (String profileId : entry.getValue()) {
403 sb.append(String.format("\n%s (source: %s)", profileId, entry.getKey()));
404 if (!profileIds.contains(profileId)) {
405 profileIds.add(profileId);
406 }
407 }
408 }
409 getLog().info(sb.toString());
410 }
411 return profileIds;
412 }
413
414 public MavenProject getProject() {
415 return project;
416 }
417
418 public ArtifactRepository getLocalRepository() {
419 return localRepository;
420 }
421
422 public MavenProjectHelper getProjectHelper() {
423 return projectHelper;
424 }
425
426 public Graph getGraph() {
427 if (graph == null) {
428 graph = newGraph();
429 }
430 return graph;
431 }
432
433 public AntProfileManager getAntProfileManager() {
434 return antProfileManager;
435 }
436
437
438
439
440 public static AntBuildMojo getInstance() {
441 return instance.get();
442 }
443
444 }