vmassol 2002/11/11 10:26:44
Modified: src/plugins-build/cactus plugin.jelly project.xml
Added: src/plugins-build/cactus/src/java/org/apache/maven/cactus
CactusScanner.java CactusScannerTag.java
CactusTagLibrary.java
Log:
Added automatic discovery of Cactus test cases.
Revision Changes Path
1.12 +34 -5 jakarta-turbine-maven/src/plugins-build/cactus/plugin.jelly
Index: plugin.jelly
===================================================================
RCS file: /home/cvs/jakarta-turbine-maven/src/plugins-build/cactus/plugin.jelly,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- plugin.jelly 10 Nov 2002 16:10:34 -0000 1.11
+++ plugin.jelly 11 Nov 2002 18:26:44 -0000 1.12
@@ -5,7 +5,8 @@
Cactus plugin for Maven.
=============================================================================
-->
-<project xmlns:j="jelly:core" xmlns:dvsl="dvsl">
+<project xmlns:j="jelly:core" xmlns:dvsl="dvsl"
+ xmlns:cactus="jelly:org.apache.maven.cactus.CactusTagLibrary">
<!-- Import all the jelly scripts found in the maven.cactus.conf.dir
directory. They are jelly scripts to start/stop the different
@@ -129,10 +130,37 @@
<!--
========================================================================
+ Test initialization.
+ ========================================================================
+ -->
+ <goal name="cactus:test-init">
+
+ <path id="cactus.scanner.classpath">
+ <path refid="maven.dependency.classpath"/>
+ <pathElement location="${maven.build.dest}"/>
+ <pathElement location="${maven.cactus.classes.dir}"/>
+ <pathElement location="${plugin.getDependencyPath('cactus:cactus')}"/>
+ <pathElement location="${plugin.getDependencyPath('commons-logging')}"/>
+ <pathElement location="${plugin.getDependencyPath('junit')}"/>
+ <pathElement location="${plugin.getDependencyPath('commons-httpclient')}"/>
+ <pathElement location="${plugin.getDependencyPath('aspectj:aspectjrt')}"/>
+ <j:forEach var="lib" items="${pom.dependencies}">
+ <pathElement
location="${maven.repo.local}/${lib.getProjectId()}/jars/${lib.getArtifact()}"/>
+ </j:forEach>
+ </path>
+
+ <cactus:scanner var="cactusScanner" classpathref="cactus.scanner.classpath">
+ <fileset dir="${maven.cactus.classes.dir}" includes="**/*.class"/>
+ </cactus:scanner>
+
+ </goal>
+
+ <!--
+ ========================================================================
Start the Cactus tests using the <junit> Ant task.
========================================================================
-->
- <goal name="cactus:test">
+ <goal name="cactus:test" prereqs="cactus:test-init">
<mkdir dir="${maven.cactus.test.reportsDirectory}"/>
<mkdir dir="${maven.cactus.build.resources.dir}"/>
@@ -167,9 +195,10 @@
<pathelement path="${plugin.getDependencyPath('xml-apis')}"/>
<pathelement path="${plugin.getDependencyPath('xerces')}"/>
</classpath>
- <batchtest todir="${maven.cactus.test.reportsDirectory}">
- <fileset dir="${maven.cactus.src.dir}"/>
- </batchtest>
+
+ <j:forEach var="test" items="${cactusScanner.iterator()}">
+ <test name="${test}" todir="${maven.cactus.test.reportsDirectory}"/>
+ </j:forEach>
</junit>
1.18 +28 -2 jakarta-turbine-maven/src/plugins-build/cactus/project.xml
Index: project.xml
===================================================================
RCS file: /home/cvs/jakarta-turbine-maven/src/plugins-build/cactus/project.xml,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- project.xml 6 Nov 2002 22:08:21 -0000 1.17
+++ project.xml 11 Nov 2002 18:26:44 -0000 1.18
@@ -117,6 +117,30 @@
</properties>
</dependency>
+ <dependency>
+ <id>ant:ant</id>
+ <version>1.5</version>
+ <properties>
+ <classloader>root</classloader>
+ </properties>
+ </dependency>
+
+ <dependency>
+ <id>commons-jelly</id>
+ <version>SNAPSHOT</version>
+ <properties>
+ <classloader>root.maven</classloader>
+ </properties>
+ </dependency>
+
+ <dependency>
+ <id>commons-beanutils</id>
+ <version>1.4.1</version>
+ <properties>
+ <classloader>root.maven</classloader>
+ </properties>
+ </dependency>
+
<!-- Should not be needed but it seems there is a bug with Maven when junit
dependency is added -->
<dependency>
@@ -138,8 +162,10 @@
</dependency>
</dependencies>
-
- <build/>
+
+ <build>
+ <sourceDirectory>src/java</sourceDirectory>
+ </build>
</project>
1.1
jakarta-turbine-maven/src/plugins-build/cactus/src/java/org/apache/maven/cactus/CactusScanner.java
Index: CactusScanner.java
===================================================================
package org.apache.maven.cactus;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Maven" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Maven", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* ====================================================================
*/
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.cactus.AbstractTestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Modifier;
import java.lang.reflect.Method;
/**
* Process {@link FileSet} and extracts classes that are Cactus tests. A
* class is considered to be a Cactus Test Case if:
* <ul>
* <li>It extends {@link AbstractTestCase}</li>
* <li>It is not abstract</li>
* <li>It has at least one method that starts with "test", returns void and
* takes no parameters</li>
* </ul>
*
* @author <a href="mailto:vmassol@;apache.org">Vincent Massol</a>
* @version $Id: CactusScanner.java,v 1.1 2002/11/11 18:26:44 vmassol Exp $
*/
public class CactusScanner
{
private Log log = LogFactory.getLog(CactusScanner.class);
/**
* The Ant project
*/
private Project project;
/**
* Lists of Cactus class names that were found in the {@link FileSet}
*/
private List cactusTests = new ArrayList();
public void setProject(Project project)
{
this.project = project;
}
public void clear()
{
this.cactusTests.clear();
}
/**
* @return the list of valid Cactus test cases
*/
public Iterator iterator() {
return this.cactusTests.iterator();
}
/**
* Finds the Cactus test cases from a list of files.
*
* @param fs the list of files in which to look for Cactus tests
* @param classpath the classpaths needed to load the test classes
*/
public void processFileSet(FileSet fs, Path classpath)
{
DirectoryScanner ds = fs.getDirectoryScanner(this.project);
ds.scan();
String[] files = ds.getIncludedFiles();
for (int i = 0; i < files.length; i++)
{
// The path is supposed to be a relative path that matches the
// package directory structure. Thus we only need to replace
// the directory separator char by a "." and remove the file
// extension to get the FQN java class name.
// Is it a java class file?
if (files[i].endsWith(".class"))
{
String fqn = files[i]
.substring(0, files[i].length() - ".class".length())
.replace(File.separatorChar, '.');
log.debug("Found candidate class: [" + fqn + "]");
// Is it a Cactus test case?
if (isCactusTestCase(fqn, classpath))
{
log.debug("Found Cactus test case: [" + fqn + "]");
this.cactusTests.add(fqn);
}
}
}
}
/**
* @param className the fully qualified name of the class to check
* @param classpath the classpaths needed to load the test classes
* @return true if the class is a Cactus test case
*/
private boolean isCactusTestCase(String className, Path classpath)
{
Class clazz = loadClass(className, classpath);
if (clazz == null)
{
return false;
}
Class abstractTestCaseClass = null;
try
{
abstractTestCaseClass = clazz.getClassLoader().loadClass(
AbstractTestCase.class.getName());
}
catch (ClassNotFoundException e)
{
log.debug("Cannot load class", e);
return false;
}
if (!abstractTestCaseClass.isAssignableFrom(clazz))
{
log.debug("Not a Cactus test as class [" + className + "] does "
+ "not inherit from [" + AbstractTestCase.class.getName()
+ "]");
return false;
}
// the class must not be abstract
if (Modifier.isAbstract(clazz.getModifiers()))
{
log.debug("Not a Cactus test as class [" + className + "] is "
+ "abstract");
return false;
}
// the class must have at least one test, i.e. a public method
// starting with "test" and that takes no parameters
boolean hasTestMethod = false;
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getName().startsWith("test")
&& (methods[i].getReturnType() == Void.TYPE)
&& (methods[i].getParameterTypes().length == 0))
{
hasTestMethod = true;
break;
}
}
if (!hasTestMethod)
{
log.debug("Not a Cactus test as class [" + className + "] has "
+ "no method that start with \"test\", returns void and has "
+ "no parameters");
return false;
}
return true;
}
/**
* @param className the fully qualified name of the class to check
* @param classpath the classpaths needed to load the test classes
* @return the class object loaded by reflection from its string name
*/
private Class loadClass(String className, Path classpath)
{
Class clazz = null;
try
{
clazz = createClassLoader(classpath).loadClass(className);
}
catch (ClassNotFoundException e)
{
log.error("Failed to load class [" + className + "]", e);
}
return clazz;
}
/**
* @param classpath the classpaths needed to load the test classes
* @return a ClassLoader that has all the needed classpaths for loading
* the Cactus tests classes
*/
private ClassLoader createClassLoader(Path classpath)
{
URL[] urls = new URL[classpath.size()];
try
{
for (int i = 0; i < classpath.size(); i++)
{
log.debug("Adding ["
+ new File(classpath.list()[i]).toURL() + "] "
+ "to class loader classpath");
urls[i] = new File(classpath.list()[i]).toURL();
}
}
catch (MalformedURLException e)
{
log.debug("Invalid URL", e);
}
return new URLClassLoader(urls);
}
}
1.1
jakarta-turbine-maven/src/plugins-build/cactus/src/java/org/apache/maven/cactus/CactusScannerTag.java
Index: CactusScannerTag.java
===================================================================
package org.apache.maven.cactus;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Maven" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Maven", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* ====================================================================
*/
import org.apache.commons.jelly.TagSupport;
import org.apache.commons.jelly.XMLOutput;
import org.apache.commons.jelly.MissingAttributeException;
import org.apache.commons.jelly.tags.ant.TaskSource;
import org.apache.commons.jelly.tags.ant.AntTagLibrary;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
/**
* Cactus Jelly Tag that scans Ant FileSets and return a list of
* qualified class name that are Cactus TestCases (i.e.
* ServletTestCase, JspTestCase or FilterTestCase) or subclasses
* of Cactus TestCases.
*
* Note: This is useful when used with the <junit> Ant
* task for example, in order to find out the list of tests to
* execute.
*
* @author <a href="mailto:vmassol@;apache.org">Vincent Massol</a>
* @version $Id: CactusScannerTag.java,v 1.1 2002/11/11 18:26:44 vmassol Exp $
*/
public class CactusScannerTag extends TagSupport implements TaskSource
{
private Log log = LogFactory.getLog(CactusScannerTag.class);
/**
* The {@link CactusScanner} object that is exposed by this tag
* to the Jelly script.
*/
private CactusScanner cactusScanner;
/**
* We need to save the fileset as its XML attributes are set after the
* fileset object is created and thus we need to wait until it is
* completely initialized before being able to process it using
* {@link CactusScanner#processFileSet}.
*/
private FileSet fileset;
/**
* Nested <classpath> tag values. This is the classpath that will
* be used to dynamically load the test classes to decide whether they
* are Cactus tests or not.
*
* Note: There is a bug in Jelly and it does not work yet. ATM you should
* use the classpathref attribute instead.
*/
private Path classpath;
/**
* Reference to an Ant {@link Path} object containing the classpath.
* @see #classpath
*/
private String classpathref;
/**
* The Jelly variable (exposed to the Jelly script) that will
* contain a reference to the {@link CactusScanner} object.
*/
private String var;
public CactusScannerTag()
{
this.cactusScanner = new CactusScanner();
}
/**
* @see TagSupport#doTag(XMLOutput)
*/
public void doTag(XMLOutput xmlOutput) throws Exception
{
this.cactusScanner.setProject(AntTagLibrary.getProject(context));
this.cactusScanner.clear();
// run the body first to configure the task via nested tags
invokeBody(xmlOutput);
// Process the fileset to extract Cactus test cases. We need to pass
// the project dependency classpath as the CactusScanner will need
// to load the cactus test classes to decide whether they are Cactus
// test case or not and that needs the dependent jars to be in the
// classpath.
Path cp = this.classpath;
if (this.classpathref != null)
{
cp = (Path) AntTagLibrary.getProject(
context).getReference(this.classpathref);
}
this.cactusScanner.processFileSet(this.fileset, cp);
// output the cactusScanner
if ( var == null )
{
throw new MissingAttributeException( "var" );
}
context.setVariable(var, cactusScanner);
}
/**
* This method is called internally by Jelly to know on which object to
* call the {@link TaskSource#setTaskProperty} method.
*
* @see TaskSource#getTaskObject()
*/
public Object getTaskObject()
{
return this;
}
/**
* @see TaskSource#setTaskProperty(String, Object)
*/
public void setTaskProperty(String name, Object value) throws Exception
{
BeanUtils.setProperty(this, name, value);
}
/**
* Adds a set of files (nested fileset attribute). This method is called
* dynamically by {@link #setTaskProperty}.
*/
public void addFileset(FileSet set)
{
log.debug("Adding fileset [" + set + "]");
this.fileset = set;
}
public Path createClasspath()
{
log.debug("Creating classpath");
if (this.classpath == null)
{
this.classpath = new Path(AntTagLibrary.getProject(context));
}
return this.classpath.createPath();
}
public Path getClasspath()
{
return this.classpath;
}
public void setClasspath(Path classpath)
{
log.debug("Setting classpath [" + classpath + "]");
if (this.classpath == null)
{
this.classpath = classpath;
} else {
this.classpath.append(classpath);
}
}
public void setClasspathRef(Reference r)
{
createClasspath().setRefid(r);
}
/**
* @return the Cactus scanner object
*/
public CactusScanner getCactusScanner()
{
return this.cactusScanner;
}
/**
* Sets the name of the variable exported by this tag
*/
public void setVar(String var)
{
this.var = var;
}
public void setClasspathref(String classpathref)
{
this.classpathref = classpathref;
}
}
1.1
jakarta-turbine-maven/src/plugins-build/cactus/src/java/org/apache/maven/cactus/CactusTagLibrary.java
Index: CactusTagLibrary.java
===================================================================
package org.apache.maven.cactus;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Maven" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Maven", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* ====================================================================
*/
import org.apache.commons.jelly.TagLibrary;
/**
* Maven tag library for use in Jelly scripts.
*
* @author <a href="[EMAIL PROTECTED]">Vincent Massol</a>
* @version $Id: CactusTagLibrary.java,v 1.1 2002/11/11 18:26:44 vmassol Exp $
*/
public class CactusTagLibrary extends TagLibrary
{
public CactusTagLibrary()
{
registerTag("scanner", CactusScannerTag.class);
}
}
--
To unsubscribe, e-mail: <mailto:turbine-maven-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:turbine-maven-dev-help@;jakarta.apache.org>