Clover coverage report - PLT Utilities Test Coverage (plt-20120304-r5436)
Coverage timestamp: Sat Mar 3 2012 22:01:56 CST
file stats: LOC: 143   Methods: 8
NCLOC: 56   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ShadowingClassLoader.java 100% 100% 100% 100%
coverage
 1    /*BEGIN_COPYRIGHT_BLOCK*
 2   
 3    PLT Utilities BSD License
 4   
 5    Copyright (c) 2007-2010 JavaPLT group at Rice University
 6    All rights reserved.
 7   
 8    Developed by: Java Programming Languages Team
 9    Rice University
 10    http://www.cs.rice.edu/~javaplt/
 11   
 12    Redistribution and use in source and binary forms, with or without modification, are permitted
 13    provided that the following conditions are met:
 14   
 15    - Redistributions of source code must retain the above copyright notice, this list of conditions
 16    and the following disclaimer.
 17    - Redistributions in binary form must reproduce the above copyright notice, this list of
 18    conditions and the following disclaimer in the documentation and/or other materials provided
 19    with the distribution.
 20    - Neither the name of the JavaPLT group, Rice University, nor the names of the library's
 21    contributors may be used to endorse or promote products derived from this software without
 22    specific prior written permission.
 23   
 24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 25    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 26    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND
 27    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 28    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 29    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 30    IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 31    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32   
 33    *END_COPYRIGHT_BLOCK*/
 34   
 35    package edu.rice.cs.plt.reflect;
 36   
 37    import java.net.URL;
 38    import edu.rice.cs.plt.iter.IterUtil;
 39   
 40    import static edu.rice.cs.plt.debug.DebugUtil.debug;
 41   
 42    /**
 43    * A class loader that hides a set of classes and related resources. This allows classes
 44    * with the same name (but perhaps a different implementation) to be cleanly loaded by a child loader.
 45    */
 46    public class ShadowingClassLoader extends ClassLoader {
 47   
 48    private final Iterable<? extends String> _prefixes;
 49    private final boolean _blackList;
 50    private final boolean _filterBootClasses;
 51   
 52    /**
 53    * Create a ShadowingClassLoader that will hide non-bootstrap classes matching the given prefixes.
 54    * @param parent The parent loader
 55    * @param excludePrefixes A set of class name prefixes to match. Each prefix must be a package or class
 56    * name (partial names, like {@code "java.lang.Stri"}, will not match the full class
 57    * name).
 58    */
 59  4 public static ShadowingClassLoader blackList(ClassLoader parent, String... excludePrefixes) {
 60  4 return new ShadowingClassLoader(parent, true, IterUtil.asIterable(excludePrefixes), false);
 61    }
 62   
 63    /**
 64    * Create a ShadowingClassLoader that will hide all non-bootstrap classes except those matching the
 65    * given prefixes.
 66    * @param parent The parent loader
 67    * @param includePrefixes A set of class name prefixes to match. Each prefix must be a package or class
 68    * name (partial names, like {@code "java.lang.Stri"}, will not match the full class
 69    * name).
 70    */
 71  2 public static ShadowingClassLoader whiteList(ClassLoader parent, String... includePrefixes) {
 72  2 return new ShadowingClassLoader(parent, false, IterUtil.asIterable(includePrefixes), false);
 73    }
 74   
 75    /**
 76    * @param parent The parent loader
 77    * @param blackList If {@code true}, classes matching {@code prefixes} are prevented from loading; otherwise,
 78    * all classes <em>except</em> those matching {@code prefixes} are prevented from loading.
 79    * @param prefixes A set of class name prefixes to which class names will be compared. Each prefix must
 80    * be a package or class name (partial names, like {@code "java.lang.Stri"}, will not
 81    * match the full class name).
 82    * @param filterBootClasses Whether classes and resources available to the bootstrap class loader should
 83    * be hidden. If {@code true}, care must be taken to ensure that essential
 84    * classes (like {@code java.lang.Object}) are available when needed.
 85    */
 86  7 public ShadowingClassLoader(ClassLoader parent, boolean blackList, Iterable<? extends String> prefixes,
 87    boolean filterBootClasses) {
 88  7 super(parent);
 89  7 _blackList = blackList;
 90  7 _prefixes = prefixes;
 91  7 _filterBootClasses = filterBootClasses;
 92    }
 93   
 94    /**
 95    * If the given class is shadowed, a {@code ClassNotFoundException} will
 96    * occur; otherwise, the method delegates to the parent class loader.
 97    */
 98  15 @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
 99  15 if ((_filterBootClasses || !isBootClass(name)) && matchesPrefixes(name) == _blackList) {
 100  6 throw new ClassNotFoundException(name + " is being shadowed");
 101    }
 102    else {
 103    // can't use getParent().loadClass(name) because parent may be null
 104  9 return super.loadClass(name, resolve);
 105    }
 106    }
 107   
 108  2 @Override public URL getResource(String name) {
 109  2 if ((_filterBootClasses || !isBootResource(name)) &&
 110    matchesPrefixes(name.replace('/', '.')) == _blackList) {
 111  1 return null;
 112    }
 113    else {
 114    // can't use getParent().getResource(name) because parent may be null
 115  1 return super.getResource(name);
 116    }
 117    }
 118   
 119    // Ideally, we should override getResources() as well. Unfortunately, it's final in Java 1.4.
 120   
 121    /** As a side effect, loads the given class in the bootstrap class loader. */
 122  13 private boolean isBootClass(String name) {
 123  3 try { ReflectUtil.BOOT_CLASS_LOADER.loadClass(name); return true; }
 124  10 catch (ClassNotFoundException e) { return false; }
 125    }
 126   
 127  2 private boolean isBootResource(String name) {
 128  2 return ReflectUtil.BOOT_CLASS_LOADER.getResource(name) != null;
 129    }
 130   
 131  14 private boolean matchesPrefixes(String name) {
 132    // TODO: improve efficiency by using a sorted data structure
 133  14 for (String p : _prefixes) {
 134  19 if (name.startsWith(p)) {
 135  8 if (name.equals(p) || name.startsWith(p + ".") || name.startsWith(p + "$")) {
 136  7 return true;
 137    }
 138    }
 139    }
 140  7 return false;
 141    }
 142   
 143    }