1package junit.runner;
2
3import java.io.File;
4import java.util.Enumeration;
5import java.util.Hashtable;
6import java.util.StringTokenizer;
7import java.util.Vector;
8
9/**
10 * An implementation of a TestCollector that consults the
11 * class path. It considers all classes on the class path
12 * excluding classes in JARs. It leaves it up to subclasses
13 * to decide whether a class is a runnable Test.
14 *
15 * @see TestCollector
16 */
17public abstract class ClassPathTestCollector implements TestCollector {
18
19	static final int SUFFIX_LENGTH= ".class".length();
20
21	public ClassPathTestCollector() {
22	}
23
24	public Enumeration collectTests() {
25		String classPath= System.getProperty("java.class.path");
26		Hashtable result = collectFilesInPath(classPath);
27		return result.elements();
28	}
29
30	public Hashtable collectFilesInPath(String classPath) {
31		Hashtable result= collectFilesInRoots(splitClassPath(classPath));
32		return result;
33	}
34
35	Hashtable collectFilesInRoots(Vector roots) {
36		Hashtable result= new Hashtable(100);
37		Enumeration e= roots.elements();
38		while (e.hasMoreElements())
39			gatherFiles(new File((String)e.nextElement()), "", result);
40		return result;
41	}
42
43	void gatherFiles(File classRoot, String classFileName, Hashtable result) {
44		File thisRoot= new File(classRoot, classFileName);
45		if (thisRoot.isFile()) {
46			if (isTestClass(classFileName)) {
47				String className= classNameFromFile(classFileName);
48				result.put(className, className);
49			}
50			return;
51		}
52		String[] contents= thisRoot.list();
53		if (contents != null) {
54			for (int i= 0; i < contents.length; i++)
55				gatherFiles(classRoot, classFileName+File.separatorChar+contents[i], result);
56		}
57	}
58
59	Vector splitClassPath(String classPath) {
60		Vector result= new Vector();
61		String separator= System.getProperty("path.separator");
62		StringTokenizer tokenizer= new StringTokenizer(classPath, separator);
63		while (tokenizer.hasMoreTokens())
64			result.addElement(tokenizer.nextToken());
65		return result;
66	}
67
68	protected boolean isTestClass(String classFileName) {
69		return
70			classFileName.endsWith(".class") &&
71			classFileName.indexOf('$') < 0 &&
72			classFileName.indexOf("Test") > 0;
73	}
74
75	protected String classNameFromFile(String classFileName) {
76		// convert /a/b.class to a.b
77		String s= classFileName.substring(0, classFileName.length()-SUFFIX_LENGTH);
78		String s2= s.replace(File.separatorChar, '.');
79		if (s2.startsWith("."))
80			return s2.substring(1);
81		return s2;
82	}
83}
84