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: JomcResourceTransformer.java 5043 2015-05-27 07:03:39Z schulte $ 029 * 030 */ 031package org.jomc.mojo; 032 033import java.io.File; 034import java.io.IOException; 035import java.io.InputStream; 036import java.io.OutputStream; 037import java.net.MalformedURLException; 038import java.net.URISyntaxException; 039import java.net.URL; 040import java.util.Iterator; 041import java.util.List; 042import java.util.Map; 043import java.util.jar.JarEntry; 044import java.util.jar.JarOutputStream; 045import javax.xml.bind.JAXBElement; 046import javax.xml.bind.JAXBException; 047import javax.xml.bind.Marshaller; 048import javax.xml.bind.Unmarshaller; 049import javax.xml.bind.util.JAXBResult; 050import javax.xml.bind.util.JAXBSource; 051import javax.xml.transform.Transformer; 052import javax.xml.transform.TransformerConfigurationException; 053import javax.xml.transform.TransformerException; 054import javax.xml.transform.TransformerFactory; 055import javax.xml.transform.stream.StreamSource; 056import org.apache.maven.plugins.shade.resource.ResourceTransformer; 057import org.codehaus.plexus.logging.AbstractLogEnabled; 058import org.codehaus.plexus.util.StringUtils; 059import org.jomc.model.ModelObject; 060import org.jomc.model.Module; 061import org.jomc.model.Modules; 062import org.jomc.model.modlet.DefaultModelProvider; 063import org.jomc.modlet.DefaultModelContext; 064import org.jomc.modlet.DefaultModletProvider; 065import org.jomc.modlet.ModelContext; 066import org.jomc.modlet.ModelContextFactory; 067import org.jomc.modlet.ModelException; 068import org.jomc.modlet.Modlet; 069import org.jomc.modlet.ModletObject; 070import org.jomc.modlet.Modlets; 071 072/** 073 * Maven Shade Plugin {@code ResourceTransformer} implementation for shading JOMC resources. 074 * 075 * <p> 076 * <b>Maven Shade Plugin Usage</b><pre> 077 * <transformer implementation="org.jomc.mojo.JomcResourceTransformer"> 078 * <model>http://jomc.org/model</model> 079 * <modelContextFactoryClassName>class name</modelContextFactoryClassName> 080 * <modelContextAttributes> 081 * <modelContextAttribute> 082 * <key>The name of the attribute</key> 083 * <value>The name of the attribute</value> 084 * <type>The name of the class of the object.</type> 085 * </modelContextAttribute> 086 * </modelContextAttributes/> 087 * <moduleEncoding>${project.build.sourceEncoding}</moduleEncoding> 088 * <moduleName>${project.name}</moduleName> 089 * <moduleVersion>${project.version}</moduleVersion> 090 * <moduleVendor>${project.organization.name}</moduleVendor> 091 * <moduleResource>META-INF/custom-jomc.xml</moduleResource> 092 * <moduleResources> 093 * <moduleResource>META-INF/jomc.xml</moduleResource> 094 * </moduleResources> 095 * <moduleIncludes> 096 * <moduleInclude>module name</moduleInclude> 097 * </moduleIncludes> 098 * <moduleExcludes> 099 * <moduleExclude>module name</moduleExclude> 100 * </moduleExcludes> 101 * <modletEncoding>${project.build.sourceEncoding}</modletEncoding> 102 * <modletName>${project.name}</modletName> 103 * <modletVersion>${project.version}</modletVersion> 104 * <modletVendor>${project.organization.name}</modletVendor> 105 * <modletResource>META-INF/custom-jomc-modlet.xml</modletResource> 106 * <modletResources> 107 * <modletResource>META-INF/jomc-modlet.xml</modletResource> 108 * </modletResources> 109 * <modletIncludes> 110 * <modletInclude>modlet name</modletInclude> 111 * </modletIncludes> 112 * <modletExcludes> 113 * <modletExclude>modlet name</modletExclude> 114 * </modletExcludes> 115 * <modelObjectStylesheet>Location of a XSLT document to use for transforming the merged model document.</modelObjectStylesheet> 116 * <modletObjectStylesheet>Location of a XSLT document to use for transforming the merged modlet document.</modletObjectStylesheet> 117 * <providerLocation>META-INF/custom-services</providerLocation> 118 * <platformProviderLocation>${java.home}/jre/lib/custom-jomc.properties</platformProviderLocation> 119 * <modletLocation>META-INF/custom-jomc-modlet.xml</modletLocation> 120 * <modletSchemaSystemId>http://custom.host.tld/custom/path/jomc-modlet-1.9.xsd</modletSchemaSystemId> 121 * </transformer> 122 * </pre></p> 123 * 124 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 125 * @version $JOMC: JomcResourceTransformer.java 5043 2015-05-27 07:03:39Z schulte $ 126 * @plexus.component role="org.apache.maven.plugins.shade.resource.ResourceTransformer" 127 * role-hint="JOMC" 128 */ 129public class JomcResourceTransformer extends AbstractLogEnabled implements ResourceTransformer 130{ 131 132 /** 133 * Type of a resource. 134 */ 135 private enum ResourceType 136 { 137 138 /** 139 * Model object resource. 140 */ 141 MODEL_OBJECT_RESOURCE, 142 /** 143 * Modlet object resource. 144 */ 145 MODLET_OBJECT_RESOURCE 146 147 } 148 149 /** 150 * Prefix prepended to log messages. 151 */ 152 private static final String LOG_PREFIX = "[JOMC] "; 153 154 /** 155 * The identifier of the model to process. 156 */ 157 private String model = ModelObject.MODEL_PUBLIC_ID; 158 159 /** 160 * The encoding of the assembled module. 161 */ 162 private String moduleEncoding; 163 164 /** 165 * The name of the assembled module. 166 */ 167 private String moduleName; 168 169 /** 170 * The version of the assembled module. 171 */ 172 private String moduleVersion; 173 174 /** 175 * The vendor of the assembled module. 176 */ 177 private String moduleVendor; 178 179 /** 180 * The resource name of the assembled module. 181 */ 182 private String moduleResource = DefaultModelProvider.getDefaultModuleLocation(); 183 184 /** 185 * Names of resources to process. 186 */ 187 private String[] moduleResources = 188 { 189 DefaultModelProvider.getDefaultModuleLocation() 190 }; 191 192 /** 193 * Included modules. 194 */ 195 private List<String> moduleIncludes; 196 197 /** 198 * Excluded modules. 199 */ 200 private List<String> moduleExcludes; 201 202 /** 203 * The encoding of the assembled modlet. 204 */ 205 private String modletEncoding; 206 207 /** 208 * The name of the assembled modlet. 209 */ 210 private String modletName; 211 212 /** 213 * The version of the assembled modlet. 214 */ 215 private String modletVersion; 216 217 /** 218 * The vendor of the assembled modlet. 219 */ 220 private String modletVendor; 221 222 /** 223 * The resource name of the assembled modlet resources. 224 */ 225 private String modletResource = DefaultModletProvider.getDefaultModletLocation(); 226 227 /** 228 * Names of modlet resources to process. 229 */ 230 private String[] modletResources = 231 { 232 DefaultModletProvider.getDefaultModletLocation() 233 }; 234 235 /** 236 * Included modlets. 237 */ 238 private List<String> modletIncludes; 239 240 /** 241 * Excluded modlets. 242 */ 243 private List<String> modletExcludes; 244 245 /** 246 * Location of a XSLT document to use for transforming the merged model document. 247 */ 248 private String modelObjectStylesheet; 249 250 /** 251 * Location of a XSLT document to use for transforming the merged modlet document. 252 */ 253 private String modletObjectStylesheet; 254 255 /** 256 * The location to search for providers. 257 */ 258 private String providerLocation; 259 260 /** 261 * The location to search for platform providers. 262 */ 263 private String platformProviderLocation; 264 265 /** 266 * The system id of the modlet schema. 267 */ 268 private String modletSchemaSystemId; 269 270 /** 271 * The location to search for modlets. 272 */ 273 private String modletLocation; 274 275 /** 276 * Name of the {@code ModelContext} implementation class. 277 * 278 * @since 1.2 279 */ 280 private String modelContextFactoryClassName; 281 282 /** 283 * {@code ModelContext} attributes to apply. 284 * 285 * @since 1.2 286 */ 287 private List<ModelContextAttribute> modelContextAttributes; 288 289 /** 290 * Modlet resources. 291 */ 292 private Modlets modlets = new Modlets(); 293 294 /** 295 * Model resources. 296 */ 297 private Modules modules = new Modules(); 298 299 /** 300 * Type of the currently processed resource or {@code null}. 301 */ 302 private ResourceType currentResourceType; 303 304 /** 305 * The JOMC JAXB marshaller of the instance. 306 */ 307 private Marshaller jomcMarshaller; 308 309 /** 310 * The JOMC JAXB unmarshaller of the instance. 311 */ 312 private Unmarshaller jomcUnmarshaller; 313 314 /** 315 * The modlet JAXB marshaller of the instance. 316 */ 317 private Marshaller modletMarshaller; 318 319 /** 320 * The modlet JAXB unmarshaller of the instance. 321 */ 322 private Unmarshaller modletUnmarshaller; 323 324 /** 325 * Creates a new {@code JomcResourceTransformer} instance. 326 */ 327 public JomcResourceTransformer() 328 { 329 super(); 330 } 331 332 public boolean canTransformResource( final String arg ) 333 { 334 boolean transformable = false; 335 this.currentResourceType = null; 336 final String name = normalizeResourceName( arg ); 337 338 if ( name != null ) 339 { 340 if ( this.moduleResources != null ) 341 { 342 for ( final String r : this.moduleResources ) 343 { 344 if ( name.equals( normalizeResourceName( r ) ) ) 345 { 346 this.currentResourceType = ResourceType.MODEL_OBJECT_RESOURCE; 347 348 if ( this.getLogger() != null && this.getLogger().isDebugEnabled() ) 349 { 350 this.getLogger().debug( LOG_PREFIX + Messages.getMessage( 351 "processingModuleResource", arg ) ); 352 353 } 354 355 transformable = true; 356 break; 357 } 358 } 359 } 360 361 if ( !transformable && this.modletResources != null ) 362 { 363 for ( final String r : this.modletResources ) 364 { 365 if ( name.equals( normalizeResourceName( r ) ) ) 366 { 367 this.currentResourceType = ResourceType.MODLET_OBJECT_RESOURCE; 368 369 if ( this.getLogger() != null && this.getLogger().isDebugEnabled() ) 370 { 371 this.getLogger().debug( LOG_PREFIX + Messages.getMessage( 372 "processingModletResource", arg ) ); 373 374 } 375 376 transformable = true; 377 break; 378 } 379 } 380 } 381 382 if ( !transformable && ( name.equals( normalizeResourceName( this.modletResource ) ) 383 || name.equals( normalizeResourceName( this.moduleResource ) ) ) ) 384 { 385 if ( this.getLogger() != null && this.getLogger().isWarnEnabled() ) 386 { 387 this.getLogger().warn( LOG_PREFIX + Messages.getMessage( "overridingResource", arg ) ); 388 } 389 390 transformable = true; 391 this.currentResourceType = null; 392 } 393 } 394 395 return transformable; 396 } 397 398 public void processResource( final InputStream in ) throws IOException 399 { 400 try 401 { 402 if ( in != null && this.currentResourceType != null ) 403 { 404 switch ( this.currentResourceType ) 405 { 406 case MODEL_OBJECT_RESOURCE: 407 Object modelObject = this.unmarshalModelObject( in ); 408 409 if ( modelObject instanceof JAXBElement<?> ) 410 { 411 modelObject = ( (JAXBElement<?>) modelObject ).getValue(); 412 } 413 if ( modelObject instanceof Modules ) 414 { 415 this.modules.getModule().addAll( ( (Modules) modelObject ).getModule() ); 416 } 417 if ( modelObject instanceof Module ) 418 { 419 this.modules.getModule().add( (Module) modelObject ); 420 } 421 break; 422 423 case MODLET_OBJECT_RESOURCE: 424 Object modletObject = this.unmarshalModletObject( in ); 425 426 if ( modletObject instanceof JAXBElement<?> ) 427 { 428 modletObject = ( (JAXBElement<?>) modletObject ).getValue(); 429 } 430 if ( modletObject instanceof Modlets ) 431 { 432 this.modlets.getModlet().addAll( ( (Modlets) modletObject ).getModlet() ); 433 } 434 if ( modletObject instanceof Modlet ) 435 { 436 this.modlets.getModlet().add( (Modlet) modletObject ); 437 } 438 break; 439 440 default: 441 throw new AssertionError( this.currentResourceType ); 442 443 } 444 } 445 } 446 catch ( final InstantiationException e ) 447 { 448 // JDK: As of JDK 6, "new IOException( message, cause )". 449 throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e ); 450 } 451 catch ( final JAXBException e ) 452 { 453 String message = Messages.getMessage( e ); 454 if ( message == null && e.getLinkedException() != null ) 455 { 456 message = Messages.getMessage( e.getLinkedException() ); 457 } 458 459 // JDK: As of JDK 6, "new IOException( message, cause )". 460 throw (IOException) new IOException( message ).initCause( e ); 461 } 462 catch ( final ModelException e ) 463 { 464 // JDK: As of JDK 6, "new IOException( message, cause )". 465 throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e ); 466 } 467 } 468 469 public void processResource( final String name, final InputStream in, final List relocators ) throws IOException 470 { 471 this.processResource( in ); 472 } 473 474 public boolean hasTransformedResource() 475 { 476 return !( this.modules.getModule().isEmpty() && this.modlets.getModlet().isEmpty() ); 477 } 478 479 public void modifyOutputStream( final JarOutputStream out ) throws IOException 480 { 481 if ( StringUtils.isEmpty( this.model ) ) 482 { 483 throw new IOException( Messages.getMessage( "mandatoryParameter", "model" ) ); 484 } 485 if ( StringUtils.isEmpty( this.modletName ) ) 486 { 487 throw new IOException( Messages.getMessage( "mandatoryParameter", "modletName" ) ); 488 } 489 if ( StringUtils.isEmpty( this.modletResource ) ) 490 { 491 throw new IOException( Messages.getMessage( "mandatoryParameter", "modletResource" ) ); 492 } 493 if ( StringUtils.isEmpty( this.moduleName ) ) 494 { 495 throw new IOException( Messages.getMessage( "mandatoryParameter", "moduleName" ) ); 496 } 497 if ( StringUtils.isEmpty( this.moduleResource ) ) 498 { 499 throw new IOException( Messages.getMessage( "mandatoryParameter", "moduleResource" ) ); 500 } 501 502 try 503 { 504 if ( !this.modules.getModule().isEmpty() ) 505 { 506 if ( this.moduleIncludes != null ) 507 { 508 for ( final Iterator<Module> it = this.modules.getModule().iterator(); it.hasNext(); ) 509 { 510 final Module m = it.next(); 511 512 if ( !this.moduleIncludes.contains( m.getName() ) ) 513 { 514 it.remove(); 515 516 if ( this.getLogger() != null && this.getLogger().isInfoEnabled() ) 517 { 518 this.getLogger().info( LOG_PREFIX + Messages.getMessage( 519 "excludingModule", m.getName() ) ); 520 521 } 522 } 523 } 524 } 525 526 if ( this.moduleExcludes != null ) 527 { 528 for ( final String exclude : this.moduleExcludes ) 529 { 530 final Module excluded = this.modules.getModule( exclude ); 531 532 if ( excluded != null ) 533 { 534 this.modules.getModule().remove( excluded ); 535 536 if ( this.getLogger() != null && this.getLogger().isInfoEnabled() ) 537 { 538 this.getLogger().info( LOG_PREFIX + Messages.getMessage( 539 "excludingModule", excluded.getName() ) ); 540 541 } 542 } 543 } 544 } 545 546 if ( this.getLogger() != null && this.getLogger().isInfoEnabled() ) 547 { 548 for ( final Module m : this.modules.getModule() ) 549 { 550 this.getLogger().info( LOG_PREFIX + Messages.getMessage( "includingModule", m.getName() ) ); 551 } 552 } 553 554 final Module mergedModule = this.modules.getMergedModule( this.moduleName ); 555 mergedModule.setVersion( this.moduleVersion ); 556 mergedModule.setVendor( this.moduleVendor ); 557 558 final JAXBElement<Module> transformedModule = this.transformModelObject( 559 new org.jomc.model.ObjectFactory().createModule( mergedModule ), Module.class ); 560 561 out.putNextEntry( new JarEntry( normalizeResourceName( this.moduleResource ) ) ); 562 this.marshalModelObject( transformedModule, out ); 563 } 564 565 if ( !this.modlets.getModlet().isEmpty() ) 566 { 567 if ( this.modletIncludes != null ) 568 { 569 for ( final Iterator<Modlet> it = this.modlets.getModlet().iterator(); it.hasNext(); ) 570 { 571 final Modlet m = it.next(); 572 573 if ( !this.modletIncludes.contains( m.getName() ) ) 574 { 575 it.remove(); 576 577 if ( this.getLogger() != null && this.getLogger().isInfoEnabled() ) 578 { 579 this.getLogger().info( LOG_PREFIX + Messages.getMessage( 580 "excludingModlet", m.getName() ) ); 581 582 } 583 } 584 } 585 } 586 587 if ( this.modletExcludes != null ) 588 { 589 for ( final String exclude : this.modletExcludes ) 590 { 591 final Modlet excluded = this.modlets.getModlet( exclude ); 592 593 if ( excluded != null ) 594 { 595 this.modlets.getModlet().remove( excluded ); 596 597 if ( this.getLogger() != null && this.getLogger().isInfoEnabled() ) 598 { 599 this.getLogger().info( LOG_PREFIX + Messages.getMessage( 600 "excludingModlet", excluded.getName() ) ); 601 602 } 603 } 604 } 605 } 606 607 if ( this.getLogger() != null && this.getLogger().isInfoEnabled() ) 608 { 609 for ( final Modlet m : this.modlets.getModlet() ) 610 { 611 this.getLogger().info( LOG_PREFIX + Messages.getMessage( "includingModlet", m.getName() ) ); 612 } 613 } 614 615 final Modlet mergedModlet = this.modlets.getMergedModlet( this.modletName, this.model ); 616 mergedModlet.setVendor( this.modletVendor ); 617 mergedModlet.setVersion( this.modletVersion ); 618 619 final JAXBElement<Modlet> transformedModlet = this.transformModletObject( 620 new org.jomc.modlet.ObjectFactory().createModlet( mergedModlet ), Modlet.class ); 621 622 out.putNextEntry( new JarEntry( normalizeResourceName( this.modletResource ) ) ); 623 this.marshalModletObject( transformedModlet, out ); 624 } 625 } 626 catch ( final InstantiationException e ) 627 { 628 // JDK: As of JDK 6, "new IOException( message, cause )". 629 throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e ); 630 } 631 catch ( final TransformerConfigurationException e ) 632 { 633 String message = Messages.getMessage( e ); 634 if ( message == null && e.getException() != null ) 635 { 636 message = Messages.getMessage( e.getException() ); 637 } 638 639 // JDK: As of JDK 6, "new IOException( message, cause )". 640 throw (IOException) new IOException( message ).initCause( e ); 641 } 642 catch ( final TransformerException e ) 643 { 644 String message = Messages.getMessage( e ); 645 if ( message == null && e.getException() != null ) 646 { 647 message = Messages.getMessage( e.getException() ); 648 } 649 650 // JDK: As of JDK 6, "new IOException( message, cause )". 651 throw (IOException) new IOException( message ).initCause( e ); 652 } 653 catch ( final JAXBException e ) 654 { 655 String message = Messages.getMessage( e ); 656 if ( message == null && e.getLinkedException() != null ) 657 { 658 message = Messages.getMessage( e.getLinkedException() ); 659 } 660 661 // JDK: As of JDK 6, "new IOException( message, cause )". 662 throw (IOException) new IOException( message ).initCause( e ); 663 } 664 catch ( final ModelException e ) 665 { 666 // JDK: As of JDK 6, "new IOException( message, cause )". 667 throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e ); 668 } 669 catch ( final URISyntaxException e ) 670 { 671 // JDK: As of JDK 6, "new IOException( message, cause )". 672 throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e ); 673 } 674 finally 675 { 676 this.modlets = new Modlets(); 677 this.modules = new Modules(); 678 this.jomcMarshaller = null; 679 this.jomcUnmarshaller = null; 680 this.modletMarshaller = null; 681 this.modletUnmarshaller = null; 682 } 683 } 684 685 /** 686 * Creates an {@code URL} for a given resource location. 687 * <p> 688 * This method first searches the class loader of the class for a single resource matching {@code location}. If 689 * such a resource is found, the URL of that resource is returned. If no such resource is found, an attempt is made 690 * to parse the given location to an URL. On successful parsing, that URL is returned. Failing that, the given 691 * location is interpreted as a file name. If that file is found, the URL of that file is returned. Otherwise an 692 * {@code IOException} is thrown. 693 * </p> 694 * 695 * @param location The location to create an {@code URL} from. 696 * 697 * @return An {@code URL} for {@code location}. 698 * 699 * @throws NullPointerException if {@code location} is {@code null}. 700 * @throws IOException if creating an URL fails. 701 * 702 * @since 1.2 703 */ 704 protected URL getResource( final String location ) throws IOException 705 { 706 if ( location == null ) 707 { 708 throw new NullPointerException( "location" ); 709 } 710 711 try 712 { 713 String absolute = location; 714 if ( !absolute.startsWith( "/" ) ) 715 { 716 absolute = "/" + location; 717 } 718 719 URL resource = this.getClass().getResource( absolute ); 720 if ( resource == null ) 721 { 722 try 723 { 724 resource = new URL( location ); 725 } 726 catch ( final MalformedURLException e ) 727 { 728 if ( this.getLogger() != null && this.getLogger().isDebugEnabled() ) 729 { 730 this.getLogger().debug( Messages.getMessage( e ), e ); 731 } 732 733 resource = null; 734 } 735 } 736 737 if ( resource == null ) 738 { 739 final File f = new File( location ); 740 741 if ( f.isFile() ) 742 { 743 resource = f.toURI().toURL(); 744 } 745 } 746 747 if ( resource == null ) 748 { 749 throw new IOException( Messages.getMessage( "resourceNotFound", location ) ); 750 } 751 752 return resource; 753 } 754 catch ( final MalformedURLException e ) 755 { 756 String m = Messages.getMessage( e ); 757 m = m == null ? "" : " " + m; 758 759 // JDK: As of JDK 6, "new IOException( message, cause )". 760 throw (IOException) new IOException( Messages.getMessage( 761 "malformedLocation", location, m ) ).initCause( e ); 762 763 } 764 } 765 766 private Object unmarshalModelObject( final InputStream in ) 767 throws ModelException, JAXBException, InstantiationException 768 { 769 if ( in == null ) 770 { 771 throw new NullPointerException( "in" ); 772 } 773 774 if ( this.jomcUnmarshaller == null ) 775 { 776 this.jomcUnmarshaller = this.createModelContext().createUnmarshaller( this.model ); 777 } 778 779 return this.jomcUnmarshaller.unmarshal( in ); 780 } 781 782 private void marshalModelObject( final JAXBElement<? extends ModelObject> element, final OutputStream out ) 783 throws ModelException, JAXBException, InstantiationException 784 { 785 if ( element == null ) 786 { 787 throw new NullPointerException( "element" ); 788 } 789 if ( out == null ) 790 { 791 throw new NullPointerException( "out" ); 792 } 793 794 if ( this.jomcMarshaller == null ) 795 { 796 final ModelContext modelContext = this.createModelContext(); 797 this.jomcMarshaller = modelContext.createMarshaller( this.model ); 798 this.jomcMarshaller.setSchema( modelContext.createSchema( this.model ) ); 799 this.jomcMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); 800 801 if ( this.moduleEncoding != null ) 802 { 803 this.jomcMarshaller.setProperty( Marshaller.JAXB_ENCODING, this.moduleEncoding ); 804 } 805 } 806 807 this.jomcMarshaller.marshal( element, out ); 808 } 809 810 private <T> JAXBElement<T> transformModelObject( final JAXBElement<? extends ModelObject> element, 811 final Class<T> boundType ) 812 throws ModelException, TransformerException, JAXBException, IOException, URISyntaxException, 813 InstantiationException 814 { 815 if ( element == null ) 816 { 817 throw new NullPointerException( "element" ); 818 } 819 if ( !boundType.isInstance( element.getValue() ) ) 820 { 821 throw new IllegalArgumentException( element.toString() ); 822 } 823 824 @SuppressWarnings( "unchecked" ) 825 JAXBElement<T> transformed = (JAXBElement<T>) element; 826 827 if ( this.modelObjectStylesheet != null ) 828 { 829 final Transformer transformer = TransformerFactory.newInstance().newTransformer( 830 new StreamSource( this.getResource( this.modelObjectStylesheet ).toURI().toASCIIString() ) ); 831 832 final ModelContext modelContext = this.createModelContext(); 833 final Marshaller marshaller = modelContext.createMarshaller( this.model ); 834 final Unmarshaller unmarshaller = modelContext.createUnmarshaller( this.model ); 835 final JAXBSource source = new JAXBSource( marshaller, element ); 836 final JAXBResult result = new JAXBResult( unmarshaller ); 837 838 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() ) 839 { 840 transformer.setParameter( e.getKey().toString(), e.getValue() ); 841 } 842 843 transformer.transform( source, result ); 844 845 if ( result.getResult() instanceof JAXBElement<?> 846 && boundType.isInstance( ( (JAXBElement<?>) result.getResult() ).getValue() ) ) 847 { 848 @SuppressWarnings( "unchecked" ) final JAXBElement<T> e = (JAXBElement<T>) result.getResult(); 849 transformed = e; 850 } 851 else 852 { 853 throw new ModelException( Messages.getMessage( 854 "illegalModuleTransformationResult", this.modelObjectStylesheet ) ); 855 856 } 857 } 858 859 return transformed; 860 } 861 862 private Object unmarshalModletObject( final InputStream in ) 863 throws ModelException, JAXBException, InstantiationException 864 { 865 if ( in == null ) 866 { 867 throw new NullPointerException( "in" ); 868 } 869 870 if ( this.modletUnmarshaller == null ) 871 { 872 this.modletUnmarshaller = this.createModelContext().createUnmarshaller( ModletObject.MODEL_PUBLIC_ID ); 873 } 874 875 return this.modletUnmarshaller.unmarshal( in ); 876 } 877 878 private void marshalModletObject( final JAXBElement<? extends ModletObject> element, final OutputStream out ) 879 throws ModelException, JAXBException, InstantiationException 880 { 881 if ( element == null ) 882 { 883 throw new NullPointerException( "element" ); 884 } 885 if ( out == null ) 886 { 887 throw new NullPointerException( "out" ); 888 } 889 890 if ( this.modletMarshaller == null ) 891 { 892 final ModelContext modletContext = this.createModelContext(); 893 this.modletMarshaller = modletContext.createMarshaller( ModletObject.MODEL_PUBLIC_ID ); 894 this.modletMarshaller.setSchema( modletContext.createSchema( ModletObject.MODEL_PUBLIC_ID ) ); 895 this.modletMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); 896 897 if ( this.modletEncoding != null ) 898 { 899 this.modletMarshaller.setProperty( Marshaller.JAXB_ENCODING, this.modletEncoding ); 900 } 901 } 902 903 this.modletMarshaller.marshal( element, out ); 904 } 905 906 private <T> JAXBElement<T> transformModletObject( final JAXBElement<? extends ModletObject> element, 907 final Class<T> boundType ) 908 throws ModelException, TransformerException, JAXBException, IOException, URISyntaxException, 909 InstantiationException 910 { 911 if ( element == null ) 912 { 913 throw new NullPointerException( "element" ); 914 } 915 if ( !boundType.isInstance( element.getValue() ) ) 916 { 917 throw new IllegalArgumentException( element.toString() ); 918 } 919 920 @SuppressWarnings( "unchecked" ) 921 JAXBElement<T> transformed = (JAXBElement<T>) element; 922 923 if ( this.modletObjectStylesheet != null ) 924 { 925 final Transformer transformer = TransformerFactory.newInstance().newTransformer( 926 new StreamSource( this.getResource( this.modletObjectStylesheet ).toURI().toASCIIString() ) ); 927 928 final ModelContext modletContext = this.createModelContext(); 929 final Marshaller marshaller = modletContext.createMarshaller( ModletObject.MODEL_PUBLIC_ID ); 930 final Unmarshaller unmarshaller = modletContext.createUnmarshaller( ModletObject.MODEL_PUBLIC_ID ); 931 final JAXBSource source = new JAXBSource( marshaller, element ); 932 final JAXBResult result = new JAXBResult( unmarshaller ); 933 934 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() ) 935 { 936 transformer.setParameter( e.getKey().toString(), e.getValue() ); 937 } 938 939 transformer.transform( source, result ); 940 941 if ( result.getResult() instanceof JAXBElement<?> 942 && boundType.isInstance( ( (JAXBElement<?>) result.getResult() ).getValue() ) ) 943 { 944 @SuppressWarnings( "unchecked" ) final JAXBElement<T> e = (JAXBElement<T>) result.getResult(); 945 transformed = e; 946 } 947 else 948 { 949 throw new ModelException( Messages.getMessage( 950 "illegalModletTransformationResult", this.modletObjectStylesheet ) ); 951 952 } 953 } 954 955 return transformed; 956 } 957 958 private static String normalizeResourceName( final String name ) 959 { 960 String normalized = name; 961 962 if ( normalized != null ) 963 { 964 normalized = normalized.replace( '\\', '/' ); 965 966 if ( normalized.startsWith( "/" ) ) 967 { 968 normalized = normalized.substring( 1 ); 969 } 970 971 if ( normalized.endsWith( "/" ) ) 972 { 973 normalized = normalized.substring( 0, normalized.length() ); 974 } 975 } 976 977 return normalized; 978 } 979 980 private ModelContext createModelContext() throws ModelException, InstantiationException 981 { 982 final ModelContextFactory modelContextFactory; 983 if ( this.modelContextFactoryClassName != null ) 984 { 985 modelContextFactory = ModelContextFactory.newInstance( this.modelContextFactoryClassName ); 986 } 987 else 988 { 989 modelContextFactory = ModelContextFactory.newInstance(); 990 } 991 992 final ModelContext modelContext = modelContextFactory.newModelContext(); 993 modelContext.setModletSchemaSystemId( this.modletSchemaSystemId ); 994 995 if ( this.providerLocation != null ) 996 { 997 modelContext.setAttribute( DefaultModelContext.PROVIDER_LOCATION_ATTRIBUTE_NAME, this.providerLocation ); 998 } 999 1000 if ( this.platformProviderLocation != null ) 1001 { 1002 modelContext.setAttribute( DefaultModelContext.PLATFORM_PROVIDER_LOCATION_ATTRIBUTE_NAME, 1003 this.platformProviderLocation ); 1004 1005 } 1006 1007 if ( this.modletLocation != null ) 1008 { 1009 modelContext.setAttribute( DefaultModletProvider.MODLET_LOCATION_ATTRIBUTE_NAME, this.modletLocation ); 1010 } 1011 1012 if ( this.modelContextAttributes != null ) 1013 { 1014 for ( final ModelContextAttribute e : this.modelContextAttributes ) 1015 { 1016 final Object object = e.getObject( modelContext ); 1017 1018 if ( object != null ) 1019 { 1020 modelContext.setAttribute( e.getKey(), object ); 1021 } 1022 else 1023 { 1024 modelContext.clearAttribute( e.getKey() ); 1025 } 1026 } 1027 } 1028 1029 return modelContext; 1030 } 1031 1032}