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 4613 2012-09-22 10:07:08Z schulte $ 029 * 030 */ 031package org.jomc.ant; 032 033import java.io.Closeable; 034import java.io.File; 035import java.io.FileOutputStream; 036import java.io.IOException; 037import java.io.InputStream; 038import java.io.OutputStream; 039import java.net.MalformedURLException; 040import java.net.URL; 041import java.net.URLClassLoader; 042import java.util.ArrayList; 043import java.util.Collections; 044import java.util.Enumeration; 045import java.util.HashSet; 046import java.util.Iterator; 047import java.util.List; 048import java.util.Set; 049import javax.xml.bind.JAXBElement; 050import javax.xml.bind.JAXBException; 051import org.apache.commons.io.IOUtils; 052import org.apache.commons.lang.StringUtils; 053import org.apache.tools.ant.Project; 054import org.apache.tools.ant.types.Path; 055import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; 056import org.jomc.modlet.ModelContext; 057import org.jomc.modlet.ModelContextFactory; 058import org.jomc.modlet.ModelException; 059import org.jomc.modlet.Modlet; 060import org.jomc.modlet.ModletObject; 061import org.jomc.modlet.Modlets; 062import org.jomc.modlet.ObjectFactory; 063import org.jomc.modlet.Schema; 064import org.jomc.modlet.Schemas; 065import org.jomc.modlet.Service; 066import org.jomc.modlet.Services; 067import org.jomc.util.ParseException; 068import org.jomc.util.TokenMgrError; 069import org.jomc.util.VersionParser; 070 071/** 072 * Class loader supporting JOMC resources backed by a project. 073 * 074 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 075 * @version $JOMC: ProjectClassLoader.java 4613 2012-09-22 10:07:08Z schulte $ 076 */ 077public 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 @Override 525 @IgnoreJRERequirement 526 public void close() throws IOException 527 { 528 for ( final Iterator<File> it = this.temporaryResources.iterator(); it.hasNext(); ) 529 { 530 final File temporaryResource = it.next(); 531 532 if ( temporaryResource.exists() && temporaryResource.delete() ) 533 { 534 it.remove(); 535 } 536 } 537 538 if ( Closeable.class.isAssignableFrom( ProjectClassLoader.class ) ) 539 { 540 super.close(); 541 } 542 } 543 544 /** 545 * Removes temporary resources. 546 * @throws Throwable if finalization fails. 547 */ 548 @Override 549 protected void finalize() throws Throwable 550 { 551 for ( final Iterator<File> it = this.temporaryResources.iterator(); it.hasNext(); ) 552 { 553 final File temporaryResource = it.next(); 554 555 if ( temporaryResource.exists() && !temporaryResource.delete() ) 556 { 557 temporaryResource.deleteOnExit(); 558 } 559 560 it.remove(); 561 } 562 563 super.finalize(); 564 } 565 566 private URL filterProviders( final URL resource ) throws IOException 567 { 568 InputStream in = null; 569 boolean suppressExceptionOnClose = true; 570 571 try 572 { 573 URL filteredResource = resource; 574 in = resource.openStream(); 575 final List<String> lines = IOUtils.readLines( in, "UTF-8" ); 576 final List<String> filteredLines = new ArrayList<String>( lines.size() ); 577 578 for ( String line : lines ) 579 { 580 if ( !this.getProviderExcludes().contains( line.trim() ) ) 581 { 582 filteredLines.add( line.trim() ); 583 } 584 else 585 { 586 this.getExcludedProviders().add( line.trim() ); 587 this.getProject().log( Messages.getMessage( "providerExclusion", resource.toExternalForm(), 588 line.trim() ), Project.MSG_DEBUG ); 589 590 } 591 } 592 593 if ( lines.size() != filteredLines.size() ) 594 { 595 OutputStream out = null; 596 final File tmpResource = File.createTempFile( this.getClass().getName(), ".rsrc" ); 597 this.temporaryResources.add( tmpResource ); 598 599 try 600 { 601 out = new FileOutputStream( tmpResource ); 602 IOUtils.writeLines( filteredLines, System.getProperty( "line.separator", "\n" ), out, "UTF-8" ); 603 suppressExceptionOnClose = false; 604 } 605 finally 606 { 607 try 608 { 609 if ( out != null ) 610 { 611 out.close(); 612 } 613 614 suppressExceptionOnClose = true; 615 } 616 catch ( final IOException e ) 617 { 618 if ( suppressExceptionOnClose ) 619 { 620 this.project.log( Messages.getMessage( e ), e, Project.MSG_ERR ); 621 } 622 else 623 { 624 throw e; 625 } 626 } 627 } 628 629 filteredResource = tmpResource.toURI().toURL(); 630 } 631 632 suppressExceptionOnClose = false; 633 return filteredResource; 634 } 635 finally 636 { 637 try 638 { 639 if ( in != null ) 640 { 641 in.close(); 642 } 643 } 644 catch ( final IOException e ) 645 { 646 if ( suppressExceptionOnClose ) 647 { 648 this.project.log( Messages.getMessage( e ), e, Project.MSG_ERR ); 649 } 650 else 651 { 652 throw e; 653 } 654 } 655 } 656 } 657 658 private URL filterModlets( final URL resource ) throws ModelException, IOException, JAXBException 659 { 660 InputStream in = null; 661 boolean suppressExceptionOnClose = true; 662 663 try 664 { 665 URL filteredResource = resource; 666 final ModelContext modelContext = ModelContextFactory.newInstance().newModelContext(); 667 in = resource.openStream(); 668 final JAXBElement<?> e = 669 (JAXBElement<?>) modelContext.createUnmarshaller( ModletObject.MODEL_PUBLIC_ID ).unmarshal( in ); 670 671 final Object o = e.getValue(); 672 Modlets modlets = null; 673 boolean filtered = false; 674 675 if ( o instanceof Modlets ) 676 { 677 modlets = (Modlets) o; 678 } 679 else if ( o instanceof Modlet ) 680 { 681 modlets = new Modlets(); 682 modlets.getModlet().add( (Modlet) o ); 683 } 684 685 if ( modlets != null ) 686 { 687 for ( final Iterator<Modlet> it = modlets.getModlet().iterator(); it.hasNext(); ) 688 { 689 final Modlet m = it.next(); 690 691 if ( this.getModletExcludes().contains( m.getName() ) ) 692 { 693 it.remove(); 694 filtered = true; 695 this.addExcludedModlet( m ); 696 this.getProject().log( Messages.getMessage( "modletExclusion", resource.toExternalForm(), 697 m.getName() ), Project.MSG_DEBUG ); 698 699 continue; 700 } 701 702 if ( this.filterModlet( m, resource.toExternalForm() ) ) 703 { 704 filtered = true; 705 } 706 } 707 708 if ( filtered ) 709 { 710 final File tmpResource = File.createTempFile( this.getClass().getName(), ".rsrc" ); 711 this.temporaryResources.add( tmpResource ); 712 modelContext.createMarshaller( ModletObject.MODEL_PUBLIC_ID ).marshal( 713 new ObjectFactory().createModlets( modlets ), tmpResource ); 714 715 filteredResource = tmpResource.toURI().toURL(); 716 } 717 } 718 719 suppressExceptionOnClose = false; 720 return filteredResource; 721 } 722 finally 723 { 724 try 725 { 726 if ( in != null ) 727 { 728 in.close(); 729 } 730 } 731 catch ( final IOException e ) 732 { 733 if ( suppressExceptionOnClose ) 734 { 735 this.project.log( Messages.getMessage( e ), e, Project.MSG_ERR ); 736 } 737 else 738 { 739 throw e; 740 } 741 } 742 } 743 } 744 745 private boolean filterModlet( final Modlet modlet, final String resourceInfo ) 746 { 747 boolean filteredSchemas = false; 748 boolean filteredServices = false; 749 750 if ( modlet.getSchemas() != null ) 751 { 752 final Schemas schemas = new Schemas(); 753 754 for ( Schema s : modlet.getSchemas().getSchema() ) 755 { 756 if ( !this.getSchemaExcludes().contains( s.getPublicId() ) ) 757 { 758 schemas.getSchema().add( s ); 759 } 760 else 761 { 762 this.getProject().log( Messages.getMessage( "schemaExclusion", resourceInfo, s.getPublicId() ), 763 Project.MSG_DEBUG ); 764 765 this.addExcludedSchema( s ); 766 filteredSchemas = true; 767 } 768 } 769 770 if ( filteredSchemas ) 771 { 772 modlet.setSchemas( schemas ); 773 } 774 } 775 776 if ( modlet.getServices() != null ) 777 { 778 final Services services = new Services(); 779 780 for ( Service s : modlet.getServices().getService() ) 781 { 782 if ( !this.getServiceExcludes().contains( s.getClazz() ) ) 783 { 784 services.getService().add( s ); 785 } 786 else 787 { 788 this.getProject().log( Messages.getMessage( "serviceExclusion", resourceInfo, s.getClazz() ), 789 Project.MSG_DEBUG ); 790 791 this.addExcludedService( s ); 792 filteredServices = true; 793 } 794 } 795 796 if ( filteredServices ) 797 { 798 modlet.setServices( services ); 799 } 800 } 801 802 return filteredSchemas || filteredServices; 803 } 804 805 private void addExcludedModlet( final Modlet modlet ) 806 { 807 try 808 { 809 final Modlet m = this.getExcludedModlets().getModlet( modlet.getName() ); 810 811 if ( m != null ) 812 { 813 if ( m.getVersion() != null && modlet.getVersion() != null 814 && VersionParser.compare( m.getVersion(), modlet.getVersion() ) < 0 ) 815 { 816 this.getExcludedModlets().getModlet().remove( m ); 817 this.getExcludedModlets().getModlet().add( modlet ); 818 } 819 } 820 else 821 { 822 this.getExcludedModlets().getModlet().add( modlet ); 823 } 824 } 825 catch ( final ParseException e ) 826 { 827 this.getProject().log( Messages.getMessage( e ), e, Project.MSG_WARN ); 828 } 829 catch ( final TokenMgrError e ) 830 { 831 this.getProject().log( Messages.getMessage( e ), e, Project.MSG_WARN ); 832 } 833 } 834 835 private void addExcludedSchema( final Schema schema ) 836 { 837 if ( this.getExcludedSchemas().getSchemaBySystemId( schema.getSystemId() ) == null ) 838 { 839 this.getExcludedSchemas().getSchema().add( schema ); 840 } 841 } 842 843 private void addExcludedService( final Service service ) 844 { 845 for ( int i = 0, s0 = this.getExcludedServices().getService().size(); i < s0; i++ ) 846 { 847 final Service s = this.getExcludedServices().getService().get( i ); 848 849 if ( s.getIdentifier().equals( service.getIdentifier() ) && s.getClazz().equals( service.getClazz() ) ) 850 { 851 return; 852 } 853 } 854 855 this.getExcludedServices().getService().add( service ); 856 } 857 858 private static Set<String> readDefaultExcludes( final String location ) throws IOException 859 { 860 InputStream resource = null; 861 boolean suppressExceptionOnClose = true; 862 Set<String> defaultExcludes = null; 863 864 try 865 { 866 resource = ProjectClassLoader.class.getResourceAsStream( location ); 867 868 if ( resource != null ) 869 { 870 final List<String> lines = IOUtils.readLines( resource, "UTF-8" ); 871 defaultExcludes = new HashSet<String>( lines.size() ); 872 873 for ( String line : lines ) 874 { 875 final String trimmed = line.trim(); 876 877 if ( trimmed.contains( "#" ) || StringUtils.isEmpty( trimmed ) ) 878 { 879 continue; 880 } 881 882 defaultExcludes.add( trimmed ); 883 } 884 } 885 886 suppressExceptionOnClose = false; 887 return defaultExcludes != null 888 ? Collections.unmodifiableSet( defaultExcludes ) : Collections.<String>emptySet(); 889 890 } 891 finally 892 { 893 try 894 { 895 if ( resource != null ) 896 { 897 resource.close(); 898 } 899 } 900 catch ( final IOException e ) 901 { 902 if ( !suppressExceptionOnClose ) 903 { 904 throw e; 905 } 906 } 907 } 908 } 909 910}