View Javadoc
1   package org.apache.maven.plugins.ear.it;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * Base class for ear test cases.
53   * 
54   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
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       * The base directory.
66       */
67      private File basedir;
68  
69      private File settingsFile = new File( getBasedir().getAbsolutePath(), "target/test-classes/settings.xml" );
70  
71      /**
72       * Execute the EAR plugin for the specified project.
73       * 
74       * @param projectName the name of the project
75       * @param expectNoError true/false
76       * @param cleanBeforeExecute call clean plugin before execution
77       * @return the base directory of the project
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          // Let's add alternate settings.xml setting so that the latest dependencies are used
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          // On linux and MacOS X, an exception is thrown if a build failure occurs underneath
96          try
97          {
98              verifier.execute();
99          }
100         catch ( VerificationException e )
101         {
102             // @TODO needs to be handled nicely in the verifier
103             if ( expectNoError || !e.getMessage().contains( "Exit code was non-zero" ) )
104             {
105                 throw e;
106             }
107         }
108 
109         // If no error is expected make sure that error logs are free
110         if ( expectNoError )
111         {
112             verifier.verifyErrorFreeLog();
113         }
114         return testDir;
115     }
116 
117     /**
118      * Execute the EAR plugin for the specified project.
119      * 
120      * @param projectName the name of the project
121      * @return the base directory of the project
122      */
123     protected File executeMojo( final String projectName )
124         throws VerificationException, IOException
125     {
126         return executeMojo( projectName, true, true );
127     }
128 
129     /**
130      * Executes the specified projects and asserts the given artifacts. Asserts the deployment descriptors are valid.
131      * Asserts Class-Path entry of manifest of EAR modules.
132      *
133      * @param projectName the project to test
134      * @param earModuleName the name of 1st level EAR module in multi-module project or {@code null}
135      *                      if project is single-module
136      * @param expectedArtifacts the list of artifacts to be found in the EAR archive
137      * @param artifactsDirectory whether the artifact from {@code expectedArtifacts} list is an exploded or not
138      * @param artifactsToValidateManifest the list of EAR archive artifacts to validate Class-Path entry of artifact
139      *                                    manifest or {@code null} if there is no need to validate Class-Path entry
140      * @param artifactsToValidateManifestDirectory whether the artifact from {@code artifactsToValidateManifest} list is
141      *                                             an exploded or not, can be {@code null} if
142      *                                             {@code artifactsToValidateManifest} is {@code null}
143      * @param expectedClassPathElements the list of elements of Class-Path entry of manifest, rows should match
144      *                                  artifacts passed in {@code artifactsToValidateManifest} parameter;
145      *                                  can be {@code null} if {@code artifactsToValidateManifest} is {@code null}
146      * @param cleanBeforeExecute call clean plugin before execution
147      * @return the base directory of the project
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      * Executes the specified projects and asserts the given artifacts. Assert the deployment descriptors are valid.
172      *
173      * @param projectName the project to test
174      * @param expectedArtifacts the list of artifacts to be found in the EAR archive
175      * @param artifactsDirectory whether the artifact from {@code expectedArtifacts} list is an exploded or not
176      * @return the base directory of the project
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      * Executes the specified projects and asserts the given artifacts as artifacts (non directory)
187      * 
188      * @param projectName the project to test
189      * @param expectedArtifacts the list of artifacts to be found in the EAR archive
190      * @return the base directory of the project
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      * Executes the specified projects and asserts the given artifacts as artifacts (non directory)
200      *
201      * @param projectName the project to test
202      * @param expectedArtifacts the list of artifacts to be found in the EAR archive
203      * @param cleanBeforeExecute call clean plugin before execution
204      * @return the base directory of the project
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         // sanity check
251         assertEquals( "Wrong parameter, artifacts mismatch directory flags", artifactNames.length,
252                       artifactsDirectory.length );
253 
254         File dir = getEarDirectory( baseDir, projectName );
255 
256         // Let's build the expected directories sort list
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      * Asserts that given EAR archive artifacts have expected entries and don't have unexpected entries.
283      *
284      * @param baseDir the directory of the tested project
285      * @param projectName the project to test
286      * @param earModuleName the name of 1st level EAR module in multi-module project or {@code null}
287      *                      if project is single-module
288      * @param artifacts the list of artifacts to be found in the EAR archive
289      * @param artifactsDirectory whether the artifact from {@code artifacts} list is an exploded or not
290      * @param includedEntries entries which should exist in artifacts, rows should match artifacts passed in
291      *                        {@code artifacts} parameter; can be {@code null} if there is no need to assert
292      *                        existence of entries in artifacts
293      * @param excludedEntries entries which should not exist in artifacts, rows should match artifacts passed in
294      *                        {@code artifacts} parameter; can be {@code null} if there is no need to assert
295      *                        absence of paths in artifacts
296      * @throws IOException exception in case of failure during reading of artifact archive.
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          * Kinda complex. If we found a file, we always add it to the list of files. If a directory is within the
429          * expectedDirectories short list we add it but we don't add it's content. Otherwise, we don't add the directory
430          * *BUT* we browse it's content
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     // Generated application.xml stuff
475 
476     /**
477      * Asserts that the deployment descriptors have been generated successfully.
478      * 
479      * This test assumes that deployment descriptors are located in the {@code expected-META-INF} directory of the
480      * project. Note that the {@code MANIFEST.mf} file is ignored and is not tested.
481      * 
482      * @param baseDir the directory of the tested project
483      * @param projectName the name of the project
484      * @throws IOException exception in case of an error.
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             // Make sure we have the same number of files
503             assertEquals( "Number of Deployment descriptor(s) mismatch", expectedDeploymentDescriptors.length,
504                           actualDeploymentDescriptors.length );
505 
506             // Sort the files so that we have the same behavior here
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      * Asserts that given EAR archive artifacts have expected elements in artifact manifest Class-Path entry.
555      *
556      * @param baseDir the directory of the tested project
557      * @param projectName the name of the project
558      * @param artifacts the list of EAR archive artifacts to validate Class-Path entry of artifact manifest or
559      *                  {@code null} if there is no need to validate Class-Path entry
560      * @param artifactsDirectory whether the artifact from {@code artifacts} list is an exploded or not,
561      *                           can be {@code null} if {@code artifacts} is {@code null}
562      * @param expectedClassPathElements the list of expected elements of Class-Path entry of manifest, rows should match
563      *                                  artifacts passed in {@code artifacts} parameter; can be {@code null}
564      *                                  if {@code artifacts} is {@code null}
565      * @throws IOException exception in case of failure during reading of artifact manifest.
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      * Retrieves elements of Class-Path entry of manifest of given EAR module.
605      *
606      * @param earFile the EAR file to investigate
607      * @param artifact the name of artifact in EAR archive representing EAR module
608      * @return elements of Class-Path entry of manifest of EAR module which is represented by
609      * {@code artifact} artifact in {@code earFile} file
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 }