PageRenderTime 86ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 1ms

/maven-amps-plugin/src/main/java/com/atlassian/maven/plugins/amps/MavenGoals.java

https://bitbucket.org/mmeinhold/amps
Java | 1776 lines | 1454 code | 180 blank | 142 comment | 74 complexity | fa8af6db0894d3bca0679c2b2bde43d7 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. package com.atlassian.maven.plugins.amps;
  2. import java.io.File;
  3. import java.io.FileFilter;
  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.*;
  10. import java.util.jar.Manifest;
  11. import java.util.regex.Matcher;
  12. import com.atlassian.maven.plugins.amps.util.*;
  13. import com.atlassian.maven.plugins.amps.util.minifier.ResourcesMinifier;
  14. import com.google.common.base.Predicate;
  15. import com.google.common.collect.Collections2;
  16. import com.sun.jersey.wadl.resourcedoc.ResourceDocletJSON;
  17. import org.apache.commons.io.FileUtils;
  18. import org.apache.commons.io.IOUtils;
  19. import org.apache.commons.io.filefilter.FileFilterUtils;
  20. import org.apache.commons.io.filefilter.IOFileFilter;
  21. import org.apache.commons.io.filefilter.TrueFileFilter;
  22. import org.apache.commons.lang.StringUtils;
  23. import org.apache.maven.artifact.DependencyResolutionRequiredException;
  24. import org.apache.maven.model.Dependency;
  25. import org.apache.maven.model.Plugin;
  26. import org.apache.maven.model.Resource;
  27. import org.apache.maven.plugin.MojoExecutionException;
  28. import org.apache.maven.plugin.logging.Log;
  29. import org.apache.maven.project.MavenProject;
  30. import org.codehaus.plexus.components.interactivity.PrompterException;
  31. import org.codehaus.plexus.util.xml.Xpp3Dom;
  32. import org.twdata.maven.mojoexecutor.MojoExecutor;
  33. import org.twdata.maven.mojoexecutor.MojoExecutor.Element;
  34. import org.twdata.maven.mojoexecutor.MojoExecutor.ExecutionEnvironment;
  35. import aQute.lib.osgi.Constants;
  36. import static com.atlassian.maven.plugins.amps.util.FileUtils.file;
  37. import static com.atlassian.maven.plugins.amps.util.FileUtils.fixWindowsSlashes;
  38. import static org.twdata.maven.mojoexecutor.MojoExecutor.artifactId;
  39. import static org.twdata.maven.mojoexecutor.MojoExecutor.configuration;
  40. import static org.twdata.maven.mojoexecutor.MojoExecutor.element;
  41. import static org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo;
  42. import static org.twdata.maven.mojoexecutor.MojoExecutor.goal;
  43. import static org.twdata.maven.mojoexecutor.MojoExecutor.groupId;
  44. import static org.twdata.maven.mojoexecutor.MojoExecutor.name;
  45. import static org.twdata.maven.mojoexecutor.MojoExecutor.plugin;
  46. import static org.twdata.maven.mojoexecutor.MojoExecutor.version;
  47. /**
  48. * Executes specific maven goals
  49. */
  50. public class MavenGoals
  51. {
  52. private final MavenContext ctx;
  53. private final Log log;
  54. private final Map<String, String> pluginArtifactIdToVersionMap;
  55. private final Map<String, Container> idToContainerMap = new HashMap<String, Container>()
  56. {{
  57. put("tomcat5x", new Container("tomcat5x", "org.apache.tomcat", "apache-tomcat", "5.5.26"));
  58. put("tomcat6x", new Container("tomcat6x", "org.apache.tomcat", "apache-tomcat", "6.0.20"));
  59. put("tomcat7x", new Container("tomcat7x", "org.apache.tomcat", "apache-tomcat", "7.0.32", "windows-x64"));
  60. put("resin3x", new Container("resin3x", "com.caucho", "resin", "3.0.26"));
  61. put("jboss42x", new Container("jboss42x", "org.jboss.jbossas", "jbossas", "4.2.3.GA"));
  62. put("jetty6x", new Container("jetty6x"));
  63. }};
  64. private final Map<String, String> defaultArtifactIdToVersionMap = new HashMap<String, String>()
  65. {{
  66. put("maven-cli-plugin", "0.7");
  67. put("org.codehaus.cargo:cargo-maven2-plugin", "1.2.3");
  68. put("atlassian-pdk", "2.3.1");
  69. put("maven-archetype-plugin", "2.0-alpha-4");
  70. put("maven-bundle-plugin", "2.3.7");
  71. put("yuicompressor-maven-plugin", "1.3.0");
  72. put("build-helper-maven-plugin", "1.7");
  73. // You can't actually override the version a plugin if defined in the project, so these don't actually do
  74. // anything, since the super pom already defines versions.
  75. put("maven-dependency-plugin", "2.5.1");
  76. put("maven-resources-plugin", "2.3");
  77. put("maven-jar-plugin", "2.2");
  78. //put("maven-surefire-plugin", "2.4.3");
  79. put("maven-surefire-plugin", "2.12.4");
  80. put("maven-failsafe-plugin", "2.9");
  81. put("maven-exec-plugin", "1.2.1");
  82. }};
  83. public MavenGoals(final MavenContext ctx)
  84. {
  85. this.ctx = ctx;
  86. this.log = ctx.getLog();
  87. this.pluginArtifactIdToVersionMap = Collections.unmodifiableMap(defaultArtifactIdToVersionMap);
  88. }
  89. private ExecutionEnvironment executionEnvironment()
  90. {
  91. return ctx.getExecutionEnvironment();
  92. }
  93. public MavenProject getContextProject()
  94. {
  95. return ctx.getProject();
  96. }
  97. public void executeAmpsRecursively(final String ampsVersion, final String ampsGoal, Xpp3Dom cfg) throws MojoExecutionException
  98. {
  99. executeMojo(
  100. plugin(
  101. groupId("com.atlassian.maven.plugins"),
  102. artifactId("maven-amps-plugin"),
  103. version(ampsVersion)
  104. ),
  105. goal(ampsGoal),
  106. cfg,
  107. executionEnvironment());
  108. }
  109. public void startCli(final PluginInformation pluginInformation, final int port) throws MojoExecutionException
  110. {
  111. final String pluginId = pluginInformation.getId();
  112. final List<Element> configs = new ArrayList<Element>();
  113. configs.add(element(name("commands"),
  114. element(name("pi"),
  115. "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
  116. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:compress-resources" + " "
  117. + "org.apache.maven.plugins:maven-resources-plugin:resources" + " "
  118. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
  119. + "compile" + " "
  120. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
  121. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-manifest" + " "
  122. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " "
  123. + "org.apache.maven.plugins:maven-install-plugin:install" + " "
  124. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:install"),
  125. element(name("tpi"),
  126. "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
  127. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:compress-resources" + " "
  128. + "org.apache.maven.plugins:maven-resources-plugin:resources" + " "
  129. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
  130. + "compile" + " "
  131. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
  132. + "org.apache.maven.plugins:maven-resources-plugin:testResources" + " "
  133. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-test-plugin-descriptor" + " "
  134. +"com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-test-bundled-dependencies" + " "
  135. + "org.apache.maven.plugins:maven-compiler-plugin:testCompile" + " "
  136. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-test-manifest" + " "
  137. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-manifest" + " "
  138. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-test-manifest" + " "
  139. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " "
  140. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-jar" + " "
  141. + "org.apache.maven.plugins:maven-install-plugin:install" + " "
  142. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:install" + " "
  143. + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-install"),
  144. element(name("package"),
  145. "org.apache.maven.plugins:maven-resources-plugin: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. public void createPlugin(final String productId, AmpsCreatePluginPrompter createPrompter) throws MojoExecutionException
  166. {
  167. CreatePluginProperties props = null;
  168. Properties systemProps = System.getProperties();
  169. if(systemProps.containsKey("groupId")
  170. && systemProps.containsKey("artifactId")
  171. && systemProps.containsKey("version")
  172. && systemProps.containsKey("package")
  173. )
  174. {
  175. props = new CreatePluginProperties(systemProps.getProperty("groupId")
  176. ,systemProps.getProperty("artifactId")
  177. ,systemProps.getProperty("version")
  178. ,systemProps.getProperty("package")
  179. );
  180. }
  181. if(null == props)
  182. {
  183. try
  184. {
  185. props = createPrompter.prompt();
  186. }
  187. catch (PrompterException e)
  188. {
  189. throw new MojoExecutionException("Unable to gather properties",e);
  190. }
  191. }
  192. if(null != props)
  193. {
  194. ExecutionEnvironment execEnv = executionEnvironment();
  195. Properties sysProps = execEnv.getMavenSession().getExecutionProperties();
  196. sysProps.setProperty("groupId",props.getGroupId());
  197. sysProps.setProperty("artifactId",props.getArtifactId());
  198. sysProps.setProperty("version",props.getVersion());
  199. sysProps.setProperty("package",props.getThePackage());
  200. executeMojo(
  201. plugin(
  202. groupId("org.apache.maven.plugins"),
  203. artifactId("maven-archetype-plugin"),
  204. version(defaultArtifactIdToVersionMap.get("maven-archetype-plugin"))
  205. ),
  206. goal("generate"),
  207. configuration(
  208. element(name("archetypeGroupId"), "com.atlassian.maven.archetypes"),
  209. element(name("archetypeArtifactId"), (productId.equals("all") ? "" : productId + "-") + "plugin-archetype"),
  210. element(name("archetypeVersion"), VersionUtils.getVersion()),
  211. element(name("interactiveMode"), "false")
  212. ),
  213. execEnv);
  214. File pluginDir = new File(ctx.getProject().getBasedir(),props.getArtifactId());
  215. if(pluginDir.exists())
  216. {
  217. File src = new File(pluginDir,"src");
  218. File test = new File(src,"test");
  219. File java = new File(test,"java");
  220. String packagePath = props.getThePackage().replaceAll("\\.", Matcher.quoteReplacement(File.separator));
  221. File packageFile = new File(java,packagePath);
  222. File packageUT = new File(packageFile,"ut");
  223. File packageIT = new File(packageFile,"it");
  224. File ut = new File(new File(java,"ut"),packagePath);
  225. File it = new File(new File(java,"it"),packagePath);
  226. if(packageFile.exists())
  227. {
  228. try
  229. {
  230. if(packageUT.exists())
  231. {
  232. FileUtils.copyDirectory(packageUT, ut);
  233. }
  234. if(packageIT.exists())
  235. {
  236. FileUtils.copyDirectory(packageIT, it);
  237. }
  238. IOFileFilter filter = FileFilterUtils.and(FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("it")),FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("ut")));
  239. com.atlassian.maven.plugins.amps.util.FileUtils.cleanDirectory(java,filter);
  240. }
  241. catch (IOException e)
  242. {
  243. //for now just ignore
  244. }
  245. }
  246. }
  247. }
  248. }
  249. public void copyBundledDependencies() throws MojoExecutionException
  250. {
  251. executeMojo(
  252. plugin(
  253. groupId("org.apache.maven.plugins"),
  254. artifactId("maven-dependency-plugin"),
  255. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  256. ),
  257. goal("copy-dependencies"),
  258. configuration(
  259. element(name("includeScope"), "runtime"),
  260. element(name("excludeScope"), "provided"),
  261. element(name("excludeScope"), "test"),
  262. element(name("includeTypes"), "jar"),
  263. element(name("outputDirectory"), "${project.build.outputDirectory}/META-INF/lib")
  264. ),
  265. executionEnvironment()
  266. );
  267. }
  268. public void copyTestBundledDependencies(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
  269. {
  270. StringBuilder sb = new StringBuilder();
  271. for(ProductArtifact artifact : testBundleExcludes)
  272. {
  273. log.info("excluding artifact from test jar: " + artifact.getArtifactId());
  274. sb.append(",").append(artifact.getArtifactId());
  275. }
  276. String customExcludes = sb.toString();
  277. executeMojo(
  278. plugin(
  279. groupId("org.apache.maven.plugins"),
  280. artifactId("maven-dependency-plugin"),
  281. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  282. ),
  283. goal("copy-dependencies"),
  284. configuration(
  285. element(name("includeScope"), "test"),
  286. element(name("excludeScope"), "provided"),
  287. element(name("excludeArtifactIds"),"junit" + customExcludes),
  288. element(name("useSubDirectoryPerScope"),"true"),
  289. element(name("outputDirectory"), "${project.build.directory}/testlibs")
  290. ),
  291. executionEnvironment()
  292. );
  293. File targetDir = new File(ctx.getProject().getBuild().getDirectory());
  294. File testlibsDir = new File(targetDir,"testlibs");
  295. File compileLibs = new File(testlibsDir,"compile");
  296. File testLibs = new File(testlibsDir,"test");
  297. File testClassesDir = new File(ctx.getProject().getBuild().getTestOutputDirectory());
  298. File metainfDir = new File(testClassesDir,"META-INF");
  299. File libDir = new File(metainfDir,"lib");
  300. try
  301. {
  302. compileLibs.mkdirs();
  303. testLibs.mkdirs();
  304. libDir.mkdirs();
  305. FileUtils.copyDirectory(compileLibs,libDir);
  306. FileUtils.copyDirectory(testLibs,libDir);
  307. }
  308. catch (IOException e)
  309. {
  310. throw new MojoExecutionException("unable to copy test libs", e);
  311. }
  312. }
  313. public void copyTestBundledDependenciesExcludingTestScope(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
  314. {
  315. StringBuilder sb = new StringBuilder();
  316. for(ProductArtifact artifact : testBundleExcludes)
  317. {
  318. log.info("excluding artifact from test jar: " + artifact.getArtifactId());
  319. sb.append(",").append(artifact.getArtifactId());
  320. }
  321. String customExcludes = sb.toString();
  322. executeMojo(
  323. plugin(
  324. groupId("org.apache.maven.plugins"),
  325. artifactId("maven-dependency-plugin"),
  326. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  327. ),
  328. goal("copy-dependencies"),
  329. configuration(
  330. element(name("includeScope"), "runtime"),
  331. element(name("excludeScope"), "provided"),
  332. element(name("excludeScope"), "test"),
  333. element(name("includeTypes"), "jar"),
  334. element(name("excludeArtifactIds"),"junit" + customExcludes),
  335. element(name("outputDirectory"), "${project.build.testOutputDirectory}/META-INF/lib")
  336. ),
  337. executionEnvironment()
  338. );
  339. }
  340. public void extractBundledDependencies() throws MojoExecutionException
  341. {
  342. executeMojo(
  343. plugin(
  344. groupId("org.apache.maven.plugins"),
  345. artifactId("maven-dependency-plugin"),
  346. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  347. ),
  348. goal("unpack-dependencies"),
  349. configuration(
  350. element(name("includeScope"), "runtime"),
  351. element(name("excludeScope"), "provided"),
  352. element(name("excludeScope"), "test"),
  353. element(name("includeTypes"), "jar"),
  354. element(name("excludes"), "META-INF/MANIFEST.MF, META-INF/*.DSA, META-INF/*.SF"),
  355. element(name("outputDirectory"), "${project.build.outputDirectory}")
  356. ),
  357. executionEnvironment()
  358. );
  359. }
  360. public void extractTestBundledDependenciesExcludingTestScope(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
  361. {
  362. StringBuilder sb = new StringBuilder();
  363. for(ProductArtifact artifact : testBundleExcludes)
  364. {
  365. sb.append(",").append(artifact.getArtifactId());
  366. }
  367. String customExcludes = sb.toString();
  368. executeMojo(
  369. plugin(
  370. groupId("org.apache.maven.plugins"),
  371. artifactId("maven-dependency-plugin"),
  372. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  373. ),
  374. goal("unpack-dependencies"),
  375. configuration(
  376. element(name("includeScope"), "runtime"),
  377. element(name("excludeScope"), "provided"),
  378. element(name("excludeScope"), "test"),
  379. element(name("includeTypes"), "jar"),
  380. element(name("excludeArtifactIds"),"junit" + customExcludes),
  381. element(name("excludes"), "META-INF/MANIFEST.MF, META-INF/*.DSA, META-INF/*.SF"),
  382. element(name("outputDirectory"), "${project.build.testOutputDirectory}")
  383. ),
  384. executionEnvironment()
  385. );
  386. }
  387. public void extractTestBundledDependencies(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
  388. {
  389. StringBuilder sb = new StringBuilder();
  390. for(ProductArtifact artifact : testBundleExcludes)
  391. {
  392. sb.append(",").append(artifact.getArtifactId());
  393. }
  394. String customExcludes = sb.toString();
  395. executeMojo(
  396. plugin(
  397. groupId("org.apache.maven.plugins"),
  398. artifactId("maven-dependency-plugin"),
  399. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  400. ),
  401. goal("unpack-dependencies"),
  402. configuration(
  403. element(name("includeScope"), "test"),
  404. element(name("excludeScope"), "provided"),
  405. element(name("excludeArtifactIds"),"junit" + customExcludes),
  406. element(name("includeTypes"), "jar"),
  407. element(name("useSubDirectoryPerScope"),"true"),
  408. element(name("outputDirectory"), "${project.build.directory}/testlibs")
  409. ),
  410. executionEnvironment()
  411. );
  412. File targetDir = new File(ctx.getProject().getBuild().getDirectory());
  413. File testlibsDir = new File(targetDir,"testlibs");
  414. File compileLibs = new File(testlibsDir,"compile");
  415. File testLibs = new File(testlibsDir,"test");
  416. File testClassesDir = new File(ctx.getProject().getBuild().getTestOutputDirectory());
  417. try
  418. {
  419. compileLibs.mkdirs();
  420. testLibs.mkdirs();
  421. FileUtils.copyDirectory(compileLibs,testClassesDir,FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("META-INF")));
  422. FileUtils.copyDirectory(testLibs,testClassesDir,FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("META-INF")));
  423. }
  424. catch (IOException e)
  425. {
  426. throw new MojoExecutionException("unable to copy test libs", e);
  427. }
  428. }
  429. public void compressResources(boolean useClosureForJs) throws MojoExecutionException
  430. {
  431. ResourcesMinifier.minify(ctx.getProject().getBuild().getResources(), new File(ctx.getProject().getBuild().getOutputDirectory()), useClosureForJs, log);
  432. /*
  433. executeMojo(
  434. plugin(
  435. groupId("net.alchim31.maven"),
  436. artifactId("yuicompressor-maven-plugin"),
  437. version(defaultArtifactIdToVersionMap.get("yuicompressor-maven-plugin"))
  438. ),
  439. goal("compress"),
  440. configuration(
  441. element(name("suffix"), "-min"),
  442. element(name("jswarn"), "false")
  443. ),
  444. executionEnvironment()
  445. );
  446. */
  447. }
  448. public void filterPluginDescriptor() throws MojoExecutionException
  449. {
  450. executeMojo(
  451. plugin(
  452. groupId("org.apache.maven.plugins"),
  453. artifactId("maven-resources-plugin"),
  454. version(defaultArtifactIdToVersionMap.get("maven-resources-plugin"))
  455. ),
  456. goal("copy-resources"),
  457. configuration(
  458. element(name("encoding"), "UTF-8"),
  459. element(name("resources"),
  460. element(name("resource"),
  461. element(name("directory"), "src/main/resources"),
  462. element(name("filtering"), "true"),
  463. element(name("includes"),
  464. element(name("include"), "atlassian-plugin.xml"))
  465. )
  466. ),
  467. element(name("outputDirectory"), "${project.build.outputDirectory}")
  468. ),
  469. executionEnvironment()
  470. );
  471. }
  472. public void filterTestPluginDescriptor() throws MojoExecutionException
  473. {
  474. executeMojo(
  475. plugin(
  476. groupId("org.apache.maven.plugins"),
  477. artifactId("maven-resources-plugin"),
  478. version(defaultArtifactIdToVersionMap.get("maven-resources-plugin"))
  479. ),
  480. goal("copy-resources"),
  481. configuration(
  482. element(name("encoding"), "UTF-8"),
  483. element(name("resources"),
  484. element(name("resource"),
  485. element(name("directory"), "src/test/resources"),
  486. element(name("filtering"), "true"),
  487. element(name("includes"),
  488. element(name("include"), "atlassian-plugin.xml"))
  489. )
  490. ),
  491. element(name("outputDirectory"), "${project.build.testOutputDirectory}")
  492. ),
  493. executionEnvironment()
  494. );
  495. }
  496. public void runUnitTests(Map<String, Object> systemProperties) throws MojoExecutionException {
  497. runUnitTests(systemProperties, null);
  498. }
  499. public void runUnitTests(Map<String, Object> systemProperties, String excludedGroups) throws MojoExecutionException
  500. {
  501. final Element systemProps = convertPropsToElements(systemProperties);
  502. Xpp3Dom config = configuration(
  503. systemProps,
  504. element(name("excludes"),
  505. element(name("exclude"), "it/**"),
  506. element(name("exclude"), "**/*$*")),
  507. element(name("excludedGroups"), excludedGroups)
  508. );
  509. log.info("surefire unit-test configuration:");
  510. log.info(config.toString());
  511. executeMojo(
  512. plugin(
  513. groupId("org.apache.maven.plugins"),
  514. artifactId("maven-surefire-plugin"),
  515. version(defaultArtifactIdToVersionMap.get("maven-surefire-plugin"))
  516. ),
  517. goal("test"),
  518. config,
  519. executionEnvironment()
  520. );
  521. }
  522. public File copyWebappWar(final String productId, final File targetDirectory, final ProductArtifact artifact)
  523. throws MojoExecutionException
  524. {
  525. final File webappWarFile = new File(targetDirectory, productId + "-original.war");
  526. executeMojo(
  527. plugin(
  528. groupId("org.apache.maven.plugins"),
  529. artifactId("maven-dependency-plugin"),
  530. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  531. ),
  532. goal("copy"),
  533. configuration(
  534. element(name("artifactItems"),
  535. element(name("artifactItem"),
  536. element(name("groupId"), artifact.getGroupId()),
  537. element(name("artifactId"), artifact.getArtifactId()),
  538. element(name("type"), "war"),
  539. element(name("version"), artifact.getVersion()),
  540. element(name("destFileName"), webappWarFile.getName()))),
  541. element(name("outputDirectory"), targetDirectory.getPath())
  542. ),
  543. executionEnvironment()
  544. );
  545. return webappWarFile;
  546. }
  547. public File copyArtifact(final String targetFileName, final File targetDirectory,
  548. final ProductArtifact artifact, String type) throws MojoExecutionException
  549. {
  550. final File targetFile = new File(targetDirectory, targetFileName);
  551. executeMojo(
  552. plugin(
  553. groupId("org.apache.maven.plugins"),
  554. artifactId("maven-dependency-plugin"),
  555. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  556. ),
  557. goal("copy"),
  558. configuration(
  559. element(name("artifactItems"),
  560. element(name("artifactItem"),
  561. element(name("groupId"), artifact.getGroupId()),
  562. element(name("artifactId"), artifact.getArtifactId()),
  563. element(name("type"), type),
  564. element(name("version"), artifact.getVersion()),
  565. element(name("destFileName"), targetFile.getName()))),
  566. element(name("outputDirectory"), targetDirectory.getPath())
  567. ),
  568. executionEnvironment()
  569. );
  570. return targetFile;
  571. }
  572. /**
  573. * Copies {@code artifacts} to the {@code outputDirectory}. Artifacts are looked up in order: <ol> <li>in the maven
  574. * reactor</li> <li>in the maven repositories</li> </ol> This can't be used in a goal that happens before the
  575. * <em>package</em> phase as artifacts in the reactor will be not be packaged (and therefore 'copiable') until this
  576. * phase.
  577. *
  578. * @param outputDirectory the directory to copy artifacts to
  579. * @param artifacts the list of artifact to copy to the given directory
  580. */
  581. public void copyPlugins(final File outputDirectory, final List<ProductArtifact> artifacts)
  582. throws MojoExecutionException
  583. {
  584. for (ProductArtifact artifact : artifacts)
  585. {
  586. final MavenProject artifactReactorProject = getReactorProjectForArtifact(artifact);
  587. if (artifactReactorProject != null)
  588. {
  589. log.debug(artifact + " will be copied from reactor project " + artifactReactorProject);
  590. final File artifactFile = artifactReactorProject.getArtifact().getFile();
  591. if (artifactFile == null)
  592. {
  593. log.warn("The plugin " + artifact + " is in the reactor but not the file hasn't been attached. Skipping.");
  594. }
  595. else
  596. {
  597. log.debug("Copying " + artifactFile + " to " + outputDirectory);
  598. try
  599. {
  600. FileUtils.copyFile(artifactFile, new File(outputDirectory, artifactFile.getName()));
  601. }
  602. catch (IOException e)
  603. {
  604. throw new MojoExecutionException("Could not copy " + artifact + " to " + outputDirectory, e);
  605. }
  606. }
  607. }
  608. else
  609. {
  610. executeMojo(
  611. plugin(
  612. groupId("org.apache.maven.plugins"),
  613. artifactId("maven-dependency-plugin"),
  614. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  615. ),
  616. goal("copy"),
  617. configuration(
  618. element(name("artifactItems"),
  619. element(name("artifactItem"),
  620. element(name("groupId"), artifact.getGroupId()),
  621. element(name("artifactId"), artifact.getArtifactId()),
  622. element(name("version"), artifact.getVersion()))),
  623. element(name("outputDirectory"), outputDirectory.getPath())
  624. ),
  625. executionEnvironment());
  626. }
  627. }
  628. }
  629. private MavenProject getReactorProjectForArtifact(ProductArtifact artifact)
  630. {
  631. for (final MavenProject project : ctx.getReactor())
  632. {
  633. if (project.getGroupId().equals(artifact.getGroupId())
  634. && project.getArtifactId().equals(artifact.getArtifactId())
  635. && project.getVersion().equals(artifact.getVersion()))
  636. {
  637. return project;
  638. }
  639. }
  640. return null;
  641. }
  642. private void unpackContainer(final Container container) throws MojoExecutionException
  643. {
  644. executeMojo(
  645. plugin(
  646. groupId("org.apache.maven.plugins"),
  647. artifactId("maven-dependency-plugin"),
  648. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  649. ),
  650. goal("unpack"),
  651. configuration(
  652. element(name("artifactItems"),
  653. element(name("artifactItem"),
  654. element(name("groupId"), container.getGroupId()),
  655. element(name("artifactId"), container.getArtifactId()),
  656. element(name("version"), container.getVersion()),
  657. element(name("classifier"), container.getClassifier()),
  658. element(name("type"), "zip"))),
  659. element(name("outputDirectory"), container.getRootDirectory(getBuildDirectory()))
  660. ),
  661. executionEnvironment());
  662. }
  663. private String getBuildDirectory()
  664. {
  665. return ctx.getProject().getBuild().getDirectory();
  666. }
  667. private static Xpp3Dom configurationWithoutNullElements(Element... elements)
  668. {
  669. List<Element> nonNullElements = new ArrayList<Element>();
  670. for (Element e : elements)
  671. {
  672. if (e != null)
  673. {
  674. nonNullElements.add(e);
  675. }
  676. }
  677. return configuration(nonNullElements.toArray(new Element[nonNullElements.size()]));
  678. }
  679. public int startWebapp(final String productInstanceId, final File war, final Map<String, String> systemProperties, final List<ProductArtifact> extraContainerDependencies,
  680. final Product webappContext) throws MojoExecutionException
  681. {
  682. final Container container = findContainer(webappContext.getContainerId());
  683. File containerDir = new File(container.getRootDirectory(getBuildDirectory()));
  684. // retrieve non-embedded containers
  685. if (!container.isEmbedded())
  686. {
  687. if (containerDir.exists())
  688. {
  689. log.info("Reusing unpacked container '" + container.getId() + "' from " + containerDir.getPath());
  690. }
  691. else
  692. {
  693. log.info("Unpacking container '" + container.getId() + "' from container artifact: " + container.toString());
  694. unpackContainer(container);
  695. }
  696. }
  697. final int rmiPort = pickFreePort(0);
  698. int actualHttpPort;
  699. String protocol = "http";
  700. if(webappContext.getUseHttps())
  701. {
  702. actualHttpPort = 443;
  703. protocol = "https";
  704. }
  705. else
  706. {
  707. actualHttpPort = pickFreePort(webappContext.getHttpPort());
  708. }
  709. final List<Element> sysProps = new ArrayList<Element>();
  710. for (final Map.Entry<String, String> entry : systemProperties.entrySet())
  711. {
  712. sysProps.add(element(name(entry.getKey()), entry.getValue()));
  713. }
  714. log.info("Starting " + productInstanceId + " on the " + container.getId() + " container on ports "
  715. + actualHttpPort + " (" + protocol + ") and " + rmiPort + " (rmi)");
  716. final String baseUrl = getBaseUrl(webappContext, actualHttpPort);
  717. sysProps.add(element(name("baseurl"), baseUrl));
  718. final List<Element> deps = new ArrayList<Element>();
  719. for (final ProductArtifact dep : extraContainerDependencies)
  720. {
  721. deps.add(element(name("dependency"),
  722. element(name("location"), webappContext.getArtifactRetriever().resolve(dep))
  723. ));
  724. }
  725. for (DataSource dataSource : webappContext.getDataSources())
  726. {
  727. for (ProductArtifact containerDependency : dataSource.getLibArtifacts())
  728. {
  729. deps.add(element(name("dependency"),
  730. element(name("location"), webappContext.getArtifactRetriever().resolve(containerDependency))
  731. ));
  732. }
  733. }
  734. final List<Element> props = new ArrayList<Element>();
  735. for (final Map.Entry<String, String> entry : systemProperties.entrySet())
  736. {
  737. props.add(element(name(entry.getKey()), entry.getValue()));
  738. }
  739. props.add(element(name("cargo.servlet.port"), String.valueOf(actualHttpPort)));
  740. if(webappContext.getUseHttps())
  741. {
  742. props.add(element(name("cargo.protocol"), protocol));
  743. }
  744. props.add(element(name("cargo.rmi.port"), String.valueOf(rmiPort)));
  745. props.add(element(name("cargo.jvmargs"), webappContext.getJvmArgs()));
  746. int startupTimeout = webappContext.getStartupTimeout();
  747. if (Boolean.FALSE.equals(webappContext.getSynchronousStartup()))
  748. {
  749. startupTimeout = 0;
  750. }
  751. Plugin cargo = cargo(webappContext);
  752. executeMojo(
  753. cargo,
  754. goal("start"),
  755. configurationWithoutNullElements(
  756. element(name("deployables"),
  757. element(name("deployable"),
  758. element(name("groupId"), "foo"),
  759. element(name("artifactId"), "bar"),
  760. element(name("type"), "war"),
  761. element(name("location"), war.getPath()),
  762. element(name("properties"),
  763. element(name("context"), webappContext.getContextPath())
  764. )
  765. )
  766. ),
  767. waitElement(cargo), // This may be null
  768. element(name("container"),
  769. element(name("containerId"), container.getId()),
  770. element(name("type"), container.getType()),
  771. element(name("home"), container.getInstallDirectory(getBuildDirectory())),
  772. element(name("output"), webappContext.getOutput()),
  773. element(name("systemProperties"), sysProps.toArray(new Element[sysProps.size()])),
  774. element(name("dependencies"), deps.toArray(new Element[deps.size()])),
  775. element(name("timeout"), String.valueOf(startupTimeout))
  776. ),
  777. element(name("configuration"),
  778. element(name("home"), container.getConfigDirectory(getBuildDirectory(), productInstanceId)),
  779. element(name("type"), "standalone"),
  780. element(name("properties"), props.toArray(new Element[props.size()]))
  781. )
  782. ),
  783. executionEnvironment()
  784. );
  785. return actualHttpPort;
  786. }
  787. public void stopWebapp(final String productId, final String containerId, final Product webappContext) throws MojoExecutionException
  788. {
  789. final Container container = findContainer(containerId);
  790. String actualShutdownTimeout = webappContext.getSynchronousStartup() ? "0" : String.valueOf(webappContext.getShutdownTimeout());
  791. executeMojo(
  792. cargo(webappContext),
  793. goal("stop"),
  794. configuration(
  795. element(name("container"),
  796. element(name("containerId"), container.getId()),
  797. element(name("type"), container.getType()),
  798. element(name("timeout"), actualShutdownTimeout),
  799. // org.codehaus.cargo
  800. element(name("home"), container.getInstallDirectory(getBuildDirectory()))
  801. ),
  802. element(name("configuration"),
  803. // org.twdata.maven
  804. element(name("home"), container.getConfigDirectory(getBuildDirectory(), productId))/*,
  805. // we don't need that atm. since timeout is 0 for org.codehaus.cargo
  806. element(name("properties"), createShutdownPortsPropertiesConfiguration(webappContext)) */
  807. )
  808. ),
  809. executionEnvironment()
  810. );
  811. }
  812. /**
  813. * Cargo waits (org.codehaus.cargo.container.tomcat.internal.AbstractCatalinaInstalledLocalContainer#waitForCompletion(boolean waitForStarting)) for 3 ports, but the AJP and RMI ports may
  814. * not be correct (see below), so we configure it to wait on the HTTP port only.
  815. *
  816. * Since we're not configuring the AJP port it defaults to 8009. All the Studio applications are currently using 8009 (by default, since not configured in startWebapp)
  817. * which means that this port might have been taken by a different application (the container will still come up though, see
  818. * "INFO: Port busy 8009 java.net.BindException: Address already in use" in the log). Thus we don't want to wait for it because it might be still open also the container
  819. * is shut down.
  820. *
  821. * The RMI port is randomly chosen (see startWebapp), thus we don't have any information close at hand. As a future optimisation, e.g. when we move away from cargo to let's say
  822. * Apache's Tomcat Maven Plugin we could retrieve the actualy configuration from the server.xml on shutdown and thus know exactly for what which port to wait until it gets closed.
  823. * We could do that already in cargo (e.g. container/tomcat6x/<productHome>/conf/server.xml) but that means that we have to support all the containers we are supporting with cargo.
  824. *
  825. * Since the HTTP port is the only one that interests us, we set all three ports to this one when calling stop. But since that may be randomly chosen as well we might be waiting
  826. * for the wrong port to get closed. Since this is the minor use case, one has to either accept the timeout if the default port is open, or configure product.stop.timeout to 0 in
  827. * order to skip the wait.
  828. */
  829. private Element[] createShutdownPortsPropertiesConfiguration(final Product webappContext)
  830. {
  831. final List<Element> properties = new ArrayList<Element>();
  832. String portUsedToDetermineIfShutdownSucceeded = String.valueOf(webappContext.getHttpPort());
  833. properties.add(element(name("cargo.servlet.port"), portUsedToDetermineIfShutdownSucceeded));
  834. properties.add(element(name("cargo.rmi.port"), portUsedToDetermineIfShutdownSucceeded));
  835. properties.add(element(name("cargo.tomcat.ajp.port"), portUsedToDetermineIfShutdownSucceeded));
  836. return properties.toArray(new Element[properties.size()]);
  837. }
  838. /**
  839. * THIS USED TO Decide whether to use the org.twdata.maven.cargo-maven2-plugin or the org.codehaus.cargo.cargo-maven2-plugin.
  840. * <p/>
  841. * This has now been changed to just return the codehaus version since there are new features/fixes we need and the twdata version is no longer useful.
  842. */
  843. private Plugin cargo(Product context)
  844. {
  845. log.info("using codehaus cargo v" + pluginArtifactIdToVersionMap.get("org.codehaus.cargo:cargo-maven2-plugin"));
  846. return plugin(
  847. groupId("org.codehaus.cargo"),
  848. artifactId("cargo-maven2-plugin"),
  849. version(pluginArtifactIdToVersionMap.get("org.codehaus.cargo:cargo-maven2-plugin")));
  850. }
  851. private Element waitElement(Plugin cargo)
  852. {
  853. if (cargo.getGroupId().equals("org.twdata.maven"))
  854. {
  855. return element(name("wait"), "false");
  856. }
  857. // If not using twdata's cargo, we avoid passing wait=false, because it's the default and it generates
  858. // a deprecation warning
  859. return null;
  860. }
  861. public static String getBaseUrl(Product product, int actualHttpPort)
  862. {
  863. return getBaseUrl(product.getServer(), product.getHttpPort(), product.getContextPath());
  864. }
  865. private static String getBaseUrl(String server, int actualHttpPort, String contextPath)
  866. {
  867. String port = actualHttpPort != 80 ? ":" + actualHttpPort : "";
  868. server = server.startsWith("http") ? server : "http://" + server;
  869. if (!contextPath.startsWith("/") && StringUtils.isNotBlank(contextPath))
  870. {
  871. contextPath = "/" + contextPath;
  872. }
  873. return server + port + contextPath;
  874. }
  875. public void runIntegrationTests(String testGroupId, String containerId, List<String> includes, List<String> excludes, Map<String, Object> systemProperties, final File targetDirectory)
  876. throws MojoExecutionException
  877. {
  878. List<Element> includeElements = new ArrayList<Element>(includes.size());
  879. for (String include : includes)
  880. {
  881. includeElements.add(element(name("include"), include));
  882. }
  883. List<Element> excludeElements = new ArrayList<Element>(excludes.size() + 2);
  884. excludeElements.add(element(name("exclude"), "**/*$*"));
  885. excludeElements.add(element(name("exclude"), "**/Abstract*"));
  886. for (String exclude : excludes)
  887. {
  888. excludeElements.add(element(name("exclude"), exclude));
  889. }
  890. final String testOutputDir = targetDirectory.getAbsolutePath() + "/" + testGroupId + "/" + containerId + "/surefire-reports";
  891. final String reportsDirectory = "reportsDirectory";
  892. systemProperties.put(reportsDirectory, testOutputDir);
  893. final Element systemProps = convertPropsToElements(systemProperties);
  894. final Xpp3Dom itconfig = configuration(
  895. element(name("includes"),
  896. includeElements.toArray(new Element[includeElements.size()])
  897. ),
  898. element(name("excludes"),
  899. excludeElements.toArray(new Element[excludeElements.size()])
  900. ),
  901. systemProps,
  902. element(name(reportsDirectory), testOutputDir)
  903. );
  904. final Xpp3Dom verifyconfig = configuration(element(name(reportsDirectory), testOutputDir));
  905. log.info("Failsafe integration-test configuration:");
  906. log.info(itconfig.toString());
  907. executeMojo(
  908. plugin(
  909. groupId("org.apache.maven.plugins"),
  910. artifactId("maven-failsafe-plugin"),
  911. version(defaultArtifactIdToVersionMap.get("maven-failsafe-plugin"))
  912. ),
  913. goal("integration-test"),
  914. itconfig,
  915. executionEnvironment()
  916. );
  917. executeMojo(
  918. plugin(
  919. groupId("org.apache.maven.plugins"),
  920. artifactId("maven-failsafe-plugin"),
  921. version(defaultArtifactIdToVersionMap.get("maven-failsafe-plugin"))
  922. ),
  923. goal("verify"),
  924. verifyconfig,
  925. executionEnvironment()
  926. );
  927. }
  928. /**
  929. * Converts a map of System properties to maven config elements
  930. */
  931. private Element convertPropsToElements(Map<String, Object> systemProperties)
  932. {
  933. ArrayList<Element> properties = new ArrayList<Element>();
  934. /*
  935. OLD surefire 2.4.3 style
  936. // add extra system properties... overwriting any of the hard coded values above.
  937. for (Map.Entry<String, Object> entry: systemProperties.entrySet())
  938. {
  939. properties.add(
  940. element(name("property"),
  941. element(name("name"), entry.getKey()),
  942. element(name("value"), entry.getValue().toString())));
  943. }
  944. return element(name("systemProperties"), properties.toArray(new Element[properties.size()]));
  945. */
  946. // NEW surefire 2.12 style
  947. for (Map.Entry<String, Object> entry: systemProperties.entrySet())
  948. {
  949. log.info("adding system property to configuration: " + entry.getKey() + "::" + entry.getValue());
  950. properties.add(element(name(entry.getKey()),entry.getValue().toString()));
  951. }
  952. return element(name("systemPropertyVariables"), properties.toArray(new Element[properties.size()]));
  953. }
  954. private Container findContainer(final String containerId)
  955. {
  956. final Container container = idToContainerMap.get(containerId);
  957. if (container == null)
  958. {
  959. throw new IllegalArgumentException("Container " + containerId + " not supported");
  960. }
  961. return container;
  962. }
  963. int pickFreePort(final int requestedPort)
  964. {
  965. ServerSocket socket = null;
  966. try
  967. {
  968. socket = new ServerSocket(requestedPort);
  969. return requestedPort > 0 ? requestedPort : socket.getLocalPort();
  970. }
  971. catch (final IOException e)
  972. {
  973. // happens if the requested port is taken, so we need to pick a new one
  974. ServerSocket zeroSocket = null;
  975. try
  976. {
  977. zeroSocket = new ServerSocket(0);
  978. return zeroSocket.getLocalPort();
  979. }
  980. catch (final IOException ex)
  981. {
  982. throw new RuntimeException("Error opening socket", ex);
  983. }
  984. finally
  985. {
  986. closeSocket(zeroSocket);
  987. }
  988. }
  989. finally
  990. {
  991. closeSocket(socket);
  992. }
  993. }
  994. private void closeSocket(ServerSocket socket)
  995. {
  996. if (socket != null)
  997. {
  998. try
  999. {
  1000. socket.close();
  1001. }
  1002. catch (final IOException e)
  1003. {
  1004. throw new RuntimeException("Error closing socket", e);
  1005. }
  1006. }
  1007. }
  1008. public void installPlugin(PdkParams pdkParams)
  1009. throws MojoExecutionException
  1010. {
  1011. final String baseUrl = getBaseUrl(pdkParams.getServer(), pdkParams.getPort(), pdkParams.getContextPath());
  1012. executeMojo(
  1013. plugin(
  1014. groupId("com.atlassian.maven.plugins"),
  1015. artifactId("atlassian-pdk"),
  1016. version(pluginArtifactIdToVersionMap.get("atlassian-pdk"))
  1017. ),
  1018. goal("install"),
  1019. configuration(
  1020. element(name("pluginFile"), pdkParams.getPluginFile()),
  1021. element(name("username"), pdkParams.getUsername()),
  1022. element(name("password"), pdkParams.getPassword()),
  1023. element(name("serverUrl"), baseUrl),
  1024. element(name("pluginKey"), pdkParams.getPluginKey())
  1025. ),
  1026. executionEnvironment()
  1027. );
  1028. }
  1029. public void uninstallPlugin(final String pluginKey, final String server, final int port, final String contextPath)
  1030. throws MojoExecutionException
  1031. {
  1032. final String baseUrl = getBaseUrl(server, port, contextPath);
  1033. executeMojo(
  1034. plugin(
  1035. groupId("com.atlassian.maven.plugins"),
  1036. artifactId("atlassian-pdk"),
  1037. version(pluginArtifactIdToVersionMap.get("atlassian-pdk"))
  1038. ),
  1039. goal("uninstall"),
  1040. configuration(
  1041. element(name("username"), "admin"),
  1042. element(name("password"), "admin"),
  1043. element(name("serverUrl"), baseUrl),
  1044. element(name("pluginKey"), pluginKey)
  1045. ),
  1046. executionEnvironment()
  1047. );
  1048. }
  1049. public void installIdeaPlugin() throws MojoExecutionException
  1050. {
  1051. executeMojo(
  1052. plugin(
  1053. groupId("org.twdata.maven"),
  1054. artifactId("maven-cli-plugin"),
  1055. version(pluginArtifactIdToVersionMap.get("maven-cli-plugin"))
  1056. ),
  1057. goal("idea"),
  1058. configuration(),
  1059. executionEnvironment()
  1060. );
  1061. }
  1062. public File copyDist(final File targetDirectory, final ProductArtifact artifact) throws MojoExecutionException
  1063. {
  1064. return copyZip(targetDirectory, artifact, "test-dist.zip");
  1065. }
  1066. public File copyHome(final File targetDirectory, final ProductArtifact artifact) throws MojoExecutionException
  1067. {
  1068. return copyZip(targetDirectory, artifact, artifact.getArtifactId() + ".zip");
  1069. }
  1070. public File copyZip(final File targetDirectory, final ProductArtifact artifact, final String localName) throws MojoExecutionException
  1071. {
  1072. final File artifactZip = new File(targetDirectory, localName);
  1073. executeMojo(
  1074. plugin(
  1075. groupId("org.apache.maven.plugins"),
  1076. artifactId("maven-dependency-plugin"),
  1077. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  1078. ),
  1079. goal("copy"),
  1080. configuration(
  1081. element(name("artifactItems"),
  1082. element(name("artifactItem"),
  1083. element(name("groupId"), artifact.getGroupId()),
  1084. element(name("artifactId"), artifact.getArtifactId()),
  1085. element(name("type"), "zip"),
  1086. element(name("version"), artifact.getVersion()),
  1087. element(name("destFileName"), artifactZip.getName()))),
  1088. element(name("outputDirectory"), artifactZip.getParent())
  1089. ),
  1090. executionEnvironment()
  1091. );
  1092. return artifactZip;
  1093. }
  1094. public void generateBundleManifest(final Map<String, String> instructions, final Map<String, String> basicAttributes) throws MojoExecutionException
  1095. {
  1096. final List<Element> instlist = new ArrayList<Element>();
  1097. for (final Map.Entry<String, String> entry : instructions.entrySet())
  1098. {
  1099. instlist.add(element(entry.getKey(), entry.getValue()));
  1100. }
  1101. if (!instructions.containsKey(Constants.IMPORT_PACKAGE))
  1102. {
  1103. instlist.add(element(Constants.IMPORT_PACKAGE, "*;resolution:=optional"));
  1104. // BND will expand the wildcard to a list of actually-used packages, but this tells it to mark
  1105. // them all as optional
  1106. }
  1107. for (final Map.Entry<String, String> entry : basicAttributes.entrySet())
  1108. {
  1109. instlist.add(element(entry.getKey(), entry.getValue()));
  1110. }
  1111. executeMojo(
  1112. plugin(
  1113. groupId("org.apache.felix"),
  1114. artifactId("maven-bundle-plugin"),
  1115. version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
  1116. ),
  1117. goal("manifest"),
  1118. configuration(
  1119. element(name("supportedProjectTypes"),
  1120. element(name("supportedProjectType"), "jar"),
  1121. element(name("supportedProjectType"), "bundle"),
  1122. element(name("supportedProjectType"), "war"),
  1123. element(name("supportedProjectType"), "atlassian-plugin")),
  1124. element(name("instructions"), instlist.toArray(new Element[instlist.size()]))
  1125. ),
  1126. executionEnvironment()
  1127. );
  1128. }
  1129. public void generateTestBundleManifest(final Map<String, String> instructions, final Map<String, String> basicAttributes) throws MojoExecutionException
  1130. {
  1131. final List<Element> instlist = new ArrayList<Element>();
  1132. for (final Map.Entry<String, String> entry : instructions.entrySet())
  1133. {
  1134. instlist.add(element(entry.getKey(), entry.getValue()));
  1135. }
  1136. if (!instructions.containsKey(Constants.IMPORT_PACKAGE))
  1137. {
  1138. instlist.add(element(Constants.IMPORT_PACKAGE, "*;resolution:=optional"));
  1139. // BND will expand the wildcard to a list of actually-used packages, but this tells it to mark
  1140. // them all as optional
  1141. }
  1142. for (final Map.Entry<String, String> entry : basicAttributes.entrySet())
  1143. {
  1144. instlist.add(element(entry.getKey(), entry.getValue()));
  1145. }
  1146. executeMojo(
  1147. plugin(
  1148. groupId("org.apache.felix"),
  1149. artifactId("maven-bundle-plugin"),
  1150. version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
  1151. ),
  1152. goal("manifest"),
  1153. configuration(
  1154. element(name("manifestLocation"),"${project.build.testOutputDirectory}/META-INF"),
  1155. element(name("supportedProjectTypes"),
  1156. element(name("supportedProjectType"), "jar"),
  1157. element(name("supportedProjectType"), "bundle"),
  1158. element(name("supportedProjectType"), "war"),
  1159. element(name("supportedProjectType"), "atlassian-plugin")),
  1160. element(name("instructions"), instlist.toArray(new Element[instlist.size()]))
  1161. ),
  1162. executionEnvironment()
  1163. );
  1164. }
  1165. public void generateMinimalManifest(final Map<String, String> basicAttributes) throws MojoExecutionException
  1166. {
  1167. File metaInf = file(ctx.getProject().getBuild().getOutputDirectory(), "META-INF");
  1168. if (!metaInf.exists())
  1169. {
  1170. metaInf.mkdirs();
  1171. }
  1172. File mf = file(ctx.getProject().getBuild().getOutputDirectory(), "META-INF", "MANIFEST.MF");
  1173. Manifest m = new Manifest();
  1174. m.getMainAttributes().putValue("Manifest-Version", "1.0");
  1175. for (Map.Entry<String, String> entry : basicAttributes.entrySet())
  1176. {
  1177. m.getMainAttributes().putValue(entry.getKey(), entry.getValue());
  1178. }
  1179. FileOutputStream fos = null;
  1180. try
  1181. {
  1182. fos = new FileOutputStream(mf);
  1183. m.write(fos);
  1184. }
  1185. catch (IOException e)
  1186. {
  1187. throw new MojoExecutionException("Unable to create manifest", e);
  1188. }
  1189. finally
  1190. {
  1191. IOUtils.closeQuietly(fos);
  1192. }
  1193. }
  1194. public void generateTestMinimalManifest(final Map<String, String> basicAttributes) throws MojoExecutionException
  1195. {
  1196. File metaInf = file(ctx.getProject().getBuild().getTestOutputDirectory(), "META-INF");
  1197. if (!metaInf.exists())
  1198. {
  1199. metaInf.mkdirs();
  1200. }
  1201. File mf = file(ctx.getProject().getBuild().getTestOutputDirectory(), "META-INF", "MANIFEST.MF");
  1202. Manifest m = new Manifest();
  1203. m.getMainAttributes().putValue("Manifest-Version", "1.0");
  1204. for (Map.Entry<String, String> entry : basicAttributes.entrySet())
  1205. {
  1206. m.getMainAttributes().putValue(entry.getKey(), entry.getValue());
  1207. }
  1208. FileOutputStream fos = null;
  1209. try
  1210. {
  1211. fos = new FileOutputStream(mf);
  1212. m.write(fos);
  1213. }
  1214. catch (IOException e)
  1215. {
  1216. throw new MojoExecutionException("Unable to create manifest", e);
  1217. }
  1218. finally
  1219. {
  1220. IOUtils.closeQuietly(fos);
  1221. }
  1222. }
  1223. public void jarWithOptionalManifest(final boolean manifestExists) throws MojoExecutionException
  1224. {
  1225. Element[] archive = new Element[0];
  1226. if (manifestExists)
  1227. {
  1228. archive = new Element[]{element(name("manifestFile"), "${project.build.outputDirectory}/META-INF/MANIFEST.MF")};
  1229. }
  1230. executeMojo(
  1231. plugin(
  1232. groupId("org.apache.maven.plugins"),
  1233. artifactId("maven-jar-plugin"),
  1234. version(defaultArtifactIdToVersionMap.get("maven-jar-plugin"))
  1235. ),
  1236. goal("jar"),
  1237. configuration(
  1238. element(name("archive"), archive)
  1239. ),
  1240. executionEnvironment()
  1241. );
  1242. }
  1243. public void jarTests(String finalName) throws MojoExecutionException
  1244. {
  1245. executeMojo(
  1246. plugin(
  1247. groupId("org.apache.maven.plugins"),
  1248. artifactId("maven-jar-plugin"),
  1249. version(defaultArtifactIdToVersionMap.get("maven-jar-plugin"))
  1250. ),
  1251. goal("test-jar"),
  1252. configuration(
  1253. element(name("finalName"), finalName),
  1254. element(name("archive"),
  1255. element(name("manifestFile"), "${project.build.testOutputDirectory}/META-INF/MANIFEST.MF"))
  1256. ),
  1257. executionEnvironment()
  1258. );
  1259. }
  1260. public void generateObrXml(File dep, File obrXml) throws MojoExecutionException
  1261. {
  1262. executeMojo(
  1263. plugin(
  1264. groupId("org.apache.felix"),
  1265. artifactId("maven-bundle-plugin"),
  1266. version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
  1267. ),
  1268. goal("install-file"),
  1269. configuration(
  1270. element(name("obrRepository"), obrXml.getPath()),
  1271. // the following three settings are required but not really used
  1272. element(name("groupId"), "doesntmatter"),
  1273. element(name("artifactId"), "doesntmatter"),
  1274. element(name("version"), "doesntmatter"),
  1275. element(name("packaging"), "jar"),
  1276. element(name("file"), dep.getPath())
  1277. ),
  1278. executionEnvironment()
  1279. );
  1280. }
  1281. /**
  1282. * Adds the file to the artifacts of this build.
  1283. * The artifact will be deployed using the name and version of the current project,
  1284. * as in if your artifactId is 'MyProject', it will be MyProject-1.0-SNAPSHOT.jar,
  1285. * overriding any artifact created at compilation time.
  1286. *
  1287. * Attached artifacts get installed (at install phase) and deployed (at deploy phase)
  1288. * @param file the file
  1289. * @param type the type of the file, default 'jar'
  1290. */
  1291. public void attachArtifact(File file, String type) throws MojoExecutionException
  1292. {
  1293. executeMojo(
  1294. plugin(
  1295. groupId("org.codehaus.mojo"),
  1296. artifactId("build-helper-maven-plugin"),
  1297. version(defaultArtifactIdToVersionMap.get("build-helper-maven-plugin"))
  1298. ),
  1299. goal("attach-artifact"),
  1300. configuration(
  1301. element(name("artifacts"),
  1302. element(name("artifact"),
  1303. element(name("file"), file.getAbsolutePath()),
  1304. element(name("type"), type)
  1305. )
  1306. )
  1307. ),
  1308. executionEnvironment());
  1309. }
  1310. public void release(String mavenArgs) throws MojoExecutionException
  1311. {
  1312. String args = "";
  1313. if(StringUtils.isNotBlank(mavenArgs)) {
  1314. args = mavenArgs;
  1315. }
  1316. executeMojo(
  1317. plugin(
  1318. groupId("org.apache.maven.plugins"),
  1319. artifactId("maven-release-plugin"),
  1320. version(defaultArtifactIdToVersionMap.get("maven-release-plugin"))
  1321. ),
  1322. goal("prepare"),
  1323. configuration(
  1324. element(name("arguments"), args)
  1325. ,element(name("autoVersionSubmodules"),"true")
  1326. ,element(name("useReleaseProfile"),"true")
  1327. ),
  1328. executionEnvironment()
  1329. );
  1330. executeMojo(
  1331. plugin(
  1332. groupId("org.apache.maven.plugins"),
  1333. artifactId("maven-release-plugin"),
  1334. version(defaultArtifactIdToVersionMap.get("maven-release-plugin"))
  1335. ),
  1336. goal("perform"),
  1337. configuration(
  1338. element(name("arguments"), args)
  1339. ),
  1340. executionEnvironment()
  1341. );
  1342. }
  1343. public void generateRestDocs() throws MojoExecutionException
  1344. {
  1345. MavenProject prj = ctx.getProject();
  1346. StringBuffer packagesPath = new StringBuffer();
  1347. List<PluginXmlUtils.RESTModuleInfo> restModules = PluginXmlUtils.getRestModules(ctx);
  1348. for(PluginXmlUtils.RESTModuleInfo moduleInfo : restModules)
  1349. {
  1350. List<String> packageList = moduleInfo.getPackagesToScan();
  1351. for(String packageToScan : packageList)
  1352. {
  1353. if(packagesPath.length() > 0)
  1354. {
  1355. packagesPath.append(File.pathSeparator);
  1356. }
  1357. String filePath = prj.getBuild().getSourceDirectory() + File.separator + packageToScan.replaceAll("\\.", Matcher.quoteReplacement(File.separator));
  1358. packagesPath.append(filePath);
  1359. }
  1360. }
  1361. if(!restModules.isEmpty() && packagesPath.length() > 0)
  1362. {
  1363. Set<String> docletPaths = new HashSet<String>();
  1364. StringBuffer docletPath = new StringBuffer(File.pathSeparator + prj.getBuild().getOutputDirectory());
  1365. String resourcedocPath = fixWindowsSlashes(prj.getBuild().getOutputDirectory() + File.separator + "resourcedoc.xml");
  1366. PluginXmlUtils.PluginInfo pluginInfo = PluginXmlUtils.getPluginInfo(ctx);
  1367. try
  1368. {
  1369. docletPaths.addAll(prj.getCompileClasspathElements());
  1370. docletPaths.addAll(prj.getRuntimeClasspathElements());
  1371. docletPaths.addAll(prj.getSystemClasspathElements());
  1372. //AMPS-663: add plugin execution classes to doclet path
  1373. URL[] pluginUrls = ((URLClassLoader)Thread.currentThread().getContextClassLoader()).getURLs();
  1374. for(URL pluginUrl : pluginUrls)
  1375. {
  1376. docletPaths.add(new File(pluginUrl.getFile()).getPath());
  1377. }
  1378. for(String path : docletPaths) {
  1379. docletPath.append(File.pathSeparator);
  1380. docletPath.append(path);
  1381. }
  1382. } catch (DependencyResolutionRequiredException e)
  1383. {
  1384. throw new MojoExecutionException("Dependencies must be resolved", e);
  1385. }
  1386. executeMojo(
  1387. plugin(
  1388. groupId("org.apache.maven.plugins"),
  1389. artifactId("maven-javadoc-plugin"),
  1390. version("2.8.1")
  1391. ),
  1392. goal("javadoc"),
  1393. configuration(
  1394. element(name("maxmemory"),"1024m"),
  1395. element(name("sourcepath"),packagesPath.toString()),
  1396. element(name("doclet"), ResourceDocletJSON.class.getName()),
  1397. element(name("docletPath"), docletPath.toString()),
  1398. element(name("docletArtifacts"),
  1399. element(name("docletArtifact"),
  1400. element(name("groupId"),"xerces"),
  1401. element(name("artifactId"),"xercesImpl"),
  1402. element(name("version"),"2.9.1")
  1403. ),
  1404. element(name("docletArtifact"),
  1405. element(name("groupId"),"commons-lang"),
  1406. element(name("artifactId"),"commons-lang"),
  1407. element(name("version"),"2.6")
  1408. )
  1409. ),
  1410. element(name("additionalparam"),"-output \"" + resourcedocPath + "\""),
  1411. element(name("useStandardDocletOptions"),"false")
  1412. ),
  1413. executionEnvironment()
  1414. );
  1415. try {
  1416. File userAppDocs = new File(prj.getBuild().getOutputDirectory(),"application-doc.xml");
  1417. if(!userAppDocs.exists())
  1418. {
  1419. String appDocText = com.atlassian.core.util.FileUtils.getResourceContent("application-doc.xml");
  1420. appDocText = StringUtils.replace(appDocText, "${rest.doc.title}", pluginInfo.getName());
  1421. appDocText = StringUtils.replace(appDocText,"${rest.doc.description}",pluginInfo.getDescription());
  1422. File appDocFile = new File(prj.getBuild().getOutputDirectory(), "application-doc.xml");
  1423. FileUtils.writeStringToFile(appDocFile,appDocText);
  1424. log.info("Wrote " + appDocFile.getAbsolutePath());
  1425. }
  1426. File userGrammars = new File(prj.getBuild().getOutputDirectory(),"application-grammars.xml");
  1427. if(!userGrammars.exists())
  1428. {
  1429. String grammarText = com.atlassian.core.util.FileUtils.getResourceContent("application-grammars.xml");
  1430. File grammarFile = new File(prj.getBuild().getOutputDirectory(), "application-grammars.xml");
  1431. FileUtils.writeStringToFile(grammarFile,grammarText);
  1432. log.info("Wrote " + grammarFile.getAbsolutePath());
  1433. }
  1434. } catch (Exception e)
  1435. {
  1436. throw new MojoExecutionException("Error writing REST application xml files",e);
  1437. }
  1438. }
  1439. }
  1440. public void copyContainerToOutputDirectory(String containerVersion) throws
  1441. MojoExecutionException
  1442. {
  1443. executeMojo(
  1444. plugin(
  1445. groupId("org.apache.maven.plugins"),
  1446. artifactId("maven-dependency-plugin"),
  1447. version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
  1448. ),
  1449. goal("copy"),
  1450. configuration(
  1451. element(name("artifactItems"),
  1452. element(name("artifactItem"),
  1453. element(name("groupId"), "com.atlassian.plugins"),
  1454. element(name("artifactId"), "remotable-plugins-container"),
  1455. element(name("version"), containerVersion))),
  1456. element(name("stripVersion"), "true"),
  1457. element(name("outputDirectory"), "${project.build.directory}")
  1458. ),
  1459. executionEnvironment()
  1460. );
  1461. }
  1462. public void debugStandaloneContainer(File pluginFile) throws MojoExecutionException
  1463. {
  1464. StringBuilder resourceProp = new StringBuilder();
  1465. @SuppressWarnings("unchecked") List<Resource> resList = getContextProject().getResources();
  1466. for (int i = 0; i < resList.size(); i++) {
  1467. resourceProp.append(resList.get(i).getDirectory());
  1468. if (i + 1 != resList.size()) {
  1469. resourceProp.append(",");
  1470. }
  1471. }
  1472. executeMojo(
  1473. plugin(
  1474. groupId("org.codehaus.mojo"),
  1475. artifactId("exec-maven-plugin"),
  1476. version(defaultArtifactIdToVersionMap.get("maven-exec-plugin"))
  1477. ),
  1478. goal("exec"),
  1479. configuration(
  1480. element(name("executable"), "java"),
  1481. element(name("arguments"),
  1482. element(name("argument"), "-Datlassian.dev.mode=true"),
  1483. element(name("argument"), "-Dplugin.resource.directories=" + resourceProp),
  1484. element(name("argument"), "-Xdebug"),
  1485. element(name("argument"), "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5004"),
  1486. element(name("argument"), "-jar"),
  1487. element(name("argument"), "${project.build.directory}/remotable-plugins-container-standalone.jar"),
  1488. element(name("argument"), pluginFile.getPath()))
  1489. ),
  1490. executionEnvironment()
  1491. );
  1492. }
  1493. private static class Container extends ProductArtifact
  1494. {
  1495. private final String id;
  1496. private final String type;
  1497. private final String classifier;
  1498. /**
  1499. * Installable container that can be downloaded by Maven.
  1500. *
  1501. * @param id identifier of container, eg. "tomcat5x".
  1502. * @param groupId groupId of container.
  1503. * @param artifactId artifactId of container.
  1504. * @param version version number of container.
  1505. */
  1506. public Container(final String id, final String groupId, final String artifactId, final String version)
  1507. {
  1508. super(groupId, artifactId, version);
  1509. this.id = id;
  1510. this.type = "installed";
  1511. this.classifier = "";
  1512. }
  1513. /**
  1514. * Installable container that can be downloaded by Maven.
  1515. *
  1516. * @param id identifier of container, eg. "tomcat5x".
  1517. * @param groupId groupId of container.
  1518. * @param artifactId artifactId of container.
  1519. * @param version version number of container.
  1520. * @param classifier classifier of the container.
  1521. */
  1522. public Container(final String id, final String groupId, final String artifactId, final String version, final String classifier)
  1523. {
  1524. super(groupId, artifactId, version);
  1525. this.id = id;
  1526. this.type = "installed";
  1527. this.classifier = classifier;
  1528. }
  1529. /**
  1530. * Embedded container packaged with Cargo.
  1531. *
  1532. * @param id identifier of container, eg. "jetty6x".
  1533. */
  1534. public Container(final String id)
  1535. {
  1536. this.id = id;
  1537. this.type = "embedded";
  1538. this.classifier = "";
  1539. }
  1540. /**
  1541. * @return identifier of container.
  1542. */
  1543. public String getId()
  1544. {
  1545. return id;
  1546. }
  1547. /**
  1548. * @return "installed" or "embedded".
  1549. */
  1550. public String getType()
  1551. {
  1552. return type;
  1553. }
  1554. /**
  1555. * @return classifier the classifier of the ProductArtifact
  1556. */
  1557. public String getClassifier()
  1558. {
  1559. return classifier;
  1560. }
  1561. /**
  1562. * @return <code>true</code> if the container type is "embedded".
  1563. */
  1564. public boolean isEmbedded()
  1565. {
  1566. return "embedded".equals(type);
  1567. }
  1568. /**
  1569. * @param buildDir project.build.directory.
  1570. * @return root directory of the container that will house the container installation and configuration.
  1571. */
  1572. public String getRootDirectory(String buildDir)
  1573. {
  1574. return buildDir + File.separator + "container" + File.separator + getId();
  1575. }
  1576. /**
  1577. * @param buildDir project.build.directory.
  1578. * @return directory housing the installed container.
  1579. */
  1580. public String getInstallDirectory(String buildDir)
  1581. {
  1582. return getRootDirectory(buildDir) + File.separator + getArtifactId() + "-" + getVersion();
  1583. }
  1584. /**
  1585. * @param buildDir project.build.directory.
  1586. * @param productId product name.
  1587. * @return directory to house the container configuration for the specified product.
  1588. */
  1589. public String getConfigDirectory(String buildDir, String productId)
  1590. {
  1591. return getRootDirectory(buildDir) + File.separator + "cargo-" + productId + "-home";
  1592. }
  1593. }
  1594. }