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: WriteModelTask.java 4613 2012-09-22 10:07:08Z schulte $ 029 * 030 */ 031package org.jomc.ant; 032 033import java.io.BufferedReader; 034import java.io.ByteArrayOutputStream; 035import java.io.File; 036import java.io.IOException; 037import java.io.OutputStreamWriter; 038import java.io.StringReader; 039import java.io.StringWriter; 040import java.util.logging.Level; 041import javax.xml.bind.JAXBException; 042import javax.xml.bind.Marshaller; 043import javax.xml.bind.util.JAXBSource; 044import org.apache.tools.ant.BuildException; 045import org.apache.tools.ant.Project; 046import org.jomc.model.Instance; 047import org.jomc.model.Module; 048import org.jomc.model.Modules; 049import org.jomc.model.Specification; 050import org.jomc.model.modlet.ModelHelper; 051import org.jomc.modlet.Model; 052import org.jomc.modlet.ModelContext; 053import org.jomc.modlet.ModelException; 054import org.jomc.modlet.ModelValidationReport; 055import org.jomc.modlet.ObjectFactory; 056 057/** 058 * Task for writing model objects. 059 * 060 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 061 * @version $JOMC: WriteModelTask.java 4613 2012-09-22 10:07:08Z schulte $ 062 */ 063public final class WriteModelTask extends JomcModelTask 064{ 065 066 /** The identifier of a specification to write. */ 067 private String specification; 068 069 /** The identifier of an implementation to write. */ 070 private String implementation; 071 072 /** The name of a module to write. */ 073 private String module; 074 075 /** The encoding to use when writing the model. */ 076 private String modelEncoding; 077 078 /** File to write the model to. */ 079 private File modelFile; 080 081 /** Creates a new {@code WriteModelTask} instance. */ 082 public WriteModelTask() 083 { 084 super(); 085 } 086 087 /** 088 * Gets the encoding of the model resource. 089 * 090 * @return The encoding of the model resource. 091 * 092 * @see #setModelEncoding(java.lang.String) 093 */ 094 public String getModelEncoding() 095 { 096 if ( this.modelEncoding == null ) 097 { 098 this.modelEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding(); 099 } 100 101 return this.modelEncoding; 102 } 103 104 /** 105 * Sets the encoding of the model resource. 106 * 107 * @param value The new encoding of the model resource or {@code null}. 108 * 109 * @see #getModelEncoding() 110 */ 111 public void setModelEncoding( final String value ) 112 { 113 this.modelEncoding = value; 114 } 115 116 /** 117 * Gets the file to write the model to. 118 * 119 * @return The file to write the model to or {@code null}. 120 * 121 * @see #setModelFile(java.io.File) 122 */ 123 public File getModelFile() 124 { 125 return this.modelFile; 126 } 127 128 /** 129 * Sets the file to write the model to. 130 * 131 * @param value The new file to write the model to or {@code null}. 132 * 133 * @see #getModelFile() 134 */ 135 public void setModelFile( final File value ) 136 { 137 this.modelFile = value; 138 } 139 140 /** 141 * Gets the identifier of a specification to write. 142 * 143 * @return The identifier of a specification to write or {@code null}. 144 * 145 * @see #setSpecification(java.lang.String) 146 */ 147 public String getSpecification() 148 { 149 return this.specification; 150 } 151 152 /** 153 * Sets the identifier of a specification to write. 154 * 155 * @param value The new identifier of a specification to write or {@code null}. 156 * 157 * @see #getSpecification() 158 */ 159 public void setSpecification( final String value ) 160 { 161 this.specification = value; 162 } 163 164 /** 165 * Gets the specification to write from a given model. 166 * 167 * @param model The model to get the specification to write from. 168 * 169 * @return The specification to write or {@code null}. 170 * 171 * @throws NullPointerException if {@code model} is {@code null}. 172 * 173 * @see #getSpecification() 174 */ 175 public Specification getSpecification( final Model model ) 176 { 177 if ( model == null ) 178 { 179 throw new NullPointerException( "model" ); 180 } 181 182 Specification s = null; 183 184 if ( this.getSpecification() != null ) 185 { 186 final Modules modules = ModelHelper.getModules( model ); 187 188 if ( modules != null ) 189 { 190 s = modules.getSpecification( this.getSpecification() ); 191 } 192 193 if ( s == null ) 194 { 195 this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN ); 196 } 197 } 198 199 return s; 200 } 201 202 /** 203 * Gets the identifier of an implementation to write. 204 * 205 * @return The identifier of an implementation to write or {@code null}. 206 * 207 * @see #setImplementation(java.lang.String) 208 */ 209 public String getImplementation() 210 { 211 return this.implementation; 212 } 213 214 /** 215 * Sets the identifier of an implementation to write. 216 * 217 * @param value The new identifier of an implementation to write or {@code null}. 218 * 219 * @see #getImplementation() 220 */ 221 public void setImplementation( final String value ) 222 { 223 this.implementation = value; 224 } 225 226 /** 227 * Gets the instance to write from a given model. 228 * 229 * @param model The model to get the instance to write from. 230 * 231 * @return The instance to write or {@code null}. 232 * 233 * @throws NullPointerException if {@code model} is {@code null}. 234 * 235 * @see #getImplementation() 236 */ 237 public Instance getInstance( final Model model ) 238 { 239 if ( model == null ) 240 { 241 throw new NullPointerException( "model" ); 242 } 243 244 Instance i = null; 245 246 if ( this.getImplementation() != null ) 247 { 248 final Modules modules = ModelHelper.getModules( model ); 249 250 if ( modules != null ) 251 { 252 i = modules.getInstance( this.getImplementation() ); 253 } 254 255 if ( i == null ) 256 { 257 this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN ); 258 } 259 } 260 261 return i; 262 } 263 264 /** 265 * Gets the identifier of a module to write. 266 * 267 * @return The identifier of a module to write or {@code null}. 268 * 269 * @see #setModule(java.lang.String) 270 */ 271 public String getModule() 272 { 273 return this.module; 274 } 275 276 /** 277 * Sets the identifier of a module to write. 278 * 279 * @param value The new identifier of a module to write or {@code null}. 280 * 281 * @see #getModule() 282 */ 283 public void setModule( final String value ) 284 { 285 this.module = value; 286 } 287 288 /** 289 * Gets the module to write from a given model. 290 * 291 * @param model The model to get the module to write from. 292 * 293 * @return The module to write or {@code null}. 294 * 295 * @throws NullPointerException if {@code model} is {@code null}. 296 * 297 * @see #getModule() 298 */ 299 public Module getModule( final Model model ) 300 { 301 if ( model == null ) 302 { 303 throw new NullPointerException( "model" ); 304 } 305 306 Module m = null; 307 308 if ( this.getModule() != null ) 309 { 310 final Modules modules = ModelHelper.getModules( model ); 311 312 if ( modules != null ) 313 { 314 m = modules.getModule( this.getModule() ); 315 } 316 317 if ( m == null ) 318 { 319 this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN ); 320 } 321 } 322 323 return m; 324 } 325 326 /** {@inheritDoc} */ 327 @Override 328 public void executeTask() throws BuildException 329 { 330 BufferedReader reader = null; 331 ProjectClassLoader classLoader = null; 332 boolean suppressExceptionOnClose = true; 333 334 try 335 { 336 classLoader = this.newProjectClassLoader(); 337 final ModelContext modelContext = this.newModelContext( classLoader ); 338 final Model model = this.getModel( modelContext ); 339 final Marshaller marshaller = modelContext.createMarshaller( this.getModel() ); 340 final ModelValidationReport validationReport = modelContext.validateModel( 341 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModel( model ) ) ); 342 343 this.logValidationReport( modelContext, validationReport ); 344 marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModelEncoding() ); 345 marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); 346 347 Model displayModel = new Model(); 348 displayModel.setIdentifier( this.getModel() ); 349 350 final Specification s = this.getSpecification( model ); 351 if ( s != null ) 352 { 353 displayModel.getAny().add( s ); 354 } 355 356 final Instance i = this.getInstance( model ); 357 if ( i != null ) 358 { 359 displayModel.getAny().add( i ); 360 } 361 362 final Module m = this.getModule( model ); 363 if ( m != null ) 364 { 365 displayModel.getAny().add( m ); 366 } 367 368 if ( displayModel.getAny().isEmpty() ) 369 { 370 displayModel = model; 371 } 372 373 if ( this.getModelFile() != null ) 374 { 375 this.log( Messages.getMessage( "writingModelObjects", this.getModel(), 376 this.getModelFile().getAbsolutePath() ), Project.MSG_INFO ); 377 378 marshaller.marshal( new ObjectFactory().createModel( displayModel ), this.getModelFile() ); 379 } 380 else 381 { 382 this.log( Messages.getMessage( "showingModelObjects", this.getModel() ), Project.MSG_INFO ); 383 384 final StringWriter writer = new StringWriter(); 385 marshaller.marshal( new ObjectFactory().createModel( displayModel ), writer ); 386 387 reader = new BufferedReader( new StringReader( writer.toString() ) ); 388 String line; 389 390 while ( ( line = reader.readLine() ) != null ) 391 { 392 this.log( line, Project.MSG_INFO ); 393 } 394 } 395 396 suppressExceptionOnClose = false; 397 } 398 catch ( final IOException e ) 399 { 400 throw new BuildException( Messages.getMessage( e ), e, this.getLocation() ); 401 } 402 catch ( final JAXBException e ) 403 { 404 String message = Messages.getMessage( e ); 405 if ( message == null ) 406 { 407 message = Messages.getMessage( e.getLinkedException() ); 408 } 409 410 throw new BuildException( message, e, this.getLocation() ); 411 } 412 catch ( final ModelException e ) 413 { 414 throw new BuildException( Messages.getMessage( e ), e, this.getLocation() ); 415 } 416 finally 417 { 418 try 419 { 420 if ( reader != null ) 421 { 422 reader.close(); 423 } 424 } 425 catch ( final IOException e ) 426 { 427 if ( suppressExceptionOnClose ) 428 { 429 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e ); 430 } 431 else 432 { 433 throw new BuildException( Messages.getMessage( e ), e, this.getLocation() ); 434 } 435 } 436 finally 437 { 438 try 439 { 440 if ( classLoader != null ) 441 { 442 classLoader.close(); 443 } 444 } 445 catch ( final IOException e ) 446 { 447 if ( suppressExceptionOnClose ) 448 { 449 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e ); 450 } 451 else 452 { 453 throw new BuildException( Messages.getMessage( e ), e, this.getLocation() ); 454 } 455 } 456 } 457 } 458 } 459 460 /** {@inheritDoc} */ 461 @Override 462 public WriteModelTask clone() 463 { 464 return (WriteModelTask) super.clone(); 465 } 466 467}