View Javadoc
1   package org.codehaus.mojo.jaxb2.javageneration;
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 org.apache.maven.artifact.DependencyResolutionRequiredException;
23  import org.apache.maven.model.Resource;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugins.annotations.LifecyclePhase;
26  import org.apache.maven.plugins.annotations.Mojo;
27  import org.apache.maven.plugins.annotations.Parameter;
28  import org.apache.maven.plugins.annotations.ResolutionScope;
29  import org.codehaus.mojo.jaxb2.AbstractJaxbMojo;
30  import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities;
31  import org.codehaus.mojo.jaxb2.shared.filters.Filter;
32  import org.codehaus.mojo.jaxb2.shared.filters.Filters;
33  import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter;
34  
35  import java.io.File;
36  import java.net.URL;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.Collections;
40  import java.util.List;
41  
42  /**
43   * <p>Mojo that creates test-scope Java source or binaries from XML schema(s)
44   * by invoking the JAXB XJC binding compiler. This implementation is tailored
45   * to use the JAXB Reference Implementation from project Kenai.</p>
46   * <p>Note that the TestXjcMojo was completely re-implemented for the 2.x versions.
47   * Its configuration semantics and parameter set is <strong>not necessarily
48   * backwards compatible</strong> with the 1.x plugin versions. If you are
49   * upgrading from version 1.x of the plugin, read the documentation carefully.</p>
50   *
51   * @author <a href="mailto:lj@jguru.se">Lennart J&ouml;relid</a>
52   * @see <a href="https://jaxb.java.net/">The JAXB Reference Implementation</a>
53   */
54  @Mojo(name = "testXjc",
55          defaultPhase = LifecyclePhase.GENERATE_TEST_SOURCES,
56          requiresDependencyResolution = ResolutionScope.TEST,
57          threadSafe = false)
58  public class TestXjcMojo extends AbstractJavaGeneratorMojo {
59  
60      /**
61       * The last part of the stale fileName for this TestXjcMojo.
62       */
63      public static final String STALE_FILENAME = "testXjcStaleFlag";
64  
65      /**
66       * Standard directory path (relative to basedir) searched recursively for test
67       * source files (typically XSDs), unless overridden by an <code>testSources</code> configuration element.
68       */
69      public static final String STANDARD_TEST_SOURCE_DIRECTORY = "src/test/xsd";
70  
71      /**
72       * Default exclude Filters for test sources, used unless overridden by an
73       * explicit configuration in the {@code testSourceExcludeFilters} parameter.
74       */
75      public static final List<Filter<File>> STANDARD_TEST_SOURCE_EXCLUDE_FILTERS;
76  
77      /**
78       * <p>Standard directory path (relative to basedir) searched recursively for XJB
79       * files, unless overridden by an <code>testXjbSources</code> configuration element.
80       * As explained in the JAXB specification, XJB files (JAXB Xml Binding files)
81       * are used to configure parts of the Java source generation.</p>
82       */
83      public static final String STANDARD_TEST_XJB_DIRECTORY = "src/test/xjb";
84  
85      /**
86       * Default List of exclude Filters for XJB files, unless overridden by providing
87       * an explicit configuration in the {@code testXjbExcludeFilters} parameter.
88       */
89      public static final List<Filter<File>> STANDARD_TEST_XJB_EXCLUDE_FILTERS;
90  
91      static {
92  
93          final List<Filter<File>> xjbTemp = new ArrayList<Filter<File>>();
94          xjbTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
95          xjbTemp.add(new PatternFileFilter(Arrays.asList("\\.xsd"), true));
96          STANDARD_TEST_XJB_EXCLUDE_FILTERS = Collections.unmodifiableList(xjbTemp);
97  
98          final List<Filter<File>> xsdTemp = new ArrayList<Filter<File>>();
99          xsdTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
100         xsdTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb"), true));
101         STANDARD_TEST_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(xsdTemp);
102     }
103 
104     /**
105      * <p>Corresponding XJC parameter: {@code d}.</p>
106      * <p>The working directory where the generated Java test source files are created.</p>
107      */
108     @Parameter(defaultValue = "${project.build.directory}/generated-test-sources/jaxb", required = true)
109     private File outputDirectory;
110 
111     /**
112      * <p>Parameter holding List of XSD paths to files and/or directories which should be recursively searched
113      * for XSD files. Only files or directories that actually exist will be included (in the case of files)
114      * or recursively searched for XSD files to include (in the case of directories).
115      * Configure using standard Maven structure for Lists:</p>
116      * <pre>
117      * <code>
118      *   &lt;configuration>
119      *   ...
120      *       &lt;testSources>
121      *          &lt;testSource>some/explicit/relative/file.xsd&lt;/testSource>
122      *          &lt;testSource>/another/absolute/path/to/a/specification.xsd&lt;/testSource>
123      *          &lt;testSource>a/directory/holding/xsds&lt;/testSource>
124      *      &lt;/testSources>
125      *   &lt;/configuration>
126      * </code>
127      * </pre>
128      *
129      * @see #STANDARD_TEST_SOURCE_DIRECTORY
130      */
131     @Parameter(required = false)
132     private List<String> testSources;
133 
134     /**
135      * <p>Parameter holding List of XJB Files and/or directories which should be recursively searched
136      * for XJB files. Only files or directories that actually exist will be included (in the case of files)
137      * or recursively searched for XJB files to include (in the case of directories). JAXB binding files are
138      * used to configure parts of the Java source generation.
139      * Supply the configuration using the standard Maven structure for configuring plugin Lists:</p>
140      * <pre>
141      * <code>
142      *   &lt;configuration>
143      *   ...
144      *       &lt;testXjbSources>
145      *          &lt;testXjbSource>bindings/aBindingConfiguration.xjb&lt;/testXjbSource>
146      *          &lt;testXjbSource>bindings/config/directory&lt;/testXjbSource>
147      *      &lt;/testXjbSources>
148      *   &lt;/configuration>
149      * </code>
150      * </pre>
151      *
152      * @see #STANDARD_TEST_XJB_DIRECTORY
153      */
154     @Parameter(required = false)
155     private List<String> testXjbSources;
156 
157     /**
158      * <p>Parameter holding a List of Filters, used to match all files under the {@code testSources} directories
159      * which should <strong>not</strong> be considered XJC test source files. (The filters identify files to
160      * exclude, and hence this parameter is called {@code testS§ourceExcludeFilters}). If a file under any of the
161      * test source directories matches at least one of the Filters supplied in the {@code testSourceExcludeFilters},
162      * it is not considered an XJC source file, and therefore excluded from processing.</p>
163      * <p>If not explicitly provided, the Mojo uses the value within {@code STANDARD_TEST_SOURCE_EXCLUDE_FILTERS}.
164      * The algorithm for finding XJC test sources is as follows:</p>
165      * <ol>
166      * <li>Find all files given in the testSources List. Any Directories provided are searched for files
167      * recursively.</li>
168      * <li>Exclude any found files matching any of the supplied {@code testSourceExcludeFilters} List.</li>
169      * <li>The remaining Files are submitted for processing by the XJC tool.</li>
170      * </ol>
171      * <p><strong>Example:</strong> The following configuration would exclude any sources whose names end with
172      * {@code txt} or {@code foo}:</p>
173      * <pre>
174      *     <code>
175      *         &lt;configuration>
176      *         ...
177      *              &lt;testSourceExcludeFilters>
178      *                  &lt;suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">txt&lt;/suffixFilter>
179      *                  &lt;suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">foo&lt;/suffixFilter>
180      *              &lt;/testSourceExcludeFilters>
181      *         &lt;/configuration>
182      *     </code>
183      * </pre>
184      *
185      * @see #STANDARD_TEST_SOURCE_EXCLUDE_FILTERS
186      * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter
187      * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter
188      * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter
189      */
190     @Parameter(required = false)
191     private List<Filter<File>> testSourceExcludeFilters;
192 
193     /***
194      * <p>Parameter holding a List of Filters, used to match all files under the {@code testXjbSources} directories
195      * which should <strong>not</strong> be considered XJB files. (The filters identify files to exclude, and hence
196      * this parameter is called {@code testXjbExcludeFilters}). If a file matches at least one of the supplied Filters,
197      * it is not considered an XJB file, and therefore excluded from processing.</p>
198      * <p>If not explicitly provided, the Mojo uses the value within {@code STANDARD_TEST_XJB_EXCLUDE_FILTERS}.</p>
199      * <p><strong>Example:</strong> The following configuration would exclude any XJB files whose names end with
200      * {@code xml} or {@code foo}:</p>
201      * <pre>
202      *     <code>
203      *         &lt;configuration>
204      *         ...
205      *              &lt;testXjbExcludeFilters>
206      *                  &lt;suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">xml&lt;/suffixFilter>
207      *                  &lt;suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">foo&lt;/suffixFilter>
208      *              &lt;/sourceExcludeFilters>
209      *         &lt;/testXjbExcludeFilters>
210      *     </code>
211      * </pre>
212      *
213      * @see #STANDARD_TEST_XJB_EXCLUDE_FILTERS
214      * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter
215      * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter
216      * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter
217      */
218     @Parameter(required = false)
219     private List<Filter<File>> testXjbExcludeFilters;
220 
221     /**
222      * Indicate if the XjcMojo execution should be skipped.
223      */
224     @Parameter(property = "xjc.test.skip", defaultValue = "false")
225     private boolean skipTestXjc;
226 
227     /**
228      * {@inheritDoc}
229      */
230     @Override
231     protected boolean shouldExecutionBeSkipped() {
232         return skipTestXjc;
233     }
234 
235     /**
236      * {@inheritDoc}
237      */
238     @Override
239     protected List<URL> getSources() {
240 
241         final List<Filter<File>> excludePatterns = testSourceExcludeFilters == null
242                 ? STANDARD_TEST_SOURCE_EXCLUDE_FILTERS
243                 : testSourceExcludeFilters;
244         Filters.initialize(getLog(), excludePatterns);
245 
246         // All done.
247         return FileSystemUtilities.filterFiles(
248                 getProject().getBasedir(),
249                 testSources,
250                 Arrays.asList(STANDARD_TEST_SOURCE_DIRECTORY),
251                 getLog(),
252                 "testSources",
253                 excludePatterns);
254     }
255 
256     /**
257      * {@inheritDoc}
258      */
259     @Override
260     protected List<File> getSourceXJBs() {
261 
262         final List<Filter<File>> excludePatterns = testXjbExcludeFilters == null
263                 ? STANDARD_TEST_XJB_EXCLUDE_FILTERS
264                 : testXjbExcludeFilters;
265         Filters.initialize(getLog(), excludePatterns);
266 
267         return FileSystemUtilities.filterFiles(
268                 getProject().getBasedir(),
269                 testXjbSources,
270                 STANDARD_TEST_XJB_DIRECTORY,
271                 getLog(),
272                 "testXjbSources",
273                 excludePatterns);
274     }
275 
276     /**
277      * {@inheritDoc}
278      */
279     @Override
280     protected String getStaleFileName() {
281         return STALE_FILENAME;
282     }
283 
284     /**
285      * {@inheritDoc}
286      */
287     @Override
288     protected File getOutputDirectory() {
289         return outputDirectory;
290     }
291 
292     /**
293      * {@inheritDoc}
294      */
295     @Override
296     protected List<String> getClasspath() throws MojoExecutionException {
297         try {
298             return (List<String>) getProject().getTestClasspathElements();
299         } catch (DependencyResolutionRequiredException e) {
300             throw new MojoExecutionException("Could not retrieve Compile classpath.", e);
301         }
302     }
303 
304     /**
305      * {@inheritDoc}
306      */
307     @Override
308     protected void addGeneratedSourcesToProjectSourceRoot() {
309         getProject().addTestCompileSourceRoot(getOutputDirectory().getAbsolutePath());
310     }
311 
312     /**
313      * {@inheritDoc}
314      */
315     @Override
316     protected void addResource(final Resource resource) {
317         getProject().addTestResource(resource);
318     }
319 }