/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.utility.classes;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* The ClassSearcher provides utility methods to search classes.
*
* @author Marvin Froehlich (aka Qudus)
*/
public class ClassSearcher
{
/**
* Reads all classnames in a given folder and its subfolders and
* puts them into the List.
*
* @param baseFolder the folder from which to read the classes
* @param folder the folder from which to read the classes as a File object
* @param classes the List to put the classname into
*/
private static void findClassNamesFromFolder( String baseFolder, File folder, String[] packagePrefixes, ClassSearchCriterium crit, List< Class< ? >> classes )
{
for ( File file: folder.listFiles() )
{
if ( file.isDirectory() )
{
findClassNamesFromFolder( baseFolder, file, packagePrefixes, crit, classes );
}
else if ( file.getAbsolutePath().endsWith( ".class" ) )
{
final int lastIndex = Math.max( 0, file.getAbsolutePath().lastIndexOf( baseFolder ) ) + baseFolder.length();
String className = file.getAbsolutePath().substring( lastIndex ).replace( '\\', '/' ).replace( '/', '.' );
className = className.substring( 0, className.length() - 6 );
for ( String pkgName: packagePrefixes )
{
if ( className.startsWith( pkgName + "." ) )
{
try
{
Class< ? > clazz = Class.forName( className, false, ClassSearcher.class.getClassLoader() );
if ( crit.check( clazz ) )
classes.add( clazz );
}
catch ( ClassNotFoundException e )
{
e.printStackTrace();
}
break;
}
}
}
}
}
/**
* Reads all classnames in a given folder and its subfolders and
* puts them into the List.
*
* @param baseFolder the folder from which to read the classes
* @param classes the List to put the classname into
*/
private static void findClassNamesFromFolder( String folderName, String[] packagePrefixes, ClassSearchCriterium crit, List< Class< ? >> classes )
{
findClassNamesFromFolder( folderName + File.separator, new File( folderName ), packagePrefixes, crit, classes );
}
/**
* Reads all classes in given packages from a JarFile and puts their names
* into a List.
*
* @param jarFilename the filename of the jar
* @param classes the List to put the classnames into
*/
private static void findClassNamesFromJar( String jarFilename, String[] packagePrefixes, ClassSearchCriterium crit, List< Class< ? >> classes )
{
if ( !( new File( jarFilename ).exists() ) )
{
System.err.println( "Couldn't find jar file " + jarFilename );
return;
}
try
{
JarFile jar = new JarFile( jarFilename );
Enumeration< JarEntry > jarEntries = jar.entries();
while ( jarEntries.hasMoreElements() )
{
JarEntry jarEntry = jarEntries.nextElement();
for ( int i = 0; i < packagePrefixes.length; i++ )
{
if ( ( jarEntry.getName().startsWith( packagePrefixes[ i ] + "/" ) ) && ( jarEntry.getName().endsWith( ".class" ) ) )
{
String className = jarEntry.getName().replace( '/', '.' );
className = className.substring( 0, className.length() - 6 );
try
{
Class< ? > clazz = Class.forName( className, false, ClassSearcher.class.getClassLoader() );
if ( crit.check( clazz ) )
classes.add( clazz );
}
catch ( ClassNotFoundException e )
{
e.printStackTrace();
}
}
}
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
/**
* Reads all classnames from given packages into a List, that match certrain
* criteria.
*
* @param packagePrefixes dot separated package prefix names (like "org.xith3d.test")
* @param crit the Criterium to check for each class
*
* @return the filled up List
*/
public static List< Class< ? >> findClasses( String[] packagePrefixes, ClassSearchCriterium crit )
{
String[] packagePrifixes_slash = new String[ packagePrefixes.length ];
for ( int i = 0; i < packagePrefixes.length; i++ )
{
packagePrifixes_slash[ i ] = packagePrefixes[ i ].replace( '.', '/' );
}
List< Class< ? >> classes = new ArrayList< Class< ? >>();
String[] classPath = System.getProperty( "java.class.path" ).split( System.getProperty( "path.separator" ) );
for ( String cp: classPath )
{
if ( cp.endsWith( ".jar" ) )
{
findClassNamesFromJar( cp, packagePrifixes_slash, crit, classes );
}
else
{
findClassNamesFromFolder( cp, packagePrefixes, crit, classes );
}
}
Collections.sort( classes, new Comparator< Class< ? >>()
{
public int compare( Class< ? > c1, Class< ? > c2 )
{
// TODO Auto-generated method stub
return 0;
}
} );
return ( classes );
}
}