package junit.runner;

import java.lang.reflect.*;
import junit.runner.*;
import junit.framework.*;

/**
 * An implementation of a TestCollector that loads
 * all classes on the class path and tests whether
 * it is assignable from Test or provides a static suite method.
 * @see TestCollector
 */
public class LoadingTestCollector extends ClassPathTestCollector {
	
	TestCaseClassLoader fLoader;
	
	public LoadingTestCollector() {
		fLoader= new TestCaseClassLoader();
	}
	
	protected boolean isTestClass(String classFileName) {	
		try {
			if (classFileName.endsWith(".class")) {
				Class testClass= classFromFile(classFileName);
				return (testClass != null) && isTestClass(testClass);
			}
		} 
		catch (ClassNotFoundException expected) {
		}
		catch (NoClassDefFoundError notFatal) {
		} 
		return false;
	}
	
	Class classFromFile(String classFileName) throws ClassNotFoundException {
		String className= classNameFromFile(classFileName);
		if (!fLoader.isExcluded(className))
			return fLoader.loadClass(className, false);
		return null;
	}
	
	boolean isTestClass(Class testClass) {
		if (hasSuiteMethod(testClass))
			return true;
		if (Test.class.isAssignableFrom(testClass) &&
			Modifier.isPublic(testClass.getModifiers()) &&
			hasPublicConstructor(testClass)) 
			return true;
		return false;
	}
	
	boolean hasSuiteMethod(Class testClass) {
		try {
			Method suiteMethod= testClass.getMethod(BaseTestRunner.SUITE_METHODNAME, new Class[0]);
	 	} catch(Exception e) {
	 		return false;
		}
		return true;
	}
	
	boolean hasPublicConstructor(Class testClass) {
		Class[] args= { String.class };
		Constructor c= null;
		try {
			c= testClass.getConstructor(args);
		} catch(Exception e) {
			return false;
		}
		return true;
	}

}
