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