Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 202   Methods: 7
NCLOC: 108   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SelectedClassnameClassLoader.java 46.7% 74% 85.7% 65.5%
coverage coverage
 1    package org.jboss.cache.marshall;
 2   
 3    import org.apache.commons.logging.Log;
 4    import org.apache.commons.logging.LogFactory;
 5   
 6    import java.io.ByteArrayOutputStream;
 7    import java.io.FileNotFoundException;
 8    import java.io.IOException;
 9    import java.io.InputStream;
 10    import java.util.Map;
 11   
 12    /**
 13    * A ClassLoader that loads classes whose classname begins with one of a
 14    * given set of strings, without attempting first to delegate to its
 15    * parent loader.
 16    * <p>
 17    * This class is intended to allow emulation of 2 different types of common J2EE
 18    * classloading situations.
 19    * <ul>
 20    * <li>Servlet-style child-first classloading, where this class is the
 21    * child loader.</li>
 22    * <li>Parent-first classloading where the parent does not have access to
 23    * certain classes</li>
 24    * </ul>
 25    * </p>
 26    * <p>
 27    * This class can also be configured to raise a ClassNotFoundException if
 28    * asked to load certain classes, thus allowing classes on the classpath
 29    * to be hidden from a test environment.
 30    * </p>
 31    *
 32    * @author Brian Stansberry
 33    *
 34    */
 35    public class SelectedClassnameClassLoader extends ClassLoader {
 36   
 37    private String[] includedClasses = null;
 38    private String[] excludedClasses = null;
 39    private String[] notFoundClasses = null;
 40    private Log log = LogFactory.getLog(SelectedClassnameClassLoader.class);
 41   
 42    private Map classes = new java.util.HashMap();
 43   
 44    /**
 45    * Creates a new classloader that loads the given classes.
 46    *
 47    * @param includedClasses array of class or package names that should be
 48    * directly loaded by this loader. Classes
 49    * whose name starts with any of the strings
 50    * in this array will be loaded by this class,
 51    * unless their name appears in
 52    * <code>excludedClasses</code>.
 53    * Can be <code>null</code>
 54    * @param excludedClasses array of class or package names that should NOT
 55    * be directly loaded by this loader. Loading of
 56    * classes whose name starts with any of the
 57    * strings in this array will be delegated to
 58    * <code>parent</code>, even if the classes
 59    * package or classname appears in
 60    * <code>includedClasses</code>. Typically this
 61    * parameter is used to exclude loading one or
 62    * more classes in a package whose other classes
 63    * are loaded by this object.
 64    * @param parent ClassLoader to which loading of classes should
 65    * be delegated if necessary
 66    */
 67  35 public SelectedClassnameClassLoader(String[] includedClasses,
 68    String[] excludedClasses,
 69    ClassLoader parent) {
 70  35 super(parent);
 71  35 this.includedClasses = includedClasses;
 72  35 this.excludedClasses = excludedClasses;
 73    }
 74   
 75    /**
 76    * Creates a new classloader that loads the given classes.
 77    *
 78    * @param includedClasses array of class or package names that should be
 79    * directly loaded by this loader. Classes
 80    * whose name starts with any of the strings
 81    * in this array will be loaded by this class,
 82    * unless their name appears in
 83    * <code>excludedClasses</code>.
 84    * Can be <code>null</code>
 85    * @param excludedClasses array of class or package names that should NOT
 86    * be directly loaded by this loader. Loading of
 87    * classes whose name starts with any of the
 88    * strings in this array will be delegated to
 89    * <code>parent</code>, even if the classes
 90    * package or classname appears in
 91    * <code>includedClasses</code>. Typically this
 92    * parameter is used to exclude loading one or
 93    * more classes in a package whose other classes
 94    * are loaded by this object.
 95    * @param notFoundClasses array of class or package names for which this
 96    * should raise a ClassNotFoundException
 97    * @param parent ClassLoader to which loading of classes should
 98    * be delegated if necessary
 99    */
 100  2 public SelectedClassnameClassLoader(String[] includedClasses,
 101    String[] excludedClasses,
 102    String[] notFoundClasses,
 103    ClassLoader parent) {
 104  2 super(parent);
 105  2 this.includedClasses = includedClasses;
 106  2 this.excludedClasses = excludedClasses;
 107  2 this.notFoundClasses = notFoundClasses;
 108    }
 109   
 110  482 protected synchronized Class loadClass(String name, boolean resolve)
 111    throws ClassNotFoundException
 112    {
 113  482 log.info("In SelectedClassnameClassLoader.loadClass("+name+","+resolve+")");
 114  482 if (isIncluded(name) && (isExcluded(name) == false)) {
 115  79 Class c = findClass(name);
 116   
 117  79 if (resolve) {
 118  0 resolveClass(c);
 119    }
 120  79 return c;
 121    }
 122    else {
 123  403 return super.loadClass(name, resolve);
 124    }
 125    }
 126   
 127  79 protected Class findClass(String name) throws ClassNotFoundException {
 128   
 129  79 log.info("In SelectedClassnameClassLoader.findClass()");
 130  79 Class result = (Class)classes.get(name);
 131  79 if(result != null){
 132  36 return result;
 133    }
 134   
 135  43 if (isIncluded(name) && (isExcluded(name) == false)) {
 136  43 try {
 137  43 InputStream is = getResourceAsStream( name.replace('.','/').concat(".class"));
 138  43 byte[] bytes = new byte[1024];
 139  43 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
 140  43 int read;
 141  ? while ((read = is.read(bytes)) > -1) {
 142  77 baos.write(bytes, 0, read);
 143    }
 144  43 bytes = baos.toByteArray();
 145  43 result = this.defineClass(name, bytes, 0, bytes.length);
 146    } catch (FileNotFoundException e) {
 147  0 throw new ClassNotFoundException("cannot find " + name, e);
 148    } catch (IOException e) {
 149  0 throw new ClassNotFoundException("cannot read " + name, e);
 150    }
 151    }
 152  0 else if (isNotFound(name)) {
 153  0 throw new ClassNotFoundException(name + " is discarded");
 154    }
 155    else {
 156  0 result = super.findClass(name);
 157    }
 158   
 159  43 classes.put(name, result);
 160   
 161  43 return result;
 162    }
 163   
 164  525 private boolean isIncluded(String className) {
 165   
 166  525 if (includedClasses != null) {
 167  267 for (int i = 0; i < includedClasses.length; i++) {
 168  486 if (className.startsWith(includedClasses[i])) {
 169  122 return true;
 170    }
 171    }
 172    }
 173   
 174  403 return false;
 175    }
 176   
 177  122 private boolean isExcluded(String className) {
 178   
 179  122 if (excludedClasses != null) {
 180  122 for (int i = 0; i < excludedClasses.length; i++) {
 181  0 if (className.startsWith(excludedClasses[i])) {
 182  0 return true;
 183    }
 184    }
 185    }
 186   
 187  122 return false;
 188    }
 189   
 190  0 private boolean isNotFound(String className) {
 191   
 192  0 if (notFoundClasses != null) {
 193  0 for (int i = 0; i < notFoundClasses.length; i++) {
 194  0 if (className.startsWith(notFoundClasses[i])) {
 195  0 return true;
 196    }
 197    }
 198    }
 199   
 200  0 return false;
 201    }
 202    }