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 }