1   package com.atlassian.maven.plugins.amps;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.net.ServerSocket;
6   import java.util.ArrayList;
7   import java.util.Collections;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  
12  import com.atlassian.core.util.FileUtils;
13  import com.atlassian.maven.plugins.amps.util.VersionUtils;
14  
15  import org.apache.maven.plugin.MojoExecutionException;
16  import org.apache.maven.plugin.logging.Log;
17  import org.apache.maven.project.MavenProject;
18  import org.codehaus.plexus.util.xml.Xpp3Dom;
19  import org.twdata.maven.mojoexecutor.MojoExecutor.Element;
20  import org.twdata.maven.mojoexecutor.MojoExecutor.ExecutionEnvironment;
21  
22  import static org.twdata.maven.mojoexecutor.MojoExecutor.artifactId;
23  import static org.twdata.maven.mojoexecutor.MojoExecutor.configuration;
24  import static org.twdata.maven.mojoexecutor.MojoExecutor.element;
25  import static org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo;
26  import static org.twdata.maven.mojoexecutor.MojoExecutor.goal;
27  import static org.twdata.maven.mojoexecutor.MojoExecutor.groupId;
28  import static org.twdata.maven.mojoexecutor.MojoExecutor.name;
29  import static org.twdata.maven.mojoexecutor.MojoExecutor.plugin;
30  import static org.twdata.maven.mojoexecutor.MojoExecutor.version;
31  
32  /**
33   * Executes specific maven goals
34   */
35  public class MavenGoals
36  {
37      private final MavenContext ctx;
38  
39      private final Log log;
40      private final Map<String, String> pluginArtifactIdToVersionMap;
41  
42      private final Map<String, Container> idToContainerMap = new HashMap<String, Container>()
43      {{
44              put("tomcat5x", new Container("tomcat5x", "org.apache.tomcat", "apache-tomcat", "5.5.26"));
45              put("tomcat6x", new Container("tomcat6x", "org.apache.tomcat", "apache-tomcat", "6.0.20"));
46              put("resin3x", new Container("resin3x", "com.caucho", "resin", "3.0.26"));
47              put("jboss42x", new Container("jboss42x", "org.jboss.jbossas", "jbossas", "4.2.3.GA"));
48              put("jetty6x", new Container("jetty6x"));
49          }};
50  
51      private final Map<String, String> defaultArtifactIdToVersionMap = new HashMap<String, String>()
52      {{
53              put("maven-cli-plugin", "0.7");
54              put("cargo-maven2-plugin", "1.0-beta-2-db2");
55              put("atlassian-pdk", "2.1.8");
56              put("maven-archetype-plugin", "2.0-alpha-4");
57              put("maven-bundle-plugin", "2.0.0");
58              put("yuicompressor-maven-plugin", "0.7.1");
59  
60              // You can't actually override the version a plugin if defined in the project, so these don't actually do
61              // anything, since the super pom already defines versions.
62              put("maven-dependency-plugin", "2.0");
63              put("maven-resources-plugin", "2.3");
64              put("maven-jar-plugin", "2.2");
65              put("maven-surefire-plugin", "2.4.3");
66  
67          }};
68  
69      public MavenGoals(final MavenContext ctx)
70      {
71          this(ctx, Collections.<String, String>emptyMap());
72      }
73  
74      public MavenGoals(final MavenContext ctx, final Map<String, String> pluginToVersionMap)
75      {
76          this.ctx = ctx;
77  
78          this.log = ctx.getLog();
79  
80          final Map<String, String> map = new HashMap<String, String>(defaultArtifactIdToVersionMap);
81          map.putAll(pluginToVersionMap);
82          this.pluginArtifactIdToVersionMap = Collections.unmodifiableMap(map);
83      }
84  
85      private ExecutionEnvironment executionEnvironment()
86      {
87          return ctx.getExecutionEnvironment();
88      }
89  
90      public MavenProject getContextProject()
91      {
92          return ctx.getProject();
93      }
94  
95      public void executeAmpsRecursively(final String ampsVersion, final String ampsGoal, Xpp3Dom cfg) throws MojoExecutionException
96      {
97          executeMojo(
98              plugin(
99                  groupId("com.atlassian.maven.plugins"),
100                 artifactId("maven-amps-plugin"),
101                 version(ampsVersion)
102             ),
103             goal(ampsGoal),
104             cfg,
105             executionEnvironment());
106     }
107 
108     public void startCli(final PluginInformation pluginInformation, final int port) throws MojoExecutionException
109     {
110         final String pluginId = pluginInformation.getId();
111 
112         final List<Element> configs = new ArrayList<Element>();
113         configs.add(element(name("commands"),
114                 element(name("pi"),
115                         "resources" + " "
116                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
117                         + "compile" + " "
118                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
119                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:compress-resources" + " "
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                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:install"),
124                 element(name("tpi"),
125                         "testResources" + " "
126                         + "testCompile" + " "
127                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-jar" + " "
128                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-install"),
129                 element(name("package"),
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:generate-manifest" + " "
135                         + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " ")));
136         if (port > 0)
137         {
138             configs.add(element(name("port"), String.valueOf(port)));
139         }
140         executeMojo(
141                 plugin(
142                         groupId("org.twdata.maven"),
143                         artifactId("maven-cli-plugin"),
144                         version(pluginArtifactIdToVersionMap.get("maven-cli-plugin"))
145                 ),
146                 goal("execute"),
147                 configuration(configs.toArray(new Element[0])),
148                 executionEnvironment());
149     }
150 
151     public void createPlugin(final String productId) throws MojoExecutionException
152     {
153         executeMojo(
154                 plugin(
155                         groupId("org.apache.maven.plugins"),
156                         artifactId("maven-archetype-plugin"),
157                         version(defaultArtifactIdToVersionMap.get("maven-archetype-plugin"))
158                 ),
159                 goal("generate"),
160                 configuration(
161                         element(name("archetypeGroupId"), "com.atlassian.maven.archetypes"),
162                         element(name("archetypeArtifactId"), productId + "-plugin-archetype"),
163                         element(name("archetypeVersion"), VersionUtils.getVersion())
164                 ),
165                 executionEnvironment());
166     }
167 
168     public void copyBundledDependencies() throws MojoExecutionException
169     {
170         executeMojo(
171                 plugin(
172                         groupId("org.apache.maven.plugins"),
173                         artifactId("maven-dependency-plugin"),
174                         version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
175                 ),
176                 goal("copy-dependencies"),
177                 configuration(
178                         element(name("includeScope"), "runtime"),
179                         element(name("excludeScope"), "provided"),
180                         element(name("excludeScope"), "test"),
181                         element(name("includeTypes"), "jar"),
182                         element(name("outputDirectory"), "${project.build.outputDirectory}/META-INF/lib")
183                 ),
184                 executionEnvironment()
185         );
186     }
187 
188     public void extractBundledDependencies() throws MojoExecutionException
189     {
190          executeMojo(
191                  plugin(
192                         groupId("org.apache.maven.plugins"),
193                         artifactId("maven-dependency-plugin"),
194                         version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
195                 ),
196                 goal("unpack-dependencies"),
197                 configuration(
198                         element(name("includeScope"), "runtime"),
199                         element(name("excludeScope"), "provided"),
200                         element(name("excludeScope"), "test"),
201                         element(name("includeTypes"), "jar"),
202                         element(name("excludes"), "META-INF/MANIFEST.MF, META-INF/*.DSA, META-INF/*.SF"),
203                         element(name("outputDirectory"), "${project.build.outputDirectory}")
204                 ),
205                 executionEnvironment()
206         );
207     }
208 
209     public void compressResources() throws MojoExecutionException
210     {
211         executeMojo(
212                 plugin(
213                         groupId("net.sf.alchim"),
214                         artifactId("yuicompressor-maven-plugin"),
215                         version(defaultArtifactIdToVersionMap.get("yuicompressor-maven-plugin"))
216                 ),
217                 goal("compress"),
218                 configuration(
219                         element(name("suffix"), "-min"),
220                         element(name("jswarn"), "false")
221                 ),
222                 executionEnvironment()
223         );
224     }
225 
226     public void filterPluginDescriptor() throws MojoExecutionException
227     {
228         executeMojo(
229                 plugin(
230                         groupId("org.apache.maven.plugins"),
231                         artifactId("maven-resources-plugin"),
232                         version(defaultArtifactIdToVersionMap.get("maven-resources-plugin"))
233                 ),
234                 goal("copy-resources"),
235                 configuration(
236                         element(name("encoding"), "UTF-8"),
237                         element(name("resources"),
238                                 element(name("resource"),
239                                         element(name("directory"), "src/main/resources"),
240                                         element(name("filtering"), "true"),
241                                         element(name("includes"),
242                                                 element(name("include"), "atlassian-plugin.xml"))
243                                 )
244                         ),
245                         element(name("outputDirectory"), "${project.build.outputDirectory}")
246                 ),
247                 executionEnvironment()
248         );
249     }
250 
251     public void runUnitTests(Map<String, Object> systemProperties) throws MojoExecutionException
252     {
253         final Element systemProps = convertPropsToElements(systemProperties);
254 
255         executeMojo(
256                 plugin(
257                         groupId("org.apache.maven.plugins"),
258                         artifactId("maven-surefire-plugin"),
259                         version(defaultArtifactIdToVersionMap.get("maven-surefire-plugin"))
260                 ),
261                 goal("test"),
262                 configuration(
263                         systemProps,
264                         element(name("excludes"),
265                                 element(name("exclude"), "it/**"),
266                                 element(name("exclude"), "**/*$*"))
267                 ),
268                 executionEnvironment()
269         );
270     }
271 
272     public File copyWebappWar(final String productId, final File targetDirectory, final ProductArtifact artifact)
273             throws MojoExecutionException
274     {
275         final File webappWarFile = new File(targetDirectory, productId + "-original.war");
276         executeMojo(
277                 plugin(
278                         groupId("org.apache.maven.plugins"),
279                         artifactId("maven-dependency-plugin"),
280                         version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
281                 ),
282                 goal("copy"),
283                 configuration(
284                         element(name("artifactItems"),
285                                 element(name("artifactItem"),
286                                         element(name("groupId"), artifact.getGroupId()),
287                                         element(name("artifactId"), artifact.getArtifactId()),
288                                         element(name("type"), "war"),
289                                         element(name("version"), artifact.getVersion()),
290                                         element(name("destFileName"), webappWarFile.getName()))),
291                         element(name("outputDirectory"), targetDirectory.getPath())
292                 ),
293                 executionEnvironment()
294         );
295         return webappWarFile;
296     }
297 
298     /**
299      * Copies {@code artifacts} to the {@code outputDirectory}. Artifacts are looked up in order: <ol> <li>in the maven
300      * reactor</li> <li>in the maven repositories</li> </ol> This can't be used in a goal that happens before the
301      * <em>package</em> phase as artifacts in the reactor will be not be packaged (and therefore 'copiable') until this
302      * phase.
303      *
304      * @param outputDirectory the directory to copy artifacts to
305      * @param artifacts       the list of artifact to copy to the given directory
306      */
307     public void copyPlugins(final File outputDirectory, final List<ProductArtifact> artifacts)
308             throws MojoExecutionException
309     {
310         for (ProductArtifact artifact : artifacts)
311         {
312             final MavenProject artifactReactorProject = getReactorProjectForArtifact(artifact);
313             if (artifactReactorProject != null)
314             {
315 
316                 log.debug(artifact + " will be copied from reactor project " + artifactReactorProject);
317                 final File artifactFile = artifactReactorProject.getArtifact().getFile();
318                 if (artifactFile == null)
319                 {
320                     log.warn("The plugin " + artifact + " is in the reactor but not the file hasn't been attached.  Skipping.");
321                 }
322                 else
323                 {
324                     log.debug("Copying " + artifactFile + " to " + outputDirectory);
325                     try
326                     {
327                         FileUtils.copyFile(artifactFile, new File(outputDirectory, artifactFile.getName()));
328                     }
329                     catch (IOException e)
330                     {
331                         throw new MojoExecutionException("Could not copy " + artifact + " to " + outputDirectory, e);
332                     }
333                 }
334 
335             }
336             else
337             {
338                 executeMojo(
339                         plugin(
340                                 groupId("org.apache.maven.plugins"),
341                                 artifactId("maven-dependency-plugin"),
342                                 version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
343                         ),
344                         goal("copy"),
345                         configuration(
346                                 element(name("artifactItems"),
347                                         element(name("artifactItem"),
348                                                 element(name("groupId"), artifact.getGroupId()),
349                                                 element(name("artifactId"), artifact.getArtifactId()),
350                                                 element(name("version"), artifact.getVersion()))),
351                                 element(name("outputDirectory"), outputDirectory.getPath())
352                         ),
353                         executionEnvironment());
354             }
355         }
356     }
357 
358     private MavenProject getReactorProjectForArtifact(ProductArtifact artifact)
359     {
360         for (final MavenProject project : ctx.getReactor())
361         {
362             if (project.getGroupId().equals(artifact.getGroupId())
363                     && project.getArtifactId().equals(artifact.getArtifactId())
364                     && project.getVersion().equals(artifact.getVersion()))
365             {
366                 return project;
367             }
368         }
369         return null;
370     }
371 
372     private void unpackContainer(final Container container) throws MojoExecutionException
373     {
374         executeMojo(
375                 plugin(
376                         groupId("org.apache.maven.plugins"),
377                         artifactId("maven-dependency-plugin"),
378                         version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
379                 ),
380                 goal("unpack"),
381                 configuration(
382                         element(name("artifactItems"),
383                                 element(name("artifactItem"),
384                                         element(name("groupId"), container.getGroupId()),
385                                         element(name("artifactId"), container.getArtifactId()),
386                                         element(name("version"), container.getVersion()),
387                                         element(name("type"), "zip"))),
388                         element(name("outputDirectory"), container.getRootDirectory(getBuildDirectory()))
389                 ),
390                 executionEnvironment());
391     }
392 
393     private String getBuildDirectory()
394     {
395         return ctx.getProject().getBuild().getDirectory();
396     }
397 
398     public int startWebapp(final String productInstanceId, final File war, final Map<String, String> systemProperties, final List<ProductArtifact> extraContainerDependencies,
399                            final Product webappContext) throws MojoExecutionException
400     {
401         final Container container = findContainer(webappContext.getContainerId());
402         File containerDir = new File(container.getRootDirectory(getBuildDirectory()));
403 
404         // retrieve non-embedded containers
405         if (!container.isEmbedded())
406         {
407             if (containerDir.exists())
408             {
409                 log.info("Reusing unpacked container '" + container.getId() + "' from " + containerDir.getPath());
410             }
411             else
412             {
413                 log.info("Unpacking container '" + container.getId() + "' from container artifact: " + container.toString());
414                 unpackContainer(container);
415             }
416         }
417 
418         final int rmiPort = pickFreePort(0);
419         final int actualHttpPort = pickFreePort(webappContext.getHttpPort());
420         final List<Element> sysProps = new ArrayList<Element>();
421         if (webappContext.getJvmArgs() == null)
422         {
423             webappContext.setJvmArgs("-Xmx512m -XX:MaxPermSize=160m");
424         }
425 
426         for (final Map.Entry<String, String> entry : systemProperties.entrySet())
427         {
428             webappContext.setJvmArgs(webappContext.getJvmArgs() + " -D" + entry.getKey() + "=\"" + entry.getValue() + "\"");
429             sysProps.add(element(name(entry.getKey()), entry.getValue()));
430         }
431         log.info("Starting " + productInstanceId + " on the " + container.getId() + " container on ports "
432                 + actualHttpPort + " (http) and " + rmiPort + " (rmi)");
433 
434         final String baseUrl = getBaseUrl(webappContext.getServer(), actualHttpPort, webappContext.getContextPath());
435         sysProps.add(element(name("baseurl"), baseUrl));
436 
437         final List<Element> deps = new ArrayList<Element>();
438         for (final ProductArtifact dep : extraContainerDependencies)
439 
440         {
441             deps.add(element(name("dependency"),
442                     element(name("location"), webappContext.getArtifactRetriever().resolve(dep))
443             ));
444         }
445 
446         final List<Element> props = new ArrayList<Element>();
447         for (final Map.Entry<String, String> entry : systemProperties.entrySet())
448         {
449             props.add(element(name(entry.getKey()), entry.getValue()));
450         }
451         props.add(element(name("cargo.servlet.port"), String.valueOf(actualHttpPort)));
452         props.add(element(name("cargo.rmi.port"), String.valueOf(rmiPort)));
453         props.add(element(name("cargo.jvmargs"), webappContext.getJvmArgs()));
454 
455         executeMojo(
456                 plugin(
457                         groupId("org.twdata.maven"),
458                         artifactId("cargo-maven2-plugin"),
459                         version(pluginArtifactIdToVersionMap.get("cargo-maven2-plugin"))
460                 ),
461                 goal("start"),
462                 configuration(
463                         element(name("wait"), "false"),
464                         element(name("container"),
465                                 element(name("containerId"), container.getId()),
466                                 element(name("type"), container.getType()),
467                                 element(name("home"), container.getInstallDirectory(getBuildDirectory())),
468                                 element(name("output"), webappContext.getOutput()),
469                                 element(name("systemProperties"), sysProps.toArray(new Element[sysProps.size()])),
470                                 element(name("dependencies"), deps.toArray(new Element[deps.size()])),
471                                 element(name("timeout"), String.valueOf(webappContext.getStartupTimeout()))
472                         ),
473                         element(name("configuration"),
474                                 element(name("home"), container.getConfigDirectory(getBuildDirectory(), productInstanceId)),
475                                 element(name("type"), "standalone"),
476                                 element(name("properties"), props.toArray(new Element[props.size()])),
477                                 element(name("deployables"),
478                                         element(name("deployable"),
479                                                 element(name("groupId"), "foo"),
480                                                 element(name("artifactId"), "bar"),
481                                                 element(name("type"), "war"),
482                                                 element(name("location"), war.getPath()),
483                                                 element(name("properties"),
484                                                         element(name("context"), webappContext.getContextPath())
485                                                 )
486                                         )
487                                 )
488                         )
489                 ),
490                 executionEnvironment()
491         );
492         return actualHttpPort;
493     }
494 
495     public static String getBaseUrl(final String server, final int actualHttpPort, final String contextPath)
496     {
497         return "http://" + server + ":" + actualHttpPort + contextPath;
498     }
499 
500     public void runTests(String productId, String containerId, List<String> includes, List<String> excludes, Map<String, Object> systemProperties, final File targetDirectory)
501     		throws MojoExecutionException
502 	{
503     	List<Element> includeElements = new ArrayList<Element>(includes.size());
504     	for (String include : includes)
505     	{
506     		includeElements.add(element(name("include"), include));
507     	}
508 
509         List<Element> excludeElements = new ArrayList<Element>(excludes.size() + 2);
510         excludeElements.add(element(name("exclude"), "**/*$*"));
511         excludeElements.add(element(name("exclude"), "**/Abstract*"));
512         for (String exclude : excludes)
513         {
514         	excludeElements.add(element(name("exclude"), exclude));
515         }
516 
517         final String testOutputDir = targetDirectory.getAbsolutePath() + "/" + productId + "/" + containerId + "/surefire-reports";
518         final String reportsDirectory = "reportsDirectory";
519         systemProperties.put(reportsDirectory, testOutputDir);
520 
521         final Element systemProps = convertPropsToElements(systemProperties);
522 
523 
524         executeMojo(
525                 plugin(
526                         groupId("org.apache.maven.plugins"),
527                         artifactId("maven-surefire-plugin"),
528                         version(defaultArtifactIdToVersionMap.get("maven-surefire-plugin"))
529                 ),
530                 goal("test"),
531                 configuration(
532                         element(name("includes"),
533                         		includeElements.toArray(new Element[includeElements.size()])
534                         ),
535                         element(name("excludes"),
536                                 excludeElements.toArray(new Element[excludeElements.size()])
537                         ),
538                         systemProps,
539                         element(name(reportsDirectory), testOutputDir)
540                 ),
541                 executionEnvironment()
542         );
543 	}
544 
545     /**
546      * Converts a map of System properties to maven config elements
547      */
548     private Element convertPropsToElements(Map<String, Object> systemProperties)
549     {
550         ArrayList<Element> properties = new ArrayList<Element>();
551 
552         // add extra system properties... overwriting any of the hard coded values above.
553         for (Map.Entry<String, Object> entry: systemProperties.entrySet())
554         {
555             properties.add(
556                     element(name("property"),
557                             element(name("name"), entry.getKey()),
558                             element(name("value"), entry.getValue().toString())));
559         }
560 
561         return element(name("systemProperties"), properties.toArray(new Element[properties.size()]));
562     }
563 
564     private Container findContainer(final String containerId)
565     {
566         final Container container = idToContainerMap.get(containerId);
567         if (container == null)
568         {
569             throw new IllegalArgumentException("Container " + containerId + " not supported");
570         }
571         return container;
572     }
573 
574     int pickFreePort(final int requestedPort)
575     {
576         ServerSocket socket = null;
577         try
578         {
579             socket = new ServerSocket(requestedPort);
580             return requestedPort > 0 ? requestedPort : socket.getLocalPort();
581         }
582         catch (final IOException e)
583         {
584             // happens if the requested port is taken, so we need to pick a new one
585             ServerSocket zeroSocket = null;
586             try
587             {
588                 zeroSocket = new ServerSocket(0);
589                 return zeroSocket.getLocalPort();
590             }
591             catch (final IOException ex)
592             {
593                 throw new RuntimeException("Error opening socket", ex);
594             }
595             finally
596             {
597                 closeSocket(zeroSocket);
598             }
599         }
600         finally
601         {
602             closeSocket(socket);
603         }
604     }
605 
606     private void closeSocket(ServerSocket socket)
607     {
608         if (socket != null)
609         {
610             try
611             {
612                 socket.close();
613             }
614             catch (final IOException e)
615             {
616                 throw new RuntimeException("Error closing socket", e);
617             }
618         }
619     }
620 
621     public void stopWebapp(final String productId, final String containerId,
622                            final Product webappContext) throws MojoExecutionException
623     {
624         final Container container = findContainer(containerId);
625         executeMojo(
626                 plugin(
627                         groupId("org.twdata.maven"),
628                         artifactId("cargo-maven2-plugin"),
629                         version(pluginArtifactIdToVersionMap.get("cargo-maven2-plugin"))
630                 ),
631                 goal("stop"),
632                 configuration(
633                         element(name("container"),
634                                 element(name("containerId"), container.getId()),
635                                 element(name("type"), container.getType()),
636                                 element(name("timeout"), String.valueOf(webappContext.getShutdownTimeout()))
637                         ),
638                         element(name("configuration"),
639                                 element(name("home"), container.getConfigDirectory(getBuildDirectory(), productId))
640                         )
641                 ),
642                 executionEnvironment()
643         );
644     }
645 
646     public void installPlugin(PdkParams pdkParams)
647             throws MojoExecutionException
648     {
649         final String baseUrl = getBaseUrl(pdkParams.getServer(), pdkParams.getPort(), pdkParams.getContextPath());
650         executeMojo(
651                 plugin(
652                         groupId("com.atlassian.maven.plugins"),
653                         artifactId("atlassian-pdk"),
654                         version(pluginArtifactIdToVersionMap.get("atlassian-pdk"))
655                 ),
656                 goal("install"),
657                 configuration(
658                         element(name("pluginFile"), pdkParams.getPluginFile()),
659                         element(name("username"), pdkParams.getUsername()),
660                         element(name("password"), pdkParams.getPassword()),
661                         element(name("serverUrl"), baseUrl),
662                         element(name("pluginKey"), pdkParams.getPluginKey())
663                 ),
664                 executionEnvironment()
665         );
666     }
667 
668     public void uninstallPlugin(final String pluginKey, final String server, final int port, final String contextPath)
669             throws MojoExecutionException
670     {
671         final String baseUrl = getBaseUrl(server, port, contextPath);
672         executeMojo(
673                 plugin(
674                         groupId("com.atlassian.maven.plugins"),
675                         artifactId("atlassian-pdk"),
676                         version(pluginArtifactIdToVersionMap.get("atlassian-pdk"))
677                 ),
678                 goal("uninstall"),
679                 configuration(
680                         element(name("username"), "admin"),
681                         element(name("password"), "admin"),
682                         element(name("serverUrl"), baseUrl),
683                         element(name("pluginKey"), pluginKey)
684                 ),
685                 executionEnvironment()
686         );
687     }
688 
689     public void installIdeaPlugin() throws MojoExecutionException
690     {
691         executeMojo(
692                 plugin(
693                         groupId("org.twdata.maven"),
694                         artifactId("maven-cli-plugin"),
695                         version(pluginArtifactIdToVersionMap.get("maven-cli-plugin"))
696                 ),
697                 goal("idea"),
698                 configuration(),
699                 executionEnvironment()
700         );
701     }
702 
703     public File copyDist(final File targetDirectory, final ProductArtifact artifact) throws MojoExecutionException
704     {
705         return copyZip(targetDirectory, artifact, "test-dist.zip");
706     }
707 
708     public File copyHome(final File targetDirectory, final ProductArtifact artifact) throws MojoExecutionException
709     {
710         return copyZip(targetDirectory, artifact, artifact.getArtifactId() + ".zip");
711     }
712 
713     public File copyZip(final File targetDirectory, final ProductArtifact artifact, final String localName) throws MojoExecutionException
714     {
715         final File artifactZip = new File(targetDirectory, localName);
716         executeMojo(
717                 plugin(
718                         groupId("org.apache.maven.plugins"),
719                         artifactId("maven-dependency-plugin"),
720                         version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
721                 ),
722                 goal("copy"),
723                 configuration(
724                         element(name("artifactItems"),
725                                 element(name("artifactItem"),
726                                         element(name("groupId"), artifact.getGroupId()),
727                                         element(name("artifactId"), artifact.getArtifactId()),
728                                         element(name("type"), "zip"),
729                                         element(name("version"), artifact.getVersion()),
730                                         element(name("destFileName"), artifactZip.getName()))),
731                         element(name("outputDirectory"), artifactZip.getParent())
732                 ),
733                 executionEnvironment()
734         );
735         return artifactZip;
736     }
737 
738     public void generateManifest(final Map<String, String> instructions) throws MojoExecutionException
739     {
740         final List<Element> instlist = new ArrayList<Element>();
741         for (final Map.Entry<String, String> entry : instructions.entrySet())
742         {
743             instlist.add(element(entry.getKey(), entry.getValue()));
744         }
745         executeMojo(
746                 plugin(
747                         groupId("org.apache.felix"),
748                         artifactId("maven-bundle-plugin"),
749                         version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
750                 ),
751                 goal("manifest"),
752                 configuration(
753                         element(name("supportedProjectTypes"),
754                                 element(name("supportedProjectType"), "jar"),
755                                 element(name("supportedProjectType"), "bundle"),
756                                 element(name("supportedProjectType"), "war"),
757                                 element(name("supportedProjectType"), "atlassian-plugin")),
758                         element(name("instructions"), instlist.toArray(new Element[instlist.size()]))
759                 ),
760                 executionEnvironment()
761         );
762     }
763 
764     public void jarWithOptionalManifest(final boolean manifestExists) throws MojoExecutionException
765     {
766         Element[] archive = new Element[0];
767         if (manifestExists)
768         {
769             archive = new Element[]{element(name("manifestFile"), "${project.build.outputDirectory}/META-INF/MANIFEST.MF")};
770         }
771 
772         executeMojo(
773                 plugin(
774                         groupId("org.apache.maven.plugins"),
775                         artifactId("maven-jar-plugin"),
776                         version(defaultArtifactIdToVersionMap.get("maven-jar-plugin"))
777                 ),
778                 goal("jar"),
779                 configuration(
780                         element(name("archive"), archive)
781                 ),
782                 executionEnvironment()
783         );
784     }
785 
786     public void jarTests(String finalName) throws MojoExecutionException
787     {
788         executeMojo(
789                 plugin(
790                         groupId("org.apache.maven.plugins"),
791                         artifactId("maven-jar-plugin"),
792                         version(defaultArtifactIdToVersionMap.get("maven-jar-plugin"))
793                 ),
794                 goal("test-jar"),
795                 configuration(
796                         element(name("finalName"), finalName),
797                         element(name("archive"),
798                             element(name("manifestFile"), "${project.build.testOutputDirectory}/META-INF/MANIFEST.MF"))
799                 ),
800                 executionEnvironment()
801         );
802     }
803 
804     public void generateObrXml(File dep, File obrXml) throws MojoExecutionException
805     {
806         executeMojo(
807                 plugin(
808                         groupId("org.apache.felix"),
809                         artifactId("maven-bundle-plugin"),
810                         version(defaultArtifactIdToVersionMap.get("maven-bundle-plugin"))
811                 ),
812                 goal("install-file"),
813                 configuration(
814                         element(name("obrRepository"), obrXml.getPath()),
815 
816                         // the following three settings are required but not really used
817                         element(name("groupId"), "doesntmatter"),
818                         element(name("artifactId"), "doesntmatter"),
819                         element(name("version"), "doesntmatter"),
820 
821                         element(name("packaging"), "jar"),
822                         element(name("file"), dep.getPath())
823 
824                 ),
825                 executionEnvironment()
826         );
827     }
828 
829     private static class Container extends ProductArtifact
830     {
831         private final String id;
832         private final String type;
833 
834         /**
835          * Installable container that can be downloaded by Maven.
836          *
837          * @param id         identifier of container, eg. "tomcat5x".
838          * @param groupId    groupId of container.
839          * @param artifactId artifactId of container.
840          * @param version    version number of container.
841          */
842         public Container(final String id, final String groupId, final String artifactId, final String version)
843         {
844             super(groupId, artifactId, version);
845             this.id = id;
846             this.type = "installed";
847         }
848 
849         /**
850          * Embedded container packaged with Cargo.
851          *
852          * @param id identifier of container, eg. "jetty6x".
853          */
854         public Container(final String id)
855         {
856             this.id = id;
857             this.type = "embedded";
858         }
859 
860         /**
861          * @return identifier of container.
862          */
863         public String getId()
864         {
865             return id;
866         }
867 
868         /**
869          * @return "installed" or "embedded".
870          */
871         public String getType()
872         {
873             return type;
874         }
875 
876         /**
877          * @return <code>true</code> if the container type is "embedded".
878          */
879         public boolean isEmbedded()
880         {
881             return "embedded".equals(type);
882         }
883 
884         /**
885          * @param buildDir project.build.directory.
886          * @return root directory of the container that will house the container installation and configuration.
887          */
888         public String getRootDirectory(String buildDir)
889         {
890             return buildDir + File.separator + "container" + File.separator + getId();
891         }
892 
893         /**
894          * @param buildDir project.build.directory.
895          * @return directory housing the installed container.
896          */
897         public String getInstallDirectory(String buildDir)
898         {
899             return getRootDirectory(buildDir) + File.separator + getArtifactId() + "-" + getVersion();
900         }
901 
902         /**
903          * @param buildDir  project.build.directory.
904          * @param productId product name.
905          * @return directory to house the container configuration for the specified product.
906          */
907         public String getConfigDirectory(String buildDir, String productId)
908         {
909             return getRootDirectory(buildDir) + File.separator + "cargo-" + productId + "-home";
910         }
911     }
912 }