001/* 002 * Copyright (C) Christian Schulte <cs@schulte.it>, 2005-206 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: CommitClassesTask.java 5043 2015-05-27 07:03:39Z schulte $ 029 * 030 */ 031package org.jomc.ant; 032 033import java.io.File; 034import java.io.IOException; 035import java.util.ArrayList; 036import java.util.LinkedList; 037import java.util.List; 038import java.util.logging.Level; 039import javax.xml.bind.JAXBContext; 040import javax.xml.bind.JAXBException; 041import javax.xml.bind.util.JAXBSource; 042import javax.xml.transform.Source; 043import javax.xml.transform.Transformer; 044import javax.xml.transform.TransformerConfigurationException; 045import org.apache.tools.ant.BuildException; 046import org.jomc.ant.types.TransformerResourceType; 047import org.jomc.model.Implementation; 048import org.jomc.model.Module; 049import org.jomc.model.Specification; 050import org.jomc.modlet.Model; 051import org.jomc.modlet.ModelContext; 052import org.jomc.modlet.ModelException; 053import org.jomc.modlet.ModelValidationReport; 054import org.jomc.modlet.ObjectFactory; 055import org.jomc.tools.ClassFileProcessor; 056 057/** 058 * Task for committing model objects to class files. 059 * 060 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 061 * @version $JOMC: CommitClassesTask.java 5043 2015-05-27 07:03:39Z schulte $ 062 */ 063public final class CommitClassesTask extends ClassFileProcessorTask 064{ 065 066 /** 067 * The directory holding the class files to commit model objects to. 068 */ 069 private File classesDirectory; 070 071 /** 072 * XSLT documents to use for transforming model objects. 073 */ 074 private List<TransformerResourceType> modelObjectStylesheetResources; 075 076 /** 077 * Creates a new {@code CommitClassesTask} instance. 078 */ 079 public CommitClassesTask() 080 { 081 super(); 082 } 083 084 /** 085 * Gets the directory holding the class files to commit model objects to. 086 * 087 * @return The directory holding the class files to commit model objects to or {@code null}. 088 * 089 * @see #setClassesDirectory(java.io.File) 090 */ 091 public File getClassesDirectory() 092 { 093 return this.classesDirectory; 094 } 095 096 /** 097 * Sets the directory holding the class files to commit model objects to. 098 * 099 * @param value The new directory holding the class files to commit model objects to or {@code null}. 100 * 101 * @see #getClassesDirectory() 102 */ 103 public void setClassesDirectory( final File value ) 104 { 105 this.classesDirectory = value; 106 } 107 108 /** 109 * Gets the XSLT documents to use for transforming model objects. 110 * <p> 111 * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make 112 * to the returned list will be present inside the object. This is why there is no {@code set} method for the 113 * model object stylesheet resources property. 114 * </p> 115 * 116 * @return The XSLT documents to use for transforming model objects. 117 * 118 * @see #createModelObjectStylesheetResource() 119 */ 120 public List<TransformerResourceType> getModelObjectStylesheetResources() 121 { 122 if ( this.modelObjectStylesheetResources == null ) 123 { 124 this.modelObjectStylesheetResources = new LinkedList<TransformerResourceType>(); 125 } 126 127 return this.modelObjectStylesheetResources; 128 } 129 130 /** 131 * Creates a new {@code modelObjectStylesheetResource} element instance. 132 * 133 * @return A new {@code modelObjectStylesheetResource} element instance. 134 * 135 * @see #getModelObjectStylesheetResources() 136 */ 137 public TransformerResourceType createModelObjectStylesheetResource() 138 { 139 final TransformerResourceType modelObjectStylesheetResource = new TransformerResourceType(); 140 this.getModelObjectStylesheetResources().add( modelObjectStylesheetResource ); 141 return modelObjectStylesheetResource; 142 } 143 144 /** 145 * {@inheritDoc} 146 */ 147 @Override 148 public void preExecuteTask() throws BuildException 149 { 150 super.preExecuteTask(); 151 152 this.assertNotNull( "classesDirectory", this.getClassesDirectory() ); 153 this.assertLocationsNotNull( this.getModelObjectStylesheetResources() ); 154 } 155 156 /** 157 * Commits model objects to class files. 158 * 159 * @throws BuildException if committing model objects fails. 160 */ 161 @Override 162 public void processClassFiles() throws BuildException 163 { 164 ProjectClassLoader classLoader = null; 165 boolean suppressExceptionOnClose = true; 166 167 try 168 { 169 this.log( Messages.getMessage( "committingModelObjects", this.getModel() ) ); 170 171 classLoader = this.newProjectClassLoader(); 172 final ModelContext context = this.newModelContext( classLoader ); 173 final ClassFileProcessor tool = this.newClassFileProcessor(); 174 final JAXBContext jaxbContext = context.createContext( this.getModel() ); 175 final Model model = this.getModel( context ); 176 final Source source = new JAXBSource( jaxbContext, new ObjectFactory().createModel( model ) ); 177 final ModelValidationReport validationReport = context.validateModel( this.getModel(), source ); 178 179 this.logValidationReport( context, validationReport ); 180 tool.setModel( model ); 181 182 final List<Transformer> transformers = 183 new ArrayList<Transformer>( this.getModelObjectStylesheetResources().size() ); 184 185 for ( int i = 0, s0 = this.getModelObjectStylesheetResources().size(); i < s0; i++ ) 186 { 187 final Transformer transformer = 188 this.getTransformer( this.getModelObjectStylesheetResources().get( i ) ); 189 190 if ( transformer != null ) 191 { 192 transformers.add( transformer ); 193 } 194 } 195 196 if ( validationReport.isModelValid() ) 197 { 198 final Specification s = this.getSpecification( model ); 199 final Implementation i = this.getImplementation( model ); 200 final Module m = this.getModule( model ); 201 202 if ( s != null ) 203 { 204 tool.commitModelObjects( s, context, this.getClassesDirectory() ); 205 206 if ( !transformers.isEmpty() ) 207 { 208 tool.transformModelObjects( s, context, this.getClassesDirectory(), transformers ); 209 } 210 } 211 212 if ( i != null ) 213 { 214 tool.commitModelObjects( i, context, this.getClassesDirectory() ); 215 216 if ( !transformers.isEmpty() ) 217 { 218 tool.transformModelObjects( i, context, this.getClassesDirectory(), transformers ); 219 } 220 } 221 222 if ( m != null ) 223 { 224 tool.commitModelObjects( m, context, this.getClassesDirectory() ); 225 226 if ( !transformers.isEmpty() ) 227 { 228 tool.transformModelObjects( m, context, this.getClassesDirectory(), transformers ); 229 } 230 } 231 232 if ( this.isModulesProcessingRequested() ) 233 { 234 tool.commitModelObjects( context, this.getClassesDirectory() ); 235 236 if ( !transformers.isEmpty() ) 237 { 238 tool.transformModelObjects( context, this.getClassesDirectory(), transformers ); 239 } 240 } 241 242 suppressExceptionOnClose = false; 243 } 244 else 245 { 246 throw new ModelException( Messages.getMessage( "invalidModel", this.getModel() ) ); 247 } 248 } 249 catch ( final IOException e ) 250 { 251 throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() ); 252 } 253 catch ( final JAXBException e ) 254 { 255 throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() ); 256 } 257 catch ( final TransformerConfigurationException e ) 258 { 259 throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() ); 260 } 261 catch ( final ModelException e ) 262 { 263 throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() ); 264 } 265 finally 266 { 267 try 268 { 269 if ( classLoader != null ) 270 { 271 classLoader.close(); 272 } 273 } 274 catch ( final IOException e ) 275 { 276 if ( suppressExceptionOnClose ) 277 { 278 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e ); 279 } 280 else 281 { 282 throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() ); 283 } 284 } 285 } 286 } 287 288 /** 289 * {@inheritDoc} 290 */ 291 @Override 292 public CommitClassesTask clone() 293 { 294 final CommitClassesTask clone = (CommitClassesTask) super.clone(); 295 clone.classesDirectory = 296 this.classesDirectory != null ? new File( this.classesDirectory.getAbsolutePath() ) : null; 297 298 if ( this.modelObjectStylesheetResources != null ) 299 { 300 clone.modelObjectStylesheetResources = 301 new ArrayList<TransformerResourceType>( this.modelObjectStylesheetResources.size() ); 302 303 for ( final TransformerResourceType e : this.modelObjectStylesheetResources ) 304 { 305 clone.modelObjectStylesheetResources.add( e.clone() ); 306 } 307 } 308 309 return clone; 310 } 311 312}