Java cvprof Coverage Report for
TestCaseClassLoader.java

    1   package junit.runner;
    2   
    3   import java.util.*;
    4   import java.io.*;
    5   import java.net.URL;
    6   import java.util.zip.*;
    7   
    8   /**
    9    * A custom class loader which enables the reloading
   10    * of classes for each test run. The class loader
   11    * can be configured with a list of package paths that
   12    * should be excluded from loading. The loading
   13    * of these packages is delegated to the system class
   14    * loader. They will be shared across test runs.
   15    * <p>
   16    * The list of excluded package paths is specified in
   17    * a properties file "excluded.properties" that is located in 
   18    * the same place as the TestCaseClassLoader class.
   19    * <p>
   20    * <b>Known limitation:</b> the TestCaseClassLoader cannot load classes
   21    * from jar files.
   22    */
   23   
   24   
   25   public class TestCaseClassLoader extends ClassLoader {
   26   	/** scanned class path */
   27   	private Vector fPathItems;
   28   	/** default excluded paths */
   29   	private String[] defaultExclusions= {
   30   		"junit.framework.", 
   31   		"junit.extensions.", 
   32   		"junit.runner."
   33   	};
   34   	/** name of excluded properties file */
   35   	static final String EXCLUDED_FILE= "excluded.properties";
   36   	/** excluded paths */
   37   	private Vector fExcluded;
   38   	 
   39   	/**
   40   	 * Constructs a TestCaseLoader. It scans the class path
   41   	 * and the excluded package paths
   42   	 */
   43   	public TestCaseClassLoader() {
   44   		this(System.getProperty("java.class.path"));
   45   	}
   46   	
   47   	/**
   48   	 * Constructs a TestCaseLoader. It scans the class path
   49   	 * and the excluded package paths
   50   	 */
   51   	public TestCaseClassLoader(String classPath) {
   52   		scanPath(classPath);
   53   		readExcludedPackages();
   54   	}
   55   
   56   	private void scanPath(String classPath) {
   57   		String separator= System.getProperty("path.separator");
   58   		fPathItems= new Vector(10);
   59   		StringTokenizer st= new StringTokenizer(classPath, separator);
   60   		while (st.hasMoreTokens()) {
   61   			fPathItems.addElement(st.nextToken());
   62   		}
   63   	}
   64   	
   65   	public URL getResource(String name) {
   66 > 		return ClassLoader.getSystemResource(name);
   67   	}
   68   	
   69   	public InputStream getResourceAsStream(String name) {
   70 > 		return ClassLoader.getSystemResourceAsStream(name);
   71   	} 
   72   	
   73   	public boolean isExcluded(String name) {
   74   		for (int i= 0; i < fExcluded.size(); i++) {
   75   			if (name.startsWith((String) fExcluded.elementAt(i))) {
   76   				return true;
   77   			}
   78   		}
   79   		return false;	
   80   	}
   81   	
   82   	public synchronized Class loadClass(String name, boolean resolve)
   83   		throws ClassNotFoundException {
   84   			
   85   		Class c= findLoadedClass(name);
   86   		if (c != null)
   87 > 			return c;
   88   		//
   89   		// Delegate the loading of excluded classes to the
   90   		// standard class loader.
   91   		//
   92   		if (isExcluded(name)) {
   93   			try {
   94   				c= findSystemClass(name);
   95   				return c;
   96 > 			} catch (ClassNotFoundException e) {
   97   				// keep searching
   98 > 			}
   99   		}
  100   		if (c == null) {
  101   			byte[] data= lookupClassData(name);
  102   			if (data == null)
  103 > 				throw new ClassNotFoundException();
  104   			c= defineClass(name, data, 0, data.length);
  105   		}
  106   		if (resolve) 
  107   			resolveClass(c);
  108   		return c;
  109   	}
  110   	
  111   	private byte[] lookupClassData(String className) throws ClassNotFoundException {
  112   		byte[] data= null;
  113   		for (int i= 0; i < fPathItems.size(); i++) {
  114   			String path= (String) fPathItems.elementAt(i);
  115   			String fileName= className.replace('.', '/')+".class";
  116   			if (isJar(path)) {
  117   				data= loadJarData(path, fileName);
  118   			} else {
  119   				data= loadFileData(path, fileName);
  120   			}
  121   			if (data != null)
  122   				return data;
  123   		}
  124   		throw new ClassNotFoundException(className);
  125   	}
  126   		
  127   	boolean isJar(String pathEntry) {
  128   		return pathEntry.endsWith(".jar") || pathEntry.endsWith(".zip");
  129   	}
  130   
  131   	private byte[] loadFileData(String path, String fileName) {
  132   		File file= new File(path, fileName);
  133   		if (file.exists()) { 
  134   			return getClassData(file);
  135   		}
  136   		return null;
  137   	}
  138   	
  139   	private byte[] getClassData(File f) {
  140   		try {
  141   			FileInputStream stream= new FileInputStream(f);
  142   			ByteArrayOutputStream out= new ByteArrayOutputStream(1000);
  143   			byte[] b= new byte[1000];
  144   			int n;
  145   			while ((n= stream.read(b)) != -1) 
  146   				out.write(b, 0, n);
  147   			stream.close();
  148   			out.close();
  149   			return out.toByteArray();
  150   
  151 > 		} catch (IOException e) {
  152 > 		}
  153 > 		return null;
  154   	}
  155   
  156   	private byte[] loadJarData(String path, String fileName) {
  157   		ZipFile zipFile= null;
  158   		InputStream stream= null;
  159   		File archive= new File(path);
  160   		if (!archive.exists())
  161 > 			return null;
  162   		try {
  163   			zipFile= new ZipFile(archive);
  164   		} catch(IOException io) {
  165 > 			return null;
  166   		}
  167   		ZipEntry entry= zipFile.getEntry(fileName);
  168   		if (entry == null)
  169 > 			return null;
  170   		int size= (int) entry.getSize();
  171   		try {
  172   			stream= zipFile.getInputStream(entry);
  173   			byte[] data= new byte[size];
  174   			int pos= 0;
  175   			while (pos < size) {
  176   				int n= stream.read(data, pos, data.length - pos);
  177   				pos += n;
  178   			}
  179   			zipFile.close();
  180   			return data;
  181 > 		} catch (IOException e) {
  182 > 		} finally {
  183   			try {
  184   				if (stream != null)
  185   					stream.close();
  186   			} catch (IOException e) {
  187   			}
  188   		}
  189 > 		return null;
  190   	}
  191   	
  192   	private void readExcludedPackages() {		
  193   		fExcluded= new Vector(10);
  194   		for (int i= 0; i < defaultExclusions.length; i++)
  195   			fExcluded.addElement(defaultExclusions[i]);
  196   			
  197   		InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE);
  198   		if (is == null) 
  199 > 			return;
  200   		Properties p= new Properties();
  201   		try {
  202   			p.load(is);
  203   		}
  204   		catch (IOException e) {
  205 > 			return;
  206   		} finally {
  207   			try {
  208   				is.close();
  209   			} catch (IOException e) {
  210   			}
  211   		}
  212   		for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) {
  213   			String key= (String)e.nextElement();
  214   			if (key.startsWith("excluded.")) {
  215   				String path= p.getProperty(key);
  216   				path= path.trim();
  217   				if (path.endsWith("*"))
  218   					path= path.substring(0, path.length()-1);
  219   				if (path.length() > 0) 
  220   					fExcluded.addElement(path);				
  221   			}
  222   		}
  223   	}
  224   }