PageRenderTime 111ms CodeModel.GetById 14ms app.highlight 86ms 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

Large files files are truncated, but you can click here to view the full file

   1package com.atlassian.maven.plugins.amps;
   2
   3import java.io.File;
   4import java.io.FileFilter;
   5import java.io.FileOutputStream;
   6import java.io.IOException;
   7import java.net.ServerSocket;
   8import java.net.URL;
   9import java.net.URLClassLoader;
  10import java.util.*;
  11import java.util.jar.Manifest;
  12import java.util.regex.Matcher;
  13
  14import com.atlassian.maven.plugins.amps.util.*;
  15import com.atlassian.maven.plugins.amps.util.minifier.ResourcesMinifier;
  16
  17import com.google.common.base.Predicate;
  18import com.google.common.collect.Collections2;
  19import com.sun.jersey.wadl.resourcedoc.ResourceDocletJSON;
  20
  21import org.apache.commons.io.FileUtils;
  22import org.apache.commons.io.IOUtils;
  23import org.apache.commons.io.filefilter.FileFilterUtils;
  24import org.apache.commons.io.filefilter.IOFileFilter;
  25import org.apache.commons.io.filefilter.TrueFileFilter;
  26import org.apache.commons.lang.StringUtils;
  27import org.apache.maven.artifact.DependencyResolutionRequiredException;
  28import org.apache.maven.model.Dependency;
  29import org.apache.maven.model.Plugin;
  30import org.apache.maven.model.Resource;
  31import org.apache.maven.plugin.MojoExecutionException;
  32import org.apache.maven.plugin.logging.Log;
  33import org.apache.maven.project.MavenProject;
  34import org.codehaus.plexus.components.interactivity.PrompterException;
  35import org.codehaus.plexus.util.xml.Xpp3Dom;
  36import org.twdata.maven.mojoexecutor.MojoExecutor;
  37import org.twdata.maven.mojoexecutor.MojoExecutor.Element;
  38import org.twdata.maven.mojoexecutor.MojoExecutor.ExecutionEnvironment;
  39
  40import aQute.lib.osgi.Constants;
  41
  42import static com.atlassian.maven.plugins.amps.util.FileUtils.file;
  43import static com.atlassian.maven.plugins.amps.util.FileUtils.fixWindowsSlashes;
  44import static org.twdata.maven.mojoexecutor.MojoExecutor.artifactId;
  45import static org.twdata.maven.mojoexecutor.MojoExecutor.configuration;
  46import static org.twdata.maven.mojoexecutor.MojoExecutor.element;
  47import static org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo;
  48import static org.twdata.maven.mojoexecutor.MojoExecutor.goal;
  49import static org.twdata.maven.mojoexecutor.MojoExecutor.groupId;
  50import static org.twdata.maven.mojoexecutor.MojoExecutor.name;
  51import static org.twdata.maven.mojoexecutor.MojoExecutor.plugin;
  52import static org.twdata.maven.mojoexecutor.MojoExecutor.version;
  53
  54/**
  55 * Executes specific maven goals
  56 */
  57public class MavenGoals
  58{
  59    private final MavenContext ctx;
  60
  61    private final Log log;
  62    private final Map<String, String> pluginArtifactIdToVersionMap;
  63
  64    private final Map<String, Container> idToContainerMap = new HashMap<String, Container>()
  65    {{
  66            put("tomcat5x", new Container("tomcat5x", "org.apache.tomcat", "apache-tomcat", "5.5.26"));
  67            put("tomcat6x", new Container("tomcat6x", "org.apache.tomcat", "apache-tomcat", "6.0.20"));
  68            put("tomcat7x", new Container("tomcat7x", "org.apache.tomcat", "apache-tomcat", "7.0.32", "windows-x64"));
  69            put("resin3x", new Container("resin3x", "com.caucho", "resin", "3.0.26"));
  70            put("jboss42x", new Container("jboss42x", "org.jboss.jbossas", "jbossas", "4.2.3.GA"));
  71            put("jetty6x", new Container("jetty6x"));
  72        }};
  73
  74    private final Map<String, String> defaultArtifactIdToVersionMap = new HashMap<String, String>()
  75    {{
  76            put("maven-cli-plugin", "0.7");
  77            put("org.codehaus.cargo:cargo-maven2-plugin", "1.2.3");
  78            put("atlassian-pdk", "2.3.1");
  79            put("maven-archetype-plugin", "2.0-alpha-4");
  80            put("maven-bundle-plugin", "2.3.7");
  81            put("yuicompressor-maven-plugin", "1.3.0");
  82            put("build-helper-maven-plugin", "1.7");
  83
  84            // You can't actually override the version a plugin if defined in the project, so these don't actually do
  85            // anything, since the super pom already defines versions.
  86            put("maven-dependency-plugin", "2.5.1");
  87            put("maven-resources-plugin", "2.3");
  88            put("maven-jar-plugin", "2.2");
  89            //put("maven-surefire-plugin", "2.4.3");
  90            put("maven-surefire-plugin", "2.12.4");
  91            put("maven-failsafe-plugin", "2.9");
  92            put("maven-exec-plugin", "1.2.1");
  93
  94        }};
  95
  96    public MavenGoals(final MavenContext ctx)
  97    {
  98        this.ctx = ctx;
  99
 100        this.log = ctx.getLog();
 101
 102        this.pluginArtifactIdToVersionMap = Collections.unmodifiableMap(defaultArtifactIdToVersionMap);
 103    }
 104
 105    private ExecutionEnvironment executionEnvironment()
 106    {
 107        return ctx.getExecutionEnvironment();
 108    }
 109
 110    public MavenProject getContextProject()
 111    {
 112        return ctx.getProject();
 113    }
 114
 115    public void executeAmpsRecursively(final String ampsVersion, final String ampsGoal, Xpp3Dom cfg) throws MojoExecutionException
 116    {
 117        executeMojo(
 118            plugin(
 119                groupId("com.atlassian.maven.plugins"),
 120                artifactId("maven-amps-plugin"),
 121                version(ampsVersion)
 122            ),
 123            goal(ampsGoal),
 124            cfg,
 125            executionEnvironment());
 126    }
 127
 128    public void startCli(final PluginInformation pluginInformation, final int port) throws MojoExecutionException
 129    {
 130        final String pluginId = pluginInformation.getId();
 131
 132        final List<Element> configs = new ArrayList<Element>();
 133        configs.add(element(name("commands"),
 134                element(name("pi"),
 135                        "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
 136                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:compress-resources" + " "
 137                                + "org.apache.maven.plugins:maven-resources-plugin:resources" + " "
 138                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
 139                                + "compile" + " "
 140                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
 141                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-manifest" + " "
 142                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " "
 143                                + "org.apache.maven.plugins:maven-install-plugin:install" + " "
 144                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:install"),
 145                element(name("tpi"),
 146                        "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
 147                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:compress-resources" + " "
 148                                + "org.apache.maven.plugins:maven-resources-plugin:resources" + " "
 149                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
 150                                + "compile" + " "
 151                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
 152                                + "org.apache.maven.plugins:maven-resources-plugin:testResources" + " "
 153                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-test-plugin-descriptor" + " "
 154                                +"com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-test-bundled-dependencies" + " "
 155                                + "org.apache.maven.plugins:maven-compiler-plugin:testCompile" + " "
 156                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-test-manifest" + " "
 157                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-manifest" + " "
 158                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:validate-test-manifest" + " "
 159                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " "
 160                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-jar" + " "
 161                                + "org.apache.maven.plugins:maven-install-plugin:install" + " "
 162                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:install" + " "
 163                                + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:test-install"),
 164                element(name("package"),
 165                        "org.apache.maven.plugins:maven-resources-plugin:resources" + " "
 166                        + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:filter-plugin-descriptor" + " "
 167                        + "compile" + " "
 168                        + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:copy-bundled-dependencies" + " "
 169                        + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:generate-manifest" + " "
 170                        + "com.atlassian.maven.plugins:maven-" + pluginId + "-plugin:jar" + " ")));
 171        if (port > 0)
 172        {
 173            configs.add(element(name("port"), String.valueOf(port)));
 174        }
 175        executeMojo(
 176                plugin(
 177                        groupId("org.twdata.maven"),
 178                        artifactId("maven-cli-plugin"),
 179                        version(pluginArtifactIdToVersionMap.get("maven-cli-plugin"))
 180                ),
 181                goal("execute"),
 182                configuration(configs.toArray(new Element[0])),
 183                executionEnvironment());
 184    }
 185
 186    public void createPlugin(final String productId, AmpsCreatePluginPrompter createPrompter) throws MojoExecutionException
 187    {
 188        CreatePluginProperties props = null;
 189        Properties systemProps = System.getProperties();
 190
 191        if(systemProps.containsKey("groupId")
 192                && systemProps.containsKey("artifactId")
 193                && systemProps.containsKey("version")
 194                && systemProps.containsKey("package")
 195                )
 196        {
 197            props = new CreatePluginProperties(systemProps.getProperty("groupId")
 198                    ,systemProps.getProperty("artifactId")
 199                    ,systemProps.getProperty("version")
 200                    ,systemProps.getProperty("package")
 201                    );
 202        }
 203
 204        if(null == props)
 205        {
 206            try
 207            {
 208                props = createPrompter.prompt();
 209            }
 210            catch (PrompterException e)
 211            {
 212                throw new MojoExecutionException("Unable to gather properties",e);
 213            }
 214        }
 215
 216        if(null != props)
 217        {
 218            ExecutionEnvironment execEnv = executionEnvironment();
 219
 220            Properties sysProps = execEnv.getMavenSession().getExecutionProperties();
 221            sysProps.setProperty("groupId",props.getGroupId());
 222            sysProps.setProperty("artifactId",props.getArtifactId());
 223            sysProps.setProperty("version",props.getVersion());
 224            sysProps.setProperty("package",props.getThePackage());
 225
 226            executeMojo(
 227                    plugin(
 228                            groupId("org.apache.maven.plugins"),
 229                            artifactId("maven-archetype-plugin"),
 230                            version(defaultArtifactIdToVersionMap.get("maven-archetype-plugin"))
 231                    ),
 232                    goal("generate"),
 233                    configuration(
 234                            element(name("archetypeGroupId"), "com.atlassian.maven.archetypes"),
 235                            element(name("archetypeArtifactId"), (productId.equals("all") ? "" : productId + "-") + "plugin-archetype"),
 236                            element(name("archetypeVersion"), VersionUtils.getVersion()),
 237                            element(name("interactiveMode"), "false")
 238                    ),
 239                    execEnv);
 240
 241            File pluginDir = new File(ctx.getProject().getBasedir(),props.getArtifactId());
 242
 243            if(pluginDir.exists())
 244            {
 245                File src = new File(pluginDir,"src");
 246                File test = new File(src,"test");
 247                File java = new File(test,"java");
 248
 249                String packagePath = props.getThePackage().replaceAll("\\.", Matcher.quoteReplacement(File.separator));
 250                File packageFile = new File(java,packagePath);
 251                File packageUT = new File(packageFile,"ut");
 252                File packageIT = new File(packageFile,"it");
 253
 254                File ut = new File(new File(java,"ut"),packagePath);
 255                File it = new File(new File(java,"it"),packagePath);
 256
 257                if(packageFile.exists())
 258                {
 259                    try
 260                    {
 261                        if(packageUT.exists())
 262                        {
 263                            FileUtils.copyDirectory(packageUT, ut);
 264                        }
 265
 266                        if(packageIT.exists())
 267                        {
 268                            FileUtils.copyDirectory(packageIT, it);
 269                        }
 270
 271                        IOFileFilter filter = FileFilterUtils.and(FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("it")),FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("ut")));
 272
 273                        com.atlassian.maven.plugins.amps.util.FileUtils.cleanDirectory(java,filter);
 274
 275                    }
 276                    catch (IOException e)
 277                    {
 278                        //for now just ignore
 279                    }
 280                }
 281            }
 282        }
 283    }
 284
 285    public void copyBundledDependencies() throws MojoExecutionException
 286    {
 287        executeMojo(
 288                plugin(
 289                        groupId("org.apache.maven.plugins"),
 290                        artifactId("maven-dependency-plugin"),
 291                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 292                ),
 293                goal("copy-dependencies"),
 294                configuration(
 295                        element(name("includeScope"), "runtime"),
 296                        element(name("excludeScope"), "provided"),
 297                        element(name("excludeScope"), "test"),
 298                        element(name("includeTypes"), "jar"),
 299                        element(name("outputDirectory"), "${project.build.outputDirectory}/META-INF/lib")
 300                ),
 301                executionEnvironment()
 302        );
 303    }
 304
 305    public void copyTestBundledDependencies(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
 306    {
 307        StringBuilder sb = new StringBuilder();
 308
 309        for(ProductArtifact artifact : testBundleExcludes)
 310        {
 311            log.info("excluding artifact from test jar: " + artifact.getArtifactId());
 312                sb.append(",").append(artifact.getArtifactId());
 313        }
 314
 315        String customExcludes = sb.toString();
 316
 317        executeMojo(
 318                plugin(
 319                        groupId("org.apache.maven.plugins"),
 320                        artifactId("maven-dependency-plugin"),
 321                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 322                ),
 323                goal("copy-dependencies"),
 324                configuration(
 325                        element(name("includeScope"), "test"),
 326                        element(name("excludeScope"), "provided"),
 327                        element(name("excludeArtifactIds"),"junit" + customExcludes),
 328                        element(name("useSubDirectoryPerScope"),"true"),
 329                        element(name("outputDirectory"), "${project.build.directory}/testlibs")
 330                ),
 331                executionEnvironment()
 332        );
 333
 334        File targetDir = new File(ctx.getProject().getBuild().getDirectory());
 335        File testlibsDir = new File(targetDir,"testlibs");
 336        File compileLibs = new File(testlibsDir,"compile");
 337        File testLibs = new File(testlibsDir,"test");
 338
 339
 340        File testClassesDir = new File(ctx.getProject().getBuild().getTestOutputDirectory());
 341        File metainfDir = new File(testClassesDir,"META-INF");
 342        File libDir = new File(metainfDir,"lib");
 343
 344        try
 345        {
 346            compileLibs.mkdirs();
 347            testLibs.mkdirs();
 348            libDir.mkdirs();
 349
 350            FileUtils.copyDirectory(compileLibs,libDir);
 351            FileUtils.copyDirectory(testLibs,libDir);
 352        }
 353        catch (IOException e)
 354        {
 355            throw new MojoExecutionException("unable to copy test libs", e);
 356        }
 357
 358    }
 359
 360    public void copyTestBundledDependenciesExcludingTestScope(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
 361    {
 362        StringBuilder sb = new StringBuilder();
 363
 364        for(ProductArtifact artifact : testBundleExcludes)
 365        {
 366            log.info("excluding artifact from test jar: " + artifact.getArtifactId());
 367            sb.append(",").append(artifact.getArtifactId());
 368        }
 369
 370        String customExcludes = sb.toString();
 371
 372        executeMojo(
 373                plugin(
 374                        groupId("org.apache.maven.plugins"),
 375                        artifactId("maven-dependency-plugin"),
 376                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 377                ),
 378                goal("copy-dependencies"),
 379                configuration(
 380                        element(name("includeScope"), "runtime"),
 381                        element(name("excludeScope"), "provided"),
 382                        element(name("excludeScope"), "test"),
 383                        element(name("includeTypes"), "jar"),
 384                        element(name("excludeArtifactIds"),"junit" + customExcludes),
 385                        element(name("outputDirectory"), "${project.build.testOutputDirectory}/META-INF/lib")
 386                ),
 387                executionEnvironment()
 388        );
 389    }
 390
 391    public void extractBundledDependencies() throws MojoExecutionException
 392    {
 393         executeMojo(
 394                 plugin(
 395                        groupId("org.apache.maven.plugins"),
 396                        artifactId("maven-dependency-plugin"),
 397                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 398                ),
 399                goal("unpack-dependencies"),
 400                configuration(
 401                        element(name("includeScope"), "runtime"),
 402                        element(name("excludeScope"), "provided"),
 403                        element(name("excludeScope"), "test"),
 404                        element(name("includeTypes"), "jar"),
 405                        element(name("excludes"), "META-INF/MANIFEST.MF, META-INF/*.DSA, META-INF/*.SF"),
 406                        element(name("outputDirectory"), "${project.build.outputDirectory}")
 407                ),
 408                executionEnvironment()
 409        );
 410    }
 411
 412    public void extractTestBundledDependenciesExcludingTestScope(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
 413    {
 414        StringBuilder sb = new StringBuilder();
 415
 416        for(ProductArtifact artifact : testBundleExcludes)
 417        {
 418            sb.append(",").append(artifact.getArtifactId());
 419        }
 420
 421        String customExcludes = sb.toString();
 422
 423        executeMojo(
 424                plugin(
 425                        groupId("org.apache.maven.plugins"),
 426                        artifactId("maven-dependency-plugin"),
 427                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 428                ),
 429                goal("unpack-dependencies"),
 430                configuration(
 431                        element(name("includeScope"), "runtime"),
 432                        element(name("excludeScope"), "provided"),
 433                        element(name("excludeScope"), "test"),
 434                        element(name("includeTypes"), "jar"),
 435                        element(name("excludeArtifactIds"),"junit" + customExcludes),
 436                        element(name("excludes"), "META-INF/MANIFEST.MF, META-INF/*.DSA, META-INF/*.SF"),
 437                        element(name("outputDirectory"), "${project.build.testOutputDirectory}")
 438                ),
 439                executionEnvironment()
 440        );
 441    }
 442
 443    public void extractTestBundledDependencies(List<ProductArtifact> testBundleExcludes) throws MojoExecutionException
 444    {
 445        StringBuilder sb = new StringBuilder();
 446
 447        for(ProductArtifact artifact : testBundleExcludes)
 448        {
 449            sb.append(",").append(artifact.getArtifactId());
 450        }
 451
 452        String customExcludes = sb.toString();
 453
 454        executeMojo(
 455                plugin(
 456                        groupId("org.apache.maven.plugins"),
 457                        artifactId("maven-dependency-plugin"),
 458                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 459                ),
 460                goal("unpack-dependencies"),
 461                configuration(
 462                        element(name("includeScope"), "test"),
 463                        element(name("excludeScope"), "provided"),
 464                        element(name("excludeArtifactIds"),"junit" + customExcludes),
 465                        element(name("includeTypes"), "jar"),
 466                        element(name("useSubDirectoryPerScope"),"true"),
 467                        element(name("outputDirectory"), "${project.build.directory}/testlibs")
 468                ),
 469                executionEnvironment()
 470        );
 471
 472        File targetDir = new File(ctx.getProject().getBuild().getDirectory());
 473        File testlibsDir = new File(targetDir,"testlibs");
 474        File compileLibs = new File(testlibsDir,"compile");
 475        File testLibs = new File(testlibsDir,"test");
 476
 477
 478        File testClassesDir = new File(ctx.getProject().getBuild().getTestOutputDirectory());
 479
 480        try
 481        {
 482            compileLibs.mkdirs();
 483            testLibs.mkdirs();
 484
 485            FileUtils.copyDirectory(compileLibs,testClassesDir,FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("META-INF")));
 486            FileUtils.copyDirectory(testLibs,testClassesDir,FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("META-INF")));
 487        }
 488        catch (IOException e)
 489        {
 490            throw new MojoExecutionException("unable to copy test libs", e);
 491        }
 492    }
 493
 494    public void compressResources(boolean useClosureForJs) throws MojoExecutionException
 495    {
 496
 497        ResourcesMinifier.minify(ctx.getProject().getBuild().getResources(), new File(ctx.getProject().getBuild().getOutputDirectory()), useClosureForJs, log);
 498        /*
 499        executeMojo(
 500                plugin(
 501                        groupId("net.alchim31.maven"),
 502                        artifactId("yuicompressor-maven-plugin"),
 503                        version(defaultArtifactIdToVersionMap.get("yuicompressor-maven-plugin"))
 504                ),
 505                goal("compress"),
 506                configuration(
 507                        element(name("suffix"), "-min"),
 508                        element(name("jswarn"), "false")
 509                ),
 510                executionEnvironment()
 511        );
 512        */
 513    }
 514
 515    public void filterPluginDescriptor() throws MojoExecutionException
 516    {
 517        executeMojo(
 518                plugin(
 519                        groupId("org.apache.maven.plugins"),
 520                        artifactId("maven-resources-plugin"),
 521                        version(defaultArtifactIdToVersionMap.get("maven-resources-plugin"))
 522                ),
 523                goal("copy-resources"),
 524                configuration(
 525                        element(name("encoding"), "UTF-8"),
 526                        element(name("resources"),
 527                                element(name("resource"),
 528                                        element(name("directory"), "src/main/resources"),
 529                                        element(name("filtering"), "true"),
 530                                        element(name("includes"),
 531                                                element(name("include"), "atlassian-plugin.xml"))
 532                                )
 533                        ),
 534                        element(name("outputDirectory"), "${project.build.outputDirectory}")
 535                ),
 536                executionEnvironment()
 537        );
 538    }
 539
 540    public void filterTestPluginDescriptor() throws MojoExecutionException
 541    {
 542        executeMojo(
 543                plugin(
 544                        groupId("org.apache.maven.plugins"),
 545                        artifactId("maven-resources-plugin"),
 546                        version(defaultArtifactIdToVersionMap.get("maven-resources-plugin"))
 547                ),
 548                goal("copy-resources"),
 549                configuration(
 550                        element(name("encoding"), "UTF-8"),
 551                        element(name("resources"),
 552                                element(name("resource"),
 553                                        element(name("directory"), "src/test/resources"),
 554                                        element(name("filtering"), "true"),
 555                                        element(name("includes"),
 556                                                element(name("include"), "atlassian-plugin.xml"))
 557                                )
 558                        ),
 559                        element(name("outputDirectory"), "${project.build.testOutputDirectory}")
 560                ),
 561                executionEnvironment()
 562        );
 563
 564    }
 565
 566    public void runUnitTests(Map<String, Object> systemProperties) throws MojoExecutionException {
 567        runUnitTests(systemProperties, null);
 568    }
 569
 570    public void runUnitTests(Map<String, Object> systemProperties, String excludedGroups) throws MojoExecutionException
 571    {
 572        final Element systemProps = convertPropsToElements(systemProperties);
 573        Xpp3Dom config = configuration(
 574                systemProps,
 575                element(name("excludes"),
 576                        element(name("exclude"), "it/**"),
 577                        element(name("exclude"), "**/*$*")),
 578
 579                element(name("excludedGroups"), excludedGroups)
 580        );
 581
 582        log.info("surefire unit-test configuration:");
 583        log.info(config.toString());
 584
 585        executeMojo(
 586                plugin(
 587                        groupId("org.apache.maven.plugins"),
 588                        artifactId("maven-surefire-plugin"),
 589                        version(defaultArtifactIdToVersionMap.get("maven-surefire-plugin"))
 590                ),
 591                goal("test"),
 592                config,
 593                executionEnvironment()
 594        );
 595    }
 596
 597    public File copyWebappWar(final String productId, final File targetDirectory, final ProductArtifact artifact)
 598            throws MojoExecutionException
 599    {
 600        final File webappWarFile = new File(targetDirectory, productId + "-original.war");
 601        executeMojo(
 602                plugin(
 603                        groupId("org.apache.maven.plugins"),
 604                        artifactId("maven-dependency-plugin"),
 605                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 606                ),
 607                goal("copy"),
 608                configuration(
 609                        element(name("artifactItems"),
 610                                element(name("artifactItem"),
 611                                        element(name("groupId"), artifact.getGroupId()),
 612                                        element(name("artifactId"), artifact.getArtifactId()),
 613                                        element(name("type"), "war"),
 614                                        element(name("version"), artifact.getVersion()),
 615                                        element(name("destFileName"), webappWarFile.getName()))),
 616                        element(name("outputDirectory"), targetDirectory.getPath())
 617                ),
 618                executionEnvironment()
 619        );
 620        return webappWarFile;
 621    }
 622
 623    public File copyArtifact(final String targetFileName, final File targetDirectory,
 624                             final ProductArtifact artifact, String type) throws MojoExecutionException
 625    {
 626        final File targetFile = new File(targetDirectory, targetFileName);
 627        executeMojo(
 628                plugin(
 629                        groupId("org.apache.maven.plugins"),
 630                        artifactId("maven-dependency-plugin"),
 631                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 632                ),
 633                goal("copy"),
 634                configuration(
 635                        element(name("artifactItems"),
 636                                element(name("artifactItem"),
 637                                        element(name("groupId"), artifact.getGroupId()),
 638                                        element(name("artifactId"), artifact.getArtifactId()),
 639                                        element(name("type"), type),
 640                                        element(name("version"), artifact.getVersion()),
 641                                        element(name("destFileName"), targetFile.getName()))),
 642                        element(name("outputDirectory"), targetDirectory.getPath())
 643                ),
 644                executionEnvironment()
 645        );
 646        return targetFile;
 647    }
 648
 649    /**
 650     * Copies {@code artifacts} to the {@code outputDirectory}. Artifacts are looked up in order: <ol> <li>in the maven
 651     * reactor</li> <li>in the maven repositories</li> </ol> This can't be used in a goal that happens before the
 652     * <em>package</em> phase as artifacts in the reactor will be not be packaged (and therefore 'copiable') until this
 653     * phase.
 654     *
 655     * @param outputDirectory the directory to copy artifacts to
 656     * @param artifacts       the list of artifact to copy to the given directory
 657     */
 658    public void copyPlugins(final File outputDirectory, final List<ProductArtifact> artifacts)
 659            throws MojoExecutionException
 660    {
 661        for (ProductArtifact artifact : artifacts)
 662        {
 663            final MavenProject artifactReactorProject = getReactorProjectForArtifact(artifact);
 664            if (artifactReactorProject != null)
 665            {
 666
 667                log.debug(artifact + " will be copied from reactor project " + artifactReactorProject);
 668                final File artifactFile = artifactReactorProject.getArtifact().getFile();
 669                if (artifactFile == null)
 670                {
 671                    log.warn("The plugin " + artifact + " is in the reactor but not the file hasn't been attached.  Skipping.");
 672                }
 673                else
 674                {
 675                    log.debug("Copying " + artifactFile + " to " + outputDirectory);
 676                    try
 677                    {
 678                        FileUtils.copyFile(artifactFile, new File(outputDirectory, artifactFile.getName()));
 679                    }
 680                    catch (IOException e)
 681                    {
 682                        throw new MojoExecutionException("Could not copy " + artifact + " to " + outputDirectory, e);
 683                    }
 684                }
 685
 686            }
 687            else
 688            {
 689                executeMojo(
 690                        plugin(
 691                                groupId("org.apache.maven.plugins"),
 692                                artifactId("maven-dependency-plugin"),
 693                                version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 694                        ),
 695                        goal("copy"),
 696                        configuration(
 697                                element(name("artifactItems"),
 698                                        element(name("artifactItem"),
 699                                                element(name("groupId"), artifact.getGroupId()),
 700                                                element(name("artifactId"), artifact.getArtifactId()),
 701                                                element(name("version"), artifact.getVersion()))),
 702                                element(name("outputDirectory"), outputDirectory.getPath())
 703                        ),
 704                        executionEnvironment());
 705            }
 706        }
 707    }
 708
 709    private MavenProject getReactorProjectForArtifact(ProductArtifact artifact)
 710    {
 711        for (final MavenProject project : ctx.getReactor())
 712        {
 713            if (project.getGroupId().equals(artifact.getGroupId())
 714                    && project.getArtifactId().equals(artifact.getArtifactId())
 715                    && project.getVersion().equals(artifact.getVersion()))
 716            {
 717                return project;
 718            }
 719        }
 720        return null;
 721    }
 722
 723    private void unpackContainer(final Container container) throws MojoExecutionException
 724    {
 725        executeMojo(
 726                plugin(
 727                        groupId("org.apache.maven.plugins"),
 728                        artifactId("maven-dependency-plugin"),
 729                        version(defaultArtifactIdToVersionMap.get("maven-dependency-plugin"))
 730                ),
 731                goal("unpack"),
 732                configuration(
 733                        element(name("artifactItems"),
 734                                element(name("artifactItem"),
 735                                        element(name("groupId"), container.getGroupId()),
 736                                        element(name("artifactId"), container.getArtifactId()),
 737                                        element(name("version"), container.getVersion()),
 738                                        element(name("classifier"), container.getClassifier()),
 739                                        element(name("type"), "zip"))),
 740                        element(name("outputDirectory"), container.getRootDirectory(getBuildDirectory()))
 741                ),
 742                executionEnvironment());
 743    }
 744
 745    private String getBuildDirectory()
 746    {
 747        return ctx.getProject().getBuild().getDirectory();
 748    }
 749
 750    private static Xpp3Dom configurationWithoutNullElements(Element... elements)
 751    {
 752        List<Element> nonNullElements = new ArrayList<Element>();
 753        for (Element e : elements)
 754        {
 755            if (e != null)
 756            {
 757                nonNullElements.add(e);
 758            }
 759        }
 760
 761        return configuration(nonNullElements.toArray(new Element[nonNullElements.size()]));
 762    }
 763
 764    public int startWebapp(final String productInstanceId, final File war, final Map<String, String> systemProperties, final List<ProductArtifact> extraContainerDependencies,
 765                           final Product webappContext) throws MojoExecutionException
 766    {
 767        final Container container = findContainer(webappContext.getContainerId());
 768        File containerDir = new File(container.getRootDirectory(getBuildDirectory()));
 769
 770        // retrieve non-embedded containers
 771        if (!container.isEmbedded())
 772        {
 773            if (containerDir.exists())
 774            {
 775                log.info("Reusing unpacked container '" + container.getId() + "' from " + containerDir.getPath());
 776            }
 777            else
 778            {
 779                log.info("Unpacking container '" + container.getId() + "' from container artifact: " + container.toString());
 780                unpackContainer(container);
 781            }
 782        }
 783
 784        final int rmiPort = pickFreePort(0);
 785        int actualHttpPort;
 786        String protocol = "http";
 787
 788        if(webappContext.getUseHttps())
 789        {
 790            actualHttpPort = 443;
 791            protocol = "https";
 792        }
 793        else
 794        {
 795            actualHttpPort = pickFreePort(webappContext.getHttpPort());
 796        }
 797
 798        final List<Element> sysProps = new ArrayList<Element>();
 799
 800        for (final Map.Entry<String, String> entry : systemProperties.entrySet())
 801        {
 802            sysProps.add(element(name(entry.getKey()), entry.getValue()));
 803        }
 804        log.info("Starting " + productInstanceId + " on the " + container.getId() + " container on ports "
 805                + actualHttpPort + " (" + protocol + ") and " + rmiPort + " (rmi)");
 806
 807        final String baseUrl = getBaseUrl(webappContext, actualHttpPort);
 808        sysProps.add(element(name("baseurl"), baseUrl));
 809
 810        final List<Element> deps = new ArrayList<Element>();
 811        for (final ProductArtifact dep : extraContainerDependencies)
 812        {
 813            deps.add(element(name("dependency"),
 814                    element(name("location"), webappContext.getArtifactRetriever().resolve(dep))
 815            ));
 816        }
 817
 818        for (DataSource dataSource : webappContext.getDataSources())
 819        {
 820            for (ProductArtifact containerDependency : dataSource.getLibArtifacts())
 821            {
 822                deps.add(element(name("dependency"),
 823                        element(name("location"), webappContext.getArtifactRetriever().resolve(containerDependency))
 824                        ));
 825            }
 826        }
 827
 828        final List<Element> props = new ArrayList<Element>();
 829        for (final Map.Entry<String, String> entry : systemProperties.entrySet())
 830        {
 831            props.add(element(name(entry.getKey()), entry.getValue()));
 832        }
 833        props.add(element(name("cargo.servlet.port"), String.valueOf(actualHttpPort)));
 834
 835        if(webappContext.getUseHttps())
 836        {
 837            props.add(element(name("cargo.protocol"), protocol));
 838        }
 839
 840        props.add(element(name("cargo.rmi.port"), String.valueOf(rmiPort)));
 841        props.add(element(name("cargo.jvmargs"), webappContext.getJvmArgs()));
 842
 843        int startupTimeout = webappContext.getStartupTimeout();
 844        if (Boolean.FALSE.equals(webappContext.getSynchronousStartup()))
 845        {
 846            startupTimeout = 0;
 847        }
 848
 849        Plugin cargo = cargo(webappContext);
 850
 851        executeMojo(
 852                cargo,
 853                goal("start"),
 854                configurationWithoutNullElements(
 855                        element(name("deployables"),
 856                                element(name("deployable"),
 857                                        element(name("groupId"), "foo"),
 858                                        element(name("artifactId"), "bar"),
 859                                        element(name("type"), "war"),
 860                                        element(name("location"), war.getPath()),
 861                                        element(name("properties"),
 862                                                element(name("context"), webappContext.getContextPath())
 863                                        )
 864                                )
 865                        ),
 866                        waitElement(cargo), // This may be null
 867                        element(name("container"),
 868                                element(name("containerId"), container.getId()),
 869                                element(name("type"), container.getType()),
 870                                element(name("home"), container.getInstallDirectory(getBuildDirectory())),
 871                                element(name("output"), webappContext.getOutput()),
 872                                element(name("systemProperties"), sysProps.toArray(new Element[sysProps.size()])),
 873                                element(name("dependencies"), deps.toArray(new Element[deps.size()])),
 874                                element(name("timeout"), String.valueOf(startupTimeout))
 875                        ),
 876                        element(name("configuration"),
 877                                element(name("home"), container.getConfigDirectory(getBuildDirectory(), productInstanceId)),
 878                                element(name("type"), "standalone"),
 879                                element(name("properties"), props.toArray(new Element[props.size()]))
 880
 881                        )
 882                ),
 883                executionEnvironment()
 884        );
 885        return actualHttpPort;
 886    }
 887
 888    public void stopWebapp(final String productId, final String containerId, final Product webappContext) throws MojoExecutionException
 889    {
 890        final Container container = findContainer(containerId);
 891
 892        String actualShutdownTimeout = webappContext.getSynchronousStartup() ? "0" : String.valueOf(webappContext.getShutdownTimeout());
 893
 894        executeMojo(
 895        cargo(webappContext),
 896        goal("stop"),
 897        configuration(
 898             element(name("container"),
 899                     element(name("containerId"), container.getId()),
 900                     element(name("type"), container.getType()),
 901                     element(name("timeout"), actualShutdownTimeout),
 902                     // org.codehaus.cargo
 903                     element(name("home"), container.getInstallDirectory(getBuildDirectory()))
 904             ),
 905             element(name("configuration"),
 906                     // org.twdata.maven
 907                     element(name("home"), container.getConfigDirectory(getBuildDirectory(), productId))/*,
 908                     // we don't need that atm. since timeout is 0 for org.codehaus.cargo
 909                     element(name("properties"), createShutdownPortsPropertiesConfiguration(webappContext)) */
 910             )
 911        ),
 912        executionEnvironment()
 913        );
 914    }
 915
 916    /**
 917     * Cargo waits (org.codehaus.cargo.container.tomcat.internal.AbstractCatalinaInstalledLocalContainer#waitForCompletion(boolean waitForStarting)) for 3 ports, but the AJP and RMI ports may
 918     * not be correct (see below), so we configure it to wait on the HTTP port only.
 919     *
 920     * 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)
 921     * which means that this port might have been taken by a different application (the container will still come up though, see
 922     * "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
 923     * is shut down.
 924     *
 925     * 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
 926     * 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.
 927     * 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.
 928     *
 929     * 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
 930     * 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
 931     * order to skip the wait.
 932     */
 933    private Element[] createShutdownPortsPropertiesConfiguration(final Product webappContext)
 934    {
 935        final List<Element> properties = new ArrayList<Element>();
 936        String portUsedToDetermineIfShutdownSucceeded = String.valueOf(webappContext.getHttpPort());
 937        properties.add(element(name("cargo.servlet.port"), portUsedToDetermineIfShutdownSucceeded));
 938        properties.add(element(name("cargo.rmi.port"), portUsedToDetermineIfShutdownSucceeded));
 939        properties.add(element(name("cargo.tomcat.ajp.port"), portUsedToDetermineIfShutdownSucceeded));
 940        return properties.toArray(new Element[properties.size()]);
 941    }
 942
 943    /**
 944     * THIS USED TO Decide whether to use the org.twdata.maven.cargo-maven2-plugin or the org.codehaus.cargo.cargo-maven2-plugin.
 945     * <p/>
 946     * 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.
 947     */
 948    private Plugin cargo(Product context)
 949    {
 950        log.info("using codehaus cargo v" + pluginArtifactIdToVersionMap.get("org.codehaus.cargo:cargo-maven2-plugin"));
 951        return plugin(
 952                groupId("org.codehaus.cargo"),
 953                artifactId("cargo-maven2-plugin"),
 954                version(pluginArtifactIdToVersionMap.get("org.codehaus.cargo:cargo-maven2-plugin")));
 955    }
 956
 957    private Element waitElement(Plugin cargo)
 958    {
 959        if (cargo.getGroupId().equals("org.twdata.maven"))
 960        {
 961            return element(name("wait"), "false");
 962        }
 963        // If not using twdata's cargo, we avoid passing wait=false, because it's the default and it generates
 964        // a deprecation warning
 965        return null;
 966    }
 967
 968    public static String getBaseUrl(Product product, int actualHttpPort)
 969    {
 970        return getBaseUrl(product.getServer(), product.getHttpPort(), product.getContextPath());
 971    }
 972
 973    private static String getBaseUrl(String server, int actualHttpPort, String contextPath)
 974    {
 975        String port = actualHttpPort != 80 ? ":" + actualHttpPort : "";
 976        server = server.startsWith("http") ? server : "http://" + server;
 977        if (!contextPath.startsWith("/") && StringUtils.isNotBlank(contextPath))
 978        {
 979            contextPath = "/" + contextPath;
 980        }
 981        return server + port + contextPath;
 982    }
 983
 984    public void runIntegrationTests(String testGroupId, String containerId, List<String> includes, List<String> excludes, Map<String, Object> systemProperties, final File targetDirectory)
 985    		throws MojoExecutionException
 986	{
 987    	List<Element> includeElements = new ArrayList<Element>(includes.size());
 988    	for (String include : includes)
 989    	{
 990    		includeElements.add(element(name("include"), include));
 991    	}
 992
 993        List<Element> excludeElements = new ArrayList<Element>(excludes.size() + 2);
 994        excludeElements.add(element(name("exclude"), "**/*$*"));
 995        excludeElements.add(element(name("exclude"), "**/Abstract*"));
 996        for (String exclude : excludes)
 997        {
 998        	excludeElements.add(element(name("exclude"), exclude));
 999        }
1000
1001        final String testOutputDir = targetDirectory.getAbsolutePath() + "/" + testGroupId + "/" + containerId + "/surefire-reports";
1002        final String reportsDirectory = "reportsDirectory";
1003        systemProperties.put(reportsDirectory, testOutputDir);
1004
1005        final Element systemProps = convertPropsToElements(systemProperties);
1006        final Xpp3Dom itconfig = configuration(
1007                element(name("includes"),
1008                        includeElements.toArray(new Element[includeElements.size()])
1009                ),
1010                element(name("excludes"),
1011                        excludeElements.toArray(new Element[excludeElements.size()])
1012                ),
1013                systemProps,
1014                element(name(reportsDirectory), testOutputDir)
1015        );
1016
1017        final Xpp3Dom verifyconfig = configuration(element(name(reportsDirectory), testOutputDir));
1018
1019        log.info("Failsafe integration-test configuration:");
1020        log.info(itconfig.toString());
1021
1022        executeMojo(
1023                plugin(
1024                        groupId("org.apache.maven.plugins"),
1025                        artifactId("maven-failsafe-plugin"),
1026                        version(defaultArtifactIdToVersionMap.get("maven-failsafe-plugin"))
1027                ),
1028                goal("integration-test"),
1029                itconfig,
1030                executionEnvironment()
1031        );
1032
1033        executeMojo(
1034                plugin(
1035                        groupId("org.apache.maven.plugins"),
1036                        artifactId("maven-failsafe-plugin"),
1037                        version(defaultArtifactIdToVersionMap.get("maven-failsafe-plugin"))
1038                ),
1039                goal("verify"),
1040                verifyconfig,
1041                executionEnvironment()
1042        );
1043	}
1044
1045    /**
1046     * Converts a map of System properties to maven config elements
1047     */
1048    private Element convertPropsToElements(Map<String, Object> systemProperties)
1049    {
1050        ArrayList<Element> properties = new ArrayList<Element>();
1051
1052        /*
1053        OLD surefire 2.4.3 style
1054
1055        // add extra system properties... overwriting any of the hard coded values above.
1056        for (Map.Entry<String, Object> entry: systemProperties.entrySet())
1057        {
1058            properties.add(
1059                    element(name("property"),
1060                            element(name("name"), entry.getKey()),
1061                            element(name("value"), entry.getValue().toString())));
1062        }
1063
1064        return element(name("systemProperties"), properties.toArray(new Element[properties.size()]));
1065        */
1066
1067        // NEW surefire 2.12 style
1068        for (Map.Entry<String, Object> entry: systemProperties.entrySet())
1069        {
1070            log.info("adding system property to configuration: " + entry.getKey() + "::" + entry.getValue());
1071
1072            properties.add(element(name(entry.getKey()),entry.getValue().toString()));
1073        }
1074
1075        return element(name("systemPropertyVariables"), properties.toArray(new Element[properties.size()]));
1076    }
1077
1078    private Container findContainer(final String containerId)
1079    {
1080        final Container container = idToContainerMap.get(containerId);
1081        if (container == null)
1082        {
1083            throw new IllegalArgumentException("Container " + containerId + " not supported");
1084        }
1085        return container;
1086    }
1087
1088    int pickFreePort(final int requestedPort)
1089    {
1090        ServerSocket socket = null;
1091        try
1092        {
1093            socket = new ServerSocket(requestedPort);
1094            return requestedPort > 0 ? requestedPort : socket.getLocalPort();
1095        }
1096        catch (final IOException e)
1097        {
1098            // happens if the requested port is taken, so we need to pick a new one
1099            ServerSocket zeroSocket = null;
1100            try
1101            {
1102                zeroSocket = new ServerSocket(0);
1103                return zeroSocket.getLocalPort();
1104         

Large files files are truncated, but you can click here to view the full file