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 062package net.sourceforge.cobertura.ant; 063 064import java.io.File; 065import java.io.IOException; 066import java.net.URL; 067import java.net.URLClassLoader; 068import java.util.Iterator; 069import java.util.LinkedList; 070import java.util.List; 071 072import net.sourceforge.cobertura.util.CommandLineBuilder; 073import net.sourceforge.cobertura.util.StringUtil; 074 075import org.apache.tools.ant.AntClassLoader; 076import org.apache.tools.ant.BuildException; 077import org.apache.tools.ant.DirectoryScanner; 078import org.apache.tools.ant.Project; 079import org.apache.tools.ant.taskdefs.Java; 080import org.apache.tools.ant.taskdefs.MatchingTask; 081import org.apache.tools.ant.types.FileSet; 082import org.apache.tools.ant.types.AbstractFileSet; 083import org.apache.tools.ant.types.DirSet; 084import org.apache.tools.ant.types.Path; 085import org.apache.tools.ant.types.Reference; 086 087public 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}