001/* 002 * Copyright (C) 2005 Christian Schulte <cs@schulte.it> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: AbstractClassesCommitMojo.java 5228 2016-04-24 11:08:06Z schulte $ 029 * 030 */ 031package org.jomc.mojo; 032 033import java.io.File; 034import java.util.ArrayList; 035import java.util.List; 036import java.util.logging.Level; 037import javax.xml.bind.JAXBContext; 038import javax.xml.bind.util.JAXBSource; 039import javax.xml.transform.Source; 040import javax.xml.transform.Transformer; 041import org.apache.maven.plugin.MojoExecutionException; 042import org.apache.maven.plugin.MojoFailureException; 043import org.apache.maven.plugins.annotations.Parameter; 044import org.jomc.model.Module; 045import org.jomc.modlet.ModelContext; 046import org.jomc.modlet.ModelValidationReport; 047import org.jomc.modlet.ObjectFactory; 048import org.jomc.tools.ClassFileProcessor; 049 050/** 051 * Base class for committing model objects to class files. 052 * 053 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 054 * @version $JOMC: AbstractClassesCommitMojo.java 5228 2016-04-24 11:08:06Z schulte $ 055 */ 056public abstract class AbstractClassesCommitMojo extends AbstractJomcMojo 057{ 058 059 /** 060 * Constant for the name of the tool backing the mojo. 061 */ 062 private static final String TOOLNAME = "ClassFileProcessor"; 063 064 /** 065 * XSLT document to use for transforming model objects. 066 * <p> 067 * The value of the parameter is a location to search a XSLT document at. First the value is used to search the 068 * class path of the plugin. If a class path resource is found, a XSLT document is loaded from that resource. If no 069 * class path resource is found, an attempt is made to parse the value to an URL. Succeeding that, an XSLT document 070 * is loaded from that URL (since version 1.2). Failing that, the value is interpreted as a file name of a XSLT 071 * document to load relative to the base directory of the project. If that file exists, a XSLT document is loaded 072 * from that file. If no XSLT document is found at the given location, a build failure is produced.</p> 073 * <p> 074 * <b>Note:</b> When upgrading to version 1.2, any project dependencies holding XSLT documents referenced by this 075 * parameter need to be added to the plugins' dependencies.</p> 076 * <p> 077 * <strong>Deprecated:</strong> As of JOMC 1.2, please use the 'modelObjectStylesheetResources' parameter. This 078 * parameter will be removed in version 2.0.</p> 079 */ 080 @Deprecated 081 @Parameter( name = "modelObjectStylesheet" ) 082 private String modelObjectStylesheet; 083 084 /** 085 * XSLT documents to use for transforming model objects. 086 * <pre> 087 * <modelObjectStylesheetResources> 088 * <modelObjectStylesheetResource> 089 * <location>The location of the XSLT document.</location> 090 * <optional>Flag indicating the XSLT document is optional.</optional> 091 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 092 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 093 * <transformationParameterResources> 094 * <transformationParameterResource> 095 * <location>The location of the properties resource.</location> 096 * <optional>Flag indicating the properties resource is optional.</optional> 097 * <format>The format of the properties resource.</format> 098 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 099 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 100 * </transformationParameterResource> 101 * </transformationParameterResources> 102 * <transformationParameters> 103 * <transformationParameter> 104 * <key>The name of the parameter.</key> 105 * <value>The value of the parameter.</value> 106 * <type>The name of the class of the parameter's object.</type> 107 * </transformationParameter> 108 * </transformationParameters> 109 * <transformationOutputProperties> 110 * <transformationOutputProperty> 111 * <key>The name of the property.</key> 112 * <value>The value of the property.</value> 113 * <type>The name of the class of the properties object.</type> 114 * </transformationOutputProperty> 115 * </transformationOutputProperties> 116 * </modelObjectStylesheetResource> 117 * </modelObjectStylesheetResources> 118 * </pre> 119 * <p> 120 * The location value is used to first search the class path of the plugin and the project's main or test class 121 * path. If a class path resource is found, that resource is used. If no class path resource is found, an attempt is 122 * made to parse the location value to an URL. On successful parsing, that URL is used. Otherwise the location value 123 * is interpreted as a file name relative to the base directory of the project. If that file exists, that file is 124 * used. If nothing is found at the given location, depending on the optional flag, a warning message is logged or a 125 * build failure is produced. 126 * </p> 127 * <p> 128 * The optional flag is used to flag the resource optional. When an optional resource is not found, a warning 129 * message is logged instead of producing a build failure.<br/><b>Default value is:</b> false 130 * </p> 131 * <p> 132 * The connectTimeout value is used to specify the timeout, in milliseconds, to be used when opening 133 * communications links to the resource. A timeout of zero is interpreted as an infinite timeout.<br/> 134 * <b>Default value is:</b> 60000 135 * </p> 136 * <p> 137 * The readTimeout value is used to specify the timeout, in milliseconds, to be used when reading the resource. 138 * A timeout of zero is interpreted as an infinite timeout.<br/> 139 * <b>Default value is:</b> 60000 140 * </p> 141 * 142 * @since 1.2 143 */ 144 @Parameter( name = "modelObjectStylesheetResources" ) 145 private List<ModelObjectStylesheetResource> modelObjectStylesheetResources; 146 147 /** 148 * Creates a new {@code AbstractClassesCommitMojo} instance. 149 */ 150 public AbstractClassesCommitMojo() 151 { 152 super(); 153 } 154 155 /** 156 * Gets transformers to use for transforming model objects. 157 * 158 * @param classLoader The class loader to use for loading a transformer class path resource. 159 * 160 * @return A list of transformers to use for transforming model objects. 161 * 162 * @throws NullPointerException if {@code classLoader} is {@code null}. 163 * @throws MojoExecutionException if getting the transformers fails. 164 * 165 * @deprecated As of JOMC 1.2, the dependencies of the project are no longer searched for XSLT documents. Please 166 * use method {@link #getTransformers()}. This method will be removed in version 2.0. 167 */ 168 @Deprecated 169 protected List<Transformer> getTransformers( final ClassLoader classLoader ) throws MojoExecutionException 170 { 171 if ( classLoader == null ) 172 { 173 throw new NullPointerException( "classLoader" ); 174 } 175 176 return this.getTransformers(); 177 } 178 179 /** 180 * Gets transformers to use for transforming model objects. 181 * 182 * @return A list of transformers to use for transforming model objects. 183 * 184 * @throws MojoExecutionException if getting the transformers fails. 185 * 186 * @since 1.2 187 * @deprecated As of JOMC 1.8, replaced by method {@link #getTransformers(org.jomc.modlet.ModelContext)}. This 188 * method will be removed in JOMC 2.0. 189 */ 190 @Deprecated 191 @SuppressWarnings( "deprecation" ) 192 protected List<Transformer> getTransformers() throws MojoExecutionException 193 { 194 final List<Transformer> transformers = new ArrayList<Transformer>( 195 this.modelObjectStylesheetResources != null ? this.modelObjectStylesheetResources.size() + 1 : 1 ); 196 197 if ( this.modelObjectStylesheet != null ) 198 { 199 final TransformerResourceType r = new TransformerResourceType(); 200 r.setLocation( this.modelObjectStylesheet ); 201 202 final Transformer transformer = this.getTransformer( r ); 203 204 if ( transformer != null ) 205 { 206 transformers.add( transformer ); 207 } 208 } 209 210 if ( this.modelObjectStylesheetResources != null ) 211 { 212 for ( int i = 0, s0 = this.modelObjectStylesheetResources.size(); i < s0; i++ ) 213 { 214 final Transformer transformer = this.getTransformer( this.modelObjectStylesheetResources.get( i ) ); 215 216 if ( transformer != null ) 217 { 218 transformers.add( transformer ); 219 } 220 } 221 } 222 223 return transformers; 224 } 225 226 /** 227 * Gets transformers to use for transforming model objects. 228 * 229 * @param modelContext The model context to search. 230 * 231 * @return A list of transformers to use for transforming model objects. 232 * 233 * @throws NullPointerException if {@code modelContext} is {@code null}. 234 * @throws MojoExecutionException if getting the transformers fails. 235 * 236 * @since 1.8 237 */ 238 protected List<Transformer> getTransformers( final ModelContext modelContext ) throws MojoExecutionException 239 { 240 if ( modelContext == null ) 241 { 242 throw new NullPointerException( "modelContext" ); 243 } 244 245 final List<Transformer> transformers = new ArrayList<Transformer>( 246 this.modelObjectStylesheetResources != null ? this.modelObjectStylesheetResources.size() : 0 ); 247 248 if ( this.modelObjectStylesheetResources != null ) 249 { 250 for ( int i = 0, s0 = this.modelObjectStylesheetResources.size(); i < s0; i++ ) 251 { 252 final Transformer transformer = 253 this.getTransformer( modelContext, this.modelObjectStylesheetResources.get( i ) ); 254 255 if ( transformer != null ) 256 { 257 transformers.add( transformer ); 258 } 259 } 260 } 261 262 return transformers; 263 } 264 265 @Override 266 protected void assertValidParameters() throws MojoFailureException 267 { 268 super.assertValidParameters(); 269 this.assertValidResources( this.modelObjectStylesheetResources ); 270 } 271 272 @Override 273 protected final void executeTool() throws Exception 274 { 275 this.logSeparator(); 276 277 if ( this.isClassProcessingEnabled() ) 278 { 279 this.logProcessingModule( TOOLNAME, this.getClassesModuleName() ); 280 281 final ClassLoader classLoader = this.getClassesClassLoader(); 282 final ModelContext context = this.createModelContext( classLoader ); 283 final ClassFileProcessor tool = this.createClassFileProcessor( context ); 284 final JAXBContext jaxbContext = context.createContext( this.getModel() ); 285 final List<Transformer> transformers = this.getTransformers( context ); 286 final Source source = new JAXBSource( jaxbContext, new ObjectFactory().createModel( tool.getModel() ) ); 287 final ModelValidationReport validationReport = context.validateModel( this.getModel(), source ); 288 289 this.log( context, validationReport.isModelValid() ? Level.INFO : Level.SEVERE, validationReport ); 290 291 if ( validationReport.isModelValid() ) 292 { 293 final Module module = 294 tool.getModules() != null ? tool.getModules().getModule( this.getClassesModuleName() ) : null; 295 296 if ( module != null ) 297 { 298 tool.commitModelObjects( module, context, this.getClassesDirectory() ); 299 300 if ( !transformers.isEmpty() ) 301 { 302 tool.transformModelObjects( module, context, this.getClassesDirectory(), transformers ); 303 } 304 305 this.logToolSuccess( TOOLNAME ); 306 } 307 else 308 { 309 this.logMissingModule( this.getClassesModuleName() ); 310 } 311 } 312 else 313 { 314 throw new MojoExecutionException( Messages.getMessage( "classFileProcessingFailure" ) ); 315 } 316 } 317 else if ( this.isLoggable( Level.INFO ) ) 318 { 319 this.log( Level.INFO, Messages.getMessage( "classFileProcessingDisabled" ), null ); 320 } 321 } 322 323 /** 324 * Gets the name of the module to commit class file model objects of. 325 * 326 * @return The name of the module to commit class file model objects of. 327 * 328 * @throws MojoExecutionException if getting the name fails. 329 */ 330 protected abstract String getClassesModuleName() throws MojoExecutionException; 331 332 /** 333 * Gets the class loader to use for committing class file model objects. 334 * 335 * @return The class loader to use for committing class file model objects. 336 * 337 * @throws MojoExecutionException if getting the class loader fails. 338 */ 339 protected abstract ClassLoader getClassesClassLoader() throws MojoExecutionException; 340 341 /** 342 * Gets the directory holding the class files to commit model objects to. 343 * 344 * @return The directory holding the class files to commit model objects to. 345 * 346 * @throws MojoExecutionException if getting the directory fails. 347 */ 348 protected abstract File getClassesDirectory() throws MojoExecutionException; 349 350}