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