View Javadoc
1   package org.codehaus.mojo.jaxb2.schemageneration.postprocessing;
2   
3   import org.apache.maven.plugin.MojoExecutionException;
4   import org.codehaus.mojo.jaxb2.BufferingLog;
5   import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper;
6   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.AbstractSourceCodeAwareNodeProcessingTest;
7   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor;
8   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.NoAuthorJavaDocRenderer;
9   import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation;
10  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdAnnotationProcessor;
11  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdEnumerationAnnotationProcessor;
12  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeNamespacePrefixProcessor;
13  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver;
14  import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema;
15  import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities;
16  import org.codehaus.mojo.jaxb2.shared.filters.Filter;
17  import org.codehaus.mojo.jaxb2.shared.filters.Filters;
18  import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter;
19  import org.custommonkey.xmlunit.Diff;
20  import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
21  import org.custommonkey.xmlunit.XMLAssert;
22  import org.custommonkey.xmlunit.XMLUnit;
23  import org.junit.Assert;
24  import org.junit.BeforeClass;
25  import org.junit.Test;
26  import org.w3c.dom.Document;
27  import se.jguru.shared.algorithms.api.resources.PropertyResources;
28  
29  import javax.xml.parsers.DocumentBuilder;
30  import javax.xml.parsers.DocumentBuilderFactory;
31  import javax.xml.parsers.ParserConfigurationException;
32  import javax.xml.transform.TransformerFactory;
33  import java.io.File;
34  import java.io.StringReader;
35  import java.net.MalformedURLException;
36  import java.net.URL;
37  import java.security.CodeSource;
38  import java.util.ArrayList;
39  import java.util.Collections;
40  import java.util.List;
41  import java.util.Map;
42  
43  /**
44   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>
45   */
46  public class XsdGeneratorHelperTest
47  {
48  
49      private static TransformerFactory factory;
50  
51      @BeforeClass
52      public static void setupSharedState()
53      {
54  
55          // Configure XMLUnit.
56          XMLUnit.setIgnoreWhitespace( true );
57          XMLUnit.setIgnoreAttributeOrder( true );
58  
59          // Configure the TransformerFactory
60          try
61          {
62  
63              factory = TransformerFactory.newInstance();
64              final CodeSource codeSource = factory.getClass().getProtectionDomain().getCodeSource();
65  
66              System.out.println(
67                      "-- Found TransformerFactory of type [" + factory.getClass().getName() + "] loaded from [" + codeSource.getLocation().toString() + "]" );
68  
69          }
70          catch ( Exception ex )
71          {
72              ex.printStackTrace();
73          }
74      }
75  
76      @Test( expected = MojoExecutionException.class )
77      public void validateExceptionThrownOnDuplicateURIs() throws MojoExecutionException
78      {
79  
80          // Assemble
81          final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo" );
82          final TransformSchema transformSchema2 = new TransformSchema( "foo", "bar", "bar" );
83  
84          final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
85          transformSchemas.add( transformSchema1 );
86          transformSchemas.add( transformSchema2 );
87  
88          // Act & Assert
89          XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
90          Assert.fail( "Two schemas with same URIs should yield a MojoExecutionException." );
91      }
92  
93      @Test( expected = MojoExecutionException.class )
94      public void validateExceptionThrownOnDuplicatePrefixes() throws MojoExecutionException
95      {
96  
97          // Assemble
98          final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo" );
99          final TransformSchema transformSchema2 = new TransformSchema( "bar", "foo", "bar" );
100 
101         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
102         transformSchemas.add( transformSchema1 );
103         transformSchemas.add( transformSchema2 );
104 
105         // Act & Assert
106         XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
107         Assert.fail( "Two schemas with same Prefixes should yield a MojoExecutionException." );
108     }
109 
110     @Test
111     public void validateNoExceptionThrownOnDuplicateNullPrefixes()
112     {
113         // Assemble
114         final TransformSchema transformSchema1 = new TransformSchema( "foo", null, "foo" );
115         final TransformSchema transformSchema2 = new TransformSchema( "bar", null, "bar" );
116 
117         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
118         transformSchemas.add( transformSchema1 );
119         transformSchemas.add( transformSchema2 );
120 
121         // Act & Assert
122         try
123         {
124             XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
125         }
126         catch ( MojoExecutionException e )
127         {
128             Assert.fail( "Two schemas with null Prefix should not yield a MojoExecutionException." );
129         }
130     }
131 
132     @Test
133     public void validateExceptionThrownOnDuplicateFiles()
134     {
135 
136         // Assemble
137         final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo.xsd" );
138         final TransformSchema transformSchema2 = new TransformSchema( "bar", "bar", "foo.xsd" );
139 
140         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
141         transformSchemas.add( transformSchema1 );
142         transformSchemas.add( transformSchema2 );
143 
144         // Act & Assert
145         try
146         {
147             XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
148             Assert.fail( "Two schemas with same Files should yield a MojoExecutionException." );
149         }
150         catch ( MojoExecutionException e )
151         {
152             // Validate the error message.
153             String expectedMessage = "Misconfiguration detected: Duplicate 'file' property with value [foo.xsd] " + "found in plugin configuration. Correct schema elements index (0) and (1), " + "to ensure that all 'file' values are unique.";
154             Assert.assertEquals( expectedMessage, e.getLocalizedMessage() );
155         }
156     }
157 
158     @Test( expected = MojoExecutionException.class )
159     public void validateExceptionThrownOnOnlyUriGiven() throws MojoExecutionException
160     {
161         // Assemble
162         final TransformSchema transformSchema1 = new TransformSchema( "foo", null, "" );
163 
164         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
165         transformSchemas.add( transformSchema1 );
166 
167         // Act & Assert
168         XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
169         Assert.fail( "A schema definition with no prefix or file should yield a MojoExecutionException." );
170     }
171 
172     @Test( expected = MojoExecutionException.class )
173     public void validateExceptionThrownOnNullUri() throws MojoExecutionException
174     {
175 
176         // Assemble
177         final TransformSchema transformSchema1 = new TransformSchema( null, "foo", "bar" );
178 
179         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
180         transformSchemas.add( transformSchema1 );
181 
182         // Act & Assert
183         XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
184         Assert.fail( "A schema definition with null URI should yield a MojoExecutionException." );
185     }
186 
187     @Test( expected = MojoExecutionException.class )
188     public void validateExceptionThrownOnEmptyUri() throws MojoExecutionException
189     {
190 
191         // Assemble
192         final TransformSchema transformSchema1 = new TransformSchema( "", "foo", "bar" );
193 
194         final List<TransformSchema> transformSchemas = new ArrayList<TransformSchema>();
195         transformSchemas.add( transformSchema1 );
196 
197         // Act & Assert
198         XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas );
199         Assert.fail( "A schema definition with empty URI should yield a MojoExecutionException." );
200     }
201 
202     @Test
203     public void validateProcessingNodes()
204     {
205 
206         // Assemble
207         final String newPrefix = "changedFoo";
208         final String oldPrefix = "foo";
209         final String originalXml = getXmlDocumentSample( oldPrefix );
210         final String changedXml = getXmlDocumentSample( newPrefix );
211         final NodeProcessor changeNamespacePrefixProcessor = new ChangeNamespacePrefixProcessor( oldPrefix, newPrefix );
212 
213         // Act
214         final Document processedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( originalXml ) );
215         XsdGeneratorHelper.process( processedDocument.getFirstChild(), true, changeNamespacePrefixProcessor );
216 
217         // Assert
218         final Document expectedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( changedXml ) );
219         final Diff diff = new Diff( expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier() );
220         diff.overrideElementQualifier( new ElementNameAndAttributeQualifier() );
221 
222         XMLAssert.assertXMLEqual( processedDocument, expectedDocument );
223     }
224 
225     @Test
226     public void validateProcessingXSDsWithEnumerations() throws Exception
227     {
228 
229         // Assemble
230         final BufferingLog log = new BufferingLog();
231         final JavaDocExtractor extractor = new JavaDocExtractor( log );
232         extractor.setEncoding( "UTF-8" );
233 
234         final String parentPath = "testdata/schemageneration/javadoc/enums/";
235         final URL parentPathURL = getClass().getClassLoader().getResource( parentPath );
236         Assert.assertNotNull( parentPathURL );
237 
238         final File parentDir = new File( parentPathURL.getPath() );
239         Assert.assertTrue( parentDir.exists() && parentDir.isDirectory() );
240 
241         final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>();
242         excludeFilesMatching.add( new PatternFileFilter( Collections.singletonList( "\\.xsd" ) ) );
243         Filters.initialize( log, excludeFilesMatching );
244 
245         final List<File> allSourceFiles = FileSystemUtilities.filterFiles( parentDir, null, parentDir.getAbsolutePath(),
246                 log, "allJavaFiles", excludeFilesMatching );
247         Assert.assertEquals( 3, allSourceFiles.size() );
248 
249         final List<URL> urls = new ArrayList<URL>();
250         for ( File current : allSourceFiles )
251         {
252             try
253             {
254                 urls.add( current.toURI().toURL() );
255             }
256             catch ( MalformedURLException e )
257             {
258                 throw new IllegalArgumentException(
259                         "Could not convert file [" + current.getAbsolutePath() + "] to a URL", e );
260             }
261         }
262         Assert.assertEquals( 3, urls.size() );
263 
264         extractor.addSourceURLs( urls );
265         final SearchableDocumentation docs = extractor.process();
266 
267         // #1) The raw / un-processed XSD (containing the 'before' state)
268         // #2) The processed XSD (containing the 'expected' state)
269         final String rawEnumSchema = PropertyResources.readFully( parentPath + "rawEnumSchema.xsd" );
270         final String processedEnumSchema = PropertyResources.readFully( parentPath + "processedEnumSchema.xsd" );
271         final NodeProcessor enumProcessor = new XsdEnumerationAnnotationProcessor( docs,
272                 new NoAuthorJavaDocRenderer() );
273 
274         // Act
275         final Document processedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( rawEnumSchema ) );
276         XsdGeneratorHelper.process( processedDocument.getFirstChild(), true, enumProcessor );
277         // System.out.println("Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument(processedDocument));
278 
279         // Assert
280         final Document expectedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( processedEnumSchema ) );
281         final Diff diff = new Diff( expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier() );
282         diff.overrideElementQualifier( new ElementNameAndAttributeQualifier() );
283 
284         XMLAssert.assertXMLEqual( processedDocument, expectedDocument );
285     }
286 
287     @Test
288     public void validateXmlDocumentationForWrappers() throws Exception
289     {
290 
291         // Assemble
292         final BufferingLog log = new BufferingLog();
293         final JavaDocExtractor extractor = new JavaDocExtractor( log );
294         extractor.setEncoding( "UTF-8" );
295 
296         final String parentPath = "testdata/schemageneration/javadoc/xmlwrappers/";
297         final URL parentPathURL = getClass().getClassLoader().getResource( parentPath );
298         Assert.assertNotNull( parentPathURL );
299 
300         final String schemaGenCreatedSchema = PropertyResources.readFully( parentPath + "expectedRawXmlWrappers.xsd" );
301 
302         final File parentDir = new File( parentPathURL.getPath() );
303         Assert.assertTrue( parentDir.exists() && parentDir.isDirectory() );
304 
305         final List<Filter<File>> excludeFilesMatching = new ArrayList<Filter<File>>();
306         excludeFilesMatching.add( new PatternFileFilter( Collections.singletonList( "\\.xsd" ) ) );
307         Filters.initialize( log, excludeFilesMatching );
308 
309         final List<File> allSourceFiles = FileSystemUtilities.filterFiles( parentDir, null, parentDir.getAbsolutePath(),
310                 log, "allJavaFiles", excludeFilesMatching );
311         Assert.assertEquals( 2, allSourceFiles.size() );
312 
313         final List<URL> urls = new ArrayList<URL>();
314         for ( File current : allSourceFiles )
315         {
316             try
317             {
318                 urls.add( current.toURI().toURL() );
319             }
320             catch ( MalformedURLException e )
321             {
322                 throw new IllegalArgumentException(
323                         "Could not convert file [" + current.getAbsolutePath() + "] to a URL", e );
324             }
325         }
326         Assert.assertEquals( 2, urls.size() );
327 
328         // Act
329         extractor.addSourceURLs( urls );
330         final SearchableDocumentation docs = extractor.process();
331 
332         final XsdAnnotationProcessor processor = new XsdAnnotationProcessor( docs, new NoAuthorJavaDocRenderer() );
333         final Document schemaGenCreatedDocument = XsdGeneratorHelper.parseXmlStream(
334                 new StringReader( schemaGenCreatedSchema ) );
335         XsdGeneratorHelper.process( schemaGenCreatedDocument.getFirstChild(), true, processor );
336         System.out.println(
337                 "Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument( schemaGenCreatedDocument ) );
338 
339         // Assert
340     }
341 
342     @Test
343     public void validateAcquiringFilenameToResolverMap() throws MojoExecutionException
344     {
345 
346         // Assemble
347         final String[] expectedFilenames = {"schema1.xsd", "schema2.xsd", "schema3.xsd"};
348         final URL tmpUrl = getClass().getClassLoader().getResource( "generated/schema/schema1.xsd" );
349         final File directory = new File( tmpUrl.getFile() ).getParentFile();
350 
351         // Act
352         final Map<String, SimpleNamespaceResolver> fileNameToResolverMap = XsdGeneratorHelper.getFileNameToResolverMap(
353                 directory );
354 
355         // Assert
356         Assert.assertEquals( 3, fileNameToResolverMap.size() );
357         for ( String current : expectedFilenames )
358         {
359             Assert.assertTrue( fileNameToResolverMap.keySet().contains( current ) );
360         }
361 
362         SimpleNamespaceResolver schema1Resolver = fileNameToResolverMap.get( "schema1.xsd" );
363         Assert.assertEquals( "http://yet/another/namespace", schema1Resolver.getLocalNamespaceURI() );
364         Assert.assertEquals( "schema1.xsd", schema1Resolver.getSourceFilename() );
365         final Map<String, String> schema1NamespaceURI2PrefixMap = schema1Resolver.getNamespaceURI2PrefixMap();
366         Assert.assertEquals( 1, schema1NamespaceURI2PrefixMap.size() );
367         Assert.assertEquals( "xs", schema1NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) );
368 
369         SimpleNamespaceResolver schema2Resolver = fileNameToResolverMap.get( "schema2.xsd" );
370         Assert.assertEquals( "http://some/namespace", schema2Resolver.getLocalNamespaceURI() );
371         Assert.assertEquals( "schema2.xsd", schema2Resolver.getSourceFilename() );
372         final Map<String, String> schema2NamespaceURI2PrefixMap = schema2Resolver.getNamespaceURI2PrefixMap();
373         Assert.assertEquals( 2, schema2NamespaceURI2PrefixMap.size() );
374         Assert.assertEquals( "ns1", schema2NamespaceURI2PrefixMap.get( "http://another/namespace" ) );
375         Assert.assertEquals( "xs", schema2NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) );
376 
377         SimpleNamespaceResolver schema3Resolver = fileNameToResolverMap.get( "schema3.xsd" );
378         Assert.assertEquals( "http://another/namespace", schema3Resolver.getLocalNamespaceURI() );
379         Assert.assertEquals( "schema3.xsd", schema3Resolver.getSourceFilename() );
380         final Map<String, String> schema3NamespaceURI2PrefixMap = schema3Resolver.getNamespaceURI2PrefixMap();
381         Assert.assertEquals( 3, schema3NamespaceURI2PrefixMap.size() );
382         Assert.assertEquals( "ns2", schema3NamespaceURI2PrefixMap.get( "http://yet/another/namespace" ) );
383         Assert.assertEquals( "ns1", schema3NamespaceURI2PrefixMap.get( "http://some/namespace" ) );
384         Assert.assertEquals( "xs", schema3NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) );
385     }
386 
387     //
388     // Private helpers
389     //
390 
391     private static DocumentBuilderFactory getDocumentBuilderFactory()
392     {
393 
394         final DocumentBuilderFactory toReturn = DocumentBuilderFactory.newInstance();
395         toReturn.setNamespaceAware( true );
396         return toReturn;
397     }
398 
399     private static DocumentBuilder getDocumentBuilder()
400     {
401         try
402         {
403             return getDocumentBuilderFactory().newDocumentBuilder();
404         }
405         catch ( ParserConfigurationException e )
406         {
407             throw new IllegalStateException( "Could not create DocumentBuilder", e );
408         }
409     }
410 
411     private static Document createEmptyDocument( final DocumentBuilder builder )
412     {
413         return builder.newDocument();
414     }
415 
416     private String getXmlDocumentSample( final String namespace )
417     {
418         return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" + "           xmlns:" + namespace + "=\"http://the/foo/namespace\" \n"
419                 // + "           targetNamespace=\"http://yet/another/namespace\"\n"
420                 + "           version=\"1.0\">\n" + "    <xs:element name=\"aRequiredElementInYetAnotherNamespace\" type=\"xs:string\"/>\n" + "    <" + namespace + ":aBar name=\"aFooElement\" />\n" + "</xs:schema>\n";
421     }
422 }