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