1 /*
2 * Copyright (C) Christian Schulte, 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 4613 2012-09-22 10:07:08Z 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 4613 2012-09-22 10:07:08Z schulte $
54 */
55 public abstract class AbstractClassesCommitMojo extends AbstractJomcMojo
56 {
57
58 /** Constant for the name of the tool backing the mojo. */
59 private static final String TOOLNAME = "ClassFileProcessor";
60
61 /**
62 * XSLT document to use for transforming model objects.
63 * <p>The value of the parameter is a location to search a XSLT document at. First the value is used to search the
64 * class path of the plugin. If a class path resource is found, a XSLT document is loaded from that resource. If no
65 * class path resource is found, an attempt is made to parse the value to an URL. Succeeding that, an XSLT document
66 * is loaded from that URL (since version 1.2). Failing that, the value is interpreted as a file name of a XSLT
67 * document to load relative to the base directory of the project. If that file exists, a XSLT document is loaded
68 * from that file. If no XSLT document is found at the given location, a build failure is produced.</p>
69 * <p><b>Note:</b> When upgrading to version 1.2, any project dependencies holding XSLT documents referenced by this
70 * parameter need to be added to the plugins' dependencies.</p>
71 * <p><strong>Deprecated:</strong> As of JOMC 1.2, please use the 'modelObjectStylesheetResources' parameter. This
72 * parameter will be removed in version 2.0.</p>
73 *
74 * @parameter
75 */
76 @Deprecated
77 private String modelObjectStylesheet;
78
79 /**
80 * XSLT documents to use for transforming model objects.
81 * <pre>
82 * <modelObjectStylesheetResources>
83 * <modelObjectStylesheetResource>
84 * <location>The location of the XSLT document.</location>
85 * <optional>Flag indicating the XSLT document is optional.</optional>
86 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout>
87 * <readTimeout>Timeout value, in milliseconds.</readTimeout>
88 * <transformationParameterResources>
89 * <transformationParameterResource>
90 * <location>The location of the properties resource.</location>
91 * <optional>Flag indicating the properties resource is optional.</optional>
92 * <format>The format of the properties resource.</format>
93 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout>
94 * <readTimeout>Timeout value, in milliseconds.</readTimeout>
95 * </transformationParameterResource>
96 * </transformationParameterResources>
97 * <transformationParameters>
98 * <transformationParameter>
99 * <key>The name of the parameter.</key>
100 * <value>The value of the parameter.</value>
101 * <type>The name of the class of the parameter's object.</type>
102 * </transformationParameter>
103 * </transformationParameters>
104 * <transformationOutputProperties>
105 * <transformationOutputProperty>
106 * <key>The name of the property.</key>
107 * <value>The value of the property.</value>
108 * <type>The name of the class of the properties object.</type>
109 * </transformationOutputProperty>
110 * </transformationOutputProperties>
111 * </modelObjectStylesheetResource>
112 * </modelObjectStylesheetResources>
113 * </pre>
114 * <p>The location value is used to first search the class path of the plugin. If a class path resource is found,
115 * that resource is used. If no class path resource is found, an attempt is made to parse the location value to an
116 * URL. On successful parsing, that URL is used. Otherwise the location value is interpreted as a file name relative
117 * to the base directory of the project. If that file exists, that file is used. If nothing is found at the given
118 * location, depending on the optional flag, a warning message is logged or a build failure is produced.</p>
119 * <p>The optional flag is used to flag the resource optional. When an optional resource is not found, a warning
120 * message is logged instead of producing a build failure.<br/><b>Default value is:</b> false</p>
121 * <p>The connectTimeout value is used to specify the timeout, in milliseconds, to be used when opening
122 * communications links to the resource. A timeout of zero is interpreted as an infinite timeout.<br/>
123 * <b>Default value is:</b> 60000</p>
124 * <p>The readTimeout value is used to specify the timeout, in milliseconds, to be used when reading the resource.
125 * A timeout of zero is interpreted as an infinite timeout.<br/>
126 * <b>Default value is:</b> 60000</p>
127 *
128 * @parameter
129 * @since 1.2
130 */
131 private List<ModelObjectStylesheetResource> modelObjectStylesheetResources;
132
133 /** Creates a new {@code AbstractClassesCommitMojo} instance. */
134 public AbstractClassesCommitMojo()
135 {
136 super();
137 }
138
139 /**
140 * Gets transformers to use for transforming model objects.
141 *
142 * @param classLoader The class loader to use for loading a transformer class path resource.
143 *
144 * @return A list of transformers to use for transforming model objects.
145 *
146 * @throws NullPointerException if {@code classLoader} is {@code null}.
147 * @throws MojoExecutionException if getting the transformers fails.
148 *
149 * @deprecated As of JOMC 1.2, the dependencies of the project are no longer searched for XSLT documents. Please
150 * use method {@link #getTransformers()}. This method will be removed in version 2.0.
151 */
152 @Deprecated
153 protected List<Transformer> getTransformers( final ClassLoader classLoader ) throws MojoExecutionException
154 {
155 if ( classLoader == null )
156 {
157 throw new NullPointerException( "classLoader" );
158 }
159
160 return this.getTransformers();
161 }
162
163 /**
164 * Gets transformers to use for transforming model objects.
165 *
166 * @return A list of transformers to use for transforming model objects.
167 *
168 * @throws MojoExecutionException if getting the transformers fails.
169 *
170 * @since 1.2
171 */
172 protected List<Transformer> getTransformers() throws MojoExecutionException
173 {
174 final List<Transformer> transformers = new ArrayList<Transformer>(
175 this.modelObjectStylesheetResources != null ? this.modelObjectStylesheetResources.size() + 1 : 1 );
176
177 if ( this.modelObjectStylesheet != null )
178 {
179 final TransformerResourceType r = new TransformerResourceType();
180 r.setLocation( this.modelObjectStylesheet );
181
182 final Transformer transformer = this.getTransformer( r );
183
184 if ( transformer != null )
185 {
186 transformers.add( transformer );
187 }
188 }
189
190 if ( this.modelObjectStylesheetResources != null )
191 {
192 for ( int i = 0, s0 = this.modelObjectStylesheetResources.size(); i < s0; i++ )
193 {
194 final Transformer transformer = this.getTransformer( this.modelObjectStylesheetResources.get( i ) );
195
196 if ( transformer != null )
197 {
198 transformers.add( transformer );
199 }
200 }
201 }
202
203 return transformers;
204 }
205
206 @Override
207 protected void assertValidParameters() throws MojoFailureException
208 {
209 super.assertValidParameters();
210 this.assertValidResources( this.modelObjectStylesheetResources );
211 }
212
213 @Override
214 protected final void executeTool() throws Exception
215 {
216 this.logSeparator();
217
218 if ( this.isClassProcessingEnabled() )
219 {
220 this.logProcessingModule( TOOLNAME, this.getClassesModuleName() );
221
222 final ClassLoader classLoader = this.getClassesClassLoader();
223 final ModelContext context = this.createModelContext( classLoader );
224 final ClassFileProcessor tool = this.createClassFileProcessor( context );
225 final JAXBContext jaxbContext = context.createContext( this.getModel() );
226 final List<Transformer> transformers = this.getTransformers();
227 final Source source = new JAXBSource( jaxbContext, new ObjectFactory().createModel( tool.getModel() ) );
228 final ModelValidationReport validationReport = context.validateModel( this.getModel(), source );
229
230 this.log( context, validationReport.isModelValid() ? Level.INFO : Level.SEVERE, validationReport );
231
232 if ( validationReport.isModelValid() )
233 {
234 final Module module =
235 tool.getModules() != null ? tool.getModules().getModule( this.getClassesModuleName() ) : null;
236
237 if ( module != null )
238 {
239 tool.commitModelObjects( module, context, this.getClassesDirectory() );
240
241 if ( !transformers.isEmpty() )
242 {
243 tool.transformModelObjects( module, context, this.getClassesDirectory(), transformers );
244 }
245
246 this.logToolSuccess( TOOLNAME );
247 }
248 else
249 {
250 this.logMissingModule( this.getClassesModuleName() );
251 }
252 }
253 else
254 {
255 throw new MojoExecutionException( Messages.getMessage( "classFileProcessingFailure" ) );
256 }
257 }
258 else if ( this.isLoggable( Level.INFO ) )
259 {
260 this.log( Level.INFO, Messages.getMessage( "classFileProcessingDisabled" ), null );
261 }
262 }
263
264 /**
265 * Gets the name of the module to commit class file model objects of.
266 *
267 * @return The name of the module to commit class file model objects of.
268 *
269 * @throws MojoExecutionException if getting the name fails.
270 */
271 protected abstract String getClassesModuleName() throws MojoExecutionException;
272
273 /**
274 * Gets the class loader to use for committing class file model objects.
275 *
276 * @return The class loader to use for committing class file model objects.
277 *
278 * @throws MojoExecutionException if getting the class loader fails.
279 */
280 protected abstract ClassLoader getClassesClassLoader() throws MojoExecutionException;
281
282 /**
283 * Gets the directory holding the class files to commit model objects to.
284 *
285 * @return The directory holding the class files to commit model objects to.
286 *
287 * @throws MojoExecutionException if getting the directory fails.
288 */
289 protected abstract File getClassesDirectory() throws MojoExecutionException;
290
291 }