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: ClassFileProcessor.java 4890 2014-02-24 04:00:08Z schulte $ 029 * 030 */ 031package org.jomc.tools; 032 033import java.io.ByteArrayInputStream; 034import java.io.ByteArrayOutputStream; 035import java.io.Closeable; 036import java.io.File; 037import java.io.FileInputStream; 038import java.io.IOException; 039import java.io.InputStream; 040import java.io.RandomAccessFile; 041import java.net.URL; 042import java.nio.ByteBuffer; 043import java.nio.channels.FileChannel; 044import java.nio.channels.FileLock; 045import java.text.MessageFormat; 046import java.util.List; 047import java.util.ResourceBundle; 048import java.util.logging.Level; 049import java.util.zip.GZIPInputStream; 050import java.util.zip.GZIPOutputStream; 051import javax.xml.bind.JAXBElement; 052import javax.xml.bind.JAXBException; 053import javax.xml.bind.Marshaller; 054import javax.xml.bind.Unmarshaller; 055import javax.xml.bind.util.JAXBResult; 056import javax.xml.bind.util.JAXBSource; 057import javax.xml.transform.Transformer; 058import javax.xml.transform.TransformerException; 059import javax.xml.validation.Schema; 060import org.apache.bcel.classfile.Attribute; 061import org.apache.bcel.classfile.ClassParser; 062import org.apache.bcel.classfile.Constant; 063import org.apache.bcel.classfile.ConstantPool; 064import org.apache.bcel.classfile.ConstantUtf8; 065import org.apache.bcel.classfile.JavaClass; 066import org.apache.bcel.classfile.Unknown; 067import org.jomc.model.Dependencies; 068import org.jomc.model.Dependency; 069import org.jomc.model.Implementation; 070import org.jomc.model.Implementations; 071import org.jomc.model.Message; 072import org.jomc.model.Messages; 073import org.jomc.model.ModelObject; 074import org.jomc.model.ModelObjectException; 075import org.jomc.model.Module; 076import org.jomc.model.ObjectFactory; 077import org.jomc.model.Properties; 078import org.jomc.model.Property; 079import org.jomc.model.Specification; 080import org.jomc.model.SpecificationReference; 081import org.jomc.model.Specifications; 082import org.jomc.modlet.ModelContext; 083import org.jomc.modlet.ModelException; 084import org.jomc.modlet.ModelValidationReport; 085import org.jomc.util.ParseException; 086import org.jomc.util.TokenMgrError; 087import org.jomc.util.VersionParser; 088 089/** 090 * Processes class files. 091 * 092 * <p><b>Use Cases:</b><br/><ul> 093 * <li>{@link #commitModelObjects(org.jomc.modlet.ModelContext, java.io.File) }</li> 094 * <li>{@link #commitModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) }</li> 095 * <li>{@link #commitModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) }</li> 096 * <li>{@link #commitModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) }</li> 097 * <li>{@link #validateModelObjects(org.jomc.modlet.ModelContext) }</li> 098 * <li>{@link #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext) }</li> 099 * <li>{@link #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext) }</li> 100 * <li>{@link #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext) }</li> 101 * <li>{@link #validateModelObjects(org.jomc.modlet.ModelContext, java.io.File) }</li> 102 * <li>{@link #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) }</li> 103 * <li>{@link #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) }</li> 104 * <li>{@link #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) }</li> 105 * <li>{@link #transformModelObjects(org.jomc.modlet.ModelContext, java.io.File, java.util.List) }</li> 106 * <li>{@link #transformModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File, java.util.List) }</li> 107 * <li>{@link #transformModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File, java.util.List) }</li> 108 * <li>{@link #transformModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File, java.util.List) }</li> 109 * </ul></p> 110 * 111 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 112 * @version $JOMC: ClassFileProcessor.java 4890 2014-02-24 04:00:08Z schulte $ 113 * 114 * @see #getModules() 115 */ 116public class ClassFileProcessor extends JomcTool 117{ 118 119 /** Empty byte array. */ 120 private static final byte[] NO_BYTES = 121 { 122 }; 123 124 /** Creates a new {@code ClassFileProcessor} instance. */ 125 public ClassFileProcessor() 126 { 127 super(); 128 } 129 130 /** 131 * Creates a new {@code ClassFileProcessor} instance taking a {@code ClassFileProcessor} instance to initialize the 132 * instance with. 133 * 134 * @param tool The instance to initialize the new instance with. 135 * 136 * @throws NullPointerException if {@code tool} is {@code null}. 137 * @throws IOException if copying {@code tool} fails. 138 */ 139 public ClassFileProcessor( final ClassFileProcessor tool ) throws IOException 140 { 141 super( tool ); 142 } 143 144 /** 145 * Commits model objects of the modules of the instance to class files. 146 * 147 * @param context The model context to use for committing the model objects. 148 * @param classesDirectory The directory holding the class files. 149 * 150 * @throws NullPointerException if {@code context} or {@code classesDirectory} is {@code null}. 151 * @throws IOException if committing model objects fails. 152 * 153 * @see #commitModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) 154 */ 155 public final void commitModelObjects( final ModelContext context, final File classesDirectory ) throws IOException 156 { 157 if ( context == null ) 158 { 159 throw new NullPointerException( "context" ); 160 } 161 if ( classesDirectory == null ) 162 { 163 throw new NullPointerException( "classesDirectory" ); 164 } 165 166 try 167 { 168 if ( this.getModules() != null ) 169 { 170 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 171 m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 172 173 this.commitModelObjects( this.getModules().getSpecifications(), this.getModules().getImplementations(), 174 m, classesDirectory ); 175 176 } 177 else if ( this.isLoggable( Level.WARNING ) ) 178 { 179 this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); 180 } 181 } 182 catch ( final ModelException e ) 183 { 184 // JDK: As of JDK 6, "new IOException( message, cause )". 185 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 186 } 187 } 188 189 /** 190 * Commits model objects of a given module of the modules of the instance to class files. 191 * 192 * @param module The module to process. 193 * @param context The model context to use for committing the model objects. 194 * @param classesDirectory The directory holding the class files. 195 * 196 * @throws NullPointerException if {@code module}, {@code context} or {@code classesDirectory} is {@code null}. 197 * @throws IOException if committing model objects fails. 198 * 199 * @see #commitModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) 200 * @see #commitModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) 201 */ 202 public final void commitModelObjects( final Module module, final ModelContext context, final File classesDirectory ) 203 throws IOException 204 { 205 if ( module == null ) 206 { 207 throw new NullPointerException( "module" ); 208 } 209 if ( context == null ) 210 { 211 throw new NullPointerException( "context" ); 212 } 213 if ( classesDirectory == null ) 214 { 215 throw new NullPointerException( "classesDirectory" ); 216 } 217 218 try 219 { 220 if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) 221 { 222 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 223 m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 224 225 this.commitModelObjects( module.getSpecifications(), module.getImplementations(), m, classesDirectory ); 226 } 227 else if ( this.isLoggable( Level.WARNING ) ) 228 { 229 this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); 230 } 231 } 232 catch ( final ModelException e ) 233 { 234 // JDK: As of JDK 6, "new IOException( message, cause )". 235 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 236 } 237 } 238 239 /** 240 * Commits model objects of a given specification of the modules of the instance to class files. 241 * 242 * @param specification The specification to process. 243 * @param context The model context to use for committing the model objects. 244 * @param classesDirectory The directory holding the class files. 245 * 246 * @throws NullPointerException if {@code specification}, {@code context} or {@code classesDirectory} is 247 * {@code null}. 248 * @throws IOException if committing model objects fails. 249 * 250 * @see #commitModelObjects(org.jomc.model.Specification, javax.xml.bind.Marshaller, org.apache.bcel.classfile.JavaClass) 251 */ 252 public final void commitModelObjects( final Specification specification, final ModelContext context, 253 final File classesDirectory ) throws IOException 254 { 255 if ( specification == null ) 256 { 257 throw new NullPointerException( "specification" ); 258 } 259 if ( context == null ) 260 { 261 throw new NullPointerException( "context" ); 262 } 263 if ( classesDirectory == null ) 264 { 265 throw new NullPointerException( "classesDirectory" ); 266 } 267 268 try 269 { 270 if ( this.getModules() != null 271 && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 272 { 273 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 274 m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 275 276 this.commitModelObjects( specification, m, classesDirectory ); 277 } 278 else if ( this.isLoggable( Level.WARNING ) ) 279 { 280 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 281 } 282 } 283 catch ( final ModelException e ) 284 { 285 // JDK: As of JDK 6, "new IOException( message, cause )". 286 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 287 } 288 } 289 290 /** 291 * Commits model objects of a given implementation of the modules of the instance to class files. 292 * 293 * @param implementation The implementation to process. 294 * @param context The model context to use for committing the model objects. 295 * @param classesDirectory The directory holding the class files. 296 * 297 * @throws NullPointerException if {@code implementation}, {@code context} or {@code classesDirectory} is 298 * {@code null}. 299 * @throws IOException if committing model objects fails. 300 * 301 * @see #commitModelObjects(org.jomc.model.Implementation, javax.xml.bind.Marshaller, org.apache.bcel.classfile.JavaClass) 302 */ 303 public final void commitModelObjects( final Implementation implementation, final ModelContext context, 304 final File classesDirectory ) throws IOException 305 { 306 if ( implementation == null ) 307 { 308 throw new NullPointerException( "implementation" ); 309 } 310 if ( context == null ) 311 { 312 throw new NullPointerException( "context" ); 313 } 314 if ( classesDirectory == null ) 315 { 316 throw new NullPointerException( "classesDirectory" ); 317 } 318 319 try 320 { 321 if ( this.getModules() != null 322 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 323 { 324 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 325 m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 326 327 this.commitModelObjects( implementation, m, classesDirectory ); 328 } 329 else if ( this.isLoggable( Level.WARNING ) ) 330 { 331 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 332 } 333 } 334 catch ( final ModelException e ) 335 { 336 // JDK: As of JDK 6, "new IOException( message, cause )". 337 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 338 } 339 } 340 341 /** 342 * Commits model objects of a given specification of the modules of the instance to a given class file. 343 * 344 * @param specification The specification to process. 345 * @param marshaller The marshaller to use for committing the model objects. 346 * @param javaClass The java class to commit to. 347 * 348 * @throws NullPointerException if {@code specification}, {@code marshaller} or {@code javaClass} is {@code null}. 349 * @throws IOException if committing model objects fails. 350 */ 351 public void commitModelObjects( final Specification specification, final Marshaller marshaller, 352 final JavaClass javaClass ) throws IOException 353 { 354 if ( specification == null ) 355 { 356 throw new NullPointerException( "specification" ); 357 } 358 if ( marshaller == null ) 359 { 360 throw new NullPointerException( "marshaller" ); 361 } 362 if ( javaClass == null ) 363 { 364 throw new NullPointerException( "javaClass" ); 365 } 366 367 if ( this.getModules() != null 368 && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 369 { 370 this.setClassfileAttribute( javaClass, Specification.class.getName(), this.encodeModelObject( 371 marshaller, new ObjectFactory().createSpecification( specification ) ) ); 372 373 } 374 else if ( this.isLoggable( Level.WARNING ) ) 375 { 376 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 377 } 378 } 379 380 /** 381 * Commits model objects of a given implementation of the modules of the instance to a given class file. 382 * 383 * @param implementation The implementation to process. 384 * @param marshaller The marshaller to use for committing the model objects. 385 * @param javaClass The java class to commit to. 386 * 387 * @throws NullPointerException if {@code implementation}, {@code marshaller} or {@code javaClass} is {@code null}. 388 * @throws IOException if committing model objects fails. 389 */ 390 public void commitModelObjects( final Implementation implementation, final Marshaller marshaller, 391 final JavaClass javaClass ) throws IOException 392 { 393 if ( implementation == null ) 394 { 395 throw new NullPointerException( "implementation" ); 396 } 397 if ( marshaller == null ) 398 { 399 throw new NullPointerException( "marshaller" ); 400 } 401 if ( javaClass == null ) 402 { 403 throw new NullPointerException( "javaClass" ); 404 } 405 406 if ( this.getModules() != null 407 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 408 { 409 final ObjectFactory of = new ObjectFactory(); 410 411 Dependencies dependencies = this.getModules().getDependencies( implementation.getIdentifier() ); 412 if ( dependencies == null ) 413 { 414 dependencies = new Dependencies(); 415 } 416 417 Properties properties = this.getModules().getProperties( implementation.getIdentifier() ); 418 if ( properties == null ) 419 { 420 properties = new Properties(); 421 } 422 423 Messages messages = this.getModules().getMessages( implementation.getIdentifier() ); 424 if ( messages == null ) 425 { 426 messages = new Messages(); 427 } 428 429 Specifications specifications = this.getModules().getSpecifications( implementation.getIdentifier() ); 430 if ( specifications == null ) 431 { 432 specifications = new Specifications(); 433 } 434 435 for ( int i = 0, s0 = specifications.getReference().size(); i < s0; i++ ) 436 { 437 final SpecificationReference r = specifications.getReference().get( i ); 438 439 if ( specifications.getSpecification( r.getIdentifier() ) == null && this.isLoggable( Level.WARNING ) ) 440 { 441 this.log( Level.WARNING, getMessage( "unresolvedSpecification", r.getIdentifier(), 442 implementation.getIdentifier() ), null ); 443 444 } 445 } 446 447 for ( int i = 0, s0 = dependencies.getDependency().size(); i < s0; i++ ) 448 { 449 final Dependency d = dependencies.getDependency().get( i ); 450 final Specification s = this.getModules().getSpecification( d.getIdentifier() ); 451 452 if ( s != null ) 453 { 454 if ( specifications.getSpecification( s.getIdentifier() ) == null ) 455 { 456 specifications.getSpecification().add( s ); 457 } 458 } 459 else if ( this.isLoggable( Level.WARNING ) ) 460 { 461 this.log( Level.WARNING, getMessage( "unresolvedDependencySpecification", d.getIdentifier(), 462 d.getName(), implementation.getIdentifier() ), null ); 463 464 } 465 } 466 467 this.setClassfileAttribute( javaClass, Dependencies.class.getName(), this.encodeModelObject( 468 marshaller, of.createDependencies( dependencies ) ) ); 469 470 this.setClassfileAttribute( javaClass, Properties.class.getName(), this.encodeModelObject( 471 marshaller, of.createProperties( properties ) ) ); 472 473 this.setClassfileAttribute( javaClass, Messages.class.getName(), this.encodeModelObject( 474 marshaller, of.createMessages( messages ) ) ); 475 476 this.setClassfileAttribute( javaClass, Specifications.class.getName(), this.encodeModelObject( 477 marshaller, of.createSpecifications( specifications ) ) ); 478 479 } 480 else if ( this.isLoggable( Level.WARNING ) ) 481 { 482 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 483 } 484 } 485 486 /** 487 * Validates model objects of class files of the modules of the instance. 488 * 489 * @param context The model context to use for validating model objects. 490 * 491 * @return The report of the validation or {@code null}, if no model objects are found. 492 * 493 * @throws NullPointerException if {@code context} is {@code null}. 494 * @throws IOException if validating model objects fails. 495 * 496 * @see #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext) 497 */ 498 public final ModelValidationReport validateModelObjects( final ModelContext context ) throws IOException 499 { 500 if ( context == null ) 501 { 502 throw new NullPointerException( "context" ); 503 } 504 505 try 506 { 507 ModelValidationReport report = null; 508 509 if ( this.getModules() != null ) 510 { 511 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 512 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 513 report = this.validateModelObjects( this.getModules().getSpecifications(), 514 this.getModules().getImplementations(), u, context ); 515 516 } 517 else if ( this.isLoggable( Level.WARNING ) ) 518 { 519 this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); 520 } 521 522 return report; 523 } 524 catch ( final ModelException e ) 525 { 526 // JDK: As of JDK 6, "new IOException( message, cause )". 527 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 528 } 529 } 530 531 /** 532 * Validates model objects of class files of a given module of the modules of the instance. 533 * 534 * @param module The module to process. 535 * @param context The model context to use for validating model objects. 536 * 537 * @return The report of the validation or {@code null}, if no model objects are found. 538 * 539 * @throws NullPointerException if {@code module} or {@code context} is {@code null}. 540 * @throws IOException if validating model objects fails. 541 * 542 * @see #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext) 543 * @see #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext) 544 */ 545 public final ModelValidationReport validateModelObjects( final Module module, final ModelContext context ) 546 throws IOException 547 { 548 if ( module == null ) 549 { 550 throw new NullPointerException( "module" ); 551 } 552 if ( context == null ) 553 { 554 throw new NullPointerException( "context" ); 555 } 556 557 try 558 { 559 ModelValidationReport report = null; 560 561 if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) 562 { 563 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 564 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 565 report = this.validateModelObjects( module.getSpecifications(), module.getImplementations(), u, 566 context ); 567 568 } 569 else if ( this.isLoggable( Level.WARNING ) ) 570 { 571 this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); 572 } 573 574 return report; 575 } 576 catch ( final ModelException e ) 577 { 578 // JDK: As of JDK 6, "new IOException( message, cause )". 579 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 580 } 581 } 582 583 /** 584 * Validates model objects of class files of a given specification of the modules of the instance. 585 * 586 * @param specification The specification to process. 587 * @param context The model context to use for validating model objects. 588 * 589 * @return The report of the validation or {@code null}, if no model objects are found. 590 * 591 * @throws NullPointerException if {@code specification} or {@code context} is {@code null}. 592 * 593 * @throws IOException if validating model objects fails. 594 * 595 * @see #validateModelObjects(org.jomc.model.Specification, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) 596 */ 597 public final ModelValidationReport validateModelObjects( final Specification specification, 598 final ModelContext context ) throws IOException 599 { 600 if ( specification == null ) 601 { 602 throw new NullPointerException( "specification" ); 603 } 604 if ( context == null ) 605 { 606 throw new NullPointerException( "context" ); 607 } 608 609 try 610 { 611 ModelValidationReport report = null; 612 613 if ( this.getModules() != null 614 && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 615 { 616 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 617 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 618 report = this.validateModelObjects( specification, u, context ); 619 } 620 else if ( this.isLoggable( Level.WARNING ) ) 621 { 622 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 623 } 624 625 return report; 626 } 627 catch ( final ModelException e ) 628 { 629 // JDK: As of JDK 6, "new IOException( message, cause )". 630 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 631 } 632 } 633 634 /** 635 * Validates model objects of class files of a given implementation of the modules of the instance. 636 * 637 * @param implementation The implementation to process. 638 * @param context The model context to use for validating model objects. 639 * 640 * @return The report of the validation or {@code null}, if no model objects are found. 641 * 642 * @throws NullPointerException if {@code implementation} or {@code context} is {@code null}. 643 * 644 * @throws IOException if validating model objects fails. 645 * 646 * @see #validateModelObjects(org.jomc.model.Implementation, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) 647 */ 648 public final ModelValidationReport validateModelObjects( final Implementation implementation, 649 final ModelContext context ) throws IOException 650 { 651 if ( implementation == null ) 652 { 653 throw new NullPointerException( "implementation" ); 654 } 655 if ( context == null ) 656 { 657 throw new NullPointerException( "context" ); 658 } 659 660 try 661 { 662 ModelValidationReport report = null; 663 664 if ( this.getModules() != null 665 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 666 { 667 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 668 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 669 report = this.validateModelObjects( implementation, u, context ); 670 } 671 else if ( this.isLoggable( Level.WARNING ) ) 672 { 673 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 674 } 675 676 return report; 677 } 678 catch ( final ModelException e ) 679 { 680 // JDK: As of JDK 6, "new IOException( message, cause )". 681 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 682 } 683 } 684 685 /** 686 * Validates model objects of class files of the modules of the instance. 687 * 688 * @param context The model context to use for validating model objects. 689 * @param classesDirectory The directory holding the class files. 690 * 691 * @return The report of the validation or {@code null}, if no model objects are found. 692 * 693 * @throws NullPointerException if {@code context} or {@code classesDirectory} is {@code null}. 694 * @throws IOException if validating model objects fails. 695 * 696 * @see #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) 697 */ 698 public final ModelValidationReport validateModelObjects( final ModelContext context, final File classesDirectory ) 699 throws IOException 700 { 701 if ( context == null ) 702 { 703 throw new NullPointerException( "context" ); 704 } 705 if ( classesDirectory == null ) 706 { 707 throw new NullPointerException( "classesDirectory" ); 708 } 709 710 try 711 { 712 ModelValidationReport report = null; 713 714 if ( this.getModules() != null ) 715 { 716 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 717 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 718 report = this.validateModelObjects( this.getModules().getSpecifications(), 719 this.getModules().getImplementations(), u, classesDirectory ); 720 721 } 722 else if ( this.isLoggable( Level.WARNING ) ) 723 { 724 this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); 725 } 726 727 return report; 728 } 729 catch ( final ModelException e ) 730 { 731 // JDK: As of JDK 6, "new IOException( message, cause )". 732 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 733 } 734 } 735 736 /** 737 * Validates model objects of class files of a given module of the modules of the instance. 738 * 739 * @param module The module to process. 740 * @param context The model context to use for validating model objects. 741 * @param classesDirectory The directory holding the class files. 742 * 743 * @return The report of the validation or {@code null}, if no model objects are found. 744 * 745 * @throws NullPointerException if {@code module}, {@code context} or {@code classesDirectory} is {@code null}. 746 * @throws IOException if validating model objects fails. 747 * 748 * @see #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) 749 * @see #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) 750 */ 751 public final ModelValidationReport validateModelObjects( final Module module, final ModelContext context, 752 final File classesDirectory ) throws IOException 753 { 754 if ( module == null ) 755 { 756 throw new NullPointerException( "module" ); 757 } 758 if ( context == null ) 759 { 760 throw new NullPointerException( "context" ); 761 } 762 if ( classesDirectory == null ) 763 { 764 throw new NullPointerException( "classesDirectory" ); 765 } 766 767 try 768 { 769 ModelValidationReport report = null; 770 771 if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) 772 { 773 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 774 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 775 report = this.validateModelObjects( module.getSpecifications(), module.getImplementations(), u, 776 classesDirectory ); 777 778 } 779 else if ( this.isLoggable( Level.WARNING ) ) 780 { 781 this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); 782 } 783 784 return report; 785 } 786 catch ( final ModelException e ) 787 { 788 // JDK: As of JDK 6, "new IOException( message, cause )". 789 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 790 } 791 } 792 793 /** 794 * Validates model objects of class files of a given specification of the modules of the instance. 795 * 796 * @param specification The specification to process. 797 * @param context The model context to use for validating model objects. 798 * @param classesDirectory The directory holding the class files. 799 * 800 * @return The report of the validation or {@code null}, if no model objects are found. 801 * 802 * @throws NullPointerException if {@code specification}, {@code context} or {@code classesDirectory} is 803 * {@code null}. 804 * 805 * @throws IOException if validating model objects fails. 806 * 807 * @see #validateModelObjects(org.jomc.model.Specification, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) 808 */ 809 public final ModelValidationReport validateModelObjects( final Specification specification, 810 final ModelContext context, final File classesDirectory ) 811 throws IOException 812 { 813 if ( specification == null ) 814 { 815 throw new NullPointerException( "specification" ); 816 } 817 if ( context == null ) 818 { 819 throw new NullPointerException( "context" ); 820 } 821 if ( classesDirectory == null ) 822 { 823 throw new NullPointerException( "classesDirectory" ); 824 } 825 826 try 827 { 828 ModelValidationReport report = null; 829 830 if ( this.getModules() != null 831 && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 832 { 833 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 834 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 835 report = this.validateModelObjects( specification, u, classesDirectory ); 836 } 837 else if ( this.isLoggable( Level.WARNING ) ) 838 { 839 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 840 } 841 842 return report; 843 } 844 catch ( final ModelException e ) 845 { 846 // JDK: As of JDK 6, "new IOException( message, cause )". 847 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 848 } 849 } 850 851 /** 852 * Validates model objects of class files of a given implementation of the modules of the instance. 853 * 854 * @param implementation The implementation to process. 855 * @param context The model context to use for validating model objects. 856 * @param classesDirectory The directory holding the class files. 857 * 858 * @return The report of the validation or {@code null}, if no model objects are found. 859 * 860 * @throws NullPointerException if {@code implementation}, {@code context} or {@code classesDirectory} is 861 * {@code null}. 862 * 863 * @throws IOException if validating model objects fails. 864 * 865 * @see #validateModelObjects(org.jomc.model.Implementation, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) 866 */ 867 public final ModelValidationReport validateModelObjects( final Implementation implementation, 868 final ModelContext context, final File classesDirectory ) 869 throws IOException 870 { 871 if ( implementation == null ) 872 { 873 throw new NullPointerException( "implementation" ); 874 } 875 if ( context == null ) 876 { 877 throw new NullPointerException( "context" ); 878 } 879 if ( classesDirectory == null ) 880 { 881 throw new NullPointerException( "classesDirectory" ); 882 } 883 884 try 885 { 886 ModelValidationReport report = null; 887 888 if ( this.getModules() != null 889 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 890 { 891 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 892 u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); 893 report = this.validateModelObjects( implementation, u, classesDirectory ); 894 } 895 else if ( this.isLoggable( Level.WARNING ) ) 896 { 897 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 898 } 899 900 return report; 901 } 902 catch ( final ModelException e ) 903 { 904 // JDK: As of JDK 6, "new IOException( message, cause )". 905 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 906 } 907 } 908 909 /** 910 * Validates model objects of a given specification of the modules of the instance. 911 * 912 * @param specification The specification to process. 913 * @param unmarshaller The unmarshaller to use for validating model objects. 914 * @param javaClass The java class to validate. 915 * 916 * @return The report of the validation or {@code null}, if no model objects are found. 917 * 918 * @throws NullPointerException if {@code specification}, {@code unmarshaller} or {@code javaClass} is {@code null}. 919 * @throws IOException if validating model objects fails. 920 */ 921 public ModelValidationReport validateModelObjects( final Specification specification, 922 final Unmarshaller unmarshaller, final JavaClass javaClass ) 923 throws IOException 924 { 925 if ( specification == null ) 926 { 927 throw new NullPointerException( "specification" ); 928 } 929 if ( unmarshaller == null ) 930 { 931 throw new NullPointerException( "unmarshaller" ); 932 } 933 if ( javaClass == null ) 934 { 935 throw new NullPointerException( "javaClass" ); 936 } 937 938 ModelValidationReport report = null; 939 940 if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 941 { 942 report = new ModelValidationReport(); 943 944 Specification decoded = null; 945 final byte[] bytes = this.getClassfileAttribute( javaClass, Specification.class.getName() ); 946 if ( bytes != null ) 947 { 948 decoded = this.decodeModelObject( unmarshaller, bytes, Specification.class ); 949 } 950 951 if ( decoded != null ) 952 { 953 if ( decoded.getMultiplicity() != specification.getMultiplicity() ) 954 { 955 report.getDetails().add( new ModelValidationReport.Detail( 956 "CLASS_ILLEGAL_SPECIFICATION_MULTIPLICITY", Level.SEVERE, getMessage( 957 "illegalMultiplicity", specification.getIdentifier(), 958 specification.getMultiplicity().value(), 959 decoded.getMultiplicity().value() ), 960 new ObjectFactory().createSpecification( specification ) ) ); 961 962 } 963 964 if ( decoded.getScope() == null 965 ? specification.getScope() != null 966 : !decoded.getScope().equals( specification.getScope() ) ) 967 { 968 report.getDetails().add( new ModelValidationReport.Detail( 969 "CLASS_ILLEGAL_SPECIFICATION_SCOPE", Level.SEVERE, getMessage( 970 "illegalScope", specification.getIdentifier(), 971 specification.getScope() == null ? "Multiton" : specification.getScope(), 972 decoded.getScope() == null ? "Multiton" : decoded.getScope() ), 973 new ObjectFactory().createSpecification( specification ) ) ); 974 975 } 976 977 if ( decoded.getClazz() == null 978 ? specification.getClazz() != null 979 : !decoded.getClazz().equals( specification.getClazz() ) ) 980 { 981 report.getDetails().add( new ModelValidationReport.Detail( 982 "CLASS_ILLEGAL_SPECIFICATION_CLASS", Level.SEVERE, getMessage( 983 "illegalSpecificationClass", decoded.getIdentifier(), 984 specification.getClazz(), decoded.getClazz() ), 985 new ObjectFactory().createSpecification( specification ) ) ); 986 987 } 988 } 989 else if ( this.isLoggable( Level.WARNING ) ) 990 { 991 this.log( Level.WARNING, getMessage( "cannotValidateSpecification", specification.getIdentifier(), 992 Specification.class.getName() ), null ); 993 994 } 995 } 996 else if ( this.isLoggable( Level.WARNING ) ) 997 { 998 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 999 } 1000 1001 return report; 1002 } 1003 1004 /** 1005 * Validates model objects of a given implementation of the modules of the instance. 1006 * 1007 * @param implementation The implementation to process. 1008 * @param unmarshaller The unmarshaller to use for validating model objects. 1009 * @param javaClass The java class to validate. 1010 * 1011 * @return The report of the validation or {@code null}, if no model objects are found. 1012 * 1013 * @throws NullPointerException if {@code implementation}, {@code unmarshaller} or {@code javaClass} is {@code null}. 1014 * @throws IOException if validating model objects fails. 1015 */ 1016 public ModelValidationReport validateModelObjects( final Implementation implementation, 1017 final Unmarshaller unmarshaller, final JavaClass javaClass ) 1018 throws IOException 1019 { 1020 if ( implementation == null ) 1021 { 1022 throw new NullPointerException( "implementation" ); 1023 } 1024 if ( unmarshaller == null ) 1025 { 1026 throw new NullPointerException( "unmarshaller" ); 1027 } 1028 if ( javaClass == null ) 1029 { 1030 throw new NullPointerException( "javaClass" ); 1031 } 1032 1033 try 1034 { 1035 ModelValidationReport report = null; 1036 1037 if ( this.getModules() != null 1038 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 1039 { 1040 report = new ModelValidationReport(); 1041 Dependencies dependencies = this.getModules().getDependencies( implementation.getIdentifier() ); 1042 if ( dependencies == null ) 1043 { 1044 dependencies = new Dependencies(); 1045 } 1046 1047 Properties properties = this.getModules().getProperties( implementation.getIdentifier() ); 1048 if ( properties == null ) 1049 { 1050 properties = new Properties(); 1051 } 1052 1053 Messages messages = this.getModules().getMessages( implementation.getIdentifier() ); 1054 if ( messages == null ) 1055 { 1056 messages = new Messages(); 1057 } 1058 1059 Specifications specifications = this.getModules().getSpecifications( implementation.getIdentifier() ); 1060 if ( specifications == null ) 1061 { 1062 specifications = new Specifications(); 1063 } 1064 1065 Dependencies decodedDependencies = null; 1066 byte[] bytes = this.getClassfileAttribute( javaClass, Dependencies.class.getName() ); 1067 if ( bytes != null ) 1068 { 1069 decodedDependencies = this.decodeModelObject( unmarshaller, bytes, Dependencies.class ); 1070 } 1071 1072 Properties decodedProperties = null; 1073 bytes = this.getClassfileAttribute( javaClass, Properties.class.getName() ); 1074 if ( bytes != null ) 1075 { 1076 decodedProperties = this.decodeModelObject( unmarshaller, bytes, Properties.class ); 1077 } 1078 1079 Messages decodedMessages = null; 1080 bytes = this.getClassfileAttribute( javaClass, Messages.class.getName() ); 1081 if ( bytes != null ) 1082 { 1083 decodedMessages = this.decodeModelObject( unmarshaller, bytes, Messages.class ); 1084 } 1085 1086 Specifications decodedSpecifications = null; 1087 bytes = this.getClassfileAttribute( javaClass, Specifications.class.getName() ); 1088 if ( bytes != null ) 1089 { 1090 decodedSpecifications = this.decodeModelObject( unmarshaller, bytes, Specifications.class ); 1091 } 1092 1093 if ( decodedDependencies != null ) 1094 { 1095 for ( int i = 0, s0 = decodedDependencies.getDependency().size(); i < s0; i++ ) 1096 { 1097 final Dependency decodedDependency = decodedDependencies.getDependency().get( i ); 1098 final Dependency dependency = dependencies.getDependency( decodedDependency.getName() ); 1099 final Specification s = this.getModules().getSpecification( decodedDependency.getIdentifier() ); 1100 1101 if ( dependency == null ) 1102 { 1103 report.getDetails().add( new ModelValidationReport.Detail( 1104 "CLASS_MISSING_IMPLEMENTATION_DEPENDENCY", Level.SEVERE, getMessage( 1105 "missingDependency", implementation.getIdentifier(), decodedDependency.getName() ), 1106 new ObjectFactory().createImplementation( implementation ) ) ); 1107 1108 } 1109 else if ( decodedDependency.getImplementationName() != null 1110 && dependency.getImplementationName() == null ) 1111 { 1112 report.getDetails().add( new ModelValidationReport.Detail( 1113 "CLASS_MISSING_DEPENDENCY_IMPLEMENTATION_NAME", Level.SEVERE, getMessage( 1114 "missingDependencyImplementationName", implementation.getIdentifier(), 1115 decodedDependency.getName() ), 1116 new ObjectFactory().createImplementation( implementation ) ) ); 1117 1118 } 1119 1120 if ( s != null && s.getVersion() != null && decodedDependency.getVersion() != null 1121 && VersionParser.compare( decodedDependency.getVersion(), s.getVersion() ) > 0 ) 1122 { 1123 final Module moduleOfSpecification = 1124 this.getModules().getModuleOfSpecification( s.getIdentifier() ); 1125 1126 final Module moduleOfImplementation = 1127 this.getModules().getModuleOfImplementation( implementation.getIdentifier() ); 1128 1129 report.getDetails().add( new ModelValidationReport.Detail( 1130 "CLASS_INCOMPATIBLE_IMPLEMENTATION_DEPENDENCY", Level.SEVERE, getMessage( 1131 "incompatibleDependency", javaClass.getClassName(), 1132 moduleOfImplementation == null ? "<>" : moduleOfImplementation.getName(), 1133 s.getIdentifier(), 1134 moduleOfSpecification == null ? "<>" : moduleOfSpecification.getName(), 1135 decodedDependency.getVersion(), s.getVersion() ), 1136 new ObjectFactory().createImplementation( implementation ) ) ); 1137 1138 } 1139 } 1140 } 1141 else if ( this.isLoggable( Level.WARNING ) ) 1142 { 1143 this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), 1144 Dependencies.class.getName() ), null ); 1145 1146 } 1147 1148 if ( decodedProperties != null ) 1149 { 1150 for ( int i = 0, s0 = decodedProperties.getProperty().size(); i < s0; i++ ) 1151 { 1152 final Property decodedProperty = decodedProperties.getProperty().get( i ); 1153 final Property property = properties.getProperty( decodedProperty.getName() ); 1154 1155 if ( property == null ) 1156 { 1157 report.getDetails().add( new ModelValidationReport.Detail( 1158 "CLASS_MISSING_IMPLEMENTATION_PROPERTY", Level.SEVERE, getMessage( 1159 "missingProperty", implementation.getIdentifier(), decodedProperty.getName() ), 1160 new ObjectFactory().createImplementation( implementation ) ) ); 1161 1162 } 1163 else if ( decodedProperty.getType() == null 1164 ? property.getType() != null 1165 : !decodedProperty.getType().equals( property.getType() ) ) 1166 { 1167 report.getDetails().add( new ModelValidationReport.Detail( 1168 "CLASS_ILLEGAL_IMPLEMENTATION_PROPERTY", Level.SEVERE, getMessage( 1169 "illegalPropertyType", implementation.getIdentifier(), decodedProperty.getName(), 1170 property.getType() == null ? "<>" : property.getType(), 1171 decodedProperty.getType() == null ? "<>" : decodedProperty.getType() ), 1172 new ObjectFactory().createImplementation( implementation ) ) ); 1173 1174 } 1175 } 1176 } 1177 else if ( this.isLoggable( Level.WARNING ) ) 1178 { 1179 this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), 1180 Properties.class.getName() ), null ); 1181 1182 } 1183 1184 if ( decodedMessages != null ) 1185 { 1186 for ( int i = 0, s0 = decodedMessages.getMessage().size(); i < s0; i++ ) 1187 { 1188 final Message decodedMessage = decodedMessages.getMessage().get( i ); 1189 final Message message = messages.getMessage( decodedMessage.getName() ); 1190 1191 if ( message == null ) 1192 { 1193 report.getDetails().add( new ModelValidationReport.Detail( 1194 "CLASS_MISSING_IMPLEMENTATION_MESSAGE", Level.SEVERE, getMessage( 1195 "missingMessage", implementation.getIdentifier(), decodedMessage.getName() ), 1196 new ObjectFactory().createImplementation( implementation ) ) ); 1197 1198 } 1199 } 1200 } 1201 else if ( this.isLoggable( Level.WARNING ) ) 1202 { 1203 this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), 1204 Messages.class.getName() ), null ); 1205 1206 } 1207 1208 if ( decodedSpecifications != null ) 1209 { 1210 for ( int i = 0, s0 = decodedSpecifications.getSpecification().size(); i < s0; i++ ) 1211 { 1212 final Specification decodedSpecification = decodedSpecifications.getSpecification().get( i ); 1213 final Specification specification = 1214 this.getModules().getSpecification( decodedSpecification.getIdentifier() ); 1215 1216 if ( specification == null ) 1217 { 1218 report.getDetails().add( new ModelValidationReport.Detail( 1219 "CLASS_MISSING_SPECIFICATION", Level.SEVERE, getMessage( 1220 "missingSpecification", implementation.getIdentifier(), 1221 decodedSpecification.getIdentifier() ), 1222 new ObjectFactory().createImplementation( implementation ) ) ); 1223 1224 } 1225 else 1226 { 1227 if ( decodedSpecification.getMultiplicity() != specification.getMultiplicity() ) 1228 { 1229 report.getDetails().add( new ModelValidationReport.Detail( 1230 "CLASS_ILLEGAL_SPECIFICATION_MULTIPLICITY", Level.SEVERE, getMessage( 1231 "illegalMultiplicity", specification.getIdentifier(), 1232 specification.getMultiplicity().value(), 1233 decodedSpecification.getMultiplicity().value() ), 1234 new ObjectFactory().createImplementation( implementation ) ) ); 1235 1236 } 1237 1238 if ( decodedSpecification.getScope() == null 1239 ? specification.getScope() != null 1240 : !decodedSpecification.getScope().equals( specification.getScope() ) ) 1241 { 1242 report.getDetails().add( new ModelValidationReport.Detail( 1243 "CLASS_ILLEGAL_SPECIFICATION_SCOPE", Level.SEVERE, getMessage( 1244 "illegalScope", decodedSpecification.getIdentifier(), 1245 specification.getScope() == null ? "Multiton" : specification.getScope(), 1246 decodedSpecification.getScope() == null 1247 ? "Multiton" 1248 : decodedSpecification.getScope() ), 1249 new ObjectFactory().createImplementation( implementation ) ) ); 1250 1251 } 1252 1253 if ( decodedSpecification.getClazz() == null 1254 ? specification.getClazz() != null 1255 : !decodedSpecification.getClazz().equals( specification.getClazz() ) ) 1256 { 1257 report.getDetails().add( new ModelValidationReport.Detail( 1258 "CLASS_ILLEGAL_SPECIFICATION_CLASS", Level.SEVERE, getMessage( 1259 "illegalSpecificationClass", decodedSpecification.getIdentifier(), 1260 specification.getClazz(), decodedSpecification.getClazz() ), 1261 new ObjectFactory().createImplementation( implementation ) ) ); 1262 1263 } 1264 } 1265 } 1266 1267 for ( int i = 0, s0 = decodedSpecifications.getReference().size(); i < s0; i++ ) 1268 { 1269 final SpecificationReference decodedReference = decodedSpecifications.getReference().get( i ); 1270 final Specification specification = 1271 specifications.getSpecification( decodedReference.getIdentifier() ); 1272 1273 if ( specification == null ) 1274 { 1275 report.getDetails().add( new ModelValidationReport.Detail( 1276 "CLASS_MISSING_SPECIFICATION", Level.SEVERE, getMessage( 1277 "missingSpecification", implementation.getIdentifier(), 1278 decodedReference.getIdentifier() ), 1279 new ObjectFactory().createImplementation( implementation ) ) ); 1280 1281 } 1282 else if ( decodedReference.getVersion() != null && specification.getVersion() != null 1283 && VersionParser.compare( decodedReference.getVersion(), 1284 specification.getVersion() ) != 0 ) 1285 { 1286 final Module moduleOfSpecification = 1287 this.getModules().getModuleOfSpecification( decodedReference.getIdentifier() ); 1288 1289 final Module moduleOfImplementation = 1290 this.getModules().getModuleOfImplementation( implementation.getIdentifier() ); 1291 1292 report.getDetails().add( new ModelValidationReport.Detail( 1293 "CLASS_INCOMPATIBLE_IMPLEMENTATION", Level.SEVERE, getMessage( 1294 "incompatibleImplementation", javaClass.getClassName(), 1295 moduleOfImplementation == null ? "<>" : moduleOfImplementation.getName(), 1296 specification.getIdentifier(), 1297 moduleOfSpecification == null ? "<>" : moduleOfSpecification.getName(), 1298 decodedReference.getVersion(), specification.getVersion() ), 1299 new ObjectFactory().createImplementation( implementation ) ) ); 1300 1301 } 1302 } 1303 } 1304 else if ( this.isLoggable( Level.WARNING ) ) 1305 { 1306 this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), 1307 Specifications.class.getName() ), null ); 1308 1309 } 1310 } 1311 else if ( this.isLoggable( Level.WARNING ) ) 1312 { 1313 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 1314 } 1315 1316 return report; 1317 } 1318 catch ( final ParseException e ) 1319 { 1320 // JDK: As of JDK 6, "new IOException( message, cause )". 1321 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 1322 } 1323 catch ( final TokenMgrError e ) 1324 { 1325 // JDK: As of JDK 6, "new IOException( message, cause )". 1326 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 1327 } 1328 } 1329 1330 /** 1331 * Transforms model objects of class files of the modules of the instance. 1332 * 1333 * @param context The model context to use for transforming model objects. 1334 * @param classesDirectory The directory holding the class files. 1335 * @param transformers The transformers to use for transforming model objects. 1336 * 1337 * @throws NullPointerException if {@code context}, {@code classesDirectory} or {@code transformers} is 1338 * {@code null}. 1339 * @throws IOException if transforming model objects fails. 1340 * 1341 * @see #transformModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File, java.util.List) 1342 */ 1343 public final void transformModelObjects( final ModelContext context, final File classesDirectory, 1344 final List<Transformer> transformers ) throws IOException 1345 { 1346 if ( context == null ) 1347 { 1348 throw new NullPointerException( "context" ); 1349 } 1350 if ( classesDirectory == null ) 1351 { 1352 throw new NullPointerException( "classesDirectory" ); 1353 } 1354 if ( transformers == null ) 1355 { 1356 throw new NullPointerException( "transformers" ); 1357 } 1358 if ( !classesDirectory.isDirectory() ) 1359 { 1360 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 1361 } 1362 1363 try 1364 { 1365 if ( this.getModules() != null ) 1366 { 1367 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 1368 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 1369 final Schema s = context.createSchema( this.getModel().getIdentifier() ); 1370 u.setSchema( s ); 1371 m.setSchema( s ); 1372 1373 this.transformModelObjects( this.getModules().getSpecifications(), 1374 this.getModules().getImplementations(), 1375 u, m, classesDirectory, transformers ); 1376 1377 } 1378 else if ( this.isLoggable( Level.WARNING ) ) 1379 { 1380 this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); 1381 } 1382 } 1383 catch ( final ModelException e ) 1384 { 1385 // JDK: As of JDK 6, "new IOException( message, cause )". 1386 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 1387 } 1388 } 1389 1390 /** 1391 * Transforms model objects of class files of a given module of the modules of the instance. 1392 * 1393 * @param module The module to process. 1394 * @param context The model context to use for transforming model objects. 1395 * @param classesDirectory The directory holding the class files. 1396 * @param transformers The transformers to use for transforming the model objects. 1397 * 1398 * @throws NullPointerException if {@code module}, {@code context}, {@code classesDirectory} or {@code transformers} 1399 * is {@code null}. 1400 * @throws IOException if transforming model objects fails. 1401 * 1402 * @see #transformModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File, java.util.List) 1403 * @see #transformModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File, java.util.List) 1404 */ 1405 public final void transformModelObjects( final Module module, final ModelContext context, 1406 final File classesDirectory, final List<Transformer> transformers ) 1407 throws IOException 1408 { 1409 if ( module == null ) 1410 { 1411 throw new NullPointerException( "module" ); 1412 } 1413 if ( context == null ) 1414 { 1415 throw new NullPointerException( "context" ); 1416 } 1417 if ( classesDirectory == null ) 1418 { 1419 throw new NullPointerException( "classesDirectory" ); 1420 } 1421 if ( transformers == null ) 1422 { 1423 throw new NullPointerException( "transformers" ); 1424 } 1425 if ( !classesDirectory.isDirectory() ) 1426 { 1427 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 1428 } 1429 1430 try 1431 { 1432 if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) 1433 { 1434 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 1435 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 1436 final Schema s = context.createSchema( this.getModel().getIdentifier() ); 1437 u.setSchema( s ); 1438 m.setSchema( s ); 1439 1440 this.transformModelObjects( module.getSpecifications(), module.getImplementations(), u, m, 1441 classesDirectory, transformers ); 1442 1443 } 1444 else if ( this.isLoggable( Level.WARNING ) ) 1445 { 1446 this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); 1447 } 1448 } 1449 catch ( final ModelException e ) 1450 { 1451 // JDK: As of JDK 6, "new IOException( message, cause )". 1452 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 1453 } 1454 } 1455 1456 /** 1457 * Transforms model objects of class files of a given specification of the modules of the instance. 1458 * 1459 * @param specification The specification to process. 1460 * @param context The model context to use for transforming model objects. 1461 * @param classesDirectory The directory holding the class files. 1462 * @param transformers The transformers to use for transforming the model objects. 1463 * 1464 * @throws NullPointerException if {@code specification}, {@code context}, {@code classesDirectory} or 1465 * {@code transformers} is {@code null}. 1466 * @throws IOException if transforming model objects fails. 1467 * 1468 * @see #transformModelObjects(org.jomc.model.Specification, javax.xml.bind.Marshaller, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass, java.util.List) 1469 */ 1470 public final void transformModelObjects( final Specification specification, final ModelContext context, 1471 final File classesDirectory, final List<Transformer> transformers ) 1472 throws IOException 1473 { 1474 if ( specification == null ) 1475 { 1476 throw new NullPointerException( "specification" ); 1477 } 1478 if ( context == null ) 1479 { 1480 throw new NullPointerException( "context" ); 1481 } 1482 if ( classesDirectory == null ) 1483 { 1484 throw new NullPointerException( "classesDirectory" ); 1485 } 1486 if ( transformers == null ) 1487 { 1488 throw new NullPointerException( "transformers" ); 1489 } 1490 if ( !classesDirectory.isDirectory() ) 1491 { 1492 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 1493 } 1494 1495 try 1496 { 1497 if ( this.getModules() != null 1498 && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 1499 { 1500 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 1501 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 1502 final Schema s = context.createSchema( this.getModel().getIdentifier() ); 1503 u.setSchema( s ); 1504 m.setSchema( s ); 1505 1506 this.transformModelObjects( specification, m, u, classesDirectory, transformers ); 1507 } 1508 else if ( this.isLoggable( Level.WARNING ) ) 1509 { 1510 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 1511 } 1512 } 1513 catch ( final ModelException e ) 1514 { 1515 // JDK: As of JDK 6, "new IOException( message, cause )". 1516 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 1517 } 1518 } 1519 1520 /** 1521 * Transforms model objects of class files of a given implementation of the modules of the instance. 1522 * 1523 * @param implementation The implementation to process. 1524 * @param context The model context to use for transforming model objects. 1525 * @param classesDirectory The directory holding the class files. 1526 * @param transformers The transformers to use for transforming the model objects. 1527 * 1528 * @throws NullPointerException if {@code implementation}, {@code context}, {@code classesDirectory} or 1529 * {@code transformers} is {@code null}. 1530 * @throws IOException if transforming model objects fails. 1531 * 1532 * @see #transformModelObjects(org.jomc.model.Implementation, javax.xml.bind.Marshaller, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass, java.util.List) 1533 */ 1534 public final void transformModelObjects( final Implementation implementation, final ModelContext context, 1535 final File classesDirectory, final List<Transformer> transformers ) 1536 throws IOException 1537 { 1538 if ( implementation == null ) 1539 { 1540 throw new NullPointerException( "implementation" ); 1541 } 1542 if ( context == null ) 1543 { 1544 throw new NullPointerException( "context" ); 1545 } 1546 if ( classesDirectory == null ) 1547 { 1548 throw new NullPointerException( "classesDirectory" ); 1549 } 1550 if ( transformers == null ) 1551 { 1552 throw new NullPointerException( "transformers" ); 1553 } 1554 if ( !classesDirectory.isDirectory() ) 1555 { 1556 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 1557 } 1558 1559 try 1560 { 1561 if ( this.getModules() != null 1562 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 1563 { 1564 final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); 1565 final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); 1566 final Schema s = context.createSchema( this.getModel().getIdentifier() ); 1567 u.setSchema( s ); 1568 m.setSchema( s ); 1569 1570 this.transformModelObjects( implementation, m, u, classesDirectory, transformers ); 1571 } 1572 else if ( this.isLoggable( Level.WARNING ) ) 1573 { 1574 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 1575 } 1576 } 1577 catch ( final ModelException e ) 1578 { 1579 // JDK: As of JDK 6, "new IOException( message, cause )". 1580 throw (IOException) new IOException( getMessage( e ) ).initCause( e ); 1581 } 1582 } 1583 1584 /** 1585 * Transforms model objects of a given specification of the modules of the instance. 1586 * 1587 * @param specification The specification to process. 1588 * @param marshaller The marshaller to use for transforming model objects. 1589 * @param unmarshaller The unmarshaller to use for transforming model objects. 1590 * @param javaClass The java class to transform model objects of. 1591 * @param transformers The transformers to use for transforming the model objects. 1592 * 1593 * @throws NullPointerException if {@code specification}, {@code marshaller}, {@code unmarshaller}, 1594 * {@code javaClass} or {@code transformers} is {@code null}. 1595 * @throws IOException if transforming model objects fails. 1596 */ 1597 public void transformModelObjects( final Specification specification, final Marshaller marshaller, 1598 final Unmarshaller unmarshaller, final JavaClass javaClass, 1599 final List<Transformer> transformers ) throws IOException 1600 { 1601 if ( specification == null ) 1602 { 1603 throw new NullPointerException( "specification" ); 1604 } 1605 if ( marshaller == null ) 1606 { 1607 throw new NullPointerException( "marshaller" ); 1608 } 1609 if ( unmarshaller == null ) 1610 { 1611 throw new NullPointerException( "unmarshaller" ); 1612 } 1613 if ( javaClass == null ) 1614 { 1615 throw new NullPointerException( "javaClass" ); 1616 } 1617 if ( transformers == null ) 1618 { 1619 throw new NullPointerException( "transformers" ); 1620 } 1621 1622 try 1623 { 1624 if ( this.getModules() != null 1625 && this.getModules().getSpecification( specification.getIdentifier() ) != null ) 1626 { 1627 Specification decodedSpecification = null; 1628 final ObjectFactory objectFactory = new ObjectFactory(); 1629 final byte[] bytes = this.getClassfileAttribute( javaClass, Specification.class.getName() ); 1630 if ( bytes != null ) 1631 { 1632 decodedSpecification = this.decodeModelObject( unmarshaller, bytes, Specification.class ); 1633 } 1634 1635 if ( decodedSpecification != null ) 1636 { 1637 for ( int i = 0, l = transformers.size(); i < l; i++ ) 1638 { 1639 final JAXBSource source = 1640 new JAXBSource( marshaller, objectFactory.createSpecification( decodedSpecification ) ); 1641 1642 final JAXBResult result = new JAXBResult( unmarshaller ); 1643 transformers.get( i ).transform( source, result ); 1644 1645 if ( result.getResult() instanceof JAXBElement<?> 1646 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Specification ) 1647 { 1648 decodedSpecification = (Specification) ( (JAXBElement<?>) result.getResult() ).getValue(); 1649 } 1650 else 1651 { 1652 throw new IOException( getMessage( 1653 "illegalSpecificationTransformationResult", specification.getIdentifier() ) ); 1654 1655 } 1656 } 1657 1658 this.setClassfileAttribute( javaClass, Specification.class.getName(), this.encodeModelObject( 1659 marshaller, 1660 objectFactory.createSpecification( decodedSpecification ) ) ); 1661 1662 } 1663 } 1664 else if ( this.isLoggable( Level.WARNING ) ) 1665 { 1666 this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); 1667 } 1668 } 1669 catch ( final JAXBException e ) 1670 { 1671 String message = getMessage( e ); 1672 if ( message == null && e.getLinkedException() != null ) 1673 { 1674 message = getMessage( e.getLinkedException() ); 1675 } 1676 1677 // JDK: As of JDK 6, "new IOException( message, cause )". 1678 throw (IOException) new IOException( message ).initCause( e ); 1679 } 1680 catch ( final TransformerException e ) 1681 { 1682 String message = getMessage( e ); 1683 if ( message == null && e.getException() != null ) 1684 { 1685 message = getMessage( e.getException() ); 1686 } 1687 1688 // JDK: As of JDK 6, "new IOException( message, cause )". 1689 throw (IOException) new IOException( message ).initCause( e ); 1690 } 1691 } 1692 1693 /** 1694 * Transforms model objects of a given implementation of the modules of the instance. 1695 * 1696 * @param implementation The implementation to process. 1697 * @param marshaller The marshaller to use for transforming model objects. 1698 * @param unmarshaller The unmarshaller to use for transforming model objects. 1699 * @param javaClass The java class to transform model object of. 1700 * @param transformers The transformers to use for transforming the model objects. 1701 * 1702 * @throws NullPointerException if {@code implementation}, {@code marshaller}, {@code unmarshaller}, 1703 * {@code javaClass} or {@code transformers} is {@code null}. 1704 * @throws IOException if transforming model objects fails. 1705 */ 1706 public void transformModelObjects( final Implementation implementation, final Marshaller marshaller, 1707 final Unmarshaller unmarshaller, final JavaClass javaClass, 1708 final List<Transformer> transformers ) throws IOException 1709 { 1710 if ( implementation == null ) 1711 { 1712 throw new NullPointerException( "implementation" ); 1713 } 1714 if ( marshaller == null ) 1715 { 1716 throw new NullPointerException( "marshaller" ); 1717 } 1718 if ( unmarshaller == null ) 1719 { 1720 throw new NullPointerException( "unmarshaller" ); 1721 } 1722 if ( javaClass == null ) 1723 { 1724 throw new NullPointerException( "javaClass" ); 1725 } 1726 if ( transformers == null ) 1727 { 1728 throw new NullPointerException( "transformers" ); 1729 } 1730 1731 try 1732 { 1733 if ( this.getModules() != null 1734 && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) 1735 { 1736 Dependencies decodedDependencies = null; 1737 byte[] bytes = this.getClassfileAttribute( javaClass, Dependencies.class.getName() ); 1738 if ( bytes != null ) 1739 { 1740 decodedDependencies = this.decodeModelObject( unmarshaller, bytes, Dependencies.class ); 1741 } 1742 1743 Messages decodedMessages = null; 1744 bytes = this.getClassfileAttribute( javaClass, Messages.class.getName() ); 1745 if ( bytes != null ) 1746 { 1747 decodedMessages = this.decodeModelObject( unmarshaller, bytes, Messages.class ); 1748 } 1749 1750 Properties decodedProperties = null; 1751 bytes = this.getClassfileAttribute( javaClass, Properties.class.getName() ); 1752 if ( bytes != null ) 1753 { 1754 decodedProperties = this.decodeModelObject( unmarshaller, bytes, Properties.class ); 1755 } 1756 1757 Specifications decodedSpecifications = null; 1758 bytes = this.getClassfileAttribute( javaClass, Specifications.class.getName() ); 1759 if ( bytes != null ) 1760 { 1761 decodedSpecifications = this.decodeModelObject( unmarshaller, bytes, Specifications.class ); 1762 } 1763 1764 final ObjectFactory of = new ObjectFactory(); 1765 for ( int i = 0, l = transformers.size(); i < l; i++ ) 1766 { 1767 final Transformer transformer = transformers.get( i ); 1768 1769 if ( decodedDependencies != null ) 1770 { 1771 final JAXBSource source = 1772 new JAXBSource( marshaller, of.createDependencies( decodedDependencies ) ); 1773 1774 final JAXBResult result = new JAXBResult( unmarshaller ); 1775 transformer.transform( source, result ); 1776 1777 if ( result.getResult() instanceof JAXBElement<?> 1778 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Dependencies ) 1779 { 1780 decodedDependencies = (Dependencies) ( (JAXBElement<?>) result.getResult() ).getValue(); 1781 } 1782 else 1783 { 1784 throw new IOException( getMessage( 1785 "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); 1786 1787 } 1788 } 1789 1790 if ( decodedMessages != null ) 1791 { 1792 final JAXBSource source = new JAXBSource( marshaller, of.createMessages( decodedMessages ) ); 1793 final JAXBResult result = new JAXBResult( unmarshaller ); 1794 transformer.transform( source, result ); 1795 1796 if ( result.getResult() instanceof JAXBElement<?> 1797 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Messages ) 1798 { 1799 decodedMessages = (Messages) ( (JAXBElement<?>) result.getResult() ).getValue(); 1800 } 1801 else 1802 { 1803 throw new IOException( getMessage( 1804 "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); 1805 1806 } 1807 } 1808 1809 if ( decodedProperties != null ) 1810 { 1811 final JAXBSource source = 1812 new JAXBSource( marshaller, of.createProperties( decodedProperties ) ); 1813 1814 final JAXBResult result = new JAXBResult( unmarshaller ); 1815 transformer.transform( source, result ); 1816 1817 if ( result.getResult() instanceof JAXBElement<?> 1818 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Properties ) 1819 { 1820 decodedProperties = (Properties) ( (JAXBElement<?>) result.getResult() ).getValue(); 1821 } 1822 else 1823 { 1824 throw new IOException( getMessage( 1825 "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); 1826 1827 } 1828 } 1829 1830 if ( decodedSpecifications != null ) 1831 { 1832 final JAXBSource source = 1833 new JAXBSource( marshaller, of.createSpecifications( decodedSpecifications ) ); 1834 1835 final JAXBResult result = new JAXBResult( unmarshaller ); 1836 transformer.transform( source, result ); 1837 1838 if ( result.getResult() instanceof JAXBElement<?> 1839 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Specifications ) 1840 { 1841 decodedSpecifications = (Specifications) ( (JAXBElement<?>) result.getResult() ).getValue(); 1842 } 1843 else 1844 { 1845 throw new IOException( getMessage( 1846 "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); 1847 1848 } 1849 } 1850 } 1851 1852 if ( decodedDependencies != null ) 1853 { 1854 this.setClassfileAttribute( javaClass, Dependencies.class.getName(), this.encodeModelObject( 1855 marshaller, of.createDependencies( decodedDependencies ) ) ); 1856 1857 } 1858 1859 if ( decodedMessages != null ) 1860 { 1861 this.setClassfileAttribute( javaClass, Messages.class.getName(), this.encodeModelObject( 1862 marshaller, of.createMessages( decodedMessages ) ) ); 1863 1864 } 1865 1866 if ( decodedProperties != null ) 1867 { 1868 this.setClassfileAttribute( javaClass, Properties.class.getName(), this.encodeModelObject( 1869 marshaller, of.createProperties( decodedProperties ) ) ); 1870 1871 } 1872 1873 if ( decodedSpecifications != null ) 1874 { 1875 this.setClassfileAttribute( javaClass, Specifications.class.getName(), this.encodeModelObject( 1876 marshaller, of.createSpecifications( decodedSpecifications ) ) ); 1877 1878 } 1879 } 1880 else if ( this.isLoggable( Level.WARNING ) ) 1881 { 1882 this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); 1883 } 1884 } 1885 catch ( final JAXBException e ) 1886 { 1887 String message = getMessage( e ); 1888 if ( message == null && e.getLinkedException() != null ) 1889 { 1890 message = getMessage( e.getLinkedException() ); 1891 } 1892 1893 // JDK: As of JDK 6, "new IOException( message, cause )". 1894 throw (IOException) new IOException( message ).initCause( e ); 1895 } 1896 catch ( final TransformerException e ) 1897 { 1898 String message = getMessage( e ); 1899 if ( message == null && e.getException() != null ) 1900 { 1901 message = getMessage( e.getException() ); 1902 } 1903 1904 // JDK: As of JDK 6, "new IOException( message, cause )". 1905 throw (IOException) new IOException( message ).initCause( e ); 1906 } 1907 } 1908 1909 /** 1910 * Gets an attribute from a java class. 1911 * 1912 * @param clazz The java class to get an attribute from. 1913 * @param attributeName The name of the attribute to get. 1914 * 1915 * @return The value of attribute {@code attributeName} of {@code clazz} or {@code null}, if no such attribute 1916 * exists. 1917 * 1918 * @throws NullPointerException if {@code clazz} or {@code attributeName} is {@code null}. 1919 * @throws IOException if getting the attribute fails. 1920 * 1921 * @see JavaClass#getAttributes() 1922 */ 1923 public byte[] getClassfileAttribute( final JavaClass clazz, final String attributeName ) throws IOException 1924 { 1925 if ( clazz == null ) 1926 { 1927 throw new NullPointerException( "clazz" ); 1928 } 1929 if ( attributeName == null ) 1930 { 1931 throw new NullPointerException( "attributeName" ); 1932 } 1933 1934 final Attribute[] attributes = clazz.getAttributes(); 1935 1936 for ( int i = attributes.length - 1; i >= 0; i-- ) 1937 { 1938 final Constant constant = clazz.getConstantPool().getConstant( attributes[i].getNameIndex() ); 1939 1940 if ( constant instanceof ConstantUtf8 && attributeName.equals( ( (ConstantUtf8) constant ).getBytes() ) ) 1941 { 1942 final Unknown unknown = (Unknown) attributes[i]; 1943 return unknown.getBytes(); 1944 } 1945 } 1946 1947 return null; 1948 } 1949 1950 /** 1951 * Adds or updates an attribute in a java class. 1952 * 1953 * @param clazz The class to update an attribute of. 1954 * @param attributeName The name of the attribute to update. 1955 * @param data The new data of the attribute to update the {@code clazz} with. 1956 * 1957 * @throws NullPointerException if {@code clazz} or {@code attributeName} is {@code null}. 1958 * @throws IOException if updating the class file fails. 1959 * 1960 * @see JavaClass#getAttributes() 1961 */ 1962 public void setClassfileAttribute( final JavaClass clazz, final String attributeName, final byte[] data ) 1963 throws IOException 1964 { 1965 if ( clazz == null ) 1966 { 1967 throw new NullPointerException( "clazz" ); 1968 } 1969 if ( attributeName == null ) 1970 { 1971 throw new NullPointerException( "attributeName" ); 1972 } 1973 1974 final byte[] attributeData = data != null ? data : NO_BYTES; 1975 1976 /* 1977 * The JavaTM Virtual Machine Specification - Second Edition - Chapter 4.1 1978 * 1979 * A Java virtual machine implementation is required to silently ignore any 1980 * or all attributes in the attributes table of a ClassFile structure that 1981 * it does not recognize. Attributes not defined in this specification are 1982 * not allowed to affect the semantics of the class file, but only to 1983 * provide additional descriptive information (§4.7.1). 1984 */ 1985 Attribute[] attributes = clazz.getAttributes(); 1986 1987 int attributeIndex = -1; 1988 int nameIndex = -1; 1989 1990 for ( int i = attributes.length - 1; i >= 0; i-- ) 1991 { 1992 final Constant constant = clazz.getConstantPool().getConstant( attributes[i].getNameIndex() ); 1993 1994 if ( constant instanceof ConstantUtf8 && attributeName.equals( ( (ConstantUtf8) constant ).getBytes() ) ) 1995 { 1996 attributeIndex = i; 1997 nameIndex = attributes[i].getNameIndex(); 1998 } 1999 } 2000 2001 if ( nameIndex == -1 ) 2002 { 2003 final Constant[] pool = clazz.getConstantPool().getConstantPool(); 2004 final Constant[] tmp = new Constant[ pool.length + 1 ]; 2005 System.arraycopy( pool, 0, tmp, 0, pool.length ); 2006 tmp[pool.length] = new ConstantUtf8( attributeName ); 2007 nameIndex = pool.length; 2008 clazz.setConstantPool( new ConstantPool( tmp ) ); 2009 } 2010 2011 final Unknown unknown = new Unknown( nameIndex, attributeData.length, attributeData, clazz.getConstantPool() ); 2012 2013 if ( attributeIndex == -1 ) 2014 { 2015 final Attribute[] tmp = new Attribute[ attributes.length + 1 ]; 2016 System.arraycopy( attributes, 0, tmp, 0, attributes.length ); 2017 tmp[attributes.length] = unknown; 2018 attributes = tmp; 2019 } 2020 else 2021 { 2022 attributes[attributeIndex] = unknown; 2023 } 2024 2025 clazz.setAttributes( attributes ); 2026 } 2027 2028 /** 2029 * Encodes a model object to a byte array. 2030 * 2031 * @param marshaller The marshaller to use for encoding the object. 2032 * @param modelObject The model object to encode. 2033 * 2034 * @return GZIP compressed XML document of {@code modelObject}. 2035 * 2036 * @throws NullPointerException if {@code marshaller} or {@code modelObject} is {@code null}. 2037 * @throws IOException if encoding {@code modelObject} fails. 2038 * 2039 * @see #decodeModelObject(javax.xml.bind.Unmarshaller, byte[], java.lang.Class) 2040 */ 2041 public byte[] encodeModelObject( final Marshaller marshaller, final JAXBElement<? extends ModelObject> modelObject ) 2042 throws IOException 2043 { 2044 if ( marshaller == null ) 2045 { 2046 throw new NullPointerException( "marshaller" ); 2047 } 2048 if ( modelObject == null ) 2049 { 2050 throw new NullPointerException( "modelObject" ); 2051 } 2052 2053 try 2054 { 2055 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2056 final GZIPOutputStream out = new GZIPOutputStream( baos ); 2057 marshaller.marshal( modelObject, out ); 2058 out.close(); 2059 return baos.toByteArray(); 2060 } 2061 catch ( final JAXBException e ) 2062 { 2063 String message = getMessage( e ); 2064 if ( message == null && e.getLinkedException() != null ) 2065 { 2066 message = getMessage( e.getLinkedException() ); 2067 } 2068 2069 // JDK: As of JDK 6, "new IOException( message, cause )". 2070 throw (IOException) new IOException( message ).initCause( e ); 2071 } 2072 } 2073 2074 /** 2075 * Decodes a model object from a byte array. 2076 * 2077 * @param unmarshaller The unmarshaller to use for decoding the object. 2078 * @param bytes The encoded model object to decode. 2079 * @param type The class of the type of the encoded model object. 2080 * @param <T> The type of the encoded model object. 2081 * 2082 * @return Model object decoded from {@code bytes}. 2083 * 2084 * @throws NullPointerException if {@code unmarshaller}, {@code bytes} or {@code type} is {@code null}. 2085 * @throws IOException if decoding {@code bytes} fails. 2086 * 2087 * @see #encodeModelObject(javax.xml.bind.Marshaller, javax.xml.bind.JAXBElement) 2088 */ 2089 public <T extends ModelObject> T decodeModelObject( final Unmarshaller unmarshaller, final byte[] bytes, 2090 final Class<T> type ) throws IOException 2091 { 2092 if ( unmarshaller == null ) 2093 { 2094 throw new NullPointerException( "unmarshaller" ); 2095 } 2096 if ( bytes == null ) 2097 { 2098 throw new NullPointerException( "bytes" ); 2099 } 2100 if ( type == null ) 2101 { 2102 throw new NullPointerException( "type" ); 2103 } 2104 2105 try 2106 { 2107 final ByteArrayInputStream bais = new ByteArrayInputStream( bytes ); 2108 final GZIPInputStream in = new GZIPInputStream( bais ); 2109 final JAXBElement<T> element = (JAXBElement<T>) unmarshaller.unmarshal( in ); 2110 in.close(); 2111 return element.getValue(); 2112 } 2113 catch ( final JAXBException e ) 2114 { 2115 String message = getMessage( e ); 2116 if ( message == null && e.getLinkedException() != null ) 2117 { 2118 message = getMessage( e.getLinkedException() ); 2119 } 2120 2121 // JDK: As of JDK 6, "new IOException( message, cause )". 2122 throw (IOException) new IOException( message ).initCause( e ); 2123 } 2124 } 2125 2126 private void commitModelObjects( final Specifications specifications, final Implementations implementations, 2127 final Marshaller marshaller, final File classesDirectory ) 2128 throws IOException, ModelObjectException 2129 { 2130 if ( specifications != null ) 2131 { 2132 for ( int i = specifications.getSpecification().size() - 1; i >= 0; i-- ) 2133 { 2134 this.commitModelObjects( specifications.getSpecification().get( i ), marshaller, classesDirectory ); 2135 } 2136 } 2137 2138 if ( implementations != null ) 2139 { 2140 for ( int i = implementations.getImplementation().size() - 1; i >= 0; i-- ) 2141 { 2142 this.commitModelObjects( implementations.getImplementation().get( i ), marshaller, classesDirectory ); 2143 } 2144 } 2145 } 2146 2147 private void commitModelObjects( final Specification specification, final Marshaller marshaller, 2148 final File classesDirectory ) throws IOException, ModelObjectException 2149 { 2150 if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) 2151 { 2152 final String classLocation = 2153 specification.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; 2154 2155 final File classFile = new File( classesDirectory, classLocation ); 2156 2157 if ( !classesDirectory.isDirectory() ) 2158 { 2159 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 2160 } 2161 if ( !classFile.isFile() ) 2162 { 2163 throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); 2164 } 2165 if ( !( classFile.canRead() && classFile.canWrite() ) ) 2166 { 2167 throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); 2168 } 2169 2170 if ( this.isLoggable( Level.INFO ) ) 2171 { 2172 this.log( Level.INFO, getMessage( "committing", classFile.getAbsolutePath() ), null ); 2173 } 2174 2175 final JavaClass javaClass = this.readJavaClass( classFile ); 2176 this.commitModelObjects( specification, marshaller, javaClass ); 2177 this.writeJavaClass( javaClass, classFile ); 2178 } 2179 } 2180 2181 private void commitModelObjects( final Implementation implementation, final Marshaller marshaller, 2182 final File classesDirectory ) throws IOException, ModelObjectException 2183 { 2184 if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) 2185 { 2186 final String classLocation = 2187 implementation.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; 2188 2189 final File classFile = new File( classesDirectory, classLocation ); 2190 2191 if ( !classesDirectory.isDirectory() ) 2192 { 2193 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 2194 } 2195 if ( !classFile.isFile() ) 2196 { 2197 throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); 2198 } 2199 if ( !( classFile.canRead() && classFile.canWrite() ) ) 2200 { 2201 throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); 2202 } 2203 2204 if ( this.isLoggable( Level.INFO ) ) 2205 { 2206 this.log( Level.INFO, getMessage( "committing", classFile.getAbsolutePath() ), null ); 2207 } 2208 2209 final JavaClass javaClass = this.readJavaClass( classFile ); 2210 this.commitModelObjects( implementation, marshaller, javaClass ); 2211 this.writeJavaClass( javaClass, classFile ); 2212 } 2213 } 2214 2215 private ModelValidationReport validateModelObjects( final Specifications specifications, 2216 final Implementations implementations, 2217 final Unmarshaller unmarshaller, final File classesDirectory ) 2218 throws IOException, ModelObjectException 2219 { 2220 final ModelValidationReport report = new ModelValidationReport(); 2221 2222 if ( specifications != null ) 2223 { 2224 for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ ) 2225 { 2226 final ModelValidationReport current = this.validateModelObjects( 2227 specifications.getSpecification().get( i ), unmarshaller, classesDirectory ); 2228 2229 report.getDetails().addAll( current.getDetails() ); 2230 } 2231 } 2232 2233 if ( implementations != null ) 2234 { 2235 for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ ) 2236 { 2237 final ModelValidationReport current = this.validateModelObjects( 2238 implementations.getImplementation().get( i ), unmarshaller, classesDirectory ); 2239 2240 report.getDetails().addAll( current.getDetails() ); 2241 } 2242 } 2243 2244 return report; 2245 } 2246 2247 private ModelValidationReport validateModelObjects( final Specification specification, 2248 final Unmarshaller unmarshaller, 2249 final File classesDirectory ) 2250 throws IOException, ModelObjectException 2251 { 2252 final ModelValidationReport report = new ModelValidationReport(); 2253 2254 if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) 2255 { 2256 final String classLocation = 2257 specification.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; 2258 2259 final File classFile = new File( classesDirectory, classLocation ); 2260 2261 if ( !classesDirectory.isDirectory() ) 2262 { 2263 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 2264 } 2265 if ( !classFile.isFile() ) 2266 { 2267 throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); 2268 } 2269 if ( !classFile.canRead() ) 2270 { 2271 throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); 2272 } 2273 2274 if ( this.isLoggable( Level.INFO ) ) 2275 { 2276 this.log( Level.INFO, getMessage( "validating", classFile.getAbsolutePath() ), null ); 2277 } 2278 2279 final JavaClass javaClass = this.readJavaClass( classFile ); 2280 2281 report.getDetails().addAll( 2282 this.validateModelObjects( specification, unmarshaller, javaClass ).getDetails() ); 2283 2284 } 2285 2286 return report; 2287 } 2288 2289 private ModelValidationReport validateModelObjects( final Implementation implementation, 2290 final Unmarshaller unmarshaller, 2291 final File classesDirectory ) 2292 throws IOException, ModelObjectException 2293 { 2294 final ModelValidationReport report = new ModelValidationReport(); 2295 2296 if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) 2297 { 2298 final String classLocation = 2299 implementation.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; 2300 2301 final File classFile = new File( classesDirectory, classLocation ); 2302 2303 if ( !classesDirectory.isDirectory() ) 2304 { 2305 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 2306 } 2307 if ( !classFile.isFile() ) 2308 { 2309 throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); 2310 } 2311 if ( !classFile.canRead() ) 2312 { 2313 throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); 2314 } 2315 2316 if ( this.isLoggable( Level.INFO ) ) 2317 { 2318 this.log( Level.INFO, getMessage( "validating", classFile.getAbsolutePath() ), null ); 2319 } 2320 2321 final JavaClass javaClass = this.readJavaClass( classFile ); 2322 2323 report.getDetails().addAll( 2324 this.validateModelObjects( implementation, unmarshaller, javaClass ).getDetails() ); 2325 2326 } 2327 2328 return report; 2329 } 2330 2331 private ModelValidationReport validateModelObjects( final Specifications specifications, 2332 final Implementations implementations, 2333 final Unmarshaller unmarshaller, final ModelContext context ) 2334 throws IOException, ModelException 2335 { 2336 final ModelValidationReport report = new ModelValidationReport(); 2337 2338 if ( specifications != null ) 2339 { 2340 for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ ) 2341 { 2342 final ModelValidationReport current = this.validateModelObjects( 2343 specifications.getSpecification().get( i ), unmarshaller, context ); 2344 2345 report.getDetails().addAll( current.getDetails() ); 2346 } 2347 } 2348 2349 if ( implementations != null ) 2350 { 2351 for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ ) 2352 { 2353 final ModelValidationReport current = this.validateModelObjects( 2354 implementations.getImplementation().get( i ), unmarshaller, context ); 2355 2356 report.getDetails().addAll( current.getDetails() ); 2357 } 2358 } 2359 2360 return report; 2361 } 2362 2363 private ModelValidationReport validateModelObjects( final Specification specification, 2364 final Unmarshaller unmarshaller, 2365 final ModelContext context ) throws IOException, ModelException 2366 { 2367 final ModelValidationReport report = new ModelValidationReport(); 2368 2369 if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) 2370 { 2371 final String classLocation = 2372 specification.getJavaTypeName().getClassName().replace( '.', '/' ) + ".class"; 2373 2374 final URL classUrl = context.findResource( classLocation ); 2375 2376 if ( classUrl == null ) 2377 { 2378 throw new IOException( getMessage( "resourceNotFound", classLocation ) ); 2379 } 2380 2381 if ( this.isLoggable( Level.INFO ) ) 2382 { 2383 this.log( Level.INFO, getMessage( "validatingSpecification", specification.getIdentifier() ), null ); 2384 } 2385 2386 InputStream in = null; 2387 JavaClass javaClass = null; 2388 boolean suppressExceptionOnClose = true; 2389 2390 try 2391 { 2392 in = classUrl.openStream(); 2393 javaClass = new ClassParser( in, classUrl.toExternalForm() ).parse(); 2394 suppressExceptionOnClose = false; 2395 } 2396 finally 2397 { 2398 try 2399 { 2400 if ( in != null ) 2401 { 2402 in.close(); 2403 } 2404 } 2405 catch ( final IOException e ) 2406 { 2407 if ( suppressExceptionOnClose ) 2408 { 2409 this.log( Level.SEVERE, getMessage( e ), e ); 2410 } 2411 else 2412 { 2413 throw e; 2414 } 2415 } 2416 } 2417 2418 report.getDetails().addAll( 2419 this.validateModelObjects( specification, unmarshaller, javaClass ).getDetails() ); 2420 2421 } 2422 2423 return report; 2424 } 2425 2426 private ModelValidationReport validateModelObjects( final Implementation implementation, 2427 final Unmarshaller unmarshaller, 2428 final ModelContext context ) throws IOException, ModelException 2429 { 2430 final ModelValidationReport report = new ModelValidationReport(); 2431 2432 if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) 2433 { 2434 final String classLocation = implementation.getJavaTypeName().getClassName().replace( '.', '/' ) + ".class"; 2435 final URL classUrl = context.findResource( classLocation ); 2436 2437 if ( classUrl == null ) 2438 { 2439 throw new IOException( getMessage( "resourceNotFound", classLocation ) ); 2440 } 2441 2442 if ( this.isLoggable( Level.INFO ) ) 2443 { 2444 this.log( Level.INFO, getMessage( "validatingImplementation", implementation.getIdentifier() ), null ); 2445 } 2446 2447 InputStream in = null; 2448 JavaClass javaClass = null; 2449 boolean suppressExceptionOnClose = true; 2450 2451 try 2452 { 2453 in = classUrl.openStream(); 2454 javaClass = new ClassParser( in, classUrl.toExternalForm() ).parse(); 2455 suppressExceptionOnClose = false; 2456 } 2457 finally 2458 { 2459 try 2460 { 2461 if ( in != null ) 2462 { 2463 in.close(); 2464 } 2465 } 2466 catch ( final IOException e ) 2467 { 2468 if ( suppressExceptionOnClose ) 2469 { 2470 this.log( Level.SEVERE, getMessage( e ), e ); 2471 } 2472 else 2473 { 2474 throw e; 2475 } 2476 } 2477 } 2478 2479 report.getDetails().addAll( 2480 this.validateModelObjects( implementation, unmarshaller, javaClass ).getDetails() ); 2481 2482 } 2483 2484 return report; 2485 } 2486 2487 private void transformModelObjects( final Specifications specifications, final Implementations implementations, 2488 final Unmarshaller unmarshaller, final Marshaller marshaller, 2489 final File classesDirectory, final List<Transformer> transformers ) 2490 throws IOException, ModelObjectException 2491 { 2492 if ( specifications != null ) 2493 { 2494 for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ ) 2495 { 2496 this.transformModelObjects( specifications.getSpecification().get( i ), marshaller, unmarshaller, 2497 classesDirectory, transformers ); 2498 2499 } 2500 } 2501 2502 if ( implementations != null ) 2503 { 2504 for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ ) 2505 { 2506 this.transformModelObjects( implementations.getImplementation().get( i ), marshaller, unmarshaller, 2507 classesDirectory, transformers ); 2508 2509 } 2510 } 2511 } 2512 2513 private void transformModelObjects( final Specification specification, final Marshaller marshaller, 2514 final Unmarshaller unmarshaller, final File classesDirectory, 2515 final List<Transformer> transformers ) throws IOException, ModelObjectException 2516 { 2517 if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) 2518 { 2519 final String classLocation = 2520 specification.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; 2521 2522 final File classFile = new File( classesDirectory, classLocation ); 2523 2524 if ( !classesDirectory.isDirectory() ) 2525 { 2526 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 2527 } 2528 if ( !classFile.isFile() ) 2529 { 2530 throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); 2531 } 2532 if ( !( classFile.canRead() && classFile.canWrite() ) ) 2533 { 2534 throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); 2535 } 2536 2537 if ( this.isLoggable( Level.INFO ) ) 2538 { 2539 this.log( Level.INFO, getMessage( "transforming", classFile.getAbsolutePath() ), null ); 2540 } 2541 2542 final JavaClass javaClass = this.readJavaClass( classFile ); 2543 this.transformModelObjects( specification, marshaller, unmarshaller, javaClass, transformers ); 2544 this.writeJavaClass( javaClass, classFile ); 2545 } 2546 } 2547 2548 private void transformModelObjects( final Implementation implementation, final Marshaller marshaller, 2549 final Unmarshaller unmarshaller, final File classesDirectory, 2550 final List<Transformer> transformers ) throws IOException, ModelObjectException 2551 { 2552 if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) 2553 { 2554 final String classLocation = 2555 implementation.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; 2556 2557 final File classFile = new File( classesDirectory, classLocation ); 2558 2559 if ( !classesDirectory.isDirectory() ) 2560 { 2561 throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); 2562 } 2563 if ( !classFile.isFile() ) 2564 { 2565 throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); 2566 } 2567 if ( !( classFile.canRead() && classFile.canWrite() ) ) 2568 { 2569 throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); 2570 } 2571 2572 if ( this.isLoggable( Level.INFO ) ) 2573 { 2574 this.log( Level.INFO, getMessage( "transforming", classFile.getAbsolutePath() ), null ); 2575 } 2576 2577 final JavaClass javaClass = this.readJavaClass( classFile ); 2578 this.transformModelObjects( implementation, marshaller, unmarshaller, javaClass, transformers ); 2579 this.writeJavaClass( javaClass, classFile ); 2580 } 2581 } 2582 2583 private JavaClass readJavaClass( final File classFile ) throws IOException 2584 { 2585 FileInputStream in = null; 2586 FileChannel fileChannel = null; 2587 FileLock fileLock = null; 2588 boolean suppressExceptionOnClose = true; 2589 2590 try 2591 { 2592 in = new FileInputStream( classFile ); 2593 fileChannel = in.getChannel(); 2594 fileLock = fileChannel.lock( 0, classFile.length(), true ); 2595 2596 final JavaClass javaClass = new ClassParser( in, classFile.getAbsolutePath() ).parse(); 2597 suppressExceptionOnClose = false; 2598 return javaClass; 2599 } 2600 finally 2601 { 2602 this.releaseAndClose( fileLock, fileChannel, in, suppressExceptionOnClose ); 2603 } 2604 } 2605 2606 private void writeJavaClass( final JavaClass javaClass, final File classFile ) throws IOException 2607 { 2608 RandomAccessFile randomAccessFile = null; 2609 FileChannel fileChannel = null; 2610 FileLock fileLock = null; 2611 boolean suppressExceptionOnClose = true; 2612 2613 final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 2614 javaClass.dump( byteStream ); 2615 byteStream.close(); 2616 2617 final byte[] bytes = byteStream.toByteArray(); 2618 2619 try 2620 { 2621 randomAccessFile = new RandomAccessFile( classFile, "rw" ); 2622 fileChannel = randomAccessFile.getChannel(); 2623 fileLock = fileChannel.lock(); 2624 fileChannel.truncate( bytes.length ); 2625 fileChannel.position( 0L ); 2626 fileChannel.write( ByteBuffer.wrap( bytes ) ); 2627 fileChannel.force( true ); 2628 suppressExceptionOnClose = false; 2629 } 2630 finally 2631 { 2632 this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose ); 2633 } 2634 } 2635 2636 private void releaseAndClose( final FileLock fileLock, final FileChannel fileChannel, 2637 final Closeable closeable, final boolean suppressExceptions ) 2638 throws IOException 2639 { 2640 try 2641 { 2642 if ( fileLock != null ) 2643 { 2644 fileLock.release(); 2645 } 2646 } 2647 catch ( final IOException e ) 2648 { 2649 if ( suppressExceptions ) 2650 { 2651 this.log( Level.SEVERE, null, e ); 2652 } 2653 else 2654 { 2655 throw e; 2656 } 2657 } 2658 finally 2659 { 2660 try 2661 { 2662 if ( fileChannel != null ) 2663 { 2664 fileChannel.close(); 2665 } 2666 } 2667 catch ( final IOException e ) 2668 { 2669 if ( suppressExceptions ) 2670 { 2671 this.log( Level.SEVERE, null, e ); 2672 } 2673 else 2674 { 2675 throw e; 2676 } 2677 } 2678 finally 2679 { 2680 try 2681 { 2682 if ( closeable != null ) 2683 { 2684 closeable.close(); 2685 } 2686 } 2687 catch ( final IOException e ) 2688 { 2689 if ( suppressExceptions ) 2690 { 2691 this.log( Level.SEVERE, null, e ); 2692 } 2693 else 2694 { 2695 throw e; 2696 } 2697 } 2698 } 2699 } 2700 } 2701 2702 private static String getMessage( final String key, final Object... arguments ) 2703 { 2704 return MessageFormat.format( ResourceBundle.getBundle( 2705 ClassFileProcessor.class.getName().replace( '.', '/' ) ).getString( key ), arguments ); 2706 2707 } 2708 2709 private static String getMessage( final Throwable t ) 2710 { 2711 return t != null 2712 ? t.getMessage() != null && t.getMessage().trim().length() > 0 2713 ? t.getMessage() 2714 : getMessage( t.getCause() ) 2715 : null; 2716 2717 } 2718 2719}