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