1   package com.atlassian.maven.plugins.amps;
2   
3   import com.atlassian.maven.plugins.amps.product.ProductHandler;
4   import com.google.common.collect.Lists;
5   
6   import org.apache.commons.io.IOUtils;
7   import org.apache.maven.plugin.MojoExecutionException;
8   import org.apache.maven.plugin.MojoFailureException;
9   import org.apache.maven.artifact.Artifact;
10  import org.jfrog.maven.annomojo.annotations.MojoExecute;
11  import org.jfrog.maven.annomojo.annotations.MojoGoal;
12  import org.jfrog.maven.annomojo.annotations.MojoParameter;
13  import org.jfrog.maven.annomojo.annotations.MojoRequiresDependencyResolution;
14  
15  import java.io.File;
16  import java.io.FileOutputStream;
17  import java.io.IOException;
18  import java.io.OutputStream;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Properties;
24  
25  import static org.apache.commons.lang.StringUtils.isBlank;
26  
27  /**
28   * Run the webapp
29   */
30  @MojoGoal ("run")
31  @MojoExecute (phase = "package")
32  @MojoRequiresDependencyResolution
33  public class RunMojo extends AbstractTestGroupsHandlerMojo
34  {
35      private static final char CONTROL_C = (char) 27;
36  
37      @MojoParameter (expression = "${wait}", defaultValue = "true")
38      private boolean wait;
39  
40      /**
41       * Whether or not to write properties used by the plugin to amps.properties.
42       */
43      @MojoParameter (expression = "${amps.properties}", required = true, defaultValue = "false")
44      protected boolean writePropertiesToFile;
45  
46      /**
47       * Test group to run.  If provided, used to determine the products to run.
48       */
49      @MojoParameter(expression = "${testGroup}")
50      protected String testGroup;
51  
52      /**
53       * The properties actually used by the mojo when running
54       */
55      protected final Map<String, String> properties = new HashMap<String, String>();
56  
57      protected void doExecute() throws MojoExecutionException, MojoFailureException
58      {
59          final List<ProductExecution> productExecutions = getProductExecutions();
60  
61          startProducts(productExecutions);
62      }
63  
64      protected void startProducts(List<ProductExecution> productExecutions) throws MojoExecutionException
65      {
66          List<String> successMessages = Lists.newArrayList();
67          for (ProductExecution productExecution : productExecutions)
68          {
69              final ProductHandler productHandler = productExecution.getProductHandler();
70              final Product product = productExecution.getProduct();
71              if (product.isInstallPlugin() == null)
72              {
73                  product.setInstallPlugin(shouldInstallPlugin());
74              }
75  
76              int actualHttpPort = productHandler.start(product);
77  
78              String successMessage = product.getInstanceId() + " started successfully";
79              if (actualHttpPort != 0)
80              {
81                  successMessage += " and available at http://localhost:" + actualHttpPort + product.getContextPath();
82              }
83              getLog().info(successMessage);
84  
85              successMessages.add(successMessage);
86  
87              if (writePropertiesToFile)
88              {
89                  if (productExecutions.size() == 1)
90                  {
91                      properties.put("http.port", String.valueOf(actualHttpPort));
92                      properties.put("context.path", product.getContextPath());
93                  }
94  
95                  properties.put("http." + product.getInstanceId() + ".port", String.valueOf(actualHttpPort));
96                  properties.put("context." + product.getInstanceId() + ".path", product.getContextPath());
97              }
98          }
99  
100         if (writePropertiesToFile)
101         {
102             writePropertiesFile();
103         }
104 
105         // Repeat the messages at the end, because we're developer-friendly
106         if (successMessages.size() > 1)
107         {
108             getLog().info("Summary:");
109             for (String message : successMessages)
110             {
111                 getLog().info(message);
112             }
113         }
114 
115         if (wait)
116         {
117             getLog().info("Type CTRL-C to exit");
118             try
119             {
120                 while (System.in.read() != CONTROL_C)
121                 {
122                 }
123             }
124             catch (final IOException e)
125             {
126                 // ignore
127             }
128         }
129     }
130 
131     protected List<ProductExecution> getProductExecutions() throws MojoExecutionException
132     {
133         final List<ProductExecution> productExecutions;
134         final MavenGoals goals = getMavenGoals();
135         if (!isBlank(testGroup))
136         {
137             productExecutions = getTestGroupProductExecutions(testGroup);
138         }
139         else if (!isBlank(instanceId))
140         {
141             Product ctx = getProductContexts(goals).get(instanceId);
142             if (ctx == null)
143             {
144                 throw new MojoExecutionException("No product with instance ID '" + instanceId + "'");
145             }
146             ProductHandler product = createProductHandler(ctx.getId());
147             productExecutions = Collections.singletonList(new ProductExecution(ctx, product));
148         }
149         else
150         {
151             Product ctx = getProductContexts(goals).get(getProductId());
152             ProductHandler product = createProductHandler(ctx.getId());
153             productExecutions = Collections.singletonList(new ProductExecution(ctx, product));
154         }
155         return includeStudioDependentProducts(productExecutions, goals);
156     }
157 
158     /**
159      * Only install a plugin if the installPlugin flag is true and the project is a jar.  If the test plugin was built,
160      * it will be installed as well.
161      */
162     private boolean shouldInstallPlugin()
163     {
164         Artifact artifact = getMavenContext().getProject().getArtifact();
165         return installPlugin &&
166                 (artifact != null && !"pom".equalsIgnoreCase(artifact.getType()));
167     }
168 
169     private void writePropertiesFile() throws MojoExecutionException
170     {
171         final Properties props = new Properties();
172 
173         for (Map.Entry<String, String> entry : properties.entrySet())
174         {
175             props.setProperty(entry.getKey(), entry.getValue());
176         }
177 
178         final File ampsProperties = new File(getMavenContext().getProject().getBuild().getDirectory(), "amps.properties");
179         OutputStream out = null;
180         try
181         {
182             out = new FileOutputStream(ampsProperties);
183             props.store(out, "");
184         }
185         catch (IOException e)
186         {
187             throw new MojoExecutionException("Error writing " + ampsProperties.getAbsolutePath(), e);
188         }
189         finally
190         {
191             IOUtils.closeQuietly(out);
192         }
193     }
194 }