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