EMMA Coverage Report (generated Thu Mar 15 07:05:13 CET 2012)
[all classes][org.jomc.ant]

COVERAGE SUMMARY FOR SOURCE FILE [ProjectClassLoader.java]

nameclass, %method, %block, %line, %
ProjectClassLoader.java100% (3/3)95%  (35/37)67%  (767/1141)66%  (173.6/262)

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)94%  (29/31)69%  (725/1048)70%  (167.6/241)
addExcludedModlet (Modlet): void 0%   (0/1)0%   (0/58)0%   (0/12)
jdk7Close (): void 0%   (0/1)0%   (0/38)0%   (0/9)
findResource (String): URL 100% (1/1)28%  (18/65)26%  (5/19)
filterProviders (URL): URL 100% (1/1)60%  (114/191)61%  (23.9/39)
filterModlets (URL): URL 100% (1/1)63%  (108/172)70%  (28.7/41)
readDefaultExcludes (String): Set 100% (1/1)76%  (62/82)70%  (15.4/22)
filterModlet (Modlet, String): boolean 100% (1/1)88%  (115/130)90%  (20.6/23)
finalize (): void 100% (1/1)92%  (23/25)88%  (7/8)
close (): void 100% (1/1)93%  (25/27)88%  (7/8)
<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)
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 4256 2012-02-13 06:32:10Z schulte2005 $
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.lang.reflect.InvocationTargetException;
40import java.net.MalformedURLException;
41import java.net.URL;
42import java.net.URLClassLoader;
43import java.util.ArrayList;
44import java.util.Collections;
45import java.util.Enumeration;
46import java.util.HashSet;
47import java.util.Iterator;
48import java.util.List;
49import java.util.Set;
50import javax.xml.bind.JAXBElement;
51import javax.xml.bind.JAXBException;
52import org.apache.commons.io.IOUtils;
53import org.apache.commons.lang.StringUtils;
54import org.apache.tools.ant.Project;
55import org.apache.tools.ant.types.Path;
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:schulte2005@users.sourceforge.net">Christian Schulte</a>
75 * @version $JOMC: ProjectClassLoader.java 4256 2012-02-13 06:32:10Z schulte2005 $
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    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}

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