Coverage Report - liquibase.resource.CompositeResourceAccessor
 
Classes in this File Line Coverage Branch Coverage Complexity
CompositeResourceAccessor
76%
23/30
85%
12/14
3
CompositeResourceAccessor$CompositeClassLoader
47%
9/19
25%
2/8
3
 
 1  
 package liquibase.resource;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.io.InputStream;
 5  
 import java.net.URL;
 6  
 import java.util.ArrayList;
 7  
 import java.util.Arrays;
 8  
 import java.util.Enumeration;
 9  
 import java.util.List;
 10  
 import java.util.Vector;
 11  
 
 12  
 import liquibase.util.StringUtils;
 13  
 
 14  
 /**
 15  
  * A FileOpener that will search in a List of other FileOpeners until it finds one that has a resource of the
 16  
  * appropriate name and path.
 17  
  * 
 18  
  * @author <a href="mailto:csuml@yahoo.co.uk>Paul Keeble</a>
 19  
  */
 20  
 public class CompositeResourceAccessor implements ResourceAccessor {
 21  
     List<ResourceAccessor> openers;
 22  
 
 23  
     /**
 24  
      * Creates a Composite Opener with the list specified. The List will be searched in order from beginning to end.
 25  
      * 
 26  
      * @param openers
 27  
      *            The list of Openers to use
 28  
      */
 29  0
     public CompositeResourceAccessor(List<ResourceAccessor> openers) {
 30  0
         this.openers = openers;
 31  0
     }
 32  
 
 33  
     /**
 34  
      * Creates a CompositeFileOpener with 2 entries.
 35  
      * 
 36  
      * @param openers
 37  
      *            The list of Openers to use
 38  
      */
 39  9
     public CompositeResourceAccessor(ResourceAccessor... openers) {
 40  9
         this.openers = Arrays.asList(openers);
 41  9
     }
 42  
 
 43  
     /**
 44  
      * Searches through all of the FileOpeners in order for the file.
 45  
      * <p/>
 46  
      * If none of the FileOpeners was able to produce a stream to the file then null is returned.
 47  
      */
 48  
     @Override
 49  
     public InputStream getResourceAsStream(String file) throws IOException {
 50  3
         for (ResourceAccessor o : openers) {
 51  5
             InputStream is = o.getResourceAsStream(file);
 52  5
             if (is != null)
 53  2
                 return is;
 54  3
         }
 55  1
         return null;
 56  
     }
 57  
 
 58  
     /**
 59  
      * Searches all of the FileOpeners for a directory named packageName. If no results are found within any of the
 60  
      * directories then an empty Enumeration is returned.
 61  
      */
 62  
     @Override
 63  
     public Enumeration<URL> getResources(String packageName) throws IOException {
 64  6
         Vector<URL> urls = new Vector<URL>();
 65  6
         for (ResourceAccessor o : openers) {
 66  8
             Enumeration<URL> e = o.getResources(packageName);
 67  66
             while (e.hasMoreElements()) {
 68  58
                 urls.add(e.nextElement());
 69  
             }
 70  8
             if (!urls.isEmpty())
 71  5
                 break;
 72  3
         }
 73  6
         return urls.elements();
 74  
     }
 75  
 
 76  
     @Override
 77  
     public ClassLoader toClassLoader() {
 78  5
         ClassLoader[] loaders = new ClassLoader[openers.size()];
 79  5
         int i = 0;
 80  5
         for (ResourceAccessor fo : openers) {
 81  10
             loaders[i++] = fo.toClassLoader();
 82  
         }
 83  
 
 84  5
         return new CompositeClassLoader(loaders);
 85  
     }
 86  
 
 87  
     // based on code from
 88  
     // http://fisheye.codehaus.org/browse/xstream/trunk/xstream/src/java/com/thoughtworks/xstream/core/util/CompositeClassLoader.java?r=root
 89  
     private static class CompositeClassLoader extends ClassLoader {
 90  
 
 91  5
         private final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
 92  
 
 93  5
         public CompositeClassLoader(ClassLoader... classLoaders) {
 94  5
             this.classLoaders.addAll(Arrays.asList(classLoaders));
 95  5
         }
 96  
 
 97  
         @Override
 98  
         public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
 99  2048
             for (Object classLoader1 : classLoaders) {
 100  2048
                 ClassLoader classLoader = (ClassLoader) classLoader1;
 101  
                 try {
 102  2048
                     Class classe = classLoader.loadClass(name);
 103  2048
                     if (resolve)
 104  0
                         resolveClass(classe);
 105  2048
                     return classe;
 106  0
                 } catch (ClassNotFoundException notFound) {
 107  
                     // ok.. try another one
 108  
                 }
 109  0
             }
 110  
 
 111  
             // One last try - the context class loader associated with the current thread. Often used in j2ee servers.
 112  
             // Note: The contextClassLoader cannot be added to the classLoaders list up front as the thread that
 113  
             // constructs
 114  
             // liquibase is potentially different to thread that uses it.
 115  0
             ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
 116  0
             if (contextClassLoader != null) {
 117  0
                 Class classe = contextClassLoader.loadClass(name);
 118  0
                 if (resolve)
 119  0
                     resolveClass(classe);
 120  0
                 return classe;
 121  
             } else {
 122  0
                 throw new ClassNotFoundException(name);
 123  
             }
 124  
 
 125  
         }
 126  
 
 127  
     }
 128  
 
 129  
     @Override
 130  
     public String toString() {
 131  0
         List<String> openerStrings = new ArrayList<String>();
 132  0
         for (ResourceAccessor opener : openers) {
 133  0
             openerStrings.add(opener.toString());
 134  
         }
 135  0
         return getClass().getName() + "(" + StringUtils.join(openerStrings, ",") + ")";
 136  
     }
 137  
 }