001    /*
002     * The Apache Software License, Version 1.1
003     *
004     * Copyright (C) 2000-2002 The Apache Software Foundation.  All rights
005     * reserved.
006     * Copyright (C) 2003 jcoverage ltd.
007     * Copyright (C) 2005 Mark Doliner
008     * Copyright (C) 2005 Joakim Erdfelt
009     * Copyright (C) 2005 Grzegorz Lukasik
010     * Copyright (C) 2006 Srivathsan Varadarajan
011     * Copyright (C) 2008 Matt Cordes
012     * Copyright (C) 2008 John Lewis
013     *
014     * Redistribution and use in source and binary forms, with or without
015     * modification, are permitted provided that the following conditions
016     * are met:
017     *
018     * 1. Redistributions of source code must retain the above copyright
019     *    notice, this list of conditions and the following disclaimer.
020     *
021     * 2. Redistributions in binary form must reproduce the above copyright
022     *    notice, this list of conditions and the following disclaimer in
023     *    the documentation and/or other materials provided with the
024     *    distribution.
025     *
026     * 3. The end-user documentation included with the redistribution, if
027     *    any, must include the following acknowlegement:
028     *       "This product includes software developed by the
029     *        Apache Software Foundation (http://www.apache.org/)."
030     *    Alternately, this acknowlegement may appear in the software itself,
031     *    if and wherever such third-party acknowlegements normally appear.
032     *
033     * 4. The names "Ant" and "Apache Software
034     *    Foundation" must not be used to endorse or promote products derived
035     *    from this software without prior written permission. For written
036     *    permission, please contact apache@apache.org.
037     *
038     * 5. Products derived from this software may not be called "Apache"
039     *    nor may "Apache" appear in their names without prior written
040     *    permission of the Apache Group.
041     *
042     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
043     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
044     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
045     * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
046     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
047     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
048     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
049     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
050     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
051     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
052     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
053     * SUCH DAMAGE.
054     * ====================================================================
055     *
056     * This software consists of voluntary contributions made by many
057     * individuals on behalf of the Apache Software Foundation.  For more
058     * information on the Apache Software Foundation, please see
059     * <http://www.apache.org/>.
060     */
061    
062    package net.sourceforge.cobertura.ant;
063    
064    import java.io.File;
065    import java.io.IOException;
066    import java.net.URL;
067    import java.net.URLClassLoader;
068    import java.util.Iterator;
069    import java.util.LinkedList;
070    import java.util.List;
071    
072    import net.sourceforge.cobertura.util.CommandLineBuilder;
073    import net.sourceforge.cobertura.util.StringUtil;
074    
075    import org.apache.tools.ant.AntClassLoader;
076    import org.apache.tools.ant.BuildException;
077    import org.apache.tools.ant.DirectoryScanner;
078    import org.apache.tools.ant.Project;
079    import org.apache.tools.ant.taskdefs.Java;
080    import org.apache.tools.ant.taskdefs.MatchingTask;
081    import org.apache.tools.ant.types.FileSet;
082    import org.apache.tools.ant.types.AbstractFileSet;
083    import org.apache.tools.ant.types.DirSet;
084    import org.apache.tools.ant.types.Path;
085    import org.apache.tools.ant.types.Reference;
086    
087    public abstract class CommonMatchingTask extends MatchingTask
088    {
089    
090            final String className;
091            final List fileSets = new LinkedList();
092    
093            private Java java = null;
094            private String maxMemory = null;
095    
096            public CommonMatchingTask(String className)
097            {
098                    this.className = className;
099            }
100    
101            private String getClassName()
102            {
103                    return className;
104            }
105    
106            protected Java getJava()
107            {
108                    if (java == null)
109                    {
110                            java = (Java)getProject().createTask("java");
111                            java.setTaskName(getTaskName());
112                            java.setClassname(getClassName());
113                            java.setFork(true);
114                            java.setDir(getProject().getBaseDir());
115                            if (maxMemory != null)
116                                    java.setJvmargs("-Xmx" + maxMemory);
117    
118                            /**
119                             * We replace %20 with a space character because, for some
120                             * reason, when we call Cobertura from within CruiseControl,
121                             * the classpath here contains %20's instead of spaces.  I
122                             * don't know if this is our problem, or CruiseControl, or
123                             * ant, but this seems to fix it.  --Mark
124                             */
125                            if (getClass().getClassLoader() instanceof AntClassLoader)
126                            {
127                                    String classpath = ((AntClassLoader)getClass()
128                                                    .getClassLoader()).getClasspath();
129                                    createClasspath().setPath(
130                                                    StringUtil.replaceAll(classpath, "%20", " "));
131                            }
132                            else if (getClass().getClassLoader() instanceof URLClassLoader)
133                            {
134                                    URL[] earls = ((URLClassLoader)getClass().getClassLoader())
135                                                    .getURLs();
136                                    for (int i = 0; i < earls.length; i++)
137                                    {
138                                            String classpath = (new File(earls[i].getFile())).getAbsolutePath();
139                                            createClasspath().setPath(
140                                                            StringUtil.replaceAll(classpath, "%20", " "));
141                                    }
142                            }
143                    }
144    
145                    return java;
146            }
147    
148            protected void createArgumentsForFilesets( CommandLineBuilder builder) throws IOException {
149                    Iterator iter = fileSets.iterator();
150                    boolean filesetFound = false;
151                    while (iter.hasNext())
152                    {
153                            AbstractFileSet fileSet = (AbstractFileSet)iter.next();
154    
155                            if (fileSet instanceof FileSet)
156                            {
157                                    filesetFound = true;
158                                    builder.addArg("--basedir", baseDir(fileSet));
159                                    createArgumentsForFilenames( builder, getFilenames(fileSet));
160                            }
161                            else
162                            {
163                                    if (filesetFound)
164                                    {
165                                            /*
166                                             * Once --basedir has been used, it cannot be undone without changes to the
167                                             * Main methods.   So, any dirsets have to come before filesets.
168                                             */
169                                            throw new BuildException("Dirsets have to come before filesets");
170                                    }
171                                    createArgumentsForFilenames( builder, getDirectoryScanner(fileSet).getIncludedDirectories());
172                            }
173                    }
174            }
175    
176            private void createArgumentsForFilenames( CommandLineBuilder builder, String[] filenames) throws IOException
177            {
178                    for (int i = 0; i < filenames.length; i++)
179                    {
180                            getProject().log("Adding " + filenames[i] + " to list",
181                                            Project.MSG_VERBOSE);
182                            builder.addArg(filenames[i]);
183                    }
184            }
185    
186            public Path createClasspath()
187            {
188                    return getJava().createClasspath().createPath();
189            }
190    
191            public void setClasspath(Path classpath)
192            {
193                    createClasspath().append(classpath);
194            }
195    
196            public void setClasspathRef(Reference r)
197            {
198                    createClasspath().setRefid(r);
199            }
200    
201            DirectoryScanner getDirectoryScanner(AbstractFileSet fileSet)
202            {
203                    return fileSet.getDirectoryScanner(getProject());
204            }
205    
206            String[] getIncludedFiles(AbstractFileSet fileSet)
207            {
208                    return getDirectoryScanner(fileSet).getIncludedFiles();
209            }
210    
211            String[] getExcludedFiles(FileSet fileSet)
212            {
213                    return getDirectoryScanner(fileSet).getExcludedFiles();
214            }
215    
216            String[] getFilenames(AbstractFileSet fileSet)
217            {
218                    String[] filesToReturn = getIncludedFiles(fileSet);
219    
220                    return filesToReturn;
221            }
222    
223            String baseDir(AbstractFileSet fileSet)
224            {
225                    return fileSet.getDirectoryScanner(getProject()).getBasedir()
226                                    .toString();
227            }
228    
229            public void addDirSet(DirSet dirSet)
230            {
231                    fileSets.add(dirSet);
232            }
233            
234            public void addFileset(FileSet fileSet)
235            {
236                    fileSets.add(fileSet);
237            }
238    
239            /**
240             * @param maxMemory Assumed to be something along the lines of
241             *        100M or 50K or 1G.
242             */
243            public void setMaxMemory(String maxMemory)
244            {
245                    this.maxMemory = maxMemory != null ? maxMemory.trim() : null;
246            }
247    }