001 /* 002 * Copyright (C) Christian Schulte, 2005-206 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: ProjectClassLoader.java 4256 2012-02-13 06:32:10Z schulte2005 $ 029 * 030 */ 031 package org.jomc.ant; 032 033 import java.io.Closeable; 034 import java.io.File; 035 import java.io.FileOutputStream; 036 import java.io.IOException; 037 import java.io.InputStream; 038 import java.io.OutputStream; 039 import java.lang.reflect.InvocationTargetException; 040 import java.net.MalformedURLException; 041 import java.net.URL; 042 import java.net.URLClassLoader; 043 import java.util.ArrayList; 044 import java.util.Collections; 045 import java.util.Enumeration; 046 import java.util.HashSet; 047 import java.util.Iterator; 048 import java.util.List; 049 import java.util.Set; 050 import javax.xml.bind.JAXBElement; 051 import javax.xml.bind.JAXBException; 052 import org.apache.commons.io.IOUtils; 053 import org.apache.commons.lang.StringUtils; 054 import org.apache.tools.ant.Project; 055 import org.apache.tools.ant.types.Path; 056 import org.jomc.modlet.ModelContext; 057 import org.jomc.modlet.ModelContextFactory; 058 import org.jomc.modlet.ModelException; 059 import org.jomc.modlet.Modlet; 060 import org.jomc.modlet.ModletObject; 061 import org.jomc.modlet.Modlets; 062 import org.jomc.modlet.ObjectFactory; 063 import org.jomc.modlet.Schema; 064 import org.jomc.modlet.Schemas; 065 import org.jomc.modlet.Service; 066 import org.jomc.modlet.Services; 067 import org.jomc.util.ParseException; 068 import org.jomc.util.TokenMgrError; 069 import org.jomc.util.VersionParser; 070 071 /** 072 * Class loader supporting JOMC resources backed by a project. 073 * 074 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 075 * @version $JOMC: ProjectClassLoader.java 4256 2012-02-13 06:32:10Z schulte2005 $ 076 */ 077 public class ProjectClassLoader extends URLClassLoader 078 { 079 080 /** Constant to prefix relative resource names with. */ 081 private static final String ABSOLUTE_RESOURCE_NAME_PREFIX = "/org/jomc/ant/"; 082 083 /** Empty URL array. */ 084 private static final URL[] NO_URLS = 085 { 086 }; 087 088 /** Set of modlet names to exclude. */ 089 private Set<String> modletExcludes; 090 091 /** Excluded modlets. */ 092 private Modlets excludedModlets; 093 094 /** Set of service class names to exclude. */ 095 private Set<String> serviceExcludes; 096 097 /** Excluded services. */ 098 private Services excludedServices; 099 100 /** Set of schema public ids to exclude. */ 101 private Set<String> schemaExcludes; 102 103 /** Excluded schemas. */ 104 private Schemas excludedSchemas; 105 106 /** Set of providers to exclude. */ 107 private Set<String> providerExcludes; 108 109 /** Set of excluded providers. */ 110 private Set<String> excludedProviders; 111 112 /** The project the class loader is associated with. */ 113 private final Project project; 114 115 /** Set of modlet resource locations to filter. */ 116 private Set<String> modletResourceLocations; 117 118 /** Set of provider resource locations to filter. */ 119 private Set<String> providerResourceLocations; 120 121 /** Set of temporary resources. */ 122 private final Set<File> temporaryResources = new HashSet<File>(); 123 124 /** 125 * Creates a new {@code ProjectClassLoader} instance taking a project and a class path. 126 * 127 * @param project The project to which this class loader is to belong. 128 * @param classpath The class path to use for loading. 129 * 130 * @throws MalformedURLException if {@code classpath} contains unsupported elements. 131 */ 132 public ProjectClassLoader( final Project project, final Path classpath ) throws MalformedURLException 133 { 134 super( NO_URLS, ProjectClassLoader.class.getClassLoader() ); 135 136 for ( final String name : classpath.list() ) 137 { 138 final File resolved = project.resolveFile( name ); 139 this.addURL( resolved.toURI().toURL() ); 140 } 141 142 this.project = project; 143 } 144 145 /** 146 * Gets the project of the instance. 147 * 148 * @return The project of the instance. 149 */ 150 public final Project getProject() 151 { 152 return this.project; 153 } 154 155 /** 156 * Finds a resource with a given name. 157 * 158 * @param name The name of the resource to search. 159 * 160 * @return An {@code URL} object for reading the resource or {@code null}, if no resource matching {@code name} is 161 * found. 162 */ 163 @Override 164 public URL findResource( final String name ) 165 { 166 try 167 { 168 URL resource = super.findResource( name ); 169 170 if ( resource != null ) 171 { 172 if ( this.getProviderResourceLocations().contains( name ) ) 173 { 174 resource = this.filterProviders( resource ); 175 } 176 else if ( this.getModletResourceLocations().contains( name ) ) 177 { 178 resource = this.filterModlets( resource ); 179 } 180 } 181 182 return resource; 183 } 184 catch ( final IOException e ) 185 { 186 this.getProject().log( Messages.getMessage( e ), Project.MSG_ERR ); 187 return null; 188 } 189 catch ( final JAXBException e ) 190 { 191 String message = Messages.getMessage( e ); 192 if ( message == null && e.getLinkedException() != null ) 193 { 194 message = Messages.getMessage( e.getLinkedException() ); 195 } 196 197 this.getProject().log( message, Project.MSG_ERR ); 198 return null; 199 } 200 catch ( final ModelException e ) 201 { 202 this.getProject().log( Messages.getMessage( e ), Project.MSG_ERR ); 203 return null; 204 } 205 } 206 207 /** 208 * Gets all resources matching a given name. 209 * 210 * @param name The name of the resources to get. 211 * 212 * @return An enumeration of {@code URL} objects of found resources. 213 * 214 * @throws IOException if getting resources fails. 215 */ 216 @Override 217 public Enumeration<URL> findResources( final String name ) throws IOException 218 { 219 final Enumeration<URL> allResources = super.findResources( name ); 220 Enumeration<URL> enumeration = allResources; 221 222 if ( this.getProviderResourceLocations().contains( name ) ) 223 { 224 enumeration = new Enumeration<URL>() 225 { 226 227 public boolean hasMoreElements() 228 { 229 return allResources.hasMoreElements(); 230 } 231 232 public URL nextElement() 233 { 234 try 235 { 236 return filterProviders( allResources.nextElement() ); 237 } 238 catch ( final IOException e ) 239 { 240 getProject().log( Messages.getMessage( e ), Project.MSG_ERR ); 241 return null; 242 } 243 } 244 245 }; 246 } 247 else if ( this.getModletResourceLocations().contains( name ) ) 248 { 249 enumeration = new Enumeration<URL>() 250 { 251 252 public boolean hasMoreElements() 253 { 254 return allResources.hasMoreElements(); 255 } 256 257 public URL nextElement() 258 { 259 try 260 { 261 return filterModlets( allResources.nextElement() ); 262 } 263 catch ( final IOException e ) 264 { 265 getProject().log( Messages.getMessage( e ), Project.MSG_ERR ); 266 return null; 267 } 268 catch ( final JAXBException e ) 269 { 270 String message = Messages.getMessage( e ); 271 if ( message == null && e.getLinkedException() != null ) 272 { 273 message = Messages.getMessage( e.getLinkedException() ); 274 } 275 276 getProject().log( message, Project.MSG_ERR ); 277 return null; 278 } 279 catch ( final ModelException e ) 280 { 281 getProject().log( Messages.getMessage( e ), Project.MSG_ERR ); 282 return null; 283 } 284 } 285 286 }; 287 } 288 289 return enumeration; 290 } 291 292 /** 293 * Gets a set of modlet resource locations to filter. 294 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 295 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 296 * modlet resource locations property.</p> 297 * 298 * @return A set of modlet resource locations to filter. 299 */ 300 public final Set<String> getModletResourceLocations() 301 { 302 if ( this.modletResourceLocations == null ) 303 { 304 this.modletResourceLocations = new HashSet<String>(); 305 } 306 307 return this.modletResourceLocations; 308 } 309 310 /** 311 * Gets a set of provider resource locations to filter. 312 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 313 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 314 * provider resource locations property.</p> 315 * 316 * @return A set of provider resource locations to filter. 317 */ 318 public final Set<String> getProviderResourceLocations() 319 { 320 if ( this.providerResourceLocations == null ) 321 { 322 this.providerResourceLocations = new HashSet<String>(); 323 } 324 325 return this.providerResourceLocations; 326 } 327 328 /** 329 * Gets a set of modlet names to exclude. 330 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 331 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 332 * modlet excludes property.</p> 333 * 334 * @return A set of modlet names to exclude. 335 */ 336 public final Set<String> getModletExcludes() 337 { 338 if ( this.modletExcludes == null ) 339 { 340 this.modletExcludes = new HashSet<String>(); 341 } 342 343 return this.modletExcludes; 344 } 345 346 /** 347 * Gets a set of modlet names excluded by default. 348 * 349 * @return An unmodifiable set of modlet names excluded by default. 350 * 351 * @throws IOException if reading configuration resources fails. 352 */ 353 public static Set<String> getDefaultModletExcludes() throws IOException 354 { 355 return readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultModletExcludes" ); 356 } 357 358 /** 359 * Gets a set of modlets excluded during resource loading. 360 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 361 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 362 * excluded modlets property.</p> 363 * 364 * @return A set of modlets excluded during resource loading. 365 */ 366 public final Modlets getExcludedModlets() 367 { 368 if ( this.excludedModlets == null ) 369 { 370 this.excludedModlets = new Modlets(); 371 } 372 373 return this.excludedModlets; 374 } 375 376 /** 377 * Gets a set of provider names to exclude. 378 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 379 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 380 * provider excludes property.</p> 381 * 382 * @return A set of providers to exclude. 383 */ 384 public final Set<String> getProviderExcludes() 385 { 386 if ( this.providerExcludes == null ) 387 { 388 this.providerExcludes = new HashSet<String>(); 389 } 390 391 return this.providerExcludes; 392 } 393 394 /** 395 * Gets a set of provider names excluded by default. 396 * 397 * @return An unmodifiable set of provider names excluded by default. 398 * 399 * @throws IOException if reading configuration resources fails. 400 */ 401 public static Set<String> getDefaultProviderExcludes() throws IOException 402 { 403 return readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultProviderExcludes" ); 404 } 405 406 /** 407 * Gets a set of providers excluded during resource loading. 408 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 409 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 410 * excluded providers property.</p> 411 * 412 * @return A set of providers excluded during resource loading. 413 */ 414 public final Set<String> getExcludedProviders() 415 { 416 if ( this.excludedProviders == null ) 417 { 418 this.excludedProviders = new HashSet<String>(); 419 } 420 421 return this.excludedProviders; 422 } 423 424 /** 425 * Gets a set of service class names to exclude. 426 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 427 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 428 * service excludes property.</p> 429 * 430 * @return A set of service class names to exclude. 431 */ 432 public final Set<String> getServiceExcludes() 433 { 434 if ( this.serviceExcludes == null ) 435 { 436 this.serviceExcludes = new HashSet<String>(); 437 } 438 439 return this.serviceExcludes; 440 } 441 442 /** 443 * Gets a set of service class names excluded by default. 444 * 445 * @return An unmodifiable set of service class names excluded by default. 446 * 447 * @throws IOException if reading configuration resources fails. 448 */ 449 public static Set<String> getDefaultServiceExcludes() throws IOException 450 { 451 return readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultServiceExcludes" ); 452 } 453 454 /** 455 * Gets a set of services excluded during resource loading. 456 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 457 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 458 * excluded services property.</p> 459 * 460 * @return Services excluded during resource loading. 461 */ 462 public final Services getExcludedServices() 463 { 464 if ( this.excludedServices == null ) 465 { 466 this.excludedServices = new Services(); 467 } 468 469 return this.excludedServices; 470 } 471 472 /** 473 * Gets a set of schema public identifiers to exclude. 474 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 475 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 476 * schema excludes property.</p> 477 * 478 * @return A set of schema public identifiers to exclude. 479 */ 480 public final Set<String> getSchemaExcludes() 481 { 482 if ( this.schemaExcludes == null ) 483 { 484 this.schemaExcludes = new HashSet<String>(); 485 } 486 487 return this.schemaExcludes; 488 } 489 490 /** 491 * Gets a set of schema public identifiers excluded by default. 492 * 493 * @return An unmodifiable set of schema public identifiers excluded by default. 494 * 495 * @throws IOException if reading configuration resources fails. 496 */ 497 public static Set<String> getDefaultSchemaExcludes() throws IOException 498 { 499 return readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultSchemaExcludes" ); 500 } 501 502 /** 503 * Gets a set of schemas excluded during resource loading. 504 * <p>This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make 505 * to the returned set will be present inside the object. This is why there is no {@code set} method for the 506 * excluded schemas property.</p> 507 * 508 * @return Schemas excluded during resource loading. 509 */ 510 public final Schemas getExcludedSchemas() 511 { 512 if ( this.excludedSchemas == null ) 513 { 514 this.excludedSchemas = new Schemas(); 515 } 516 517 return this.excludedSchemas; 518 } 519 520 /** 521 * Closes the class loader. 522 * @throws IOException if closing the class loader fails. 523 */ 524 public void close() throws IOException 525 { 526 for ( final Iterator<File> it = this.temporaryResources.iterator(); it.hasNext(); ) 527 { 528 final File temporaryResource = it.next(); 529 530 if ( temporaryResource.exists() && temporaryResource.delete() ) 531 { 532 it.remove(); 533 } 534 } 535 536 if ( Closeable.class.isAssignableFrom( ProjectClassLoader.class ) ) 537 { // JDK: As of JDK 7, super.close(); 538 this.jdk7Close(); 539 } 540 } 541 542 /** 543 * Removes temporary resources. 544 * @throws Throwable if finalization fails. 545 */ 546 @Override 547 protected void finalize() throws Throwable 548 { 549 for ( final Iterator<File> it = this.temporaryResources.iterator(); it.hasNext(); ) 550 { 551 final File temporaryResource = it.next(); 552 553 if ( temporaryResource.exists() && !temporaryResource.delete() ) 554 { 555 temporaryResource.deleteOnExit(); 556 } 557 558 it.remove(); 559 } 560 561 super.finalize(); 562 } 563 564 private URL filterProviders( final URL resource ) throws IOException 565 { 566 InputStream in = null; 567 boolean suppressExceptionOnClose = true; 568 569 try 570 { 571 URL filteredResource = resource; 572 in = resource.openStream(); 573 final List<String> lines = IOUtils.readLines( in, "UTF-8" ); 574 final List<String> filteredLines = new ArrayList<String>( lines.size() ); 575 576 for ( String line : lines ) 577 { 578 if ( !this.getProviderExcludes().contains( line.trim() ) ) 579 { 580 filteredLines.add( line.trim() ); 581 } 582 else 583 { 584 this.getExcludedProviders().add( line.trim() ); 585 this.getProject().log( Messages.getMessage( "providerExclusion", resource.toExternalForm(), 586 line.trim() ), Project.MSG_DEBUG ); 587 588 } 589 } 590 591 if ( lines.size() != filteredLines.size() ) 592 { 593 OutputStream out = null; 594 final File tmpResource = File.createTempFile( this.getClass().getName(), ".rsrc" ); 595 this.temporaryResources.add( tmpResource ); 596 597 try 598 { 599 out = new FileOutputStream( tmpResource ); 600 IOUtils.writeLines( filteredLines, System.getProperty( "line.separator", "\n" ), out, "UTF-8" ); 601 suppressExceptionOnClose = false; 602 } 603 finally 604 { 605 try 606 { 607 if ( out != null ) 608 { 609 out.close(); 610 } 611 612 suppressExceptionOnClose = true; 613 } 614 catch ( final IOException e ) 615 { 616 if ( suppressExceptionOnClose ) 617 { 618 this.project.log( Messages.getMessage( e ), e, Project.MSG_ERR ); 619 } 620 else 621 { 622 throw e; 623 } 624 } 625 } 626 627 filteredResource = tmpResource.toURI().toURL(); 628 } 629 630 suppressExceptionOnClose = false; 631 return filteredResource; 632 } 633 finally 634 { 635 try 636 { 637 if ( in != null ) 638 { 639 in.close(); 640 } 641 } 642 catch ( final IOException e ) 643 { 644 if ( suppressExceptionOnClose ) 645 { 646 this.project.log( Messages.getMessage( e ), e, Project.MSG_ERR ); 647 } 648 else 649 { 650 throw e; 651 } 652 } 653 } 654 } 655 656 private URL filterModlets( final URL resource ) throws ModelException, IOException, JAXBException 657 { 658 InputStream in = null; 659 boolean suppressExceptionOnClose = true; 660 661 try 662 { 663 URL filteredResource = resource; 664 final ModelContext modelContext = ModelContextFactory.newInstance().newModelContext(); 665 in = resource.openStream(); 666 final JAXBElement<?> e = 667 (JAXBElement<?>) modelContext.createUnmarshaller( ModletObject.MODEL_PUBLIC_ID ).unmarshal( in ); 668 669 final Object o = e.getValue(); 670 Modlets modlets = null; 671 boolean filtered = false; 672 673 if ( o instanceof Modlets ) 674 { 675 modlets = (Modlets) o; 676 } 677 else if ( o instanceof Modlet ) 678 { 679 modlets = new Modlets(); 680 modlets.getModlet().add( (Modlet) o ); 681 } 682 683 if ( modlets != null ) 684 { 685 for ( final Iterator<Modlet> it = modlets.getModlet().iterator(); it.hasNext(); ) 686 { 687 final Modlet m = it.next(); 688 689 if ( this.getModletExcludes().contains( m.getName() ) ) 690 { 691 it.remove(); 692 filtered = true; 693 this.addExcludedModlet( m ); 694 this.getProject().log( Messages.getMessage( "modletExclusion", resource.toExternalForm(), 695 m.getName() ), Project.MSG_DEBUG ); 696 697 continue; 698 } 699 700 if ( this.filterModlet( m, resource.toExternalForm() ) ) 701 { 702 filtered = true; 703 } 704 } 705 706 if ( filtered ) 707 { 708 final File tmpResource = File.createTempFile( this.getClass().getName(), ".rsrc" ); 709 this.temporaryResources.add( tmpResource ); 710 modelContext.createMarshaller( ModletObject.MODEL_PUBLIC_ID ).marshal( 711 new ObjectFactory().createModlets( modlets ), tmpResource ); 712 713 filteredResource = tmpResource.toURI().toURL(); 714 } 715 } 716 717 suppressExceptionOnClose = false; 718 return filteredResource; 719 } 720 finally 721 { 722 try 723 { 724 if ( in != null ) 725 { 726 in.close(); 727 } 728 } 729 catch ( final IOException e ) 730 { 731 if ( suppressExceptionOnClose ) 732 { 733 this.project.log( Messages.getMessage( e ), e, Project.MSG_ERR ); 734 } 735 else 736 { 737 throw e; 738 } 739 } 740 } 741 } 742 743 private boolean filterModlet( final Modlet modlet, final String resourceInfo ) 744 { 745 boolean filteredSchemas = false; 746 boolean filteredServices = false; 747 748 if ( modlet.getSchemas() != null ) 749 { 750 final Schemas schemas = new Schemas(); 751 752 for ( Schema s : modlet.getSchemas().getSchema() ) 753 { 754 if ( !this.getSchemaExcludes().contains( s.getPublicId() ) ) 755 { 756 schemas.getSchema().add( s ); 757 } 758 else 759 { 760 this.getProject().log( Messages.getMessage( "schemaExclusion", resourceInfo, s.getPublicId() ), 761 Project.MSG_DEBUG ); 762 763 this.addExcludedSchema( s ); 764 filteredSchemas = true; 765 } 766 } 767 768 if ( filteredSchemas ) 769 { 770 modlet.setSchemas( schemas ); 771 } 772 } 773 774 if ( modlet.getServices() != null ) 775 { 776 final Services services = new Services(); 777 778 for ( Service s : modlet.getServices().getService() ) 779 { 780 if ( !this.getServiceExcludes().contains( s.getClazz() ) ) 781 { 782 services.getService().add( s ); 783 } 784 else 785 { 786 this.getProject().log( Messages.getMessage( "serviceExclusion", resourceInfo, s.getClazz() ), 787 Project.MSG_DEBUG ); 788 789 this.addExcludedService( s ); 790 filteredServices = true; 791 } 792 } 793 794 if ( filteredServices ) 795 { 796 modlet.setServices( services ); 797 } 798 } 799 800 return filteredSchemas || filteredServices; 801 } 802 803 private void addExcludedModlet( final Modlet modlet ) 804 { 805 try 806 { 807 final Modlet m = this.getExcludedModlets().getModlet( modlet.getName() ); 808 809 if ( m != null ) 810 { 811 if ( m.getVersion() != null && modlet.getVersion() != null 812 && VersionParser.compare( m.getVersion(), modlet.getVersion() ) < 0 ) 813 { 814 this.getExcludedModlets().getModlet().remove( m ); 815 this.getExcludedModlets().getModlet().add( modlet ); 816 } 817 } 818 else 819 { 820 this.getExcludedModlets().getModlet().add( modlet ); 821 } 822 } 823 catch ( final ParseException e ) 824 { 825 this.getProject().log( Messages.getMessage( e ), e, Project.MSG_WARN ); 826 } 827 catch ( final TokenMgrError e ) 828 { 829 this.getProject().log( Messages.getMessage( e ), e, Project.MSG_WARN ); 830 } 831 } 832 833 private void addExcludedSchema( final Schema schema ) 834 { 835 if ( this.getExcludedSchemas().getSchemaBySystemId( schema.getSystemId() ) == null ) 836 { 837 this.getExcludedSchemas().getSchema().add( schema ); 838 } 839 } 840 841 private void addExcludedService( final Service service ) 842 { 843 for ( int i = 0, s0 = this.getExcludedServices().getService().size(); i < s0; i++ ) 844 { 845 final Service s = this.getExcludedServices().getService().get( i ); 846 847 if ( s.getIdentifier().equals( service.getIdentifier() ) && s.getClazz().equals( service.getClazz() ) ) 848 { 849 return; 850 } 851 } 852 853 this.getExcludedServices().getService().add( service ); 854 } 855 856 private void jdk7Close() 857 { 858 try 859 { 860 URLClassLoader.class.getMethod( "close" ).invoke( this ); 861 } 862 catch ( final NoSuchMethodException e ) 863 { 864 this.project.log( Messages.getMessage( e ), e, Project.MSG_DEBUG ); 865 } 866 catch ( final IllegalAccessException e ) 867 { 868 this.project.log( Messages.getMessage( e ), e, Project.MSG_DEBUG ); 869 } 870 catch ( final InvocationTargetException e ) 871 { 872 this.project.log( Messages.getMessage( e ), e, Project.MSG_DEBUG ); 873 } 874 } 875 876 private static Set<String> readDefaultExcludes( final String location ) throws IOException 877 { 878 InputStream resource = null; 879 boolean suppressExceptionOnClose = true; 880 Set<String> defaultExcludes = null; 881 882 try 883 { 884 resource = ProjectClassLoader.class.getResourceAsStream( location ); 885 886 if ( resource != null ) 887 { 888 final List<String> lines = IOUtils.readLines( resource, "UTF-8" ); 889 defaultExcludes = new HashSet<String>( lines.size() ); 890 891 for ( String line : lines ) 892 { 893 final String trimmed = line.trim(); 894 895 if ( trimmed.contains( "#" ) || StringUtils.isEmpty( trimmed ) ) 896 { 897 continue; 898 } 899 900 defaultExcludes.add( trimmed ); 901 } 902 } 903 904 suppressExceptionOnClose = false; 905 return defaultExcludes != null 906 ? Collections.unmodifiableSet( defaultExcludes ) : Collections.<String>emptySet(); 907 908 } 909 finally 910 { 911 try 912 { 913 if ( resource != null ) 914 { 915 resource.close(); 916 } 917 } 918 catch ( final IOException e ) 919 { 920 if ( !suppressExceptionOnClose ) 921 { 922 throw e; 923 } 924 } 925 } 926 } 927 928 }