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 private int forkedJVMDebugPort;
096
097 public CommonMatchingTask(String className)
098 {
099 this.className = className;
100 }
101
102 private String getClassName()
103 {
104 return className;
105 }
106
107 protected Java getJava()
108 {
109 if (java == null)
110 {
111 java = (Java)getProject().createTask("java");
112 java.setTaskName(getTaskName());
113 java.setClassname(getClassName());
114 java.setFork(true);
115 java.setDir(getProject().getBaseDir());
116 if (maxMemory != null)
117 java.setJvmargs("-Xmx" + maxMemory);
118 if (forkedJVMDebugPort > 0)
119 {
120 java.setJvmargs("-Xdebug");
121 java.setJvmargs("-Xrunjdwp:transport=dt_socket,address=" + forkedJVMDebugPort + ",server=y,suspend=y");
122 }
123
124 /**
125 * We replace %20 with a space character because, for some
126 * reason, when we call Cobertura from within CruiseControl,
127 * the classpath here contains %20's instead of spaces. I
128 * don't know if this is our problem, or CruiseControl, or
129 * ant, but this seems to fix it. --Mark
130 */
131 if (getClass().getClassLoader() instanceof AntClassLoader)
132 {
133 String classpath = ((AntClassLoader)getClass()
134 .getClassLoader()).getClasspath();
135 createClasspath().setPath(
136 StringUtil.replaceAll(classpath, "%20", " "));
137 }
138 else if (getClass().getClassLoader() instanceof URLClassLoader)
139 {
140 URL[] earls = ((URLClassLoader)getClass().getClassLoader())
141 .getURLs();
142 for (int i = 0; i < earls.length; i++)
143 {
144 String classpath = (new File(earls[i].getFile())).getAbsolutePath();
145 createClasspath().setPath(
146 StringUtil.replaceAll(classpath, "%20", " "));
147 }
148 }
149 }
150
151 return java;
152 }
153
154 protected void createArgumentsForFilesets( CommandLineBuilder builder) throws IOException {
155 Iterator iter = fileSets.iterator();
156 boolean filesetFound = false;
157 while (iter.hasNext())
158 {
159 AbstractFileSet fileSet = (AbstractFileSet)iter.next();
160
161 if (fileSet instanceof FileSet)
162 {
163 filesetFound = true;
164 builder.addArg("--basedir", baseDir(fileSet));
165 createArgumentsForFilenames( builder, getFilenames(fileSet));
166 }
167 else
168 {
169 if (filesetFound)
170 {
171 /*
172 * Once --basedir has been used, it cannot be undone without changes to the
173 * Main methods. So, any dirsets have to come before filesets.
174 */
175 throw new BuildException("Dirsets have to come before filesets");
176 }
177 createArgumentsForFilenames( builder, getDirectoryScanner(fileSet).getIncludedDirectories());
178 }
179 }
180 }
181
182 private void createArgumentsForFilenames( CommandLineBuilder builder, String[] filenames) throws IOException
183 {
184 for (int i = 0; i < filenames.length; i++)
185 {
186 getProject().log("Adding " + filenames[i] + " to list",
187 Project.MSG_VERBOSE);
188 builder.addArg(filenames[i]);
189 }
190 }
191
192 public Path createClasspath()
193 {
194 return getJava().createClasspath().createPath();
195 }
196
197 public void setClasspath(Path classpath)
198 {
199 createClasspath().append(classpath);
200 }
201
202 public void setClasspathRef(Reference r)
203 {
204 createClasspath().setRefid(r);
205 }
206
207 DirectoryScanner getDirectoryScanner(AbstractFileSet fileSet)
208 {
209 return fileSet.getDirectoryScanner(getProject());
210 }
211
212 String[] getIncludedFiles(AbstractFileSet fileSet)
213 {
214 return getDirectoryScanner(fileSet).getIncludedFiles();
215 }
216
217 String[] getExcludedFiles(FileSet fileSet)
218 {
219 return getDirectoryScanner(fileSet).getExcludedFiles();
220 }
221
222 String[] getFilenames(AbstractFileSet fileSet)
223 {
224 String[] filesToReturn = getIncludedFiles(fileSet);
225
226 return filesToReturn;
227 }
228
229 String baseDir(AbstractFileSet fileSet)
230 {
231 return fileSet.getDirectoryScanner(getProject()).getBasedir()
232 .toString();
233 }
234
235 public void addDirSet(DirSet dirSet)
236 {
237 fileSets.add(dirSet);
238 }
239
240 public void addFileset(FileSet fileSet)
241 {
242 fileSets.add(fileSet);
243 }
244
245 /**
246 * @param maxMemory Assumed to be something along the lines of
247 * 100M or 50K or 1G.
248 */
249 public void setMaxMemory(String maxMemory)
250 {
251 this.maxMemory = maxMemory != null ? maxMemory.trim() : null;
252 }
253
254 /**
255 * Used to debug the process that is forked to perform the operation.
256 * Setting this to a non-zero number will cause the process to open
257 * a debug port on that port number. It will suspend until a
258 * remote debugger is attached to the port.
259 *
260 * @param forkedJVMDebugPort
261 */
262 public void setForkedJVMDebugPort(int forkedJVMDebugPort)
263 {
264 this.forkedJVMDebugPort = forkedJVMDebugPort;
265 }
266
267
268 }