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: WriteModelTask.java 5179 2016-04-15 02:58:23Z 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 5179 2016-04-15 02:58:23Z schulte $ 062 */ 063public final class WriteModelTask extends JomcModelTask 064{ 065 066 /** 067 * The identifier of a specification to write. 068 */ 069 private String specification; 070 071 /** 072 * The identifier of an implementation to write. 073 */ 074 private String implementation; 075 076 /** 077 * The name of a module to write. 078 */ 079 private String module; 080 081 /** 082 * The encoding to use when writing the model. 083 */ 084 private String modelEncoding; 085 086 /** 087 * File to write the model to. 088 */ 089 private File modelFile; 090 091 /** 092 * File to write the specification to. 093 * 094 * @since 1.6 095 */ 096 private File specificationModelFile; 097 098 /** 099 * File to write the instance to. 100 * 101 * @since 1.6 102 */ 103 private File instanceModelFile; 104 105 /** 106 * File to write the module to. 107 * 108 * @since 1.6 109 */ 110 private File moduleModelFile; 111 112 /** 113 * Creates a new {@code WriteModelTask} instance. 114 */ 115 public WriteModelTask() 116 { 117 super(); 118 } 119 120 /** 121 * Gets the encoding of the model resource. 122 * 123 * @return The encoding of the model resource. 124 * 125 * @see #setModelEncoding(java.lang.String) 126 */ 127 public String getModelEncoding() 128 { 129 if ( this.modelEncoding == null ) 130 { 131 this.modelEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding(); 132 } 133 134 return this.modelEncoding; 135 } 136 137 /** 138 * Sets the encoding of the model resource. 139 * 140 * @param value The new encoding of the model resource or {@code null}. 141 * 142 * @see #getModelEncoding() 143 */ 144 public void setModelEncoding( final String value ) 145 { 146 this.modelEncoding = value; 147 } 148 149 /** 150 * Gets the file to write the model to. 151 * 152 * @return The file to write the model to or {@code null}. 153 * 154 * @see #setModelFile(java.io.File) 155 */ 156 public File getModelFile() 157 { 158 return this.modelFile; 159 } 160 161 /** 162 * Sets the file to write the model to. 163 * 164 * @param value The new file to write the model to or {@code null}. 165 * 166 * @see #getModelFile() 167 */ 168 public void setModelFile( final File value ) 169 { 170 this.modelFile = value; 171 } 172 173 /** 174 * Gets the file to write the specification to. 175 * 176 * @return The file to write the specification to or {@code null}. 177 * 178 * @see #setSpecificationModelFile(java.io.File) 179 * 180 * @since 1.6 181 */ 182 public File getSpecificationModelFile() 183 { 184 return this.specificationModelFile; 185 } 186 187 /** 188 * Sets the file to write the specification to. 189 * 190 * @param value The new file to write the specification to or {@code null}. 191 * 192 * @see #getSpecificationModelFile() 193 * 194 * @since 1.6 195 */ 196 public void setSpecificationModelFile( final File value ) 197 { 198 this.specificationModelFile = value; 199 } 200 201 /** 202 * Gets the file to write the instance to. 203 * 204 * @return The file to write the instance to or {@code null}. 205 * 206 * @see #setInstanceModelFile(java.io.File) 207 * 208 * @since 1.6 209 */ 210 public File getInstanceModelFile() 211 { 212 return this.instanceModelFile; 213 } 214 215 /** 216 * Sets the file to write the instance to. 217 * 218 * @param value The new file to write the instance to or {@code null}. 219 * 220 * @see #getInstanceModelFile() 221 * 222 * @since 1.6 223 */ 224 public void setInstanceModelFile( final File value ) 225 { 226 this.instanceModelFile = value; 227 } 228 229 /** 230 * Gets the file to write the module to. 231 * 232 * @return The file to write the module to or {@code null}. 233 * 234 * @see #setModuleModelFile(java.io.File) 235 * 236 * @since 1.6 237 */ 238 public File getModuleModelFile() 239 { 240 return this.moduleModelFile; 241 } 242 243 /** 244 * Sets the file to write the module to. 245 * 246 * @param value The new file to write the module to or {@code null}. 247 * 248 * @see #getModuleModelFile() 249 * 250 * @since 1.6 251 */ 252 public void setModuleModelFile( final File value ) 253 { 254 this.moduleModelFile = value; 255 } 256 257 /** 258 * Gets the identifier of a specification to write. 259 * 260 * @return The identifier of a specification to write or {@code null}. 261 * 262 * @see #setSpecification(java.lang.String) 263 */ 264 public String getSpecification() 265 { 266 return this.specification; 267 } 268 269 /** 270 * Sets the identifier of a specification to write. 271 * 272 * @param value The new identifier of a specification to write or {@code null}. 273 * 274 * @see #getSpecification() 275 */ 276 public void setSpecification( final String value ) 277 { 278 this.specification = value; 279 } 280 281 /** 282 * Gets the specification to write from a given model. 283 * 284 * @param model The model to get the specification to write from. 285 * 286 * @return The specification to write or {@code null}. 287 * 288 * @throws NullPointerException if {@code model} is {@code null}. 289 * 290 * @see #getSpecification() 291 */ 292 public Specification getSpecification( final Model model ) 293 { 294 if ( model == null ) 295 { 296 throw new NullPointerException( "model" ); 297 } 298 299 Specification s = null; 300 301 if ( this.getSpecification() != null ) 302 { 303 final Modules modules = ModelHelper.getModules( model ); 304 305 if ( modules != null ) 306 { 307 s = modules.getSpecification( this.getSpecification() ); 308 } 309 310 if ( s == null ) 311 { 312 this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN ); 313 } 314 } 315 316 return s; 317 } 318 319 /** 320 * Gets the identifier of an implementation to write. 321 * 322 * @return The identifier of an implementation to write or {@code null}. 323 * 324 * @see #setImplementation(java.lang.String) 325 */ 326 public String getImplementation() 327 { 328 return this.implementation; 329 } 330 331 /** 332 * Sets the identifier of an implementation to write. 333 * 334 * @param value The new identifier of an implementation to write or {@code null}. 335 * 336 * @see #getImplementation() 337 */ 338 public void setImplementation( final String value ) 339 { 340 this.implementation = value; 341 } 342 343 /** 344 * Gets the instance to write from a given model. 345 * 346 * @param model The model to get the instance to write from. 347 * 348 * @return The instance to write or {@code null}. 349 * 350 * @throws NullPointerException if {@code model} is {@code null}. 351 * 352 * @see #getImplementation() 353 */ 354 public Instance getInstance( final Model model ) 355 { 356 if ( model == null ) 357 { 358 throw new NullPointerException( "model" ); 359 } 360 361 Instance i = null; 362 363 if ( this.getImplementation() != null ) 364 { 365 final Modules modules = ModelHelper.getModules( model ); 366 367 if ( modules != null ) 368 { 369 i = modules.getInstance( this.getImplementation() ); 370 } 371 372 if ( i == null ) 373 { 374 this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN ); 375 } 376 } 377 378 return i; 379 } 380 381 /** 382 * Gets the identifier of a module to write. 383 * 384 * @return The identifier of a module to write or {@code null}. 385 * 386 * @see #setModule(java.lang.String) 387 */ 388 public String getModule() 389 { 390 return this.module; 391 } 392 393 /** 394 * Sets the identifier of a module to write. 395 * 396 * @param value The new identifier of a module to write or {@code null}. 397 * 398 * @see #getModule() 399 */ 400 public void setModule( final String value ) 401 { 402 this.module = value; 403 } 404 405 /** 406 * Gets the module to write from a given model. 407 * 408 * @param model The model to get the module to write from. 409 * 410 * @return The module to write or {@code null}. 411 * 412 * @throws NullPointerException if {@code model} is {@code null}. 413 * 414 * @see #getModule() 415 */ 416 public Module getModule( final Model model ) 417 { 418 if ( model == null ) 419 { 420 throw new NullPointerException( "model" ); 421 } 422 423 Module m = null; 424 425 if ( this.getModule() != null ) 426 { 427 final Modules modules = ModelHelper.getModules( model ); 428 429 if ( modules != null ) 430 { 431 m = modules.getModule( this.getModule() ); 432 } 433 434 if ( m == null ) 435 { 436 this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN ); 437 } 438 } 439 440 return m; 441 } 442 443 /** 444 * {@inheritDoc} 445 */ 446 @Override 447 public void executeTask() throws BuildException 448 { 449 BufferedReader reader = null; 450 ProjectClassLoader classLoader = null; 451 452 try 453 { 454 classLoader = this.newProjectClassLoader(); 455 final ModelContext modelContext = this.newModelContext( classLoader ); 456 final Model model = this.getModel( modelContext ); 457 final Marshaller marshaller = modelContext.createMarshaller( this.getModel() ); 458 final ModelValidationReport validationReport = modelContext.validateModel( 459 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModel( model ) ) ); 460 461 this.logValidationReport( modelContext, validationReport ); 462 marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModelEncoding() ); 463 marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); 464 465 Model displayModel = new Model(); 466 displayModel.setIdentifier( this.getModel() ); 467 468 final Specification s = this.getSpecification( model ); 469 if ( s != null ) 470 { 471 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createSpecification( s ) ); 472 473 if ( this.getSpecificationModelFile() != null ) 474 { 475 this.log( Messages.getMessage( "writingSpecification", s.getIdentifier(), 476 this.getSpecificationModelFile().getAbsolutePath() ), 477 Project.MSG_INFO ); 478 479 marshaller.marshal( new org.jomc.model.ObjectFactory().createSpecification( s ), 480 this.getSpecificationModelFile() ); 481 482 } 483 } 484 485 final Instance i = this.getInstance( model ); 486 if ( i != null ) 487 { 488 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createInstance( i ) ); 489 490 if ( this.getInstanceModelFile() != null ) 491 { 492 this.log( Messages.getMessage( "writingInstance", i.getIdentifier(), 493 this.getInstanceModelFile().getAbsolutePath() ), 494 Project.MSG_INFO ); 495 496 marshaller.marshal( new org.jomc.model.ObjectFactory().createInstance( i ), 497 this.getInstanceModelFile() ); 498 499 } 500 } 501 502 final Module m = this.getModule( model ); 503 if ( m != null ) 504 { 505 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createModule( m ) ); 506 507 if ( this.getModuleModelFile() != null ) 508 { 509 this.log( Messages.getMessage( "writingModule", m.getName(), 510 this.getModuleModelFile().getAbsolutePath() ), 511 Project.MSG_INFO ); 512 513 marshaller.marshal( new org.jomc.model.ObjectFactory().createModule( m ), 514 this.getModuleModelFile() ); 515 516 } 517 } 518 519 if ( displayModel.getAny().isEmpty() ) 520 { 521 displayModel = model; 522 } 523 524 if ( this.getModelFile() != null ) 525 { 526 this.log( Messages.getMessage( "writingModelObjects", this.getModel(), 527 this.getModelFile().getAbsolutePath() ), Project.MSG_INFO ); 528 529 marshaller.marshal( new ObjectFactory().createModel( displayModel ), this.getModelFile() ); 530 } 531 else 532 { 533 this.log( Messages.getMessage( "showingModelObjects", this.getModel() ), Project.MSG_INFO ); 534 535 final StringWriter writer = new StringWriter(); 536 marshaller.marshal( new ObjectFactory().createModel( displayModel ), writer ); 537 538 reader = new BufferedReader( new StringReader( writer.toString() ) ); 539 540 for ( String line = reader.readLine(); line != null; line = reader.readLine() ) 541 { 542 this.log( line, Project.MSG_INFO ); 543 } 544 545 reader.close(); 546 reader = null; 547 } 548 549 classLoader.close(); 550 classLoader = null; 551 } 552 catch ( final IOException e ) 553 { 554 throw new BuildException( Messages.getMessage( e ), e, this.getLocation() ); 555 } 556 catch ( final JAXBException e ) 557 { 558 String message = Messages.getMessage( e ); 559 if ( message == null ) 560 { 561 message = Messages.getMessage( e.getLinkedException() ); 562 } 563 564 throw new BuildException( message, e, this.getLocation() ); 565 } 566 catch ( final ModelException e ) 567 { 568 throw new BuildException( Messages.getMessage( e ), e, this.getLocation() ); 569 } 570 finally 571 { 572 try 573 { 574 if ( reader != null ) 575 { 576 reader.close(); 577 } 578 } 579 catch ( final IOException e ) 580 { 581 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e ); 582 } 583 finally 584 { 585 try 586 { 587 if ( classLoader != null ) 588 { 589 classLoader.close(); 590 } 591 } 592 catch ( final IOException e ) 593 { 594 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e ); 595 } 596 } 597 } 598 } 599 600 /** 601 * {@inheritDoc} 602 */ 603 @Override 604 public WriteModelTask clone() 605 { 606 return (WriteModelTask) super.clone(); 607 } 608 609}