Packages loader for Java

nikelin 0 Tallied Votes 407 Views Share

Simple package loader to load all packages contents from directory-based or from JAR-compressed class path entry.

import org.apache.log4j.Logger;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
* Packages loading tool
* 
* @author nikelin
*/
public class PackageLoader {
    private static final Logger log = Logger.getLogger( PackageLoader.class );

    public <T> Class<T>[] getClasses( String pkgName ) throws PackageLoaderException {
        return this.getClasses( pkgName, new InterfacesFilter( new Class[] {} ) );
    }

    public <T> Class<T>[] getClasses( String pkgName, Filter filter ) throws PackageLoaderException {
        Set<Class<T>> classes = new HashSet<Class<T>>();
        for ( String path : System.getProperty("java.class.path").split(":") ) {
            try {
                Class<T>[] collectionPart = this.getClasses( path, pkgName, filter );
                if ( collectionPart != null ) {
                    classes.addAll( Arrays.asList( collectionPart ) );
                }
            } catch ( PackageLoaderException e ) {
                continue;
            }
        }

        return classes.toArray( new Class[classes.size()] );
    }

    public <T> Class<T>[] getClasses( String path, String pkgName ) throws PackageLoaderException {
        return this.getClasses( path, pkgName, new InterfacesFilter( new Class[] {}  ) );
    }

    public <T> Class<T>[] getClasses( String path, String pkgName, Filter filter ) throws PackageLoaderException {
        if ( path.endsWith(".jar") ) {
            return this.getClassesFromJar( path, pkgName, filter );
        } else {
            return this.getClassesFromIdle( path, pkgName, filter );
        }
    }

    protected <T> Class<T>[] getClassesFromJar( String path, String pkgName, Filter filter ) throws PackageLoaderException {
        try {
            String folderName = this.convertToFolderName( pkgName );

            JarFile file = new JarFile( path );
            Enumeration entries = file.entries();
            List<URL> targetEntries = new ArrayList<URL>() ;
            while( entries.hasMoreElements() ) {
                JarEntry testing = (JarEntry) entries.nextElement();

                if ( testing.getName().contains(folderName) &&
                        !testing.isDirectory() ) {
                    if ( testing.getName().endsWith(".class") )  {
                        targetEntries.add( new URL("jar", path + "!/",  testing.getName() ) );
                    }
                }
            }

            List<Class<T>> result = new ArrayList<Class<T>>();
            URLClassLoader loader = new URLClassLoader( targetEntries.toArray( new URL[targetEntries.size()]) );
            for ( URL classUrl : targetEntries ) {
                String clsName = ( classUrl.getPath()
                                        .substring( 0 , classUrl.getPath().lastIndexOf(".") ) )
                                        .replaceAll(".class", "")
                                        .replaceAll( "/", "." );
                Class<T> clazz;
                try {
                    clazz = (Class<T>) loader.loadClass( clsName );
                    if ( filter != null && filter.filter(clazz) ) {
                        result.add(clazz);
                    }
                } catch ( Throwable e ) {
                    log.info( "Unable to load class: " + clsName, e  );
                }
            }

            return result.toArray( new Class[result.size()] );
        } catch ( Throwable e ) {
            log.error( e.getMessage(), e );
            throw new PackageLoaderException( e.getMessage() );
        }
    }

    protected <T> Class<T>[] getClassesFromIdle( String path, String pkgName, Filter filter ) throws PackageLoaderException {
        try {
            List<Class<T>> classes = new ArrayList<Class<T>>();
            String folderName = this.convertToFolderName( pkgName);

            File folder = Registry.getResourcesLoader().loadFile( folderName );
            if (  folder == null || !folder.exists() || !folder.canRead() || ( !folder.isDirectory() && !folder.getPath().endsWith(".jar") ) ) {
                return null;
            }

            if ( folder.getPath().endsWith(".jar") ) {
                classes.addAll( (List) Arrays.asList( this.getClassesFromJar( path, pkgName, filter ) ) );
            } else {
                String[] clsEntries = folder.list();
                for ( int i = 0; i < clsEntries.length; i++ ) {
                    File clsFile = new File( folder.getPath() + File.separator + clsEntries[i] );

                    if ( clsFile.isDirectory() ) {
                        continue;
                    }

                    String className = clsEntries[i].substring( 0, clsEntries[i].indexOf(".") );

                    Class<T> clazz = (Class<T>) ClassLoader.getSystemClassLoader().loadClass( pkgName + "." + className );
                    if ( filter != null && !filter.filter(clazz) ) {
                        continue;
                    }

                    classes.add( clazz );
                }
            }

            return classes.toArray( new Class[ classes.size() ] );
        } catch ( PackageLoaderException e ) {
            log.error( e.getMessage(), e );
            throw e;
        } catch ( Throwable e ) {
            log.error( e.getMessage(), e );
            throw new PackageLoaderException( e.getMessage() );
        }
    }

    private String convertToFolderName( String packageName ) {
        return packageName.replace(".", File.separator );
    }

}

class PackageLoaderException extends Exception {

    public PackageLoaderException( String message ) {
        super(message);
    }
}
NormR1 563 Posting Sage Team Colleague

When I try to compile I get:

Running: D:\Java\jdk1.6.0_02\bin\javac.exe -Xlint -g -deprecation -classpath D:\JavaDevelopment\;. PackageLoader.java

PackageLoader.java:16: cannot find symbol
symbol  : class Logger
location: class PackageLoader
    private static final Logger log = Logger.getLogger( PackageLoader.class );
                         ^
PackageLoader.java:22: cannot find symbol
symbol  : class Filter
location: class PackageLoader
    public <T> Class<T>[] getClasses( String pkgName, Filter filter ) throws PackageLoaderException {
                                                      ^
PackageLoader.java:42: cannot find symbol
symbol  : class Filter
location: class PackageLoader
    public <T> Class<T>[] getClasses( String path, String pkgName, Filter filter ) throws PackageLoaderException {
                                                                   ^
PackageLoader.java:50: cannot find symbol
symbol  : class Filter
location: class PackageLoader
    protected <T> Class<T>[] getClassesFromJar( String path, String pkgName, Filter filter ) throws PackageLoaderException {
                                                                             ^
PackageLoader.java:93: cannot find symbol
symbol  : class Filter
location: class PackageLoader
    protected <T> Class<T>[] getClassesFromIdle( String path, String pkgName, Filter filter ) throws PackageLoaderException {
                                                                              ^
PackageLoader.java:16: cannot find symbol
symbol  : variable Logger
location: class PackageLoader
    private static final Logger log = Logger.getLogger( PackageLoader.class );
                                      ^
PackageLoader.java:19: cannot find symbol
symbol  : class InterfacesFilter
location: class PackageLoader
        return this.getClasses( pkgName, new InterfacesFilter( new Class[] {} ) );
                                             ^
PackageLoader.java:35: warning: [unchecked] unchecked conversion
found   : java.lang.Class[]
required: java.lang.Class<T>[]
        return classes.toArray( new Class[classes.size()] );
                              ^
PackageLoader.java:39: cannot find symbol
symbol  : class InterfacesFilter
location: class PackageLoader
        return this.getClasses( path, pkgName, new InterfacesFilter( new Class[] {}  ) );
                                                   ^
PackageLoader.java:77: warning: [unchecked] unchecked cast
found   : java.lang.Class<capture#492 of ?>
required: java.lang.Class<T>
                    clazz = (Class<T>) loader.loadClass( clsName );
                                                       ^
PackageLoader.java:86: warning: [unchecked] unchecked conversion
found   : java.lang.Class[]
required: java.lang.Class<T>[]
            return result.toArray( new Class[result.size()] );
                                 ^
PackageLoader.java:98: cannot find symbol
symbol  : variable Registry
location: class PackageLoader
            File folder = Registry.getResourcesLoader().loadFile( folderName );
                          ^
PackageLoader.java:104: warning: [unchecked] unchecked conversion
found   : java.util.List
required: java.util.Collection<? extends java.lang.Class<T>>
                classes.addAll( (List) Arrays.asList( this.getClassesFromJar( path, pkgName, filter ) ) );
                                ^
PackageLoader.java:116: warning: [unchecked] unchecked cast
found   : java.lang.Class<capture#316 of ?>
required: java.lang.Class<T>
                    Class<T> clazz = (Class<T>) ClassLoader.getSystemClassLoader().loadClass( pkgName + "." + className );
                                                                                            ^
PackageLoader.java:125: warning: [unchecked] unchecked conversion
found   : java.lang.Class[]
required: java.lang.Class<T>[]
            return classes.toArray( new Class[ classes.size() ] );
                                  ^
PackageLoader.java:141: warning: [serial] serializable class PackageLoaderException has no definition of serialVersionUID
class PackageLoaderException extends Exception {
^
9 errors
7 warnings

9 error(s)
nikelin 0 Newbie Poster

1. Place log4j package in classpath (http://logging.apache.org/log4j/1.2/)
2. Remove "deprecated" argument
3. import InterfacesFilter from this snippet: http://www.daniweb.com/code/snippet293921.html

NormR1 563 Posting Sage Team Colleague

I don't have or want the log4j package. Too many extraneous jar files clutters up an app. Do you have a dummy class for the Logging stuff?
Where is the definition or the Filter class?

Remove "deprecated" argument

That doesn't make the code better. It just suppresses warnings.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.