001/* 002 * Copyright (C) 2014 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: DefaultModletProcessor.java 5293 2016-08-29 17:41:51Z schulte $ 029 * 030 */ 031package org.jomc.modlet; 032 033import java.io.ByteArrayInputStream; 034import java.io.ByteArrayOutputStream; 035import java.io.IOException; 036import java.lang.reflect.UndeclaredThrowableException; 037import java.net.URI; 038import java.net.URISyntaxException; 039import java.net.URL; 040import java.text.MessageFormat; 041import java.util.ArrayList; 042import java.util.Enumeration; 043import java.util.HashSet; 044import java.util.LinkedList; 045import java.util.List; 046import java.util.Locale; 047import java.util.Map; 048import java.util.Properties; 049import java.util.ResourceBundle; 050import java.util.Set; 051import java.util.concurrent.Callable; 052import java.util.concurrent.CancellationException; 053import java.util.concurrent.ExecutionException; 054import java.util.concurrent.Future; 055import java.util.logging.Level; 056import javax.xml.bind.JAXBContext; 057import javax.xml.bind.JAXBElement; 058import javax.xml.bind.JAXBException; 059import javax.xml.bind.util.JAXBResult; 060import javax.xml.bind.util.JAXBSource; 061import javax.xml.transform.ErrorListener; 062import javax.xml.transform.Transformer; 063import javax.xml.transform.TransformerConfigurationException; 064import javax.xml.transform.TransformerException; 065import javax.xml.transform.TransformerFactory; 066import javax.xml.transform.stream.StreamSource; 067 068/** 069 * Default {@code ModletProcessor} implementation. 070 * 071 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 072 * @version $JOMC: DefaultModletProcessor.java 5293 2016-08-29 17:41:51Z schulte $ 073 * @see ModelContext#processModlets(org.jomc.modlet.Modlets) 074 * @since 1.6 075 */ 076public class DefaultModletProcessor implements ModletProcessor 077{ 078 079 /** 080 * Constant for the name of the model context attribute backing property {@code enabled}. 081 * 082 * @see #processModlets(org.jomc.modlet.ModelContext, org.jomc.modlet.Modlets) 083 * @see ModelContext#getAttribute(java.lang.String) 084 */ 085 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.modlet.DefaultModletProcessor.enabledAttribute"; 086 087 /** 088 * Constant for the name of the system property controlling property {@code defaultEnabled}. 089 * 090 * @see #isDefaultEnabled() 091 */ 092 private static final String DEFAULT_ENABLED_PROPERTY_NAME = 093 "org.jomc.modlet.DefaultModletProcessor.defaultEnabled"; 094 095 /** 096 * Default value of the flag indicating the processor is enabled by default. 097 * 098 * @see #isDefaultEnabled() 099 */ 100 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE; 101 102 /** 103 * Flag indicating the processor is enabled by default. 104 */ 105 private static volatile Boolean defaultEnabled; 106 107 /** 108 * Flag indicating the processor is enabled. 109 */ 110 private volatile Boolean enabled; 111 112 /** 113 * Constant for the name of the system property controlling property {@code defaultOrdinal}. 114 * 115 * @see #getDefaultOrdinal() 116 */ 117 private static final String DEFAULT_ORDINAL_PROPERTY_NAME = 118 "org.jomc.modlet.DefaultModletProcessor.defaultOrdinal"; 119 120 /** 121 * Default value of the ordinal number of the processor. 122 * 123 * @see #getDefaultOrdinal() 124 */ 125 private static final Integer DEFAULT_ORDINAL = 0; 126 127 /** 128 * Default ordinal number of the processor. 129 */ 130 private static volatile Integer defaultOrdinal; 131 132 /** 133 * Ordinal number of the processor. 134 */ 135 private volatile Integer ordinal; 136 137 /** 138 * Constant for the name of the model context attribute backing property {@code transformerLocation}. 139 * 140 * @see #processModlets(org.jomc.modlet.ModelContext, org.jomc.modlet.Modlets) 141 * @see ModelContext#getAttribute(java.lang.String) 142 * @since 1.2 143 */ 144 public static final String TRANSFORMER_LOCATION_ATTRIBUTE_NAME = 145 "org.jomc.modlet.DefaultModletProcessor.transformerLocationAttribute"; 146 147 /** 148 * Constant for the name of the system property controlling property {@code defaultTransformerLocation}. 149 * 150 * @see #getDefaultTransformerLocation() 151 */ 152 private static final String DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME = 153 "org.jomc.modlet.DefaultModletProcessor.defaultTransformerLocation"; 154 155 /** 156 * Class path location searched for transformers by default. 157 * 158 * @see #getDefaultTransformerLocation() 159 */ 160 private static final String DEFAULT_TRANSFORMER_LOCATION = "META-INF/jomc-modlet.xsl"; 161 162 /** 163 * Default transformer location. 164 */ 165 private static volatile String defaultTransformerLocation; 166 167 /** 168 * Transformer location of the instance. 169 */ 170 private volatile String transformerLocation; 171 172 /** 173 * Creates a new {@code DefaultModletProcessor} instance. 174 */ 175 public DefaultModletProcessor() 176 { 177 super(); 178 } 179 180 /** 181 * Gets a flag indicating the processor is enabled by default. 182 * <p> 183 * The default enabled flag is controlled by system property 184 * {@code org.jomc.modlet.DefaultModletProcessor.defaultEnabled} holding a value indicating the processor is 185 * enabled by default. If that property is not set, the {@code true} default is returned. 186 * </p> 187 * 188 * @return {@code true}, if the processor is enabled by default; {@code false}, if the processor is disabled by 189 * default. 190 * 191 * @see #isEnabled() 192 * @see #setDefaultEnabled(java.lang.Boolean) 193 */ 194 public static boolean isDefaultEnabled() 195 { 196 if ( defaultEnabled == null ) 197 { 198 defaultEnabled = Boolean.valueOf( System.getProperty( 199 DEFAULT_ENABLED_PROPERTY_NAME, Boolean.toString( DEFAULT_ENABLED ) ) ); 200 201 } 202 203 return defaultEnabled; 204 } 205 206 /** 207 * Sets the flag indicating the processor is enabled by default. 208 * 209 * @param value The new value of the flag indicating the processor is enabled by default or {@code null}. 210 * 211 * @see #isDefaultEnabled() 212 */ 213 public static void setDefaultEnabled( final Boolean value ) 214 { 215 defaultEnabled = value; 216 } 217 218 /** 219 * Gets a flag indicating the processor is enabled. 220 * 221 * @return {@code true}, if the processor is enabled; {@code false}, if the processor is disabled. 222 * 223 * @see #isDefaultEnabled() 224 * @see #setEnabled(java.lang.Boolean) 225 */ 226 public final boolean isEnabled() 227 { 228 if ( this.enabled == null ) 229 { 230 this.enabled = isDefaultEnabled(); 231 } 232 233 return this.enabled; 234 } 235 236 /** 237 * Sets the flag indicating the processor is enabled. 238 * 239 * @param value The new value of the flag indicating the processor is enabled or {@code null}. 240 * 241 * @see #isEnabled() 242 */ 243 public final void setEnabled( final Boolean value ) 244 { 245 this.enabled = value; 246 } 247 248 /** 249 * Gets the default ordinal number of the processor. 250 * <p> 251 * The default ordinal number is controlled by system property 252 * {@code org.jomc.modlet.DefaultModletProvider.defaultOrdinal} holding the default ordinal number of the processor. 253 * If that property is not set, the {@code 0} default is returned. 254 * </p> 255 * 256 * @return The default ordinal number of the processor. 257 * 258 * @see #setDefaultOrdinal(java.lang.Integer) 259 */ 260 public static int getDefaultOrdinal() 261 { 262 if ( defaultOrdinal == null ) 263 { 264 defaultOrdinal = Integer.getInteger( DEFAULT_ORDINAL_PROPERTY_NAME, DEFAULT_ORDINAL ); 265 } 266 267 return defaultOrdinal; 268 } 269 270 /** 271 * Sets the default ordinal number of the processor. 272 * 273 * @param value The new default ordinal number of the processor or {@code null}. 274 * 275 * @see #getDefaultOrdinal() 276 */ 277 public static void setDefaultOrdinal( final Integer value ) 278 { 279 defaultOrdinal = value; 280 } 281 282 /** 283 * Gets the ordinal number of the processor. 284 * 285 * @return The ordinal number of the processor. 286 * 287 * @see #getDefaultOrdinal() 288 * @see #setOrdinal(java.lang.Integer) 289 */ 290 public final int getOrdinal() 291 { 292 if ( this.ordinal == null ) 293 { 294 this.ordinal = getDefaultOrdinal(); 295 } 296 297 return this.ordinal; 298 } 299 300 /** 301 * Sets the ordinal number of the processor. 302 * 303 * @param value The new ordinal number of the processor or {@code null}. 304 * 305 * @see #getOrdinal() 306 */ 307 public final void setOrdinal( final Integer value ) 308 { 309 this.ordinal = value; 310 } 311 312 /** 313 * Gets the default location searched for transformer resources. 314 * <p> 315 * The default transformer location is controlled by system property 316 * {@code org.jomc.modlet.DefaultModletProcessor.defaultTransformerLocation} holding the location to search 317 * for transformer resources by default. If that property is not set, the {@code META-INF/jomc-modlet.xsl} default 318 * is returned. 319 * </p> 320 * 321 * @return The location searched for transformer resources by default. 322 * 323 * @see #setDefaultTransformerLocation(java.lang.String) 324 */ 325 public static String getDefaultTransformerLocation() 326 { 327 if ( defaultTransformerLocation == null ) 328 { 329 defaultTransformerLocation = 330 System.getProperty( DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME, DEFAULT_TRANSFORMER_LOCATION ); 331 332 } 333 334 return defaultTransformerLocation; 335 } 336 337 /** 338 * Sets the default location searched for transformer resources. 339 * 340 * @param value The new default location to search for transformer resources or {@code null}. 341 * 342 * @see #getDefaultTransformerLocation() 343 */ 344 public static void setDefaultTransformerLocation( final String value ) 345 { 346 defaultTransformerLocation = value; 347 } 348 349 /** 350 * Gets the location searched for transformer resources. 351 * 352 * @return The location searched for transformer resources. 353 * 354 * @see #getDefaultTransformerLocation() 355 * @see #setTransformerLocation(java.lang.String) 356 */ 357 public final String getTransformerLocation() 358 { 359 if ( this.transformerLocation == null ) 360 { 361 this.transformerLocation = getDefaultTransformerLocation(); 362 } 363 364 return this.transformerLocation; 365 } 366 367 /** 368 * Sets the location searched for transformer resources. 369 * 370 * @param value The new location to search for transformer resources or {@code null}. 371 * 372 * @see #getTransformerLocation() 373 */ 374 public final void setTransformerLocation( final String value ) 375 { 376 this.transformerLocation = value; 377 } 378 379 /** 380 * Searches a given context for transformers. 381 * 382 * @param context The context to search for transformers. 383 * @param location The location to search at. 384 * 385 * @return The transformers found at {@code location} in {@code context} or {@code null}, if no transformers are 386 * found. 387 * 388 * @throws NullPointerException if {@code context} or {@code location} is {@code null}. 389 * @throws ModelException if getting the transformers fails. 390 */ 391 public List<Transformer> findTransformers( final ModelContext context, final String location ) throws ModelException 392 { 393 if ( context == null ) 394 { 395 throw new NullPointerException( "context" ); 396 } 397 if ( location == null ) 398 { 399 throw new NullPointerException( "location" ); 400 } 401 402 try 403 { 404 final long t0 = System.nanoTime(); 405 final List<Transformer> transformers = new LinkedList<Transformer>(); 406 final Enumeration<URL> transformerResourceEnumeration = context.findResources( location ); 407 final Set<URI> transformerResources = new HashSet<URI>(); 408 while ( transformerResourceEnumeration.hasMoreElements() ) 409 { 410 transformerResources.add( transformerResourceEnumeration.nextElement().toURI() ); 411 } 412 413 if ( !transformerResources.isEmpty() ) 414 { 415 final ErrorListener errorListener = new ErrorListener() 416 { 417 418 public void warning( final TransformerException exception ) throws TransformerException 419 { 420 if ( context.isLoggable( Level.WARNING ) ) 421 { 422 context.log( Level.WARNING, getMessage( exception ), exception ); 423 } 424 } 425 426 public void error( final TransformerException exception ) throws TransformerException 427 { 428 if ( context.isLoggable( Level.SEVERE ) ) 429 { 430 context.log( Level.SEVERE, getMessage( exception ), exception ); 431 } 432 433 throw exception; 434 } 435 436 public void fatalError( final TransformerException exception ) throws TransformerException 437 { 438 if ( context.isLoggable( Level.SEVERE ) ) 439 { 440 context.log( Level.SEVERE, getMessage( exception ), exception ); 441 } 442 443 throw exception; 444 } 445 446 }; 447 448 final Properties transformerParameters = this.getTransformerParameters( context ); 449 450 if ( context.getExecutorService() != null && transformerResources.size() > 1 ) 451 { 452 final ThreadLocal<TransformerFactory> threadLocalTransformerFactory = 453 new ThreadLocal<TransformerFactory>(); 454 455 final List<Callable<Transformer>> tasks = 456 new ArrayList<Callable<Transformer>>( transformerResources.size() ); 457 458 for ( final URI transformerResource : transformerResources ) 459 { 460 tasks.add( new Callable<Transformer>() 461 { 462 463 public Transformer call() throws TransformerConfigurationException, URISyntaxException 464 { 465 TransformerFactory transformerFactory = threadLocalTransformerFactory.get(); 466 if ( transformerFactory == null ) 467 { 468 transformerFactory = TransformerFactory.newInstance(); 469 threadLocalTransformerFactory.set( transformerFactory ); 470 } 471 472 return createTransformer( context, transformerFactory, transformerParameters, 473 transformerResource ); 474 475 } 476 477 } ); 478 } 479 480 for ( final Future<Transformer> task : context.getExecutorService().invokeAll( tasks ) ) 481 { 482 transformers.add( task.get() ); 483 } 484 } 485 else 486 { 487 final TransformerFactory transformerFactory = TransformerFactory.newInstance(); 488 transformerFactory.setErrorListener( errorListener ); 489 490 for ( final URI transformerResource : transformerResources ) 491 { 492 transformers.add( this.createTransformer( context, transformerFactory, transformerParameters, 493 transformerResource ) ); 494 495 } 496 } 497 } 498 499 if ( context.isLoggable( Level.FINE ) ) 500 { 501 context.log( Level.FINE, getMessage( "contextReport", transformerResources.size(), location, 502 System.nanoTime() - t0 ), null ); 503 504 } 505 506 return transformers.isEmpty() ? null : transformers; 507 } 508 catch ( final CancellationException e ) 509 { 510 throw new ModelException( getMessage( e ), e ); 511 } 512 catch ( final InterruptedException e ) 513 { 514 throw new ModelException( getMessage( e ), e ); 515 } 516 catch ( final IOException e ) 517 { 518 throw new ModelException( getMessage( e ), e ); 519 } 520 catch ( final URISyntaxException e ) 521 { 522 throw new ModelException( getMessage( e ), e ); 523 } 524 catch ( final TransformerConfigurationException e ) 525 { 526 String message = getMessage( e ); 527 if ( message == null && e.getException() != null ) 528 { 529 message = getMessage( e.getException() ); 530 } 531 532 throw new ModelException( message, e ); 533 } 534 catch ( final ExecutionException e ) 535 { 536 if ( e.getCause() instanceof URISyntaxException ) 537 { 538 throw new ModelException( getMessage( e.getCause() ), e.getCause() ); 539 } 540 else if ( e.getCause() instanceof TransformerConfigurationException ) 541 { 542 String message = getMessage( e.getCause() ); 543 if ( message == null && ( (TransformerConfigurationException) e.getCause() ).getException() != null ) 544 { 545 message = getMessage( ( (TransformerConfigurationException) e.getCause() ).getException() ); 546 } 547 548 throw new ModelException( message, e.getCause() ); 549 } 550 else if ( e.getCause() instanceof RuntimeException ) 551 { 552 // The fork-join framework breaks the exception handling contract of Callable by re-throwing any 553 // exception caught using a runtime exception. 554 if ( e.getCause().getCause() instanceof TransformerConfigurationException ) 555 { 556 String message = getMessage( e.getCause().getCause() ); 557 if ( message == null 558 && ( (TransformerConfigurationException) e.getCause().getCause() ).getException() != null ) 559 { 560 message = getMessage( ( (TransformerConfigurationException) e.getCause().getCause() ). 561 getException() ); 562 563 } 564 565 throw new ModelException( message, e.getCause().getCause() ); 566 } 567 else if ( e.getCause().getCause() instanceof URISyntaxException ) 568 { 569 throw new ModelException( getMessage( e.getCause().getCause() ), e.getCause().getCause() ); 570 } 571 else if ( e.getCause().getCause() instanceof RuntimeException ) 572 { 573 throw (RuntimeException) e.getCause().getCause(); 574 } 575 else if ( e.getCause().getCause() instanceof Error ) 576 { 577 throw (Error) e.getCause().getCause(); 578 } 579 else if ( e.getCause().getCause() instanceof Exception ) 580 { 581 // Checked exception not declared to be thrown by the Callable's 'call' method. 582 throw new UndeclaredThrowableException( e.getCause().getCause() ); 583 } 584 else 585 { 586 throw (RuntimeException) e.getCause(); 587 } 588 } 589 else if ( e.getCause() instanceof Error ) 590 { 591 throw (Error) e.getCause(); 592 } 593 else 594 { 595 // Checked exception not declared to be thrown by the Callable's 'call' method. 596 throw new UndeclaredThrowableException( e.getCause() ); 597 } 598 } 599 } 600 601 /** 602 * {@inheritDoc} 603 * 604 * @see #isEnabled() 605 * @see #getTransformerLocation() 606 * @see #findTransformers(org.jomc.modlet.ModelContext, java.lang.String) 607 * @see #ENABLED_ATTRIBUTE_NAME 608 * @see #TRANSFORMER_LOCATION_ATTRIBUTE_NAME 609 */ 610 public Modlets processModlets( final ModelContext context, final Modlets modlets ) throws ModelException 611 { 612 if ( context == null ) 613 { 614 throw new NullPointerException( "context" ); 615 } 616 if ( modlets == null ) 617 { 618 throw new NullPointerException( "modlets" ); 619 } 620 621 try 622 { 623 Modlets processed = null; 624 625 boolean contextEnabled = this.isEnabled(); 626 if ( DEFAULT_ENABLED == contextEnabled 627 && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) 628 { 629 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME ); 630 } 631 632 String contextTransformerLocation = this.getTransformerLocation(); 633 if ( DEFAULT_TRANSFORMER_LOCATION.equals( contextTransformerLocation ) 634 && context.getAttribute( TRANSFORMER_LOCATION_ATTRIBUTE_NAME ) instanceof String ) 635 { 636 contextTransformerLocation = (String) context.getAttribute( TRANSFORMER_LOCATION_ATTRIBUTE_NAME ); 637 } 638 639 if ( contextEnabled ) 640 { 641 final org.jomc.modlet.ObjectFactory objectFactory = new org.jomc.modlet.ObjectFactory(); 642 final JAXBContext jaxbContext = context.createContext( ModletObject.MODEL_PUBLIC_ID ); 643 final List<Transformer> transformers = this.findTransformers( context, contextTransformerLocation ); 644 645 if ( transformers != null ) 646 { 647 processed = modlets.clone(); 648 649 for ( int i = 0, s0 = transformers.size(); i < s0; i++ ) 650 { 651 final JAXBElement<Modlets> e = objectFactory.createModlets( processed ); 652 final JAXBSource source = new JAXBSource( jaxbContext, e ); 653 final JAXBResult result = new JAXBResult( jaxbContext ); 654 transformers.get( i ).transform( source, result ); 655 656 if ( result.getResult() instanceof JAXBElement<?> 657 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Modlets ) 658 { 659 processed = (Modlets) ( (JAXBElement<?>) result.getResult() ).getValue(); 660 } 661 else 662 { 663 throw new ModelException( getMessage( "illegalTransformationResult" ) ); 664 } 665 } 666 } 667 } 668 else if ( context.isLoggable( Level.FINER ) ) 669 { 670 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName() ), null ); 671 } 672 673 return processed; 674 } 675 catch ( final TransformerException e ) 676 { 677 String message = getMessage( e ); 678 if ( message == null && e.getException() != null ) 679 { 680 message = getMessage( e.getException() ); 681 } 682 683 throw new ModelException( message, e ); 684 } 685 catch ( final JAXBException e ) 686 { 687 String message = getMessage( e ); 688 if ( message == null && e.getLinkedException() != null ) 689 { 690 message = getMessage( e.getLinkedException() ); 691 } 692 693 throw new ModelException( message, e ); 694 } 695 } 696 697 private Transformer createTransformer( final ModelContext context, final TransformerFactory transformerFactory, 698 final Map<Object, Object> parameters, final URI transformerResource ) 699 throws TransformerConfigurationException, URISyntaxException 700 { 701 if ( context.isLoggable( Level.FINEST ) ) 702 { 703 context.log( Level.FINEST, getMessage( "processing", transformerResource.toString() ), null ); 704 } 705 706 final Transformer transformer = 707 transformerFactory.newTransformer( new StreamSource( transformerResource.toASCIIString() ) ); 708 709 transformer.setErrorListener( transformerFactory.getErrorListener() ); 710 711 for ( final Map.Entry<Object, Object> e : parameters.entrySet() ) 712 { 713 transformer.setParameter( e.getKey().toString(), e.getValue() ); 714 } 715 716 return transformer; 717 } 718 719 private Properties getTransformerParameters( final ModelContext context ) throws IOException 720 { 721 final Properties properties = new Properties(); 722 723 if ( context.getExecutorService() != null ) 724 { 725 ByteArrayInputStream in = null; 726 ByteArrayOutputStream out = null; 727 try 728 { 729 out = new ByteArrayOutputStream(); 730 System.getProperties().store( out, this.getClass().getName() ); 731 out.close(); 732 final byte[] bytes = out.toByteArray(); 733 out = null; 734 735 in = new ByteArrayInputStream( bytes ); 736 properties.load( in ); 737 in.close(); 738 in = null; 739 } 740 finally 741 { 742 try 743 { 744 if ( out != null ) 745 { 746 out.close(); 747 } 748 } 749 catch ( final IOException e ) 750 { 751 // Suppressed. 752 } 753 finally 754 { 755 try 756 { 757 if ( in != null ) 758 { 759 in.close(); 760 } 761 } 762 catch ( final IOException e ) 763 { 764 // Suppressed. 765 } 766 } 767 } 768 } 769 else 770 { 771 properties.putAll( System.getProperties() ); 772 } 773 774 return properties; 775 } 776 777 private static String getMessage( final String key, final Object... args ) 778 { 779 return MessageFormat.format( ResourceBundle.getBundle( 780 DefaultModletProcessor.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args ); 781 782 } 783 784 private static String getMessage( final Throwable t ) 785 { 786 return t != null 787 ? t.getMessage() != null && t.getMessage().trim().length() > 0 788 ? t.getMessage() 789 : getMessage( t.getCause() ) 790 : null; 791 792 } 793 794}