EMMA Coverage Report (generated Wed Mar 26 15:19:37 CET 2014)
[all classes][org.jomc.ant]

COVERAGE SUMMARY FOR SOURCE FILE [ProjectClassLoader.java]

nameclass, %method, %block, %line, %
ProjectClassLoader.java100% (3/3)97%  (35/36)73%  (769/1053)71%  (183.2/257)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ProjectClassLoader$2100% (1/1)100% (3/3)34%  (21/62)20%  (3/15)
nextElement (): URL 100% (1/1)16%  (8/49)8%   (1/13)
ProjectClassLoader$2 (ProjectClassLoader, Enumeration): void 100% (1/1)100% (9/9)100% (1/1)
hasMoreElements (): boolean 100% (1/1)100% (4/4)100% (1/1)
     
class ProjectClassLoader$1100% (1/1)100% (3/3)68%  (21/31)50%  (3/6)
nextElement (): URL 100% (1/1)44%  (8/18)25%  (1/4)
ProjectClassLoader$1 (ProjectClassLoader, Enumeration): void 100% (1/1)100% (9/9)100% (1/1)
hasMoreElements (): boolean 100% (1/1)100% (4/4)100% (1/1)
     
class ProjectClassLoader100% (1/1)97%  (29/30)76%  (727/960)75%  (177.2/236)
addExcludedModlet (Modlet): void 0%   (0/1)0%   (0/58)0%   (0/12)
findResource (String): URL 100% (1/1)28%  (18/65)26%  (5/19)
finalize (): void 100% (1/1)40%  (10/25)38%  (3/8)
filterModlets (URL): URL 100% (1/1)70%  (111/158)74%  (30.4/41)
filterProviders (URL): URL 100% (1/1)75%  (121/161)75%  (30.8/41)
readDefaultExcludes (String): Set 100% (1/1)86%  (65/76)79%  (17.3/22)
filterModlet (Modlet, String): boolean 100% (1/1)88%  (115/130)90%  (22.6/25)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
ProjectClassLoader (Project, Path): void 100% (1/1)100% (40/40)100% (7/7)
access$000 (ProjectClassLoader, URL): URL 100% (1/1)100% (4/4)100% (1/1)
access$100 (ProjectClassLoader, URL): URL 100% (1/1)100% (4/4)100% (1/1)
addExcludedSchema (Schema): void 100% (1/1)100% (13/13)100% (3/3)
addExcludedService (Service): void 100% (1/1)100% (39/39)100% (6/6)
close (): void 100% (1/1)100% (27/27)100% (8/8)
findResources (String): Enumeration 100% (1/1)100% (31/31)100% (7/7)
getDefaultModletExcludes (): Set 100% (1/1)100% (3/3)100% (1/1)
getDefaultProviderExcludes (): Set 100% (1/1)100% (3/3)100% (1/1)
getDefaultSchemaExcludes (): Set 100% (1/1)100% (3/3)100% (1/1)
getDefaultServiceExcludes (): Set 100% (1/1)100% (3/3)100% (1/1)
getExcludedModlets (): Modlets 100% (1/1)100% (11/11)100% (3/3)
getExcludedProviders (): Set 100% (1/1)100% (11/11)100% (3/3)
getExcludedSchemas (): Schemas 100% (1/1)100% (11/11)100% (3/3)
getExcludedServices (): Services 100% (1/1)100% (11/11)100% (3/3)
getModletExcludes (): Set 100% (1/1)100% (11/11)100% (3/3)
getModletResourceLocations (): Set 100% (1/1)100% (11/11)100% (3/3)
getProject (): Project 100% (1/1)100% (3/3)100% (1/1)
getProviderExcludes (): Set 100% (1/1)100% (11/11)100% (3/3)
getProviderResourceLocations (): Set 100% (1/1)100% (11/11)100% (3/3)
getSchemaExcludes (): Set 100% (1/1)100% (11/11)100% (3/3)
getServiceExcludes (): Set 100% (1/1)100% (11/11)100% (3/3)

1/*
2 *   Copyright (C) Christian Schulte, 2005-206
3 *   All rights reserved.
4 *
5 *   Redistribution and use in source and binary forms, with or without
6 *   modification, are permitted provided that the following conditions
7 *   are met:
8 *
9 *     o Redistributions of source code must retain the above copyright
10 *       notice, this list of conditions and the following disclaimer.
11 *
12 *     o Redistributions in binary form must reproduce the above copyright
13 *       notice, this list of conditions and the following disclaimer in
14 *       the documentation and/or other materials provided with the
15 *       distribution.
16 *
17 *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 *   $JOMC: ProjectClassLoader.java 4613 2012-09-22 10:07:08Z schulte $
29 *
30 */
31package org.jomc.ant;
32 
33import java.io.Closeable;
34import java.io.File;
35import java.io.FileOutputStream;
36import java.io.IOException;
37import java.io.InputStream;
38import java.io.OutputStream;
39import java.net.MalformedURLException;
40import java.net.URL;
41import java.net.URLClassLoader;
42import java.util.ArrayList;
43import java.util.Collections;
44import java.util.Enumeration;
45import java.util.HashSet;
46import java.util.Iterator;
47import java.util.List;
48import java.util.Set;
49import javax.xml.bind.JAXBElement;
50import javax.xml.bind.JAXBException;
51import org.apache.commons.io.IOUtils;
52import org.apache.commons.lang.StringUtils;
53import org.apache.tools.ant.Project;
54import org.apache.tools.ant.types.Path;
55import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
56import org.jomc.modlet.ModelContext;
57import org.jomc.modlet.ModelContextFactory;
58import org.jomc.modlet.ModelException;
59import org.jomc.modlet.Modlet;
60import org.jomc.modlet.ModletObject;
61import org.jomc.modlet.Modlets;
62import org.jomc.modlet.ObjectFactory;
63import org.jomc.modlet.Schema;
64import org.jomc.modlet.Schemas;
65import org.jomc.modlet.Service;
66import org.jomc.modlet.Services;
67import org.jomc.util.ParseException;
68import org.jomc.util.TokenMgrError;
69import org.jomc.util.VersionParser;
70 
71/**
72 * Class loader supporting JOMC resources backed by a project.
73 *
74 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
75 * @version $JOMC: ProjectClassLoader.java 4613 2012-09-22 10:07:08Z schulte $
76 */
77public class ProjectClassLoader extends URLClassLoader
78{
79 
80    /** Constant to prefix relative resource names with. */
81    private static final String ABSOLUTE_RESOURCE_NAME_PREFIX = "/org/jomc/ant/";
82 
83    /** Empty URL array. */
84    private static final URL[] NO_URLS =
85    {
86    };
87 
88    /** Set of modlet names to exclude. */
89    private Set<String> modletExcludes;
90 
91    /** Excluded modlets. */
92    private Modlets excludedModlets;
93 
94    /** Set of service class names to exclude. */
95    private Set<String> serviceExcludes;
96 
97    /** Excluded services. */
98    private Services excludedServices;
99 
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}

[all classes][org.jomc.ant]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov