KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cactus > integration > maven > CactusScanner


1 /*
2  * ========================================================================
3  *
4  * Copyright 2001-2003 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * ========================================================================
19  */

20 package org.apache.cactus.integration.maven;
21
22 import org.apache.tools.ant.DirectoryScanner;
23 import org.apache.tools.ant.Project;
24 import org.apache.tools.ant.types.FileSet;
25 import org.apache.tools.ant.types.Path;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import java.util.List JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.io.File JavaDoc;
33 import java.net.MalformedURLException JavaDoc;
34 import java.net.URLClassLoader JavaDoc;
35 import java.net.URL JavaDoc;
36 import java.lang.reflect.Modifier JavaDoc;
37 import java.lang.reflect.Method JavaDoc;
38
39 import junit.framework.TestCase;
40
41 /**
42  * Process {@link FileSet} and extracts classes that are Cactus tests. As
43  * a Cactus test can be a simple JUnit test case wrapped in a Cactus suite,
44  * it is very difficult to find out only Cactus tests. Thus, in this version,
45  * we are only finding JUnit tests.
46  *
47  * A class is considered to be a JUnit Test Case if:
48  * <ul>
49  * <li>It extends {@link TestCase}</li>
50  * <li>It is not abstract</li>
51  * <li>It has at least one method that starts with "test", returns void and
52  * takes no parameters</li>
53  * </ul>
54  *
55  * @version $Id: CactusScanner.java,v 1.3 2004/02/29 16:34:44 vmassol Exp $
56  */

57 public class CactusScanner
58 {
59     /**
60      * Log instance.
61      */

62     private Log log = LogFactory.getLog(CactusScanner.class);
63
64     /**
65      * The Ant project
66      */

67     private Project project;
68
69     /**
70      * Lists of Cactus class names that were found in the {@link FileSet}
71      */

72     private List JavaDoc cactusTests = new ArrayList JavaDoc();
73
74     /**
75      * @param theProject the Ant project that is currently executing
76      */

77     public void setProject(Project theProject)
78     {
79         this.project = theProject;
80     }
81
82     /**
83      * Remove all Cactus class names that were found in the {@link Fileset}
84      */

85     public void clear()
86     {
87         this.cactusTests.clear();
88     }
89
90     /**
91      * @return the list of valid Cactus test cases
92      */

93     public Iterator JavaDoc iterator()
94     {
95         return this.cactusTests.iterator();
96     }
97
98     /**
99      * Finds the Cactus test cases from a list of files.
100      *
101      * @param theFileset the list of files in which to look for Cactus tests
102      * @param theClasspath the classpaths needed to load the test classes
103      */

104     public void processFileSet(FileSet theFileset, Path theClasspath)
105     {
106         DirectoryScanner ds = theFileset.getDirectoryScanner(this.project);
107         ds.scan();
108         String JavaDoc[] files = ds.getIncludedFiles();
109
110         for (int i = 0; i < files.length; i++)
111         {
112             // The path is supposed to be a relative path that matches the
113
// package directory structure. Thus we only need to replace
114
// the directory separator char by a "." and remove the file
115
// extension to get the FQN java class name.
116

117             // Is it a java class file?
118
if (files[i].endsWith(".class"))
119             {
120                 String JavaDoc fqn = files[i]
121                     .substring(0, files[i].length() - ".class".length())
122                     .replace(File.separatorChar, '.');
123
124                 log.debug("Found candidate class: [" + fqn + "]");
125
126                 // Is it a Cactus test case?
127
if (isJUnitTestCase(fqn, theClasspath))
128                 {
129                     log.debug("Found Cactus test case: [" + fqn + "]");
130                     this.cactusTests.add(fqn);
131                 }
132             }
133         }
134     }
135
136     /**
137      * @param theClassName the fully qualified name of the class to check
138      * @param theClasspath the classpaths needed to load the test classes
139      * @return true if the class is a JUnit test case
140      */

141     private boolean isJUnitTestCase(String JavaDoc theClassName, Path theClasspath)
142     {
143         Class JavaDoc clazz = loadClass(theClassName, theClasspath);
144         if (clazz == null)
145         {
146             return false;
147         }
148
149         Class JavaDoc testCaseClass = null;
150         try
151         {
152             testCaseClass = clazz.getClassLoader().loadClass(
153                 TestCase.class.getName());
154         }
155         catch (ClassNotFoundException JavaDoc e)
156         {
157             log.debug("Cannot load class", e);
158             return false;
159         }
160
161         if (!testCaseClass.isAssignableFrom(clazz))
162         {
163             log.debug("Not a JUnit test as class [" + theClassName + "] does "
164                 + "not inherit from [" + TestCase.class.getName()
165                 + "]");
166             return false;
167         }
168
169         // the class must not be abstract
170
if (Modifier.isAbstract(clazz.getModifiers()))
171         {
172             log.debug("Not a JUnit test as class [" + theClassName + "] is "
173                 + "abstract");
174             return false;
175         }
176
177         // the class must have at least one test, i.e. a public method
178
// starting with "test" and that takes no parameters
179
boolean hasTestMethod = false;
180         Method JavaDoc[] methods = clazz.getMethods();
181         for (int i = 0; i < methods.length; i++)
182         {
183             if (methods[i].getName().startsWith("test")
184                 && (methods[i].getReturnType() == Void.TYPE)
185                 && (methods[i].getParameterTypes().length == 0))
186             {
187                 hasTestMethod = true;
188                 break;
189             }
190         }
191
192         if (!hasTestMethod)
193         {
194             log.debug("Not a JUnit test as class [" + theClassName + "] has "
195                 + "no method that start with \"test\", returns void and has "
196                 + "no parameters");
197             return false;
198         }
199
200         return true;
201     }
202
203     /**
204      * @param theClassName the fully qualified name of the class to check
205      * @param theClasspath the classpaths needed to load the test classes
206      * @return the class object loaded by reflection from its string name
207      */

208     private Class JavaDoc loadClass(String JavaDoc theClassName, Path theClasspath)
209     {
210         Class JavaDoc clazz = null;
211         try
212         {
213             clazz = createClassLoader(theClasspath).loadClass(theClassName);
214         }
215         catch (ClassNotFoundException JavaDoc e)
216         {
217             log.error("Failed to load class [" + theClassName + "]", e);
218         }
219         return clazz;
220     }
221
222     /**
223      * @param theClasspath the classpaths needed to load the test classes
224      * @return a ClassLoader that has all the needed classpaths for loading
225      * the Cactus tests classes
226      */

227     private ClassLoader JavaDoc createClassLoader(Path theClasspath)
228     {
229         URL JavaDoc[] urls = new URL JavaDoc[theClasspath.size()];
230
231         try
232         {
233             for (int i = 0; i < theClasspath.size(); i++)
234             {
235                 log.debug("Adding ["
236                     + new File JavaDoc(theClasspath.list()[i]).toURL() + "] "
237                     + "to class loader classpath");
238                 urls[i] = new File JavaDoc(theClasspath.list()[i]).toURL();
239             }
240         }
241         catch (MalformedURLException JavaDoc e)
242         {
243             log.debug("Invalid URL", e);
244         }
245
246         return new URLClassLoader JavaDoc(urls);
247     }
248 }
249
Popular Tags