View Javadoc
1   /*
2    *   Copyright (C) Christian Schulte <cs@schulte.it>, 2005-206
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: AbstractClassesCommitMojo.java 5043 2015-05-27 07:03:39Z schulte $
29   *
30   */
31  package org.jomc.mojo;
32  
33  import java.io.File;
34  import java.util.ArrayList;
35  import java.util.List;
36  import java.util.logging.Level;
37  import javax.xml.bind.JAXBContext;
38  import javax.xml.bind.util.JAXBSource;
39  import javax.xml.transform.Source;
40  import javax.xml.transform.Transformer;
41  import org.apache.maven.plugin.MojoExecutionException;
42  import org.apache.maven.plugin.MojoFailureException;
43  import org.jomc.model.Module;
44  import org.jomc.modlet.ModelContext;
45  import org.jomc.modlet.ModelValidationReport;
46  import org.jomc.modlet.ObjectFactory;
47  import org.jomc.tools.ClassFileProcessor;
48  
49  /**
50   * Base class for committing model objects to class files.
51   *
52   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
53   * @version $JOMC: AbstractClassesCommitMojo.java 5043 2015-05-27 07:03:39Z schulte $
54   */
55  public abstract class AbstractClassesCommitMojo extends AbstractJomcMojo
56  {
57  
58      /**
59       * Constant for the name of the tool backing the mojo.
60       */
61      private static final String TOOLNAME = "ClassFileProcessor";
62  
63      /**
64       * XSLT document to use for transforming model objects.
65       * <p>The value of the parameter is a location to search a XSLT document at. First the value is used to search the
66       * class path of the plugin. If a class path resource is found, a XSLT document is loaded from that resource. If no
67       * class path resource is found, an attempt is made to parse the value to an URL. Succeeding that, an XSLT document
68       * is loaded from that URL (since version 1.2). Failing that, the value is interpreted as a file name of a XSLT
69       * document to load relative to the base directory of the project. If that file exists, a XSLT document is loaded
70       * from that file. If no XSLT document is found at the given location, a build failure is produced.</p>
71       * <p><b>Note:</b> When upgrading to version 1.2, any project dependencies holding XSLT documents referenced by this
72       * parameter need to be added to the plugins' dependencies.</p>
73       * <p><strong>Deprecated:</strong> As of JOMC 1.2, please use the 'modelObjectStylesheetResources' parameter. This
74       * parameter will be removed in version 2.0.</p>
75       *
76       * @parameter
77       */
78      @Deprecated
79      private String modelObjectStylesheet;
80  
81      /**
82       * XSLT documents to use for transforming model objects.
83       * <pre>
84       * &lt;modelObjectStylesheetResources>
85       *   &lt;modelObjectStylesheetResource>
86       *     &lt;location>The location of the XSLT document.&lt;/location>
87       *     &lt;optional>Flag indicating the XSLT document is optional.&lt;/optional>
88       *     &lt;connectTimeout>Timeout value, in milliseconds.&lt;/connectTimeout>
89       *     &lt;readTimeout>Timeout value, in milliseconds.&lt;/readTimeout>
90       *     &lt;transformationParameterResources>
91       *       &lt;transformationParameterResource>
92       *         &lt;location>The location of the properties resource.&lt;/location>
93       *         &lt;optional>Flag indicating the properties resource is optional.&lt;/optional>
94       *         &lt;format>The format of the properties resource.&lt;/format>
95       *         &lt;connectTimeout>Timeout value, in milliseconds.&lt;/connectTimeout>
96       *         &lt;readTimeout>Timeout value, in milliseconds.&lt;/readTimeout>
97       *       &lt;/transformationParameterResource>
98       *     &lt;/transformationParameterResources>
99       *     &lt;transformationParameters>
100      *       &lt;transformationParameter>
101      *         &lt;key>The name of the parameter.&lt;/key>
102      *         &lt;value>The value of the parameter.&lt;/value>
103      *         &lt;type>The name of the class of the parameter's object.&lt;/type>
104      *       &lt;/transformationParameter>
105      *     &lt;/transformationParameters>
106      *     &lt;transformationOutputProperties>
107      *       &lt;transformationOutputProperty>
108      *         &lt;key>The name of the property.&lt;/key>
109      *         &lt;value>The value of the property.&lt;/value>
110      *         &lt;type>The name of the class of the properties object.&lt;/type>
111      *       &lt;/transformationOutputProperty>
112      *     &lt;/transformationOutputProperties>
113      *   &lt;/modelObjectStylesheetResource>
114      * &lt;/modelObjectStylesheetResources>
115      * </pre>
116      * <p>
117      * The location value is used to first search the class path of the plugin and the project's main or test class
118      * path. If a class path resource is found, that resource is used. If no class path resource is found, an attempt is
119      * made to parse the location value to an URL. On successful parsing, that URL is used. Otherwise the location value
120      * is interpreted as a file name relative to the base directory of the project. If that file exists, that file is
121      * used. If nothing is found at the given location, depending on the optional flag, a warning message is logged or a
122      * build failure is produced.
123      * </p>
124      * <p>
125      * The optional flag is used to flag the resource optional. When an optional resource is not found, a warning
126      * message is logged instead of producing a build failure.<br/><b>Default value is:</b> false
127      * </p>
128      * <p>
129      * The connectTimeout value is used to specify the timeout, in milliseconds, to be used when opening
130      * communications links to the resource. A timeout of zero is interpreted as an infinite timeout.<br/>
131      * <b>Default value is:</b> 60000
132      * </p>
133      * <p>
134      * The readTimeout value is used to specify the timeout, in milliseconds, to be used when reading the resource.
135      * A timeout of zero is interpreted as an infinite timeout.<br/>
136      * <b>Default value is:</b> 60000
137      * </p>
138      *
139      * @parameter
140      * @since 1.2
141      */
142     private List<ModelObjectStylesheetResource> modelObjectStylesheetResources;
143 
144     /**
145      * Creates a new {@code AbstractClassesCommitMojo} instance.
146      */
147     public AbstractClassesCommitMojo()
148     {
149         super();
150     }
151 
152     /**
153      * Gets transformers to use for transforming model objects.
154      *
155      * @param classLoader The class loader to use for loading a transformer class path resource.
156      *
157      * @return A list of transformers to use for transforming model objects.
158      *
159      * @throws NullPointerException if {@code classLoader} is {@code null}.
160      * @throws MojoExecutionException if getting the transformers fails.
161      *
162      * @deprecated As of JOMC 1.2, the dependencies of the project are no longer searched for XSLT documents. Please
163      * use method {@link #getTransformers()}. This method will be removed in version 2.0.
164      */
165     @Deprecated
166     protected List<Transformer> getTransformers( final ClassLoader classLoader ) throws MojoExecutionException
167     {
168         if ( classLoader == null )
169         {
170             throw new NullPointerException( "classLoader" );
171         }
172 
173         return this.getTransformers();
174     }
175 
176     /**
177      * Gets transformers to use for transforming model objects.
178      *
179      * @return A list of transformers to use for transforming model objects.
180      *
181      * @throws MojoExecutionException if getting the transformers fails.
182      *
183      * @since 1.2
184      * @deprecated As of JOMC 1.8, replaced by method {@link #getTransformers(org.jomc.modlet.ModelContext)}. This
185      * method will be removed in JOMC 2.0.
186      */
187     @Deprecated
188     @SuppressWarnings( "deprecation" )
189     protected List<Transformer> getTransformers() throws MojoExecutionException
190     {
191         final List<Transformer> transformers = new ArrayList<Transformer>(
192             this.modelObjectStylesheetResources != null ? this.modelObjectStylesheetResources.size() + 1 : 1 );
193 
194         if ( this.modelObjectStylesheet != null )
195         {
196             final TransformerResourceType r = new TransformerResourceType();
197             r.setLocation( this.modelObjectStylesheet );
198 
199             final Transformer transformer = this.getTransformer( r );
200 
201             if ( transformer != null )
202             {
203                 transformers.add( transformer );
204             }
205         }
206 
207         if ( this.modelObjectStylesheetResources != null )
208         {
209             for ( int i = 0, s0 = this.modelObjectStylesheetResources.size(); i < s0; i++ )
210             {
211                 final Transformer transformer = this.getTransformer( this.modelObjectStylesheetResources.get( i ) );
212 
213                 if ( transformer != null )
214                 {
215                     transformers.add( transformer );
216                 }
217             }
218         }
219 
220         return transformers;
221     }
222 
223     /**
224      * Gets transformers to use for transforming model objects.
225      *
226      * @param modelContext The model context to search.
227      *
228      * @return A list of transformers to use for transforming model objects.
229      *
230      * @throws NullPointerException if {@code modelContext} is {@code null}.
231      * @throws MojoExecutionException if getting the transformers fails.
232      *
233      * @since 1.8
234      */
235     protected List<Transformer> getTransformers( final ModelContext modelContext ) throws MojoExecutionException
236     {
237         if ( modelContext == null )
238         {
239             throw new NullPointerException( "modelContext" );
240         }
241 
242         final List<Transformer> transformers = new ArrayList<Transformer>(
243             this.modelObjectStylesheetResources != null ? this.modelObjectStylesheetResources.size() : 0 );
244 
245         if ( this.modelObjectStylesheetResources != null )
246         {
247             for ( int i = 0, s0 = this.modelObjectStylesheetResources.size(); i < s0; i++ )
248             {
249                 final Transformer transformer =
250                     this.getTransformer( modelContext, this.modelObjectStylesheetResources.get( i ) );
251 
252                 if ( transformer != null )
253                 {
254                     transformers.add( transformer );
255                 }
256             }
257         }
258 
259         return transformers;
260     }
261 
262     @Override
263     protected void assertValidParameters() throws MojoFailureException
264     {
265         super.assertValidParameters();
266         this.assertValidResources( this.modelObjectStylesheetResources );
267     }
268 
269     @Override
270     protected final void executeTool() throws Exception
271     {
272         this.logSeparator();
273 
274         if ( this.isClassProcessingEnabled() )
275         {
276             this.logProcessingModule( TOOLNAME, this.getClassesModuleName() );
277 
278             final ClassLoader classLoader = this.getClassesClassLoader();
279             final ModelContext context = this.createModelContext( classLoader );
280             final ClassFileProcessor tool = this.createClassFileProcessor( context );
281             final JAXBContext jaxbContext = context.createContext( this.getModel() );
282             final List<Transformer> transformers = this.getTransformers( context );
283             final Source source = new JAXBSource( jaxbContext, new ObjectFactory().createModel( tool.getModel() ) );
284             final ModelValidationReport validationReport = context.validateModel( this.getModel(), source );
285 
286             this.log( context, validationReport.isModelValid() ? Level.INFO : Level.SEVERE, validationReport );
287 
288             if ( validationReport.isModelValid() )
289             {
290                 final Module module =
291                     tool.getModules() != null ? tool.getModules().getModule( this.getClassesModuleName() ) : null;
292 
293                 if ( module != null )
294                 {
295                     tool.commitModelObjects( module, context, this.getClassesDirectory() );
296 
297                     if ( !transformers.isEmpty() )
298                     {
299                         tool.transformModelObjects( module, context, this.getClassesDirectory(), transformers );
300                     }
301 
302                     this.logToolSuccess( TOOLNAME );
303                 }
304                 else
305                 {
306                     this.logMissingModule( this.getClassesModuleName() );
307                 }
308             }
309             else
310             {
311                 throw new MojoExecutionException( Messages.getMessage( "classFileProcessingFailure" ) );
312             }
313         }
314         else if ( this.isLoggable( Level.INFO ) )
315         {
316             this.log( Level.INFO, Messages.getMessage( "classFileProcessingDisabled" ), null );
317         }
318     }
319 
320     /**
321      * Gets the name of the module to commit class file model objects of.
322      *
323      * @return The name of the module to commit class file model objects of.
324      *
325      * @throws MojoExecutionException if getting the name fails.
326      */
327     protected abstract String getClassesModuleName() throws MojoExecutionException;
328 
329     /**
330      * Gets the class loader to use for committing class file model objects.
331      *
332      * @return The class loader to use for committing class file model objects.
333      *
334      * @throws MojoExecutionException if getting the class loader fails.
335      */
336     protected abstract ClassLoader getClassesClassLoader() throws MojoExecutionException;
337 
338     /**
339      * Gets the directory holding the class files to commit model objects to.
340      *
341      * @return The directory holding the class files to commit model objects to.
342      *
343      * @throws MojoExecutionException if getting the directory fails.
344      */
345     protected abstract File getClassesDirectory() throws MojoExecutionException;
346 
347 }