1 package com.atlassian.maven.plugins.amps.product;
2
3 import com.atlassian.maven.plugins.amps.MavenGoals;
4 import com.atlassian.maven.plugins.amps.Product;
5 import com.atlassian.maven.plugins.amps.ProductArtifact;
6 import static com.atlassian.maven.plugins.amps.util.FileUtils.doesFileNameMatchArtifact;
7 import static com.atlassian.maven.plugins.amps.util.ZipUtils.unzip;
8
9 import org.apache.commons.io.FileUtils;
10 import org.apache.commons.lang.StringUtils;
11
12 import static org.apache.commons.io.FileUtils.copyFile;
13 import static org.apache.commons.io.FileUtils.iterateFiles;
14 import org.apache.maven.plugin.MojoExecutionException;
15 import org.apache.maven.project.MavenProject;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25
26 public abstract class AbstractProductHandler implements ProductHandler
27 {
28 protected final MavenGoals goals;
29 protected final MavenProject project;
30 private final PluginProvider pluginProvider;
31
32 protected AbstractProductHandler(MavenProject project, MavenGoals goals, PluginProvider pluginProvider)
33 {
34 this.project = project;
35 this.goals = goals;
36 this.pluginProvider = pluginProvider;
37 }
38
39 public final int start(final Product ctx) throws MojoExecutionException
40 {
41 final File homeDir = extractAndProcessHomeDirectory(ctx);
42 final File extractedApp = extractApplication(ctx, homeDir);
43 final File finalApp = addArtifactsAndOverrides(ctx, homeDir, extractedApp);
44 return startApplication(ctx, finalApp, homeDir, mergeSystemProperties(ctx));
45 }
46
47 protected final File extractAndProcessHomeDirectory(final Product ctx) throws MojoExecutionException
48 {
49 if (getTestResourcesArtifact() != null)
50 {
51 final File homeDir = getHomeDirectory(ctx);
52
53
54 if (!homeDir.exists())
55 {
56
57
58 final File productHomeZip = getProductHomeZip(ctx);
59 extractProductHomeZip(productHomeZip, homeDir, ctx);
60
61
62 homeDir.mkdir();
63 processHomeDirectory(ctx, homeDir);
64 }
65
66
67 try
68 {
69 overrideAndPatchHomeDir(homeDir, ctx);
70 }
71 catch (IOException e)
72 {
73 throw new MojoExecutionException("Unable to override files using src/test/resources", e);
74 }
75
76 return homeDir;
77 }
78 else
79 {
80 return getHomeDirectory(ctx);
81 }
82 }
83
84 private File getProductHomeZip(final Product ctx) throws MojoExecutionException
85 {
86 File productHomeZip = null;
87 String dpath = ctx.getDataPath();
88
89
90 if (StringUtils.isNotBlank(dpath))
91 {
92 File customHomeZip = new File(dpath);
93
94 if (customHomeZip.exists())
95 {
96 productHomeZip = customHomeZip;
97 }
98 }
99
100
101 if (productHomeZip == null)
102 {
103 productHomeZip = goals.copyHome(getBaseDirectory(ctx),
104 new ProductArtifact(
105 getTestResourcesArtifact().getGroupId(),
106 getTestResourcesArtifact().getArtifactId(),
107 ctx.getDataVersion()));
108 }
109
110 return productHomeZip;
111 }
112
113 protected void extractProductHomeZip(File productHomeZip, File homeDir, Product ctx)
114 throws MojoExecutionException
115 {
116 final File tmpDir = new File(getBaseDirectory(ctx), "tmp-resources");
117 tmpDir.mkdir();
118
119 try
120 {
121 unzip(productHomeZip, tmpDir.getPath());
122 FileUtils.copyDirectory(tmpDir.listFiles()[0], getBaseDirectory(ctx), true);
123 File tmp = new File(getBaseDirectory(ctx), ctx.getId() + "-home");
124 FileUtils.moveDirectory(tmp, homeDir);
125 }
126 catch (final IOException ex)
127 {
128 throw new MojoExecutionException("Unable to copy home directory", ex);
129 }
130 }
131
132 private void overrideAndPatchHomeDir(File homeDir, final Product ctx) throws IOException
133 {
134 final File srcDir = new File(project.getBasedir(), "src/test/resources/" + ctx.getInstanceId() + "-home");
135 if (srcDir.exists() && homeDir.exists())
136 {
137 FileUtils.copyDirectory(srcDir, homeDir);
138 }
139 }
140
141 private final File addArtifactsAndOverrides(final Product ctx, final File homeDir, final File app) throws MojoExecutionException
142 {
143 try
144 {
145 final File appDir;
146 if (app.isFile())
147 {
148 appDir = new File(getBaseDirectory(ctx), "webapp");
149 if (!appDir.exists())
150 {
151 unzip(app, appDir.getAbsolutePath());
152 }
153 }
154 else
155 {
156 appDir = app;
157 }
158
159 addArtifacts(ctx, homeDir, appDir);
160
161
162 try
163 {
164 addOverrides(appDir, ctx);
165 }
166 catch (IOException e)
167 {
168 throw new MojoExecutionException("Unable to override WAR files using src/test/resources/" + ctx.getInstanceId() + "-app", e);
169 }
170
171 if (app.isFile())
172 {
173 final File warFile = new File(app.getParentFile(), getId() + ".war");
174 com.atlassian.core.util.FileUtils.createZipFile(appDir, warFile);
175 return warFile;
176 }
177 else
178 {
179 return appDir;
180 }
181
182 }
183 catch (final Exception e)
184 {
185 e.printStackTrace();
186 throw new MojoExecutionException(e.getMessage());
187 }
188 }
189
190 private void addArtifacts(final Product ctx, final File homeDir, final File appDir)
191 throws IOException, MojoExecutionException, Exception
192 {
193 File pluginsDir = getUserInstalledPluginsDirectory(appDir, homeDir);
194 final File bundledPluginsDir = new File(getBaseDirectory(ctx), "bundled-plugins");
195
196 bundledPluginsDir.mkdir();
197
198 final File bundledPluginsZip = new File(appDir, getBundledPluginPath(ctx));
199 if (bundledPluginsZip.exists())
200 {
201 unzip(bundledPluginsZip, bundledPluginsDir.getPath());
202 }
203
204 if (isStaticPlugin())
205 {
206 if (!supportsStaticPlugins())
207 {
208 throw new MojoExecutionException("According to your atlassian-plugin.xml file, this plugin is not " +
209 "atlassian-plugins version 2. This app currently only supports atlassian-plugins " +
210 "version 2.");
211 }
212 pluginsDir = new File(appDir, "WEB-INF/lib");
213 }
214
215 if (pluginsDir == null)
216 {
217 pluginsDir = bundledPluginsDir;
218 }
219
220 createDirectory(pluginsDir);
221
222
223 if (ctx.isInstallPlugin())
224 {
225 addThisPluginToDirectory(pluginsDir);
226 addTestPluginToDirectory(pluginsDir);
227 }
228
229
230 if (!isStaticPlugin())
231 {
232 addArtifactsToDirectory(pluginProvider.provide(ctx), pluginsDir);
233 }
234
235
236 List<ProductArtifact> artifacts = new ArrayList<ProductArtifact>();
237 artifacts.addAll(getDefaultLibPlugins());
238 artifacts.addAll(ctx.getLibArtifacts());
239 addArtifactsToDirectory(artifacts, new File(appDir, "WEB-INF/lib"));
240
241 artifacts = new ArrayList<ProductArtifact>();
242 artifacts.addAll(getDefaultBundledPlugins());
243 artifacts.addAll(ctx.getBundledArtifacts());
244
245 addArtifactsToDirectory(artifacts, bundledPluginsDir);
246
247 if (bundledPluginsDir.list().length > 0)
248 {
249 com.atlassian.core.util.FileUtils.createZipFile(bundledPluginsDir, bundledPluginsZip);
250 }
251
252 if (ctx.getLog4jProperties() != null && getLog4jPropertiesPath() != null)
253 {
254 FileUtils.copyFile(ctx.getLog4jProperties(), new File(appDir, getLog4jPropertiesPath()));
255 }
256 }
257
258 abstract protected void processHomeDirectory(Product ctx, File homeDir) throws MojoExecutionException;
259 abstract protected ProductArtifact getTestResourcesArtifact();
260 abstract protected File extractApplication(Product ctx, File homeDir) throws MojoExecutionException;
261 abstract protected int startApplication(Product ctx, File app, File homeDir, Map<String, String> properties) throws MojoExecutionException;
262 abstract protected boolean supportsStaticPlugins();
263 abstract protected Collection<? extends ProductArtifact> getDefaultBundledPlugins();
264 abstract protected Collection<? extends ProductArtifact> getDefaultLibPlugins();
265 abstract protected String getBundledPluginPath(Product ctx);
266 abstract protected File getUserInstalledPluginsDirectory(File webappDir, File homeDir);
267
268 protected String getLog4jPropertiesPath()
269 {
270 return null;
271 }
272
273 protected boolean isStaticPlugin() throws IOException
274 {
275 final File atlassianPluginXml = new File(project.getBasedir(), "src/main/resources/atlassian-plugin.xml");
276 if (atlassianPluginXml.exists())
277 {
278 String text = FileUtils.readFileToString(atlassianPluginXml);
279 return !text.contains("pluginsVersion=\"2\"") && !text.contains("plugins-version=\"2\"");
280 }
281 else
282 {
283
284 return false;
285 }
286 }
287
288 protected final void addThisPluginToDirectory(final File targetDir) throws IOException
289 {
290 final File thisPlugin = getPluginFile();
291
292
293 for (final Iterator<?> iterateFiles = iterateFiles(targetDir, null, false); iterateFiles.hasNext();)
294 {
295 final File file = (File) iterateFiles.next();
296 if (doesFileNameMatchArtifact(file.getName(), project.getArtifactId()))
297 {
298 file.delete();
299 }
300 }
301
302
303 copyFile(thisPlugin, new File(targetDir, thisPlugin.getName()));
304 }
305
306 protected void addTestPluginToDirectory(final File targetDir) throws IOException
307 {
308 final File testPluginFile = getTestPluginFile();
309 if (testPluginFile.exists())
310 {
311
312 copyFile(testPluginFile, new File(targetDir, testPluginFile.getName()));
313 }
314
315 }
316
317 protected final File getPluginFile()
318 {
319 return new File(project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".jar");
320 }
321
322 protected File getTestPluginFile()
323 {
324 return new File(project.getBuild().getDirectory(), project.getBuild().getFinalName() + "-tests.jar");
325 }
326
327 protected final void addArtifactsToDirectory(final List<ProductArtifact> artifacts, final File pluginsDir) throws MojoExecutionException
328 {
329
330 if (pluginsDir.isDirectory() && pluginsDir.exists())
331 {
332 for (final Iterator<?> iterateFiles = FileUtils.iterateFiles(pluginsDir, null, false); iterateFiles.hasNext();)
333 {
334 final File file = (File) iterateFiles.next();
335 for (final ProductArtifact webappArtifact : artifacts)
336 {
337 if (!file.isDirectory() && doesFileNameMatchArtifact(file.getName(), webappArtifact.getArtifactId()))
338 {
339 file.delete();
340 }
341 }
342 }
343 }
344
345 if (!artifacts.isEmpty())
346 {
347 goals.copyPlugins(pluginsDir, artifacts);
348 }
349 }
350
351 protected final void addOverrides(File appDir, final Product ctx) throws IOException
352 {
353 final File srcDir = new File(project.getBasedir(), "src/test/resources/" + ctx.getInstanceId() + "-app");
354 if (srcDir.exists() && appDir.exists())
355 {
356 FileUtils.copyDirectory(srcDir, appDir);
357 }
358 }
359
360 public final File getBaseDirectory(Product ctx)
361 {
362 return createDirectory(new File(project.getBuild().getDirectory(), ctx.getInstanceId()));
363 }
364
365 public final File getHomeDirectory(Product ctx)
366 {
367 return new File(getBaseDirectory(ctx), "home");
368 }
369
370 protected final File createHomeDirectory(Product ctx)
371 {
372 return createDirectory(getHomeDirectory(ctx));
373 }
374
375 protected final File createDirectory(File dir)
376 {
377 if (!dir.exists() && !dir.mkdirs())
378 {
379 throw new RuntimeException("Failed to create directory " + dir.getAbsolutePath());
380 }
381 return dir;
382 }
383
384 protected final Map<String, String> mergeSystemProperties(Product ctx)
385 {
386 final Map<String, String> properties = new HashMap<String, String>();
387 properties.putAll(getSystemProperties(ctx));
388 for (Map.Entry<String, Object> entry : ctx.getSystemPropertyVariables().entrySet())
389 {
390 properties.put(entry.getKey(), (String) entry.getValue());
391 }
392 return properties;
393 }
394
395 protected abstract Map<String, String> getSystemProperties(Product ctx);
396
397 }