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