View Javadoc

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