1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.ear.it;
20
21 import javax.xml.parsers.DocumentBuilder;
22 import javax.xml.parsers.DocumentBuilderFactory;
23 import javax.xml.parsers.ParserConfigurationException;
24
25 import java.io.File;
26 import java.io.FilenameFilter;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.jar.JarFile;
33 import java.util.jar.JarInputStream;
34 import java.util.jar.Manifest;
35 import java.util.zip.ZipEntry;
36
37 import junit.framework.TestCase;
38 import org.apache.maven.plugins.ear.util.ResourceEntityResolver;
39 import org.apache.maven.shared.verifier.VerificationException;
40 import org.apache.maven.shared.verifier.Verifier;
41 import org.apache.maven.shared.verifier.util.ResourceExtractor;
42 import org.custommonkey.xmlunit.Diff;
43 import org.custommonkey.xmlunit.XMLAssert;
44 import org.junit.Assert;
45 import org.xml.sax.SAXException;
46 import org.xml.sax.helpers.DefaultHandler;
47
48
49
50
51
52
53 public abstract class AbstractEarPluginIT extends TestCase {
54
55 private static final String FINAL_NAME_PREFIX = "maven-ear-plugin-test-";
56
57 private static final String FINAL_NAME_SUFFIX = "-99.0";
58
59
60
61
62 private File basedir;
63
64 private File settingsFile = new File(getBasedir().getAbsolutePath(), "target/test-classes/settings.xml");
65
66
67
68
69
70
71
72
73
74 protected File executeMojo(final String projectName, boolean expectNoError, boolean cleanBeforeExecute)
75 throws VerificationException, IOException {
76 System.out.println(" Building: " + projectName);
77
78 File testDir = getTestDir(projectName);
79 Verifier verifier = new Verifier(testDir.getAbsolutePath());
80 verifier.setAutoclean(cleanBeforeExecute);
81
82 String localRepo = System.getProperty("localRepositoryPath");
83 verifier.setLocalRepo(localRepo);
84
85 verifier.addCliArguments("-s", settingsFile.getAbsolutePath());
86 verifier.addCliArgument("-X");
87 verifier.addCliArgument("package");
88
89
90 try {
91 verifier.execute();
92 } catch (VerificationException e) {
93
94 if (expectNoError || !e.getMessage().contains("Exit code was non-zero")) {
95 throw e;
96 }
97 }
98
99
100 if (expectNoError) {
101 verifier.verifyErrorFreeLog();
102 }
103 return testDir;
104 }
105
106
107
108
109
110
111
112 protected File executeMojo(final String projectName) throws VerificationException, IOException {
113 return executeMojo(projectName, true, true);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 protected File doTestProject(
137 final String projectName,
138 final String earModuleName,
139 final String[] expectedArtifacts,
140 boolean[] artifactsDirectory,
141 final String[] artifactsToValidateManifest,
142 boolean[] artifactsToValidateManifestDirectory,
143 final String[][] expectedClassPathElements,
144 final boolean cleanBeforeExecute)
145 throws VerificationException, IOException {
146 final File baseDir = executeMojo(projectName, true, cleanBeforeExecute);
147
148 final File earModuleDir = getEarModuleDirectory(baseDir, earModuleName);
149 assertEarArchive(earModuleDir, projectName);
150 assertEarDirectory(earModuleDir, projectName);
151 assertArchiveContent(earModuleDir, projectName, expectedArtifacts, artifactsDirectory);
152 assertDeploymentDescriptors(earModuleDir, projectName);
153 assertClassPathElements(
154 earModuleDir,
155 projectName,
156 artifactsToValidateManifest,
157 artifactsToValidateManifestDirectory,
158 expectedClassPathElements);
159
160 return baseDir;
161 }
162
163
164
165
166
167
168
169
170
171 protected File doTestProject(
172 final String projectName, final String[] expectedArtifacts, final boolean[] artifactsDirectory)
173 throws VerificationException, IOException {
174 return doTestProject(projectName, null, expectedArtifacts, artifactsDirectory, null, null, null, true);
175 }
176
177
178
179
180
181
182
183
184 protected File doTestProject(final String projectName, final String[] expectedArtifacts)
185 throws VerificationException, IOException {
186 return doTestProject(projectName, expectedArtifacts, new boolean[expectedArtifacts.length]);
187 }
188
189
190
191
192
193
194
195
196
197 protected File doTestProject(final String projectName, final String[] expectedArtifacts, boolean cleanBeforeExecute)
198 throws VerificationException, IOException {
199 return doTestProject(
200 projectName,
201 null,
202 expectedArtifacts,
203 new boolean[expectedArtifacts.length],
204 null,
205 null,
206 null,
207 cleanBeforeExecute);
208 }
209
210 protected void assertEarArchive(final File baseDir, final String projectName) {
211 assertTrue(
212 "EAR archive does not exist",
213 getEarArchive(baseDir, projectName).exists());
214 }
215
216 protected void assertEarDirectory(final File baseDir, final String projectName) {
217 assertTrue(
218 "EAR archive directory does not exist",
219 getEarDirectory(baseDir, projectName).exists());
220 }
221
222 protected File getEarModuleDirectory(final File baseDir, final String earModuleName) {
223 return earModuleName == null ? baseDir : new File(baseDir, earModuleName);
224 }
225
226 protected File getTargetDirectory(final File basedir) {
227 return new File(basedir, "target");
228 }
229
230 protected File getEarArchive(final File baseDir, final String projectName) {
231 return new File(getTargetDirectory(baseDir), buildFinalName(projectName) + ".ear");
232 }
233
234 protected File getEarDirectory(final File baseDir, final String projectName) {
235 return new File(getTargetDirectory(baseDir), buildFinalName(projectName));
236 }
237
238 protected String buildFinalName(final String projectName) {
239 return FINAL_NAME_PREFIX + projectName + FINAL_NAME_SUFFIX;
240 }
241
242 private void assertArchiveContent(
243 final File baseDir,
244 final String projectName,
245 final String[] artifactNames,
246 final boolean[] artifactsDirectory) {
247
248 assertEquals(
249 "Wrong parameter, artifacts mismatch directory flags", artifactNames.length, artifactsDirectory.length);
250
251 File dir = getEarDirectory(baseDir, projectName);
252
253
254 final List<File> expectedDirectories = new ArrayList<>();
255 for (int i = 0; i < artifactsDirectory.length; i++) {
256 if (artifactsDirectory[i]) {
257 expectedDirectories.add(new File(dir, artifactNames[i]));
258 }
259 }
260
261 final List<File> actualFiles = buildArchiveContentFiles(dir, expectedDirectories);
262 assertEquals("Artifacts mismatch " + actualFiles, artifactNames.length, actualFiles.size());
263 for (int i = 0; i < artifactNames.length; i++) {
264 String artifactName = artifactNames[i];
265 final boolean isDirectory = artifactsDirectory[i];
266 File expectedFile = new File(dir, artifactName);
267
268 assertEquals(
269 "Artifact[" + artifactName + "] not in the right form (exploded/archive",
270 isDirectory,
271 expectedFile.isDirectory());
272 assertTrue("Artifact[" + artifactName + "] not found in ear archive", actualFiles.contains(expectedFile));
273 }
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293 protected void assertEarModulesContent(
294 final File baseDir,
295 final String projectName,
296 final String earModuleName,
297 final String[] artifacts,
298 final boolean[] artifactsDirectory,
299 final String[][] includedEntries,
300 final String[][] excludedEntries)
301 throws IOException {
302 assertTrue(
303 "Wrong parameter, artifacts mismatch directory flags", artifacts.length <= artifactsDirectory.length);
304 if (includedEntries != null) {
305 assertTrue(
306 "Rows of includedEntries parameter should match items of artifacts parameter",
307 artifacts.length <= includedEntries.length);
308 }
309 if (excludedEntries != null) {
310 assertTrue(
311 "Rows of excludedEntries parameter should match items of artifacts parameter",
312 artifacts.length <= excludedEntries.length);
313 }
314
315 final File earDirectory = getEarDirectory(getEarModuleDirectory(baseDir, earModuleName), projectName);
316 for (int i = 0; i != artifacts.length; ++i) {
317 final String artifactName = artifacts[i];
318 final File module = new File(earDirectory, artifactName);
319 assertTrue("Artifact [" + artifactName + "] should exist in EAR", module.exists());
320
321 final boolean artifactDirectory = artifactsDirectory[i];
322 assertEquals(
323 "Artifact [" + artifactName + "] should be a " + (artifactDirectory ? "directory" : "file"),
324 artifactDirectory,
325 module.isDirectory());
326
327 if (includedEntries == null && excludedEntries == null) {
328 continue;
329 }
330
331 final boolean includedEntriesDefined =
332 includedEntries != null && includedEntries[i] != null && includedEntries[i].length != 0;
333 final boolean excludedEntriesDefined =
334 excludedEntries != null && excludedEntries[i] != null && excludedEntries[i].length != 0;
335 if (!includedEntriesDefined && !excludedEntriesDefined) {
336 continue;
337 }
338
339 if (artifactDirectory) {
340 if (includedEntriesDefined) {
341 for (String includedEntry : includedEntries[i]) {
342 if (includedEntry == null || includedEntry.length() == 0) {
343 continue;
344 }
345 final File inclusion = new File(artifactName, includedEntry);
346 assertTrue(
347 "Entry [" + includedEntry + "] should exist in artifact [" + artifactName + "] of EAR",
348 inclusion.exists());
349 }
350 }
351 if (excludedEntriesDefined) {
352 for (String excludedEntry : excludedEntries[i]) {
353 if (excludedEntry == null || excludedEntry.length() == 0) {
354 continue;
355 }
356 final File exclusion = new File(artifactName, excludedEntry);
357 assertFalse(
358 "Entry [" + excludedEntry + "] should not exist in artifact [" + artifactName
359 + "] of EAR",
360 exclusion.exists());
361 }
362 }
363 } else {
364 try (JarFile moduleJar = new JarFile(module)) {
365 if (includedEntriesDefined) {
366 for (String includedEntry : includedEntries[i]) {
367 if (includedEntry == null || includedEntry.length() == 0) {
368 continue;
369 }
370 final ZipEntry inclusion = moduleJar.getEntry(includedEntry);
371 assertNotNull(
372 "Entry [" + includedEntry + "] should exist in artifact [" + artifactName
373 + "] of EAR",
374 inclusion);
375 }
376 }
377 if (excludedEntriesDefined) {
378 for (String excludedEntry : excludedEntries[i]) {
379 if (excludedEntry == null || excludedEntry.length() == 0) {
380 continue;
381 }
382 final ZipEntry exclusion = moduleJar.getEntry(excludedEntry);
383 assertNull(
384 "Entry [" + excludedEntry + "] should not exist in artifact [" + artifactName
385 + "] of EAR",
386 exclusion);
387 }
388 }
389 }
390 }
391 }
392 }
393
394 private static List<File> buildArchiveContentFiles(final File baseDir, final List<File> expectedDirectories) {
395 final List<File> result = new ArrayList<>();
396 addFiles(baseDir, result, expectedDirectories);
397
398 return result;
399 }
400
401 private static void addFiles(final File directory, final List<File> files, final List<File> expectedDirectories) {
402 File[] result = directory.listFiles(new FilenameFilter() {
403 public boolean accept(File dir, String name) {
404 return !name.equals("META-INF");
405 }
406 });
407
408
409
410
411
412
413 for (File file : result) {
414 if (file.isFile()) {
415 files.add(file);
416 } else if (expectedDirectories.contains(file)) {
417 files.add(file);
418 } else {
419 addFiles(file, files, expectedDirectories);
420 }
421 }
422 }
423
424 private File getBasedir() {
425 if (basedir != null) {
426 return basedir;
427 }
428
429 final String basedirString = System.getProperty("basedir");
430 if (basedirString == null) {
431 basedir = new File("");
432 } else {
433 basedir = new File(basedirString);
434 }
435 return basedir;
436 }
437
438 protected File getTestDir(String projectName) throws IOException {
439 return ResourceExtractor.simpleExtractResources(getClass(), "/projects/" + projectName);
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453
454 protected void assertDeploymentDescriptors(final File baseDir, final String projectName) throws IOException {
455 final File earDirectory = getEarDirectory(baseDir, projectName);
456 final File[] actualDeploymentDescriptors = getDeploymentDescriptors(new File(earDirectory, "META-INF"));
457 final File[] expectedDeploymentDescriptors = getDeploymentDescriptors(new File(baseDir, "expected-META-INF"));
458
459 if (expectedDeploymentDescriptors == null) {
460 assertNull("No deployment descriptor was expected", actualDeploymentDescriptors);
461 } else {
462 assertNotNull("Missing deployment descriptor", actualDeploymentDescriptors);
463
464
465 assertEquals(
466 "Number of Deployment descriptor(s) mismatch",
467 expectedDeploymentDescriptors.length,
468 actualDeploymentDescriptors.length);
469
470
471 Arrays.sort(expectedDeploymentDescriptors);
472 Arrays.sort(actualDeploymentDescriptors);
473
474 for (int i = 0; i < expectedDeploymentDescriptors.length; i++) {
475 File expectedDeploymentDescriptor = expectedDeploymentDescriptors[i];
476 File actualDeploymentDescriptor = actualDeploymentDescriptors[i];
477
478 assertEquals(
479 "File name mismatch",
480 expectedDeploymentDescriptor.getName(),
481 actualDeploymentDescriptor.getName());
482
483 try {
484 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
485 dbf.setNamespaceAware(true);
486 dbf.setValidating(true);
487 DocumentBuilder docBuilder = dbf.newDocumentBuilder();
488 docBuilder.setEntityResolver(new ResourceEntityResolver());
489 docBuilder.setErrorHandler(new DefaultHandler());
490
491 final Diff myDiff = new Diff(
492 docBuilder.parse(expectedDeploymentDescriptor),
493 docBuilder.parse(actualDeploymentDescriptor));
494 XMLAssert.assertXMLEqual(
495 "Wrong deployment descriptor generated for[" + expectedDeploymentDescriptor.getName() + "]",
496 myDiff,
497 true);
498 } catch (SAXException | ParserConfigurationException e) {
499 e.printStackTrace();
500 fail("Could not assert deployment descriptor " + e.getMessage());
501 }
502 }
503 }
504 }
505
506 private static File[] getDeploymentDescriptors(final File ddDirectory) {
507 return ddDirectory.listFiles(new FilenameFilter() {
508 public boolean accept(File dir, String name) {
509 return !name.equalsIgnoreCase("manifest.mf");
510 }
511 });
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528 protected void assertClassPathElements(
529 final File baseDir,
530 String projectName,
531 String[] artifacts,
532 boolean[] artifactsDirectory,
533 String[][] expectedClassPathElements)
534 throws IOException {
535 if (artifacts == null) {
536 return;
537 }
538
539 assertNotNull("artifactsDirectory should be provided if artifacts is provided", artifactsDirectory);
540 assertTrue(
541 "Size of artifactsDirectory should match size of artifacts parameter",
542 artifacts.length <= artifactsDirectory.length);
543 assertNotNull(
544 "expectedClassPathElements should be provided if artifacts is provided", expectedClassPathElements);
545 assertTrue(
546 "Rows of expectedClassPathElements parameter should match items of artifacts parameter",
547 artifacts.length <= expectedClassPathElements.length);
548
549 final File earFile = getEarArchive(baseDir, projectName);
550 for (int i = 0; i != artifacts.length; ++i) {
551 final String moduleArtifact = artifacts[i];
552 final String[] classPathElements = getClassPathElements(earFile, moduleArtifact, artifactsDirectory[i]);
553 if (expectedClassPathElements[i] == null) {
554 assertNull(
555 "Class-Path entry should not exist in module [" + moduleArtifact + "] manifest",
556 classPathElements);
557 } else {
558 Assert.assertArrayEquals(
559 "Wrong elements of Class-Path entry of module [" + moduleArtifact + "] manifest",
560 expectedClassPathElements[i],
561 classPathElements);
562 }
563 }
564 }
565
566
567
568
569
570
571
572
573
574 protected String[] getClassPathElements(final File earFile, final String artifact, final boolean directory)
575 throws IOException {
576 final String classPath;
577 try (JarFile earJarFile = new JarFile(earFile)) {
578 final ZipEntry moduleEntry = earJarFile.getEntry(artifact);
579 assertNotNull("Artifact [" + artifact + "] should exist in EAR", moduleEntry);
580 if (directory) {
581 final String manifestEntryName = artifact + "/META-INF/MANIFEST.MF";
582 final ZipEntry manifestEntry = earJarFile.getEntry(manifestEntryName);
583 assertNotNull(manifestEntryName + " manifest file should exist in EAR", manifestEntry);
584 try (InputStream manifestInputStream = earJarFile.getInputStream(manifestEntry)) {
585 final Manifest manifest = new Manifest(manifestInputStream);
586 classPath = manifest.getMainAttributes().getValue("Class-Path");
587 }
588 } else {
589 try (InputStream moduleInputStream = earJarFile.getInputStream(moduleEntry);
590 JarInputStream moduleJarInputStream = new JarInputStream(moduleInputStream)) {
591 final Manifest manifest = moduleJarInputStream.getManifest();
592 assertNotNull("Artifact [" + artifact + "] of EAR should have manifest", manifest);
593 classPath = manifest.getMainAttributes().getValue("Class-Path");
594 }
595 }
596 }
597 if (classPath == null) {
598 return null;
599 }
600 final String trimmedClassPath = classPath.trim();
601 if (trimmedClassPath.length() == 0) {
602 return new String[0];
603 }
604 return trimmedClassPath.split(" ");
605 }
606 }