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 * <modelObjectStylesheetResources> 85 * <modelObjectStylesheetResource> 86 * <location>The location of the XSLT document.</location> 87 * <optional>Flag indicating the XSLT document is optional.</optional> 88 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 89 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 90 * <transformationParameterResources> 91 * <transformationParameterResource> 92 * <location>The location of the properties resource.</location> 93 * <optional>Flag indicating the properties resource is optional.</optional> 94 * <format>The format of the properties resource.</format> 95 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 96 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 97 * </transformationParameterResource> 98 * </transformationParameterResources> 99 * <transformationParameters> 100 * <transformationParameter> 101 * <key>The name of the parameter.</key> 102 * <value>The value of the parameter.</value> 103 * <type>The name of the class of the parameter's object.</type> 104 * </transformationParameter> 105 * </transformationParameters> 106 * <transformationOutputProperties> 107 * <transformationOutputProperty> 108 * <key>The name of the property.</key> 109 * <value>The value of the property.</value> 110 * <type>The name of the class of the properties object.</type> 111 * </transformationOutputProperty> 112 * </transformationOutputProperties> 113 * </modelObjectStylesheetResource> 114 * </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 }