1   package org.apache.maven.plugin.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 junit.framework.TestCase;
23  
24  import org.apache.maven.it.VerificationException;
25  import org.apache.maven.it.Verifier;
26  import org.apache.maven.it.util.ResourceExtractor;
27  import org.codehaus.plexus.util.ReaderFactory;
28  import org.custommonkey.xmlunit.Diff;
29  import org.custommonkey.xmlunit.XMLAssert;
30  import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
31  
32  import java.io.File;
33  import java.io.FilenameFilter;
34  import java.io.IOException;
35  import java.io.Reader;
36  import java.util.ArrayList;
37  import java.util.Arrays;
38  import java.util.List;
39  import java.util.Properties;
40  
41  /**
42   * Base class for ear test cases.
43   *
44   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
45   * @version $Id: AbstractEarPluginIT.java 776216 2009-05-19 07:12:32Z aheritier $
46   */
47  public abstract class AbstractEarPluginIT
48      extends TestCase
49  {
50  
51      protected final String FINAL_NAME_PREFIX = "maven-ear-plugin-test-";
52  
53      protected final String FINAL_NAME_SUFFIX = "-99.0";
54  
55      /**
56       * The base directory.
57       */
58      private File basedir;
59  
60      /**
61       * Test repository directory.
62       */
63      protected File localRepositoryDir = new File( getBasedir().getAbsolutePath(), "target/test-classes/m2repo" );
64  
65      protected File settingsFile = new File( getBasedir().getAbsolutePath(), "target/test-classes/settings.xml" );
66  
67  
68      /**
69       * Execute the EAR plugin for the specified project.
70       *
71       * @param projectName the name of the project
72       * @param properties  extra properties to be used by the embedder
73       * @return the base directory of the project
74       * @throws Exception if an error occured
75       */
76      protected File executeMojo( final String projectName, final Properties properties, boolean expectNoError )
77          throws Exception
78      {
79          System.out.println( "  Building: " + projectName );
80  
81          File testDir = getTestDir( projectName );
82          Verifier verifier = new Verifier( testDir.getAbsolutePath() );
83          // Let's add alternate settings.xml setting so that the latest dependencies are used
84          verifier.getCliOptions().add( "-s \"" + settingsFile.getAbsolutePath() + "\"" );
85          verifier.getCliOptions().add( "-X" );
86          verifier.localRepo = localRepositoryDir.getAbsolutePath();
87  
88          // On linux and macOSX, an exception is thrown if a build failure occurs underneath
89          try
90          {
91              verifier.executeGoal( "package" );
92          }
93          catch ( VerificationException e )
94          {
95              //@TODO needs to be handled nicely in the verifier
96              if ( expectNoError || e.getMessage().indexOf( "Exit code was non-zero" ) == -1 )
97              {
98                  throw e;
99              }
100         }
101 
102         // If no error is expected make sure that error logs are free
103         if ( expectNoError )
104         {
105             verifier.verifyErrorFreeLog();
106         }
107         verifier.resetStreams();
108         return testDir;
109     }
110 
111     /**
112      * Execute the EAR plugin for the specified project.
113      *
114      * @param projectName the name of the project
115      * @param properties  extra properties to be used by the embedder
116      * @return the base directory of the project
117      * @throws Exception if an error occured
118      */
119     protected File executeMojo( final String projectName, final Properties properties )
120         throws Exception
121     {
122         return executeMojo( projectName, properties, true );
123     }
124 
125 
126     /**
127      * Executes the specified projects and asserts the given artifacts.
128      *
129      * @param projectName               the project to test
130      * @param expectedArtifacts         the list of artifacts to be found in the EAR archive
131      * @param artifactsDirectory        whether the artifact is an exploded artifactsDirectory or not
132      * @param testDeploymentDescriptors whether we should test deployemnt descriptors
133      * @return the base directory of the project
134      * @throws Exception
135      */
136     protected File doTestProject( final String projectName, final String[] expectedArtifacts,
137                                   final boolean[] artifactsDirectory, boolean testDeploymentDescriptors )
138         throws Exception
139     {
140         final File baseDir = executeMojo( projectName, new Properties() );
141         assertEarArchive( baseDir, projectName );
142         assertEarDirectory( baseDir, projectName );
143 
144         assertArchiveContent( baseDir, projectName, expectedArtifacts, artifactsDirectory );
145 
146         if ( testDeploymentDescriptors )
147         {
148             assertDeploymentDescriptors( baseDir, projectName );
149         }
150 
151         return baseDir;
152 
153     }
154 
155     /**
156      * Executes the specified projects and asserts the given artifacts. Assert the
157      * deployment descriptors are valid
158      *
159      * @param projectName        the project to test
160      * @param expectedArtifacts  the list of artifacts to be found in the EAR archive
161      * @param artifactsDirectory whether the artifact is an exploded artifactsDirectory or not
162      * @return the base directory of the project
163      * @throws Exception
164      */
165     protected File doTestProject( final String projectName, final String[] expectedArtifacts,
166                                   final boolean[] artifactsDirectory )
167         throws Exception
168     {
169         return doTestProject( projectName, expectedArtifacts, artifactsDirectory, true );
170 
171     }
172 
173     /**
174      * Executes the specified projects and asserts the given artifacts as
175      * artifacts (non directory)
176      *
177      * @param projectName               the project to test
178      * @param expectedArtifacts         the list of artifacts to be found in the EAR archive
179      * @param testDeploymentDescriptors whether we should test deployemnt descriptors
180      * @return the base directory of the project
181      * @throws Exception
182      */
183     protected File doTestProject( final String projectName, final String[] expectedArtifacts,
184                                   boolean testDeploymentDescriptors )
185         throws Exception
186     {
187         return doTestProject( projectName, expectedArtifacts, new boolean[expectedArtifacts.length] );
188     }
189 
190     /**
191      * Executes the specified projects and asserts the given artifacts as
192      * artifacts (non directory). Assert the deployment descriptors are valid
193      *
194      * @param projectName       the project to test
195      * @param expectedArtifacts the list of artifacts to be found in the EAR archive
196      * @return the base directory of the project
197      * @throws Exception
198      */
199     protected File doTestProject( final String projectName, final String[] expectedArtifacts )
200         throws Exception
201     {
202         return doTestProject( projectName, expectedArtifacts, true );
203     }
204 
205     protected void assertEarArchive( final File baseDir, final String projectName )
206     {
207         assertTrue( "EAR archive does not exist", getEarArchive( baseDir, projectName ).exists() );
208     }
209 
210     protected void assertEarDirectory( final File baseDir, final String projectName )
211     {
212         assertTrue( "EAR archive directory does not exist", getEarDirectory( baseDir, projectName ).exists() );
213     }
214 
215     protected File getTargetDirectory( final File basedir )
216     {
217         return new File( basedir, "target" );
218     }
219 
220     protected File getEarArchive( final File baseDir, final String projectName )
221     {
222         return new File( getTargetDirectory( baseDir ), buildFinalName( projectName ) + ".ear" );
223     }
224 
225     protected File getEarDirectory( final File baseDir, final String projectName )
226     {
227         return new File( getTargetDirectory( baseDir ), buildFinalName( projectName ) );
228     }
229 
230     protected String buildFinalName( final String projectName )
231     {
232         return FINAL_NAME_PREFIX + projectName + FINAL_NAME_SUFFIX;
233     }
234 
235     protected void assertArchiveContent( final File baseDir, final String projectName, final String[] artifactNames,
236                                          final boolean[] artifactsDirectory )
237     {
238         // sanity check
239         assertEquals( "Wrong parameter, artifacts mismatch directory flags", artifactNames.length,
240                       artifactsDirectory.length );
241 
242         File dir = getEarDirectory( baseDir, projectName );
243 
244         // Let's build the expected directories sort list
245         final List expectedDirectories = new ArrayList();
246         for ( int i = 0; i < artifactsDirectory.length; i++ )
247         {
248             if ( artifactsDirectory[i] )
249             {
250                 expectedDirectories.add( new File( dir, artifactNames[i] ) );
251             }
252         }
253 
254         final List actualFiles = buildArchiveContentFiles( dir, expectedDirectories );
255         assertEquals( "Artifacts mismatch " + actualFiles, artifactNames.length, actualFiles.size() );
256         for ( int i = 0; i < artifactNames.length; i++ )
257         {
258             String artifactName = artifactNames[i];
259             final boolean isDirectory = artifactsDirectory[i];
260             File expectedFile = new File( dir, artifactName );
261 
262             assertEquals( "Artifact[" + artifactName + "] not in the right form (exploded/archive", isDirectory,
263                           expectedFile.isDirectory() );
264             assertTrue( "Artifact[" + artifactName + "] not found in ear archive",
265                         actualFiles.contains( expectedFile ) );
266 
267         }
268     }
269 
270     protected List buildArchiveContentFiles( final File baseDir, final List expectedDirectories )
271     {
272         final List result = new ArrayList();
273         addFiles( baseDir, result, expectedDirectories );
274 
275         return result;
276     }
277 
278     private void addFiles( final File directory, final List files, final List expectedDirectories )
279     {
280         File[] result = directory.listFiles( new FilenameFilter()
281         {
282             public boolean accept( File dir, String name )
283             {
284                 if ( name.equals( "META-INF" ) )
285                 {
286                     return false;
287                 }
288                 else
289                 {
290                     return true;
291                 }
292             }
293 
294         } );
295 
296         /*
297            Kinda complex. If we found a file, we always add it to the list
298            of files. If a directory is within the expectedDirectories short
299            list we add it but we don't add it's content. Otherwise, we don't
300            add the directory *BUT* we browse it's content
301          */
302         for ( int i = 0; i < result.length; i++ )
303         {
304             File file = result[i];
305             if ( file.isFile() )
306             {
307                 files.add( file );
308             }
309             else if ( expectedDirectories.contains( file ) )
310             {
311                 files.add( file );
312             }
313             else
314             {
315                 addFiles( file, files, expectedDirectories );
316             }
317         }
318     }
319 
320     protected File getBasedir()
321     {
322         if ( basedir != null )
323         {
324             return basedir;
325         }
326 
327         final String basedirString = System.getProperty( "basedir" );
328         if ( basedirString == null )
329         {
330             basedir = new File( "" );
331         }
332         else
333         {
334             basedir = new File( basedirString );
335         }
336         return basedir;
337     }
338 
339     protected File getTestDir( String projectName )
340         throws IOException
341     {
342         return ResourceExtractor.simpleExtractResources( getClass(), "/projects/" + projectName );
343     }
344 
345     // Generated application.xml stuff
346 
347     /**
348      * Asserts that the deployment descriptors have been generated successfully.
349      * <p/>
350      * This test assumes that deployment descriptors are located in the
351      * <tt>expected-META-INF</tt> directory of the project. Note that the
352      * <tt>MANIFEST.mf</tt> file is ignored and is not tested.
353      *
354      * @param baseDir     the directory of the tested project
355      * @param projectName the name of the project
356      */
357     protected void assertDeploymentDescriptors( final File baseDir, final String projectName )
358         throws IOException
359     {
360         final File earDirectory = getEarDirectory( baseDir, projectName );
361         final File[] actualDeploymentDescriptors = getDeploymentDescriptors( new File( earDirectory, "META-INF" ) );
362         final File[] expectedDeploymentDescriptors =
363             getDeploymentDescriptors( new File( baseDir, "expected-META-INF" ) );
364 
365         if ( expectedDeploymentDescriptors == null )
366         {
367             assertNull( "No deployment descriptor was expected", actualDeploymentDescriptors );
368         }
369         else
370         {
371             assertNotNull( "Missing deployment descriptor", actualDeploymentDescriptors );
372 
373             // Make sure we have the same number of files
374             assertEquals( "Number of Deployment descriptor(s) mismatch", expectedDeploymentDescriptors.length,
375                           actualDeploymentDescriptors.length );
376 
377             // Sort the files so that we have the same behavior here
378             Arrays.sort( expectedDeploymentDescriptors );
379             Arrays.sort( actualDeploymentDescriptors );
380 
381             for ( int i = 0; i < expectedDeploymentDescriptors.length; i++ )
382             {
383                 File expectedDeploymentDescriptor = expectedDeploymentDescriptors[i];
384                 File actualDeploymentDescriptor = actualDeploymentDescriptors[i];
385 
386                 assertEquals( "File name mismatch", expectedDeploymentDescriptor.getName(),
387                               actualDeploymentDescriptor.getName() );
388 
389                 Reader expected = null;
390                 Reader actual = null;
391                 try
392                 {
393                     expected = ReaderFactory.newXmlReader( expectedDeploymentDescriptor );
394                     actual = ReaderFactory.newXmlReader( actualDeploymentDescriptor );
395 
396                     // Make sure that it matches even if the elements are not in
397                     // the exact same order
398                     final Diff myDiff = new Diff( expected, actual );
399                     myDiff.overrideElementQualifier( new RecursiveElementNameAndTextQualifier() );
400                     XMLAssert.assertXMLEqual(
401                         "Wrong deployment descriptor generated for[" + expectedDeploymentDescriptor.getName() + "]",
402                         myDiff, true );
403                 }
404                 catch ( Exception e )
405                 {
406                     e.printStackTrace();
407                     fail( "Could not assert deployment descriptor " + e.getMessage() );
408                 }
409                 finally
410                 {
411                     if ( expected != null )
412                     {
413                         expected.close();
414                     }
415                     if ( actual != null )
416                     {
417                         actual.close();
418                     }
419                 }
420             }
421         }
422     }
423 
424     private File[] getDeploymentDescriptors( final File ddDirectory )
425     {
426         return ddDirectory.listFiles( new FilenameFilter()
427         {
428 
429             public boolean accept( File dir, String name )
430             {
431                 return !name.equalsIgnoreCase( "manifest.mf" );
432             }
433         } );
434     }
435 }