Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 225   Methods: 7
NCLOC: 132   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SelectedClassnameClassLoader.java 0% 6% 14.3% 4.6%
coverage coverage
 1    package org.jboss.cache.pojo.memory;
 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    public class SelectedClassnameClassLoader extends ClassLoader
 35    {
 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  6 public SelectedClassnameClassLoader(String[] includedClasses,
 68    String[] excludedClasses,
 69    ClassLoader parent)
 70    {
 71  6 super(parent);
 72  6 this.includedClasses = includedClasses;
 73  6 this.excludedClasses = excludedClasses;
 74    }
 75   
 76    /**
 77    * Creates a new classloader that loads the given classes.
 78    *
 79    * @param includedClasses array of class or package names that should be
 80    * directly loaded by this loader. Classes
 81    * whose name starts with any of the strings
 82    * in this array will be loaded by this class,
 83    * unless their name appears in
 84    * <code>excludedClasses</code>.
 85    * Can be <code>null</code>
 86    * @param excludedClasses array of class or package names that should NOT
 87    * be directly loaded by this loader. Loading of
 88    * classes whose name starts with any of the
 89    * strings in this array will be delegated to
 90    * <code>parent</code>, even if the classes
 91    * package or classname appears in
 92    * <code>includedClasses</code>. Typically this
 93    * parameter is used to exclude loading one or
 94    * more classes in a package whose other classes
 95    * are loaded by this object.
 96    * @param notFoundClasses array of class or package names for which this
 97    * should raise a ClassNotFoundException
 98    * @param parent ClassLoader to which loading of classes should
 99    * be delegated if necessary
 100    */
 101  0 public SelectedClassnameClassLoader(String[] includedClasses,
 102    String[] excludedClasses,
 103    String[] notFoundClasses,
 104    ClassLoader parent)
 105    {
 106  0 super(parent);
 107  0 this.includedClasses = includedClasses;
 108  0 this.excludedClasses = excludedClasses;
 109  0 this.notFoundClasses = notFoundClasses;
 110    }
 111   
 112  0 protected synchronized Class loadClass(String name, boolean resolve)
 113    throws ClassNotFoundException
 114    {
 115  0 log.info("In SelectedClassnameClassLoader.loadClass(" + name + "," + resolve + ")");
 116  0 if (isIncluded(name) && (isExcluded(name) == false))
 117    {
 118  0 Class c = findClass(name);
 119   
 120  0 if (resolve)
 121    {
 122  0 resolveClass(c);
 123    }
 124  0 return c;
 125    } else
 126    {
 127  0 return super.loadClass(name, resolve);
 128    }
 129    }
 130   
 131  0 protected Class findClass(String name) throws ClassNotFoundException
 132    {
 133   
 134  0 log.info("In SelectedClassnameClassLoader.findClass()");
 135  0 Class result = (Class) classes.get(name);
 136  0 if (result != null)
 137    {
 138  0 return result;
 139    }
 140   
 141  0 if (isIncluded(name) && (isExcluded(name) == false))
 142    {
 143  0 try
 144    {
 145  0 InputStream is = getResourceAsStream(name.replace('.', '/').concat(".class"));
 146  0 byte[] bytes = new byte[1024];
 147  0 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
 148  0 int read;
 149  0 while ((read = is.read(bytes)) > -1)
 150    {
 151  0 baos.write(bytes, 0, read);
 152    }
 153  0 bytes = baos.toByteArray();
 154  0 result = this.defineClass(name, bytes, 0, bytes.length);
 155    } catch (FileNotFoundException e)
 156    {
 157  0 throw new ClassNotFoundException("cannot find " + name, e);
 158    } catch (IOException e)
 159    {
 160  0 throw new ClassNotFoundException("cannot read " + name, e);
 161    }
 162  0 } else if (isNotFound(name))
 163    {
 164  0 throw new ClassNotFoundException(name + " is discarded");
 165    } else
 166    {
 167  0 result = super.findClass(name);
 168    }
 169   
 170  0 classes.put(name, result);
 171   
 172  0 return result;
 173    }
 174   
 175  0 private boolean isIncluded(String className)
 176    {
 177   
 178  0 if (includedClasses != null)
 179    {
 180  0 for (int i = 0; i < includedClasses.length; i++)
 181    {
 182  0 if (className.startsWith(includedClasses[i]))
 183    {
 184  0 return true;
 185    }
 186    }
 187    }
 188   
 189  0 return false;
 190    }
 191   
 192  0 private boolean isExcluded(String className)
 193    {
 194   
 195  0 if (excludedClasses != null)
 196    {
 197  0 for (int i = 0; i < excludedClasses.length; i++)
 198    {
 199  0 if (className.startsWith(excludedClasses[i]))
 200    {
 201  0 return true;
 202    }
 203    }
 204    }
 205   
 206  0 return false;
 207    }
 208   
 209  0 private boolean isNotFound(String className)
 210    {
 211   
 212  0 if (notFoundClasses != null)
 213    {
 214  0 for (int i = 0; i < notFoundClasses.length; i++)
 215    {
 216  0 if (className.startsWith(notFoundClasses[i]))
 217    {
 218  0 return true;
 219    }
 220    }
 221    }
 222   
 223  0 return false;
 224    }
 225    }