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 <thekingant@users.sourceforge.net>
008     * Copyright (C) 2005 Joakim Erdfelt <joakim@erdfelt.net>
009     *
010     * Redistribution and use in source and binary forms, with or without
011     * modification, are permitted provided that the following conditions
012     * are met:
013     *
014     * 1. Redistributions of source code must retain the above copyright
015     *    notice, this list of conditions and the following disclaimer.
016     *
017     * 2. Redistributions in binary form must reproduce the above copyright
018     *    notice, this list of conditions and the following disclaimer in
019     *    the documentation and/or other materials provided with the
020     *    distribution.
021     *
022     * 3. The end-user documentation included with the redistribution, if
023     *    any, must include the following acknowlegement:
024     *       "This product includes software developed by the
025     *        Apache Software Foundation (http://www.apache.org/)."
026     *    Alternately, this acknowlegement may appear in the software itself,
027     *    if and wherever such third-party acknowlegements normally appear.
028     *
029     * 4. The names "Ant" and "Apache Software
030     *    Foundation" must not be used to endorse or promote products derived
031     *    from this software without prior written permission. For written
032     *    permission, please contact apache@apache.org.
033     *
034     * 5. Products derived from this software may not be called "Apache"
035     *    nor may "Apache" appear in their names without prior written
036     *    permission of the Apache Group.
037     *
038     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
039     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
040     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
041     * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
042     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
043     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
044     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
045     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
046     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
047     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
048     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
049     * SUCH DAMAGE.
050     * ====================================================================
051     *
052     * This software consists of voluntary contributions made by many
053     * individuals on behalf of the Apache Software Foundation.  For more
054     * information on the Apache Software Foundation, please see
055     * <http://www.apache.org/>.
056     */
057    
058    package net.sourceforge.cobertura.ant;
059    
060    import java.io.File;
061    import java.io.FileWriter;
062    import java.io.IOException;
063    import java.net.URL;
064    import java.net.URLClassLoader;
065    import java.util.LinkedList;
066    import java.util.List;
067    
068    import org.apache.tools.ant.AntClassLoader;
069    import org.apache.tools.ant.BuildException;
070    import org.apache.tools.ant.DirectoryScanner;
071    import org.apache.tools.ant.Project;
072    import org.apache.tools.ant.taskdefs.Java;
073    import org.apache.tools.ant.taskdefs.MatchingTask;
074    import org.apache.tools.ant.types.FileSet;
075    import org.apache.tools.ant.types.Path;
076    import org.apache.tools.ant.types.Reference;
077    import org.apache.tools.ant.util.IdentityMapper;
078    import org.apache.tools.ant.util.SourceFileScanner;
079    
080    public abstract class CommonMatchingTask extends MatchingTask
081    {
082    
083            private static final String LINESEP = System
084                            .getProperty("line.separator");
085    
086            final String className;
087            final List fileSets = new LinkedList();
088    
089            private Java java = null;
090            private File commandLineFile = null;
091            private FileWriter commandLineWriter = null;
092    
093            File toDir = null;
094    
095            public CommonMatchingTask(String className)
096            {
097                    this.className = className;
098            }
099    
100            private String getClassName()
101            {
102                    return className;
103            }
104    
105            protected void initArgs()
106            {
107                    try
108                    {
109                            commandLineFile = File.createTempFile("cobertura.", ".cmdline");
110                            commandLineFile.deleteOnExit();
111                            commandLineWriter = new FileWriter(commandLineFile);
112                    }
113                    catch (IOException ioe)
114                    {
115                            getProject().log(
116                                            "Error initializing commands file "
117                                                            + commandLineFile.getAbsolutePath(),
118                                            Project.MSG_ERR);
119                            throw new BuildException("Unable to initialize commands file.");
120                    }
121            }
122    
123            protected void addArg(String arg)
124            {
125                    try
126                    {
127                            commandLineWriter.write(arg + LINESEP);
128                    }
129                    catch (IOException ioe)
130                    {
131                            getProject().log(
132                                            "Error writing commands file "
133                                                            + commandLineFile.getAbsolutePath(),
134                                            Project.MSG_ERR);
135                            throw new BuildException("Unable to write to commands file.");
136                    }
137            }
138    
139            protected void saveArgs()
140            {
141                    try
142                    {
143                            commandLineWriter.flush();
144                            commandLineWriter.close();
145                    }
146                    catch (IOException ioe)
147                    {
148                            getProject().log(
149                                            "Error saving commands file "
150                                                            + commandLineFile.getAbsolutePath(),
151                                            Project.MSG_ERR);
152                            throw new BuildException("Unable to save the commands file.");
153                    }
154    
155                    /* point to commands file */
156                    getJava().createArg().setValue("-commandsfile");
157                    getJava().createArg().setValue(commandLineFile.getAbsolutePath());
158            }
159    
160            protected void unInitArgs()
161            {
162                    commandLineFile.delete();
163            }
164    
165            protected Java getJava()
166            {
167                    if (java == null)
168                    {
169                            java = (Java)getProject().createTask("java");
170                            java.setTaskName(getTaskName());
171                            java.setClassname(getClassName());
172                            java.setFork(true);
173                            java.setDir(getProject().getBaseDir());
174    
175                            /**
176                             * We replace %20 with a space character because, for some
177                             * reason, when we call Cobertura from within CruiseControl,
178                             * the classpath here contains %20's instead of spaces.  I
179                             * don't know if this is our problem, or CruiseControl, or
180                             * ant, but this seems to fix it.  --Mark
181                             */
182                            if (getClass().getClassLoader() instanceof AntClassLoader)
183                            {
184                                    String classpath = ((AntClassLoader)getClass()
185                                                    .getClassLoader()).getClasspath();
186                                    createClasspath().setPath(classpath.replaceAll("%20", " "));
187                            }
188                            else if (getClass().getClassLoader() instanceof URLClassLoader)
189                            {
190                                    URL[] earls = ((URLClassLoader)getClass().getClassLoader())
191                                                    .getURLs();
192                                    for (int i = 0; i < earls.length; i++)
193                                    {
194                                            String classpath = earls[i].getFile();
195                                            createClasspath().setPath(
196                                                            classpath.replaceAll("%20", " "));
197                                    }
198                            }
199                    }
200    
201                    return java;
202            }
203    
204            public void setTodir(File toDir)
205            {
206                    this.toDir = toDir;
207            }
208    
209            public Path createClasspath()
210            {
211                    return getJava().createClasspath().createPath();
212            }
213    
214            public void setClasspath(Path classpath)
215            {
216                    createClasspath().append(classpath);
217            }
218    
219            public void setClasspathRef(Reference r)
220            {
221                    createClasspath().setRefid(r);
222            }
223    
224            DirectoryScanner getDirectoryScanner(FileSet fileSet)
225            {
226                    return fileSet.getDirectoryScanner(getProject());
227            }
228    
229            String[] getIncludedFiles(FileSet fileSet)
230            {
231                    return getDirectoryScanner(fileSet).getIncludedFiles();
232            }
233    
234            String[] getExcludedFiles(FileSet fileSet)
235            {
236                    return getDirectoryScanner(fileSet).getExcludedFiles();
237            }
238    
239            String[] getFilenames(FileSet fileSet)
240            {
241                    String[] filesToReturn = getIncludedFiles(fileSet);
242    
243                    if (toDir != null)
244                    {
245                            IdentityMapper m = new IdentityMapper();
246                            SourceFileScanner sfs = new SourceFileScanner(this);
247                            filesToReturn = sfs.restrict(getIncludedFiles(fileSet), fileSet
248                                            .getDir(getProject()), toDir, m);
249                    }
250    
251                    return filesToReturn;
252            }
253    
254            String baseDir(FileSet fileSet)
255            {
256                    return fileSet.getDirectoryScanner(getProject()).getBasedir()
257                                    .toString();
258            }
259    
260            public void addFileset(FileSet fileSet)
261            {
262                    fileSets.add(fileSet);
263            }
264    }