1 package com.atlassian.maven.plugins.amps;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.net.ServerSocket;
7 import java.net.URL;
8 import java.net.URLClassLoader;
9 import java.util.ArrayList;
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.jar.Manifest;
17 import java.util.regex.Matcher;
18
19 import com.atlassian.core.util.FileUtils;
20 import com.atlassian.maven.plugins.amps.util.PluginXmlUtils;
21 import com.atlassian.maven.plugins.amps.util.VersionUtils;
22
23 import com.sun.jersey.wadl.resourcedoc.ResourceDocletJSON;
24
25 import org.apache.commons.io.IOUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.maven.artifact.DependencyResolutionRequiredException;
28 import org.apache.maven.model.Plugin;
29 import org.apache.maven.plugin.MojoExecutionException;
30 import org.apache.maven.plugin.logging.Log;
31 import org.apache.maven.project.MavenProject;
32 import org.codehaus.plexus.util.xml.Xpp3Dom;
33 import org.twdata.maven.mojoexecutor.MojoExecutor.Element;
34 import org.twdata.maven.mojoexecutor.MojoExecutor.ExecutionEnvironment;
35
36 import aQute.lib.osgi.Constants;
37
38 import static com.atlassian.maven.plugins.amps.util.FileUtils.file;
39 import static com.atlassian.maven.plugins.amps.util.FileUtils.fixWindowsSlashes;
40 import static org.twdata.maven.mojoexecutor.MojoExecutor.artifactId;
41 import static org.twdata.maven.mojoexecutor.MojoExecutor.configuration;
42 import static org.twdata.maven.mojoexecutor.MojoExecutor.element;
43 import static org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo;
44 import static org.twdata.maven.mojoexecutor.MojoExecutor.goal;
45 import static org.twdata.maven.mojoexecutor.MojoExecutor.groupId;
46 import static org.twdata.maven.mojoexecutor.MojoExecutor.name;
47 import static org.twdata.maven.mojoexecutor.MojoExecutor.plugin;
48 import static org.twdata.maven.mojoexecutor.MojoExecutor.version;
49
50
51
52
53 public class MavenGoals
54 {
55 private final MavenContext ctx;
56
57 private final Log log;
58 private final Map<String, String> pluginArtifactIdToVersionMap;
59
60 private final Map<String, Container> idToContainerMap = new HashMap<String, Container>()
61 {{
62 put("tomcat5x", new Container("tomcat5x", "org.apache.tomcat", "apache-tomcat", "5.5.26"));
63 put("tomcat6x", new Container("tomcat6x", "org.apache.tomcat", "apache-tomcat", "6.0.20"));
64 put("tomcat7x", new Container("tomcat7x", "org.apache.tomcat", "apache-tomcat", "7.0.22", "windows-x64"));
65 put("resin3x", new Container("resin3x", "com.caucho", "resin", "3.0.26"));
66 put("jboss42x", new Container("jboss42x", "org.jboss.jbossas", "jbossas", "4.2.3.GA"));
67 put("jetty6x", new Container("jetty6x"));
68 }};
69
70 private final Map<String, String> defaultArtifactIdToVersionMap = new HashMap<String, String>()
71 {{
72 put("maven-cli-plugin", "0.7");
73 put("cargo-maven2-plugin", "1.0-beta-2-db2");
74
75 put("org.codehaus.cargo:cargo-maven2-plugin", "1.1.3");
76 put("atlassian-pdk", "2.3.1");
77 put("maven-archetype-plugin", "2.0-alpha-4");
78 put("maven-bundle-plugin", "2.0.0");
79 put("yuicompressor-maven-plugin", "0.7.1");
80 put("build-helper-maven-plugin", "1.7");
81
82
83
84 put("maven-dependency-plugin", "2.0");
85 put("maven-resources-plugin", "2.3");
86 put("maven-jar-plugin", "2.2");
87 put("maven-surefire-plugin", "2.4.3");
88
89 }};
90
91 public MavenGoals(final MavenContext ctx)
92 {
93 this.ctx = ctx;
94
95 this.log = ctx.getLog();
96
97 this.pluginArtifactIdToVersionMap = Collections.unmodifiableMap(defaultArtifactIdToVersionMap);
98 }
99
100 private ExecutionEnvironment executionEnvironment()
101 {
102 return ctx.getExecutionEnvironment();
103 }
104
105 public MavenProject getContextProject()
106 {
107 return ctx.getProject();
108 }
109
110 public void executeAmpsRecursively(final String ampsVersion, final String ampsGoal, Xpp3Dom cfg) throws MojoExecutionException
111 {
112 executeMojo(
113 plugin(
114 groupId("com.atlassian.maven.plugins"),
115 artifactId("maven-amps-plugin"),
116 version(ampsVersion)
117 ),
118 goal(ampsGoal),
119 cfg,
120 executionEnvironment());
121 }
122
123 public void startCli(final PluginInformation pluginInformation, final int port) throws MojoExecutionException
124 {
125 final String pluginId = pluginInformation.getId();
126
127 final List<Element> configs = new ArrayList<Element>();
128 configs.add(element(name("commands"),
129 element(name("pi"),
130 "resources" + " "
131 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
132 + "compile" + " "
133 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
134 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:compress-resources" + " "
135 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
136 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-manifest" + " "
137 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " "
138 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:install"),
139 element(name("tpi"),
140 "testResources" + " "
141 + "testCompile" + " "
142 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-jar" + " "
143 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-install"),
144 element(name("package"),
145 "resources" + " "
146 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
147 + "compile" + " "
148 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
149 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
150 + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " ")));
151 if (port > 0)
152 {
153 configs.add(element(name("port"), String.valueOf(port)));
154 }
155 executeMojo(
156 plugin(
157 groupId("org.twdata.maven"),
158 artifactId("maven-cli-plugin"),
159 version(pluginArtifactIdToVersionMap.get("maven-cli-plugin"))
160 ),
161 goal("execute"),
162 configuration(configs.toArray(new Element[0])),
163 executionEnvironment());
164 }
165
166 public void createPlugin(final String productId) throws MojoExecutionException
167 {
168 executeMojo(
169 plugin(
170 groupId("org.apache.maven.plugins"),
171 artifactId("maven-archetype-plugin"),
172 version(defaultArtifactIdToVersionMap.get("maven-archetype-plugin"))
173 ),
174 goal("generate"),
175 configuration(
176 element(name("archetypeGroupId"), "com.atlassian.maven.archetypes"),
177 element(name("archetypeArtifactId"), (productId.equals("all") ? "" : productId + "-" ) + "plugin-archetype"),
178 element(name("archetypeVersion"), VersionUtils.getVersion())
179 ),
180 executionEnvironment());
181 }
182
183 public void copyBundledDependencies() throws MojoExecutionException
184 {
185 executeMojo(
186 plugin(
187 groupId("org.apache.maven.plugins"),
188 artifactId("maven-dependency-plugin"),
189 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
190 ),
191 goal("copy-dependencies"),
192 configuration(
193 element(name("includeScope"), "runtime"),
194 element(name("excludeScope"), "provided"),
195 element(name("excludeScope"), "test"),
196 element(name("includeTypes"), "jar"),
197 element(name("outputDirectory"), "${project.build.outputDirectory}/META-INF/lib")
198 ),
199 executionEnvironment()
200 );
201 }
202
203 public void extractBundledDependencies() throws MojoExecutionException
204 {
205 executeMojo(
206 plugin(
207 groupId("org.apache.maven.plugins"),
208 artifactId("maven-dependency-plugin"),
209 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
210 ),
211 goal("unpack-dependencies"),
212 configuration(
213 element(name("includeScope"), "runtime"),
214 element(name("excludeScope"), "provided"),
215 element(name("excludeScope"), "test"),
216 element(name("includeTypes"), "jar"),
217 element(name("excludes"), "META-INF/MANIFEST.MF, META-INF/*.DSA, META-INF/*.SF"),
218 element(name("outputDirectory"), "${project.build.outputDirectory}")
219 ),
220 executionEnvironment()
221 );
222 }
223
224 public void compressResources() throws MojoExecutionException
225 {
226 executeMojo(
227 plugin(
228 groupId("net.sf.alchim"),
229 artifactId("yuicompressor-maven-plugin"),
230 version(defaultArtifactIdToVersionMap.get("yuicompressor-maven-plugin"))
231 ),
232 goal("compress"),
233 configuration(
234 element(name("suffix"), "-min"),
235 element(name("jswarn"), "false")
236 ),
237 executionEnvironment()
238 );
239 }
240
241 public void filterPluginDescriptor() throws MojoExecutionException
242 {
243 executeMojo(
244 plugin(
245 groupId("org.apache.maven.plugins"),
246 artifactId("maven-resources-plugin"),
247 version(defaultArtifactIdToVersionMap.get("maven-resources-plugin"))
248 ),
249 goal("copy-resources"),
250 configuration(
251 element(name("encoding"), "UTF-8"),
252 element(name("resources"),
253 element(name("resource"),
254 element(name("directory"), "src/main/resources"),
255 element(name("filtering"), "true"),
256 element(name("includes"),
257 element(name("include"), "atlassian-plugin.xml"))
258 )
259 ),
260 element(name("outputDirectory"), "${project.build.outputDirectory}")
261 ),
262 executionEnvironment()
263 );
264 }
265
266 public void runUnitTests(Map<String, Object> systemProperties) throws MojoExecutionException
267 {
268 final Element systemProps = convertPropsToElements(systemProperties);
269
270 executeMojo(
271 plugin(
272 groupId("org.apache.maven.plugins"),
273 artifactId("maven-surefire-plugin"),
274 version(defaultArtifactIdToVersionMap.get("maven-surefire-plugin"))
275 ),
276 goal("test"),
277 configuration(
278 systemProps,
279 element(name("excludes"),
280 element(name("exclude"), "it/**"),
281 element(name("exclude"), "**/*$*"))
282 ),
283 executionEnvironment()
284 );
285 }
286
287 public File copyWebappWar(final String productId, final File targetDirectory, final ProductArtifact artifact)
288 throws MojoExecutionException
289 {
290 final File webappWarFile = new File(targetDirectory, productId + "-original.war");
291 executeMojo(
292 plugin(
293 groupId("org.apache.maven.plugins"),
294 artifactId("maven-dependency-plugin"),
295 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
296 ),
297 goal("copy"),
298 configuration(
299 element(name("artifactItems"),
300 element(name("artifactItem"),
301 element(name("groupId"), artifact.getGroupId()),
302 element(name("artifactId"), artifact.getArtifactId()),
303 element(name("type"), "war"),
304 element(name("version"), artifact.getVersion()),
305 element(name("destFileName"), webappWarFile.getName()))),
306 element(name("outputDirectory"), targetDirectory.getPath())
307 ),
308 executionEnvironment()
309 );
310 return webappWarFile;
311 }
312
313 public File copyArtifact(final String targetFileName, final File targetDirectory,
314 final ProductArtifact artifact, String type) throws MojoExecutionException
315 {
316 final File targetFile = new File(targetDirectory, targetFileName);
317 executeMojo(
318 plugin(
319 groupId("org.apache.maven.plugins"),
320 artifactId("maven-dependency-plugin"),
321 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
322 ),
323 goal("copy"),
324 configuration(
325 element(name("artifactItems"),
326 element(name("artifactItem"),
327 element(name("groupId"), artifact.getGroupId()),
328 element(name("artifactId"), artifact.getArtifactId()),
329 element(name("type"), type),
330 element(name("version"), artifact.getVersion()),
331 element(name("destFileName"), targetFile.getName()))),
332 element(name("outputDirectory"), targetDirectory.getPath())
333 ),
334 executionEnvironment()
335 );
336 return targetFile;
337 }
338
339
340
341
342
343
344
345
346
347
348 public void copyPlugins(final File outputDirectory, final List<ProductArtifact> artifacts)
349 throws MojoExecutionException
350 {
351 for (ProductArtifact artifact : artifacts)
352 {
353 final MavenProject artifactReactorProject = getReactorProjectForArtifact(artifact);
354 if (artifactReactorProject != null)
355 {
356
357 log.debug(artifact + " will be copied from reactor project " + artifactReactorProject);
358 final File artifactFile = artifactReactorProject.getArtifact().getFile();
359 if (artifactFile == null)
360 {
361 log.warn("The plugin " + artifact + " is in the reactor but not the file hasn't been attached. Skipping.");
362 }
363 else
364 {
365 log.debug("Copying " + artifactFile + " to " + outputDirectory);
366 try
367 {
368 FileUtils.copyFile(artifactFile, new File(outputDirectory, artifactFile.getName()));
369 }
370 catch (IOException e)
371 {
372 throw new MojoExecutionException("Could not copy " + artifact + " to " + outputDirectory, e);
373 }
374 }
375
376 }
377 else
378 {
379 executeMojo(
380 plugin(
381 groupId("org.apache.maven.plugins"),
382 artifactId("maven-dependency-plugin"),
383 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
384 ),
385 goal("copy"),
386 configuration(
387 element(name("artifactItems"),
388 element(name("artifactItem"),
389 element(name("groupId"), artifact.getGroupId()),
390 element(name("artifactId"), artifact.getArtifactId()),
391 element(name("version"), artifact.getVersion()))),
392 element(name("outputDirectory"), outputDirectory.getPath())
393 ),
394 executionEnvironment());
395 }
396 }
397 }
398
399 private MavenProject getReactorProjectForArtifact(ProductArtifact artifact)
400 {
401 for (final MavenProject project : ctx.getReactor())
402 {
403 if (project.getGroupId().equals(artifact.getGroupId())
404 && project.getArtifactId().equals(artifact.getArtifactId())
405 && project.getVersion().equals(artifact.getVersion()))
406 {
407 return project;
408 }
409 }
410 return null;
411 }
412
413 private void unpackContainer(final Container container) throws MojoExecutionException
414 {
415 executeMojo(
416 plugin(
417 groupId("org.apache.maven.plugins"),
418 artifactId("maven-dependency-plugin"),
419 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
420 ),
421 goal("unpack"),
422 configuration(
423 element(name("artifactItems"),
424 element(name("artifactItem"),
425 element(name("groupId"), container.getGroupId()),
426 element(name("artifactId"), container.getArtifactId()),
427 element(name("version"), container.getVersion()),
428 element(name("classifier"), container.getClassifier()),
429 element(name("type"), "zip"))),
430 element(name("outputDirectory"), container.getRootDirectory(getBuildDirectory()))
431 ),
432 executionEnvironment());
433 }
434
435 private String getBuildDirectory()
436 {
437 return ctx.getProject().getBuild().getDirectory();
438 }
439
440 private static Xpp3Dom configurationWithoutNullElements(Element... elements)
441 {
442 List<Element> nonNullElements = new ArrayList<Element>();
443 for (Element e : elements)
444 {
445 if (e != null)
446 {
447 nonNullElements.add(e);
448 }
449 }
450
451 return configuration(nonNullElements.toArray(new Element[nonNullElements.size()]));
452 }
453
454 public int startWebapp(final String productInstanceId, final File war, final Map<String, String> systemProperties, final List<ProductArtifact> extraContainerDependencies,
455 final Product webappContext) throws MojoExecutionException
456 {
457 final Container container = findContainer(webappContext.getContainerId());
458 File containerDir = new File(container.getRootDirectory(getBuildDirectory()));
459
460
461 if (!container.isEmbedded())
462 {
463 if (containerDir.exists())
464 {
465 log.info("Reusing unpacked container '" + container.getId() + "' from " + containerDir.getPath());
466 }
467 else
468 {
469 log.info("Unpacking container '" + container.getId() + "' from container artifact: " + container.toString());
470 unpackContainer(container);
471 }
472 }
473
474 final int rmiPort = pickFreePort(0);
475 final int actualHttpPort = pickFreePort(webappContext.getHttpPort());
476 final List<Element> sysProps = new ArrayList<Element>();
477
478 for (final Map.Entry<String, String> entry : systemProperties.entrySet())
479 {
480 sysProps.add(element(name(entry.getKey()), entry.getValue()));
481 }
482 log.info("Starting " + productInstanceId + " on the " + container.getId() + " container on ports "
483 + actualHttpPort + " (http) and " + rmiPort + " (rmi)");
484
485 final String baseUrl = getBaseUrl(webappContext, actualHttpPort);
486 sysProps.add(element(name("baseurl"), baseUrl));
487
488 final List<Element> deps = new ArrayList<Element>();
489 for (final ProductArtifact dep : extraContainerDependencies)
490 {
491 deps.add(element(name("dependency"),
492 element(name("location"), webappContext.getArtifactRetriever().resolve(dep))
493 ));
494 }
495
496 final List<Element> props = new ArrayList<Element>();
497 for (final Map.Entry<String, String> entry : systemProperties.entrySet())
498 {
499 props.add(element(name(entry.getKey()), entry.getValue()));
500 }
501 props.add(element(name("cargo.servlet.port"), String.valueOf(actualHttpPort)));
502 props.add(element(name("cargo.rmi.port"), String.valueOf(rmiPort)));
503 props.add(element(name("cargo.jvmargs"), webappContext.getJvmArgs()));
504
505 int startupTimeout = webappContext.getStartupTimeout();
506 if (Boolean.FALSE.equals(webappContext.getSynchronousStartup()))
507 {
508 startupTimeout = 0;
509 }
510
511 Plugin cargo = cargo(webappContext);
512
513 executeMojo(
514 cargo,
515 goal("start"),
516 configurationWithoutNullElements(
517 waitElement(cargo),
518 element(name("container"),
519 element(name("containerId"), container.getId()),
520 element(name("type"), container.getType()),
521 element(name("home"), container.getInstallDirectory(getBuildDirectory())),
522 element(name("output"), webappContext.getOutput()),
523 element(name("systemProperties"), sysProps.toArray(new Element[sysProps.size()])),
524 element(name("dependencies"), deps.toArray(new Element[deps.size()])),
525 element(name("timeout"), String.valueOf(startupTimeout))
526 ),
527 element(name("configuration"),
528 element(name("home"), container.getConfigDirectory(getBuildDirectory(), productInstanceId)),
529 element(name("type"), "standalone"),
530 element(name("properties"), props.toArray(new Element[props.size()])),
531 element(name("deployables"),
532 element(name("deployable"),
533 element(name("groupId"), "foo"),
534 element(name("artifactId"), "bar"),
535 element(name("type"), "war"),
536 element(name("location"), war.getPath()),
537 element(name("properties"),
538 element(name("context"), webappContext.getContextPath())
539 )
540 )
541 )
542 )
543 ),
544 executionEnvironment()
545 );
546 return actualHttpPort;
547 }
548
549 public void stopWebapp(final String productId, final String containerId, final Product webappContext) throws MojoExecutionException
550 {
551 final Container container = findContainer(containerId);
552
553 String actualShutdownTimeout = webappContext.getSynchronousStartup() ? "0" : String.valueOf(webappContext.getShutdownTimeout());
554
555 executeMojo(
556 cargo(webappContext),
557 goal("stop"),
558 configuration(
559 element(name("container"),
560 element(name("containerId"), container.getId()),
561 element(name("type"), container.getType()),
562 element(name("timeout"), actualShutdownTimeout),
563
564 element(name("home"), container.getInstallDirectory(getBuildDirectory()))
565 ),
566 element(name("configuration"),
567
568 element(name("home"), container.getConfigDirectory(getBuildDirectory(), productId))
569
570
571 )
572 ),
573 executionEnvironment()
574 );
575 }
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594 private Element[] createShutdownPortsPropertiesConfiguration(final Product webappContext)
595 {
596 final List<Element> properties = new ArrayList<Element>();
597 String portUsedToDetermineIfShutdownSucceeded = String.valueOf(webappContext.getHttpPort());
598 properties.add(element(name("cargo.servlet.port"), portUsedToDetermineIfShutdownSucceeded));
599 properties.add(element(name("cargo.rmi.port"), portUsedToDetermineIfShutdownSucceeded));
600 properties.add(element(name("cargo.tomcat.ajp.port"), portUsedToDetermineIfShutdownSucceeded));
601 return properties.toArray(new Element[properties.size()]);
602 }
603
604
605
606
607
608
609
610
611
612
613
614 private Plugin cargo(Product context)
615 {
616 if (Boolean.TRUE.equals(context.getSynchronousStartup())
617
618 && !"tomcat7x".equals(context.getContainerId()))
619 {
620 return plugin(
621 groupId("org.twdata.maven"),
622 artifactId("cargo-maven2-plugin"),
623 version(pluginArtifactIdToVersionMap.get("cargo-maven2-plugin")));
624 }
625 else
626 {
627 return plugin(
628 groupId("org.codehaus.cargo"),
629 artifactId("cargo-maven2-plugin"),
630 version(pluginArtifactIdToVersionMap.get("org.codehaus.cargo:cargo-maven2-plugin")));
631 }
632 }
633
634 private Element waitElement(Plugin cargo)
635 {
636 if (cargo.getGroupId().equals("org.twdata.maven"))
637 {
638 return element(name("wait"), "false");
639 }
640
641
642 return null;
643 }
644
645 public static String getBaseUrl(Product product, int actualHttpPort)
646 {
647 return getBaseUrl(product.getServer(), product.getHttpPort(), product.getContextPath());
648 }
649
650 private static String getBaseUrl(String server, int actualHttpPort, String contextPath)
651 {
652 String port = actualHttpPort != 80 ? ":" + actualHttpPort : "";
653 server = server.startsWith("http") ? server : "http://" + server;
654 if (!contextPath.startsWith("/") && StringUtils.isNotBlank(contextPath))
655 {
656 contextPath = "/" + contextPath;
657 }
658 return server + port + contextPath;
659 }
660
661 public void runTests(String testGroupId, String containerId, List<String> includes, List<String> excludes, Map<String, Object> systemProperties, final File targetDirectory)
662 throws MojoExecutionException
663 {
664 List<Element> includeElements = new ArrayList<Element>(includes.size());
665 for (String include : includes)
666 {
667 includeElements.add(element(name("include"), include));
668 }
669
670 List<Element> excludeElements = new ArrayList<Element>(excludes.size() + 2);
671 excludeElements.add(element(name("exclude"), "**/*$*"));
672 excludeElements.add(element(name("exclude"), "**/Abstract*"));
673 for (String exclude : excludes)
674 {
675 excludeElements.add(element(name("exclude"), exclude));
676 }
677
678 final String testOutputDir = targetDirectory.getAbsolutePath() + "/" + testGroupId + "/" + containerId + "/surefire-reports";
679 final String reportsDirectory = "reportsDirectory";
680 systemProperties.put(reportsDirectory, testOutputDir);
681
682 final Element systemProps = convertPropsToElements(systemProperties);
683
684
685 executeMojo(
686 plugin(
687 groupId("org.apache.maven.plugins"),
688 artifactId("maven-surefire-plugin"),
689 version(defaultArtifactIdToVersionMap.get("maven-surefire-plugin"))
690 ),
691 goal("test"),
692 configuration(
693 element(name("includes"),
694 includeElements.toArray(new Element[includeElements.size()])
695 ),
696 element(name("excludes"),
697 excludeElements.toArray(new Element[excludeElements.size()])
698 ),
699 systemProps,
700 element(name(reportsDirectory), testOutputDir)
701 ),
702 executionEnvironment()
703 );
704 }
705
706
707
708
709 private Element convertPropsToElements(Map<String, Object> systemProperties)
710 {
711 ArrayList<Element> properties = new ArrayList<Element>();
712
713
714 for (Map.Entry<String, Object> entry: systemProperties.entrySet())
715 {
716 properties.add(
717 element(name("property"),
718 element(name("name"), entry.getKey()),
719 element(name("value"), entry.getValue().toString())));
720 }
721
722 return element(name("systemProperties"), properties.toArray(new Element[properties.size()]));
723 }
724
725 private Container findContainer(final String containerId)
726 {
727 final Container container = idToContainerMap.get(containerId);
728 if (container == null)
729 {
730 throw new IllegalArgumentException("Container " + containerId + " not supported");
731 }
732 return container;
733 }
734
735 int pickFreePort(final int requestedPort)
736 {
737 ServerSocket socket = null;
738 try
739 {
740 socket = new ServerSocket(requestedPort);
741 return requestedPort > 0 ? requestedPort : socket.getLocalPort();
742 }
743 catch (final IOException e)
744 {
745
746 ServerSocket zeroSocket = null;
747 try
748 {
749 zeroSocket = new ServerSocket(0);
750 return zeroSocket.getLocalPort();
751 }
752 catch (final IOException ex)
753 {
754 throw new RuntimeException("Error opening socket", ex);
755 }
756 finally
757 {
758 closeSocket(zeroSocket);
759 }
760 }
761 finally
762 {
763 closeSocket(socket);
764 }
765 }
766
767 private void closeSocket(ServerSocket socket)
768 {
769 if (socket != null)
770 {
771 try
772 {
773 socket.close();
774 }
775 catch (final IOException e)
776 {
777 throw new RuntimeException("Error closing socket", e);
778 }
779 }
780 }
781
782 public void installPlugin(PdkParams pdkParams)
783 throws MojoExecutionException
784 {
785 final String baseUrl = getBaseUrl(pdkParams.getServer(), pdkParams.getPort(), pdkParams.getContextPath());
786 executeMojo(
787 plugin(
788 groupId("com.atlassian.maven.plugins"),
789 artifactId("atlassian-pdk"),
790 version(pluginArtifactIdToVersionMap.get("atlassian-pdk"))
791 ),
792 goal("install"),
793 configuration(
794 element(name("pluginFile"), pdkParams.getPluginFile()),
795 element(name("username"), pdkParams.getUsername()),
796 element(name("password"), pdkParams.getPassword()),
797 element(name("serverUrl"), baseUrl),
798 element(name("pluginKey"), pdkParams.getPluginKey())
799 ),
800 executionEnvironment()
801 );
802 }
803
804 public void uninstallPlugin(final String pluginKey, final String server, final int port, final String contextPath)
805 throws MojoExecutionException
806 {
807 final String baseUrl = getBaseUrl(server, port, contextPath);
808 executeMojo(
809 plugin(
810 groupId("com.atlassian.maven.plugins"),
811 artifactId("atlassian-pdk"),
812 version(pluginArtifactIdToVersionMap.get("atlassian-pdk"))
813 ),
814 goal("uninstall"),
815 configuration(
816 element(name("username"), "admin"),
817 element(name("password"), "admin"),
818 element(name("serverUrl"), baseUrl),
819 element(name("pluginKey"), pluginKey)
820 ),
821 executionEnvironment()
822 );
823 }
824
825 public void installIdeaPlugin() throws MojoExecutionException
826 {
827 executeMojo(
828 plugin(
829 groupId("org.twdata.maven"),
830 artifactId("maven-cli-plugin"),
831 version(pluginArtifactIdToVersionMap.get("maven-cli-plugin"))
832 ),
833 goal("idea"),
834 configuration(),
835 executionEnvironment()
836 );
837 }
838
839 public File copyDist(final File targetDirectory, final ProductArtifact artifact) throws MojoExecutionException
840 {
841 return copyZip(targetDirectory, artifact, "test-dist.zip");
842 }
843
844 public File copyHome(final File targetDirectory, final ProductArtifact artifact) throws MojoExecutionException
845 {
846 return copyZip(targetDirectory, artifact, artifact.getArtifactId() + ".zip");
847 }
848
849 public File copyZip(final File targetDirectory, final ProductArtifact artifact, final String localName) throws MojoExecutionException
850 {
851 final File artifactZip = new File(targetDirectory, localName);
852 executeMojo(
853 plugin(
854 groupId("org.apache.maven.plugins"),
855 artifactId("maven-dependency-plugin"),
856 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
857 ),
858 goal("copy"),
859 configuration(
860 element(name("artifactItems"),
861 element(name("artifactItem"),
862 element(name("groupId"), artifact.getGroupId()),
863 element(name("artifactId"), artifact.getArtifactId()),
864 element(name("type"), "zip"),
865 element(name("version"), artifact.getVersion()),
866 element(name("destFileName"), artifactZip.getName()))),
867 element(name("outputDirectory"), artifactZip.getParent())
868 ),
869 executionEnvironment()
870 );
871 return artifactZip;
872 }
873
874 public void generateBundleManifest(final Map<String, String> instructions, final Map<String, String> basicAttributes) throws MojoExecutionException
875 {
876 final List<Element> instlist = new ArrayList<Element>();
877 for (final Map.Entry<String, String> entry : instructions.entrySet())
878 {
879 instlist.add(element(entry.getKey(), entry.getValue()));
880 }
881 if (!instructions.containsKey(Constants.IMPORT_PACKAGE))
882 {
883 instlist.add(element(Constants.IMPORT_PACKAGE, "*;resolution:=optional"));
884
885
886 }
887 for (final Map.Entry<String, String> entry : basicAttributes.entrySet())
888 {
889 instlist.add(element(entry.getKey(), entry.getValue()));
890 }
891 executeMojo(
892 plugin(
893 groupId("org.apache.felix"),
894 artifactId("maven-bundle-plugin"),
895 version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
896 ),
897 goal("manifest"),
898 configuration(
899 element(name("supportedProjectTypes"),
900 element(name("supportedProjectType"), "jar"),
901 element(name("supportedProjectType"), "bundle"),
902 element(name("supportedProjectType"), "war"),
903 element(name("supportedProjectType"), "atlassian-plugin")),
904 element(name("instructions"), instlist.toArray(new Element[instlist.size()]))
905 ),
906 executionEnvironment()
907 );
908 }
909
910 public void generateMinimalManifest(final Map<String, String> basicAttributes) throws MojoExecutionException
911 {
912 File metaInf = file(ctx.getProject().getBuild().getOutputDirectory(), "META-INF");
913 if (!metaInf.exists())
914 {
915 metaInf.mkdirs();
916 }
917 File mf = file(ctx.getProject().getBuild().getOutputDirectory(), "META-INF", "MANIFEST.MF");
918 Manifest m = new Manifest();
919 m.getMainAttributes().putValue("Manifest-Version", "1.0");
920 for (Map.Entry<String, String> entry : basicAttributes.entrySet())
921 {
922 m.getMainAttributes().putValue(entry.getKey(), entry.getValue());
923 }
924 FileOutputStream fos = null;
925 try
926 {
927 fos = new FileOutputStream(mf);
928 m.write(fos);
929 }
930 catch (IOException e)
931 {
932 throw new MojoExecutionException("Unable to create manifest", e);
933 }
934 finally
935 {
936 IOUtils.closeQuietly(fos);
937 }
938 }
939
940 public void jarWithOptionalManifest(final boolean manifestExists) throws MojoExecutionException
941 {
942 Element[] archive = new Element[0];
943 if (manifestExists)
944 {
945 archive = new Element[]{element(name("manifestFile"), "${project.build.outputDirectory}/META-INF/MANIFEST.MF")};
946 }
947
948 executeMojo(
949 plugin(
950 groupId("org.apache.maven.plugins"),
951 artifactId("maven-jar-plugin"),
952 version(defaultArtifactIdToVersionMap.get("maven-jar-plugin"))
953 ),
954 goal("jar"),
955 configuration(
956 element(name("archive"), archive)
957 ),
958 executionEnvironment()
959 );
960 }
961
962 public void jarTests(String finalName) throws MojoExecutionException
963 {
964 executeMojo(
965 plugin(
966 groupId("org.apache.maven.plugins"),
967 artifactId("maven-jar-plugin"),
968 version(defaultArtifactIdToVersionMap.get("maven-jar-plugin"))
969 ),
970 goal("test-jar"),
971 configuration(
972 element(name("finalName"), finalName),
973 element(name("archive"),
974 element(name("manifestFile"), "${project.build.testOutputDirectory}/META-INF/MANIFEST.MF"))
975 ),
976 executionEnvironment()
977 );
978 }
979
980 public void generateObrXml(File dep, File obrXml) throws MojoExecutionException
981 {
982 executeMojo(
983 plugin(
984 groupId("org.apache.felix"),
985 artifactId("maven-bundle-plugin"),
986 version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
987 ),
988 goal("install-file"),
989 configuration(
990 element(name("obrRepository"), obrXml.getPath()),
991
992
993 element(name("groupId"), "doesntmatter"),
994 element(name("artifactId"), "doesntmatter"),
995 element(name("version"), "doesntmatter"),
996
997 element(name("packaging"), "jar"),
998 element(name("file"), dep.getPath())
999
1000 ),
1001 executionEnvironment()
1002 );
1003 }
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015 public void attachArtifact(File file, String type) throws MojoExecutionException
1016 {
1017
1018 executeMojo(
1019 plugin(
1020 groupId("org.codehaus.mojo"),
1021 artifactId("build-helper-maven-plugin"),
1022 version(defaultArtifactIdToVersionMap.get("build-helper-maven-plugin"))
1023 ),
1024 goal("attach-artifact"),
1025 configuration(
1026 element(name("artifacts"),
1027 element(name("artifact"),
1028 element(name("file"), file.getAbsolutePath()),
1029 element(name("type"), type)
1030 )
1031 )
1032 ),
1033 executionEnvironment());
1034
1035 }
1036
1037 public void release(String mavenArgs) throws MojoExecutionException
1038 {
1039 String args = "";
1040
1041 if(StringUtils.isNotBlank(mavenArgs)) {
1042 args = mavenArgs;
1043 }
1044
1045 executeMojo(
1046 plugin(
1047 groupId("org.apache.maven.plugins"),
1048 artifactId("maven-release-plugin"),
1049 version(defaultArtifactIdToVersionMap.get("maven-release-plugin"))
1050 ),
1051 goal("prepare"),
1052 configuration(
1053 element(name("arguments"), args)
1054 ),
1055 executionEnvironment()
1056 );
1057
1058 executeMojo(
1059 plugin(
1060 groupId("org.apache.maven.plugins"),
1061 artifactId("maven-release-plugin"),
1062 version(defaultArtifactIdToVersionMap.get("maven-release-plugin"))
1063 ),
1064 goal("perform"),
1065 configuration(
1066 element(name("arguments"), args)
1067 ),
1068 executionEnvironment()
1069 );
1070 }
1071
1072 public void generateRestDocs() throws MojoExecutionException
1073 {
1074 MavenProject prj = ctx.getProject();
1075 StringBuffer packagesPath = new StringBuffer();
1076 List<PluginXmlUtils.RESTModuleInfo> restModules = PluginXmlUtils.getRestModules(ctx);
1077
1078 for(PluginXmlUtils.RESTModuleInfo moduleInfo : restModules)
1079 {
1080 List<String> packageList = moduleInfo.getPackagesToScan();
1081
1082 for(String packageToScan : packageList)
1083 {
1084 if(packagesPath.length() > 0)
1085 {
1086 packagesPath.append(File.pathSeparator);
1087 }
1088
1089 String filePath = prj.getBuild().getSourceDirectory() + File.separator + packageToScan.replaceAll("\\.", Matcher.quoteReplacement(File.separator));
1090 packagesPath.append(filePath);
1091 }
1092 }
1093
1094 if(!restModules.isEmpty() && packagesPath.length() > 0)
1095 {
1096 Set<String> docletPaths = new HashSet<String>();
1097 StringBuffer docletPath = new StringBuffer(":" + prj.getBuild().getOutputDirectory());
1098 String resourcedocPath = fixWindowsSlashes(prj.getBuild().getOutputDirectory() + File.separator + "resourcedoc.xml");
1099
1100 PluginXmlUtils.PluginInfo pluginInfo = PluginXmlUtils.getPluginInfo(ctx);
1101
1102 try
1103 {
1104 docletPaths.addAll(prj.getCompileClasspathElements());
1105 docletPaths.addAll(prj.getRuntimeClasspathElements());
1106 docletPaths.addAll(prj.getSystemClasspathElements());
1107
1108
1109 URL[] pluginUrls = ((URLClassLoader)Thread.currentThread().getContextClassLoader()).getURLs();
1110 for(URL pluginUrl : pluginUrls)
1111 {
1112 docletPaths.add(pluginUrl.getFile());
1113 }
1114
1115 for(String path : docletPaths) {
1116 docletPath.append(File.pathSeparator);
1117 docletPath.append(path);
1118 }
1119
1120 } catch (DependencyResolutionRequiredException e)
1121 {
1122 throw new MojoExecutionException("Dependencies must be resolved", e);
1123 }
1124
1125 executeMojo(
1126 plugin(
1127 groupId("org.apache.maven.plugins"),
1128 artifactId("maven-javadoc-plugin"),
1129 version("2.8.1")
1130 ),
1131 goal("javadoc"),
1132 configuration(
1133 element(name("maxmemory"),"1024m"),
1134 element(name("sourcepath"),packagesPath.toString()),
1135 element(name("doclet"), ResourceDocletJSON.class.getName()),
1136 element(name("docletPath"), docletPath.toString()),
1137 element(name("docletArtifacts"),
1138 element(name("docletArtifact"),
1139 element(name("groupId"),"xerces"),
1140 element(name("artifactId"),"xercesImpl"),
1141 element(name("version"),"2.9.1")
1142 ),
1143 element(name("docletArtifact"),
1144 element(name("groupId"),"commons-lang"),
1145 element(name("artifactId"),"commons-lang"),
1146 element(name("version"),"2.6")
1147 )
1148 ),
1149 element(name("additionalparam"),"-output \"" + resourcedocPath + "\""),
1150 element(name("useStandardDocletOptions"),"false")
1151 ),
1152 executionEnvironment()
1153 );
1154
1155 try {
1156
1157 File userAppDocs = new File(prj.getBuild().getOutputDirectory(),"application-doc.xml");
1158 if(!userAppDocs.exists())
1159 {
1160 String appDocText = FileUtils.getResourceContent("application-doc.xml");
1161 appDocText = StringUtils.replace(appDocText, "${rest.doc.title}", pluginInfo.getName());
1162 appDocText = StringUtils.replace(appDocText,"${rest.doc.description}",pluginInfo.getDescription());
1163 File appDocFile = new File(prj.getBuild().getOutputDirectory(), "application-doc.xml");
1164
1165 FileUtils.saveTextFile(appDocText, appDocFile);
1166 log.info("Wrote " + appDocFile.getAbsolutePath());
1167 }
1168
1169 File userGrammars = new File(prj.getBuild().getOutputDirectory(),"application-grammars.xml");
1170 if(!userGrammars.exists())
1171 {
1172 String grammarText = FileUtils.getResourceContent("application-grammars.xml");
1173 File grammarFile = new File(prj.getBuild().getOutputDirectory(), "application-grammars.xml");
1174
1175 FileUtils.saveTextFile(grammarText, grammarFile);
1176
1177 log.info("Wrote " + grammarFile.getAbsolutePath());
1178 }
1179
1180 } catch (Exception e)
1181 {
1182 throw new MojoExecutionException("Error writing REST application xml files",e);
1183 }
1184 }
1185 }
1186
1187 private static class Container extends ProductArtifact
1188 {
1189 private final String id;
1190 private final String type;
1191 private final String classifier;
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 public Container(final String id, final String groupId, final String artifactId, final String version)
1202 {
1203 super(groupId, artifactId, version);
1204 this.id = id;
1205 this.type = "installed";
1206 this.classifier = "";
1207 }
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 public Container(final String id, final String groupId, final String artifactId, final String version, final String classifier)
1219 {
1220 super(groupId, artifactId, version);
1221 this.id = id;
1222 this.type = "installed";
1223 this.classifier = classifier;
1224 }
1225
1226
1227
1228
1229
1230
1231 public Container(final String id)
1232 {
1233 this.id = id;
1234 this.type = "embedded";
1235 this.classifier = "";
1236 }
1237
1238
1239
1240
1241 public String getId()
1242 {
1243 return id;
1244 }
1245
1246
1247
1248
1249 public String getType()
1250 {
1251 return type;
1252 }
1253
1254
1255
1256
1257 public String getClassifier()
1258 {
1259 return classifier;
1260 }
1261
1262
1263
1264
1265 public boolean isEmbedded()
1266 {
1267 return "embedded".equals(type);
1268 }
1269
1270
1271
1272
1273
1274 public String getRootDirectory(String buildDir)
1275 {
1276 return buildDir + File.separator + "container" + File.separator + getId();
1277 }
1278
1279
1280
1281
1282
1283 public String getInstallDirectory(String buildDir)
1284 {
1285 return getRootDirectory(buildDir) + File.separator + getArtifactId() + "-" + getVersion();
1286 }
1287
1288
1289
1290
1291
1292
1293 public String getConfigDirectory(String buildDir, String productId)
1294 {
1295 return getRootDirectory(buildDir) + File.separator + "cargo-" + productId + "-home";
1296 }
1297 }
1298 }