/** * JCL (Jar Class Loader) * * Copyright (C) 2009 Xeus Technologies * * This file is part of Jar Class Loader (JCL). * Jar Class Loader (JCL) is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JarClassLoader is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JCL. If not, see <http://www.gnu.org/licenses/>. * * @author Kamran Zafar * * Contact Info: * Email: xeus.man@gmail.com * Web: http://xeustech.blogspot.com */ package xeus.jcl; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import xeus.jcl.exception.ResourceNotFoundException; import xeus.jcl.loader.Loader; /** * Abstract class loader that can load classes from different resources * * @author Kamran Zafar * */ @SuppressWarnings("unchecked") public abstract class AbstractClassLoader extends ClassLoader { protected final List<Loader> loaders = new ArrayList<Loader>(); private final Loader systemLoader = new SystemLoader(); private final Loader parentLoader = new ParentLoader(); private final Loader currentLoader = new CurrentLoader(); /** * No arguments constructor */ public AbstractClassLoader() { loaders.add( systemLoader ); loaders.add( parentLoader ); loaders.add( currentLoader ); } public void addLoader(Loader loader) { loaders.add( loader ); } /** * Override loadClass * * @see java.lang.ClassLoader#loadClass(java.lang.String) */ @Override public Class loadClass(String className) throws ClassNotFoundException { return ( loadClass( className, true ) ); } /** * Overrides the loadClass method to load classes from other resources, * JarClassLoader is the only subclass in this project that loads classes * from jar files * * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) */ @Override public Class loadClass(String className, boolean resolveIt) throws ClassNotFoundException { Collections.sort( loaders ); Class clazz = null; for( Loader l : loaders ) { if( l.isEnabled() ) { clazz = l.load( className, resolveIt ); if( clazz != null ) break; } } if( clazz == null ) throw new ClassNotFoundException( className ); return clazz; } /** * Overrides the getResourceAsStream method to load non-class resources from * other sources, JarClassLoader is the only subclass in this project that * loads non-class resources from jar files * * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String) */ @Override public InputStream getResourceAsStream(String name) { Collections.sort( loaders ); InputStream is = null; for( Loader l : loaders ) { if( l.isEnabled() ) { is = l.loadResource( name ); if( is != null ) break; } } if( is == null ) throw new ResourceNotFoundException( "Resource " + name + " not found." ); return is; } /** * System class loader * */ class SystemLoader extends Loader { private final Logger logger = Logger.getLogger( SystemLoader.class ); public SystemLoader() { order = 4; enabled = Configuration.isSystemLoaderEnabled(); } @Override public Class load(String className, boolean resolveIt) { Class result; try { result = findSystemClass( className ); } catch (ClassNotFoundException e) { return null; } if( logger.isTraceEnabled() ) logger.trace( "Returning system class " + className ); return result; } @Override public InputStream loadResource(String name) { InputStream is = getSystemResourceAsStream( name ); if( is != null ) { if( logger.isTraceEnabled() ) logger.trace( "Returning system resource " + name ); return is; } return null; } } /** * Parent class loader * */ class ParentLoader extends Loader { private final Logger logger = Logger.getLogger( ParentLoader.class ); public ParentLoader() { order = 3; enabled = Configuration.isParentLoaderEnabled(); } @Override public Class load(String className, boolean resolveIt) { Class result; try { result = getParent().loadClass( className ); } catch (ClassNotFoundException e) { return null; } if( logger.isTraceEnabled() ) logger.trace( "Returning class " + className + " loaded with parent classloader" ); return result; } @Override public InputStream loadResource(String name) { InputStream is = getParent().getResourceAsStream( name ); if( is != null ) { if( logger.isTraceEnabled() ) logger.trace( "Returning resource " + name + " loaded with parent classloader" ); return is; } return null; } } /** * Current class loader * */ class CurrentLoader extends Loader { private final Logger logger = Logger.getLogger( CurrentLoader.class ); public CurrentLoader() { order = 2; enabled = Configuration.isCurrentLoaderEnabled(); } @Override public Class load(String className, boolean resolveIt) { Class result; try { result = getClass().getClassLoader().loadClass( className ); } catch (ClassNotFoundException e) { return null; } if( logger.isTraceEnabled() ) logger.trace( "Returning class " + className + " loaded with current classloader" ); return result; } @Override public InputStream loadResource(String name) { InputStream is = getClass().getClassLoader().getResourceAsStream( name ); if( is != null ) { if( logger.isTraceEnabled() ) logger.trace( "Returning resource " + name + " loaded with current classloader" ); return is; } return null; } } public Loader getSystemLoader() { return systemLoader; } public Loader getParentLoader() { return parentLoader; } public Loader getCurrentLoader() { return currentLoader; } }