blob: e4daa1e59b9e0b00badb803d537eba606b8d4eed [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
*******************************************************************************/
package org.eclipse.rap.test;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import org.eclipse.rap.rwt.testfixture.Fixture;
public class TestCollector {
private static final String JAR_EXTENSION = ".jar";
private static final String CLASS_EXTENSION = ".class";
private final URLClassLoader classLoader;
private final List<Thread> threads;
private final List<Throwable> problems;
private final List<Class<?>> tests;
TestCollector() {
classLoader = ( URLClassLoader )getClass().getClassLoader();
threads = new Vector<Thread>();
problems = new Vector<Throwable>();
tests = new Vector<Class<?>>();
}
Class<?>[] collectTests() {
initializeFixture();
try {
scanClasspath();
} catch( IOException ioe ) {
throw new RuntimeException( ioe );
}
return sortTests();
}
protected boolean acceptPath( File file ) {
return file.toString().contains( ".test" );
}
protected boolean acceptClassName( String className ) {
return className.endsWith( "_Test" );
}
private void scanClasspath() throws IOException {
URL[] urls = classLoader.getURLs();
for( int i = 0; i < urls.length; i++ ) {
File file = new File( URLDecoder.decode( urls[ i ].getFile(), "UTF-8" ) );
if( file.exists() && acceptPath( file ) ) {
runScan( file );
}
}
waitForScan();
}
private void waitForScan() {
while( !threads.isEmpty() ) {
Thread thread = threads.remove( 0 );
try {
thread.join();
} catch( InterruptedException ie ) {
throw new RuntimeException( ie );
}
}
handleProblems();
}
private void handleProblems() {
if( !problems.isEmpty() ) {
Iterator<Throwable> iterator = problems.iterator();
while( iterator.hasNext() ) {
Throwable exception = iterator.next();
exception.printStackTrace();
}
throw new RuntimeException( "Unable to start test suite, see stacktraces." );
}
}
private void runScan( final File file ) {
Thread thread = new Thread( new Runnable() {
public void run() {
try {
scan( file );
} catch( Throwable thr ) {
problems.add( thr );
}
}
} );
threads.add( thread );
thread.setDaemon( true );
thread.start();
}
private void scan( File file ) throws IOException {
if( file.getName().endsWith( JAR_EXTENSION ) ) {
scanJar( file );
} else {
scanDirectory( file, "", file.getPath() );
}
}
private void scanJar( File file ) throws IOException {
JarInputStream inputStream = new JarInputStream( new FileInputStream( file ), false );
try {
JarEntry jarEntry = inputStream.getNextJarEntry();
while( jarEntry != null ) {
if( isClassEntry( jarEntry ) ) {
String className = toClassName( jarEntry );
addClass( className );
}
jarEntry = inputStream.getNextJarEntry();
}
} finally {
inputStream.close();
}
}
private void scanDirectory( File file, String initialPackagePath, String rootDirectory ) {
if( file.isDirectory() ) {
String packagePath = computePackagePath( file, initialPackagePath, rootDirectory );
String[] files = file.list();
for( int i = 0; i < files.length; i++ ) {
File directory = new File( file, files[ i ] );
scanDirectory( directory, packagePath, rootDirectory );
}
} else if( isClassFile( file ) ) {
String className = toClassName( file, initialPackagePath );
addClass( className );
}
}
private void addClass( String className ) {
if( acceptClassName( className ) ) {
try {
tests.add( classLoader.loadClass( className ) );
} catch( ClassNotFoundException cnfe ) {
throw new RuntimeException( cnfe );
}
}
}
private Class<?>[] sortTests() {
Class<?>[] result = new Class[ tests.size() ];
tests.toArray( result );
Arrays.sort( result, new Comparator<Class<?>>() {
public int compare( Class<?> test1, Class<?> test2 ) {
return test1.getName().compareTo( test2.getName() );
}
} );
return result;
}
private static void initializeFixture() {
Fixture.setUp();
Fixture.tearDown();
}
private static String computePackagePath( File file, String initialPackagePath, String rootDir ) {
String result;
if( file.getPath().equals( rootDir ) ) {
result = "";
} else if( initialPackagePath.length() == 0 ) {
result = file.getName();
} else {
result = initialPackagePath + "." + file.getName();
}
return result;
}
private static String toClassName( JarEntry jarEntry ) {
String result = removeClassExtension( jarEntry.getName() );
result = result.replace( '/', '.' );
return result;
}
private static String toClassName( File file, String packageName ) {
String result = removeClassExtension( file.getName() );
if( packageName.length() > 0 ) {
result = packageName + "." + result;
}
return result;
}
private static String removeClassExtension( String name ) {
return name.substring( 0, name.lastIndexOf( CLASS_EXTENSION ) );
}
private static boolean isClassEntry( JarEntry jarEntry ) {
return ( !jarEntry.isDirectory() ) && jarEntry.getName().endsWith( CLASS_EXTENSION );
}
private static boolean isClassFile( File file ) {
return file.isFile() && file.getName().endsWith( CLASS_EXTENSION );
}
}