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